[llvm-commits] [regalloc_linearscan] CVS: llvm/lib/CodeGen/RegAllocLinearScan.cpp LiveIntervals.cpp
Alkis Evlogimenos
alkis at cs.uiuc.edu
Wed Nov 12 00:51:01 PST 2003
Changes in directory llvm/lib/CodeGen:
RegAllocLinearScan.cpp updated: 1.1.2.10 -> 1.1.2.11
LiveIntervals.cpp updated: 1.1.2.8 -> 1.1.2.9
---
Log message:
Put classes the were developed in the regalloc_linearscan branch in
the llvm namespace.
---
Diffs of the changes: (+269 -106)
Index: llvm/lib/CodeGen/RegAllocLinearScan.cpp
diff -u llvm/lib/CodeGen/RegAllocLinearScan.cpp:1.1.2.10 llvm/lib/CodeGen/RegAllocLinearScan.cpp:1.1.2.11
--- llvm/lib/CodeGen/RegAllocLinearScan.cpp:1.1.2.10 Fri Nov 7 18:23:03 2003
+++ llvm/lib/CodeGen/RegAllocLinearScan.cpp Wed Nov 12 00:49:55 2003
@@ -13,6 +13,7 @@
#define DEBUG_TYPE "regalloc"
#include "llvm/Function.h"
#include "llvm/CodeGen/LiveIntervals.h"
+#include "llvm/CodeGen/LiveVariables.h"
#include "llvm/CodeGen/MachineFrameInfo.h"
#include "llvm/CodeGen/MachineFunctionPass.h"
#include "llvm/CodeGen/MachineInstr.h"
@@ -29,6 +30,8 @@
#include "Support/STLExtras.h"
#include <iostream>
+using namespace llvm;
+
namespace {
Statistic<> numSpilled ("ra-linearscan", "Number of registers spilled");
Statistic<> numReloaded("ra-linearscan", "Number of registers reloaded");
@@ -43,12 +46,16 @@
const MRegisterInfo* mri_;
MachineBasicBlock* currentMbb_;
MachineBasicBlock::iterator currentInstr_;
-
+ LiveVariables* lv_;
typedef LiveIntervals::Intervals Intervals;
const Intervals* li_;
Intervals::const_iterator currentInterval_;
IntervalPtrs active_, inactive_;
+ typedef std::vector<unsigned> Regs;
+ Regs tempUseOperands_;
+ Regs tempDefOperands_;
+
typedef LiveIntervals::MiIndex2MbbMap MiIndex2MbbMap;
MiIndex2MbbMap* mii2mbbMap_;
@@ -78,6 +85,7 @@
}
virtual void getAnalysisUsage(AnalysisUsage &AU) const {
+ AU.addRequired<LiveVariables>();
AU.addRequired<LiveIntervals>();
MachineFunctionPass::getAnalysisUsage(AU);
}
@@ -86,44 +94,52 @@
/// runOnMachineFunction - register allocate the whole function
bool runOnMachineFunction(MachineFunction&);
- /// processInterval - entry to the linear scan register
- /// allocator. this happens one every instruction we look at
+ /// processInterval - inspect current interval and add it to
+ /// the active list if required
void processInterval(unsigned curIndex);
/// processActiveIntervals - expire old intervals and move
/// non-overlapping ones to the incative list
void processActiveIntervals(unsigned curIndex);
- /// expireOldInterval - expire old intervals and move
+ /// processInactiveIntervals - expire old intervals and move
/// overlapping ones to the active list
void processInactiveIntervals(unsigned curIndex);
- /// spill - choose and spill at the current
- /// interval. Currently we spill the interval with the last
- /// end point in the active and inactive lists
- void spill();
-
- /// getFreeReg - return a free register for this virtual
- /// register if we have one, otherwise return 0
- unsigned getFreeReg(unsigned virtReg);
-
- /// freeReg - free the physical register associated with this
- /// virtual register and disassociate virtual->physical and
- /// physical->virtual mappings
- void freeReg(unsigned virtReg);
-
- /// markReg - mark the physical register as not free
- /// (preserves mappings)
- void markReg(unsigned virtReg);
-
- /// unmarkReg - mark the physical register as free (preserves
- /// mappings)
- void unmarkReg(unsigned virtReg);
+ /// spillInterval - choose and spill interval. Currently we
+ /// spill the interval with the last end point in the active
+ /// and inactive lists
+ void spillInterval();
+
+ ///
+ /// register handling helpers
+ ///
+
+ /// reservePhysReg - reserves a physical register and spills
+ /// any value assigned to it if any
+ void reservePhysReg(unsigned reg);
+
+ /// clearReservedPhysReg - marks pysical register as free for
+ /// use
+ void clearReservedPhysReg(unsigned reg);
/// physRegAvailable - returns true if the specifed physical
/// register is available
bool physRegAvailable(unsigned physReg);
+ /// getFreePhysReg - return a free physical register for this
+ /// virtual register if we have one, otherwise return 0
+ unsigned getFreePhysReg(unsigned virtReg);
+
+ /// allocateVirt2PhysReg - allocates the free physical
+ /// register to the virtual register passed as arguments
+ void allocateVirt2PhysReg(unsigned virtReg, unsigned physReg);
+
+ /// clearVirtReg - free the physical register associated with this
+ /// virtual register and disassociate virtual->physical and
+ /// physical->virtual mappings
+ void clearVirtReg(unsigned virtReg);
+
/// findOrCreateStackSlot - returns the offset of the
/// specified register on the stack allocating space if
/// necessary
@@ -133,8 +149,9 @@
void spillVirtReg(unsigned virtReg);
/// loadPhysReg - loads to the physical register the value of
- /// the virtual register specifed
- void loadPhysReg(unsigned physReg, unsigned virtReg);
+ /// the virtual register specifed. Virtual register must have
+ /// an assigned stack slot
+ void loadVirt2PhysReg(unsigned virtReg, unsigned physReg);
/// getInstructionIndex() - returns the instruction index as
/// it was computed by the live interval analysis (adjusts for
@@ -165,6 +182,7 @@
mf_ = &fn;
tm_ = &fn.getTarget();
mri_ = tm_->getRegisterInfo();
+ lv_ = &getAnalysis<LiveVariables>();
li_ = &getAnalysis<LiveIntervals>().getIntervals();
currentInterval_ = li_->begin();
active_.clear();
@@ -183,6 +201,11 @@
currentMbb_ = *mbbi;
for (currentInstr_ = currentMbb_->begin();
currentInstr_ != currentMbb_->end(); ++currentInstr_) {
+ // virtual registers that were brought in just for the
+ // computation of the value generated by this
+ // instruction. they will need to be cleared at the end
+ tempUseOperands_.clear();
+ tempDefOperands_.clear();
assert(currentInstr_ >= currentMbb_->begin() &&
currentInstr_ < currentMbb_->end() &&
@@ -200,50 +223,93 @@
DEBUG(printVirt2PhysMap());
// process the active intervals (this will potentially
- // free physical registers)
+ // expire intervals and hence free physical registers)
processActiveIntervals(curIndex);
+
+ // FIXME: holes are completely ignored for now
// processInactiveIntervals(curIndex);
+ // loop over implicit defs spilling them
+ DEBUG(std::cerr << "\t\tprocessing implicit defs:\n");
+ const TargetInstrDescriptor& tid =
+ tm_->getInstrInfo().get((*currentInstr_)->getOpcode());
+ for (const unsigned* id = tid.ImplicitDefs; *id; ++id) {
+ unsigned physReg = *id;
+ reservePhysReg(physReg);
+ }
- // get used operands into registers
- DEBUG(std::cerr << "\t\tprocessing operands:\n");
+ // loop over operands and spill all already defined
+ // physical registers
+ DEBUG(std::cerr << "\t\tprocessing already allocated physical "
+ "registers:\n");
+ for (unsigned i = 0, e = (*currentInstr_)->getNumOperands();
+ i != e; ++i) {
+ MachineOperand& op = (*currentInstr_)->getOperand(i);
+ if (op.isPhysicalRegister() &&
+ (op.opIsDefOnly() || op.opIsDefAndUse())) {
+ unsigned physReg = op.getAllocatedRegNum();
+ reservePhysReg(physReg);
+ }
+ }
+
+ // assign physical registers to used operands
+ DEBUG(std::cerr << "\t\tprocessing used operands:\n");
for (unsigned i = 0, e = (*currentInstr_)->getNumOperands();
i != e; ++i) {
MachineOperand& op = (*currentInstr_)->getOperand(i);
if (op.opIsUse() && op.isVirtualRegister()) {
unsigned virtReg = op.getAllocatedRegNum();
Virt2PhysMap::iterator it = v2pMap_.find(virtReg);
+ // virtual register is used but it is not
+ // allocated. it must be in a stack slot
if (it == v2pMap_.end()) {
- unsigned physReg = it->second;
- loadPhysReg(physReg, virtReg);
+ unsigned physReg = getFreePhysReg(virtReg);
+ if (!physReg) {
+ spillInterval();
+ physReg = getFreePhysReg(virtReg);
+ }
+ assert(physReg && "no available physical register?!");
+ loadVirt2PhysReg(virtReg, physReg);
+ tempUseOperands_.push_back(virtReg);
}
+ (*currentInstr_)->SetMachineOperandReg(i, v2pMap_[virtReg]);
}
}
- // loop over implicit defs spilling them
- DEBUG(std::cerr << "\t\tprocessing implicit defs:\n");
- const TargetInstrDescriptor& tid =
- tm_->getInstrInfo().get((*currentInstr_)->getOpcode());
- for (const unsigned* id = tid.ImplicitDefs; *id; ++id) {
- DEBUG(printVirt2PhysMap());
- unsigned virtReg = p2vMap_[*id];
- if (virtReg) {
- spillVirtReg(virtReg);
- for (IntervalPtrs::iterator
- i = active_.begin(); i != active_.end(); ) {
- if ((*i)->reg == virtReg) {
- i = active_.erase(i);
- break;
- }
- else {
- ++i;
+ processInterval(curIndex);
+
+ // assign physical registers to used operands
+ DEBUG(std::cerr << "\t\tprocessing not allocated defined "
+ "operands:\n");
+ for (unsigned i = 0, e = (*currentInstr_)->getNumOperands();
+ i != e; ++i) {
+ MachineOperand& op = (*currentInstr_)->getOperand(i);
+ if ((op.opIsDefOnly() || op.opIsDefAndUse()) &&
+ op.isVirtualRegister()) {
+ unsigned virtReg = op.getAllocatedRegNum();
+ Virt2PhysMap::iterator it = v2pMap_.find(virtReg);
+ // virtual register is defined but it is not
+ // allocated. it must be in a stack slot
+ if (it == v2pMap_.end()) {
+ unsigned physReg = getFreePhysReg(virtReg);
+ if (!physReg) {
+ spillInterval();
+ physReg = getFreePhysReg(virtReg);
}
+ assert(physReg && "no available physical register?!");
+ loadVirt2PhysReg(virtReg, physReg);
+ tempDefOperands_.push_back(virtReg);
}
+ (*currentInstr_)->SetMachineOperandReg(i, v2pMap_[virtReg]);
}
}
- processInterval(curIndex);
+ // interval maybe spilled so we need to pull in any defs
+ // temporarily and spill them after the instruction is
+ // done
+ // use our current mapping and actually replace and
+ // virtual register with its allocated physical registers
for (unsigned i = 0, e = (*currentInstr_)->getNumOperands();
i != e; ++i) {
MachineOperand& op = (*currentInstr_)->getOperand(i);
@@ -255,9 +321,48 @@
}
}
+ // loop over killed physical registers and clear them
+ DEBUG(std::cerr << "\t\tprocessing killed physical registers:\n");
+ for (LiveVariables::killed_iterator
+ ki = lv_->killed_begin(*currentInstr_),
+ ke = lv_->killed_end(*currentInstr_);
+ ki != ke; ++ki) {
+ unsigned reg = ki->second;
+ if (reg < MRegisterInfo::FirstVirtualRegister) {
+ clearReservedPhysReg(reg);
+ }
+ }
+
+ // loop over dead physical registers and clear them
+ DEBUG(std::cerr << "\t\tprocessing dead physical registers:\n");
+ for (LiveVariables::killed_iterator
+ ki = lv_->dead_begin(*currentInstr_),
+ ke = lv_->dead_end(*currentInstr_);
+ ki != ke; ++ki) {
+ unsigned reg = ki->second;
+ if (reg < MRegisterInfo::FirstVirtualRegister) {
+ clearReservedPhysReg(reg);
+ }
+ }
+
+ DEBUG(std::cerr << "\t\tclearing temporarily used operands:\n");
+ for (unsigned i = 0, e = tempUseOperands_.size(); i != e; ++i) {
+ clearVirtReg(tempUseOperands_[i]);
+ }
+
+ DEBUG(std::cerr << "\t\tspilling temporarily defined operands:\n");
+ for (unsigned i = 0, e = tempDefOperands_.size(); i != e; ++i) {
+ spillVirtReg(tempDefOperands_[i]);
+ }
+
DEBUG(std::cerr << "instruction[" << curIndex << "]: ";
(*currentInstr_)->print(std::cerr, *tm_));
}
+
+ for (unsigned i = 0, e = p2vMap_.size(); i != e; ++i) {
+ assert(p2vMap_[i] != i &&
+ "reserved physical registers at end of basic block?");
+ }
}
return true;
@@ -274,14 +379,37 @@
currentInterval_->start() == curIndex) {
DEBUG(std::cerr << "\t\tprocessing current interval:\n");
unsigned virtReg = currentInterval_->reg;
- unsigned physReg = getFreeReg(virtReg);
+ unsigned physReg = (unsigned) -1;
+ if (tm_->getInstrInfo().isTwoAddrInstr((*currentInstr_)->getOpcode())) {
+ assert((*currentInstr_)->getOperand(1).isRegister() &&
+ (*currentInstr_)->getOperand(1).getAllocatedRegNum() &&
+ (*currentInstr_)->getOperand(1).opIsUse() &&
+ "Two address instruction invalid");
+
+ physReg = (*currentInstr_)->getOperand(1).getAllocatedRegNum();
+ // remove interval from active
+ for (IntervalPtrs::iterator i = active_.begin(), e = active_.end();
+ i != e; ++i) {
+ if ((*i)->reg == p2vMap_[physReg]) {
+ active_.erase(i);
+ break;
+ }
+ }
+ tempUseOperands_.erase(remove(tempUseOperands_.begin(),
+ tempUseOperands_.end(),
+ p2vMap_[physReg]),
+ tempUseOperands_.end());
+ spillVirtReg(p2vMap_[physReg]);
+ }
+ else {
+ physReg = getFreePhysReg(virtReg);
+ }
+
if (!physReg) {
- spill();
- physReg = getFreeReg(virtReg);
+ spillInterval();
+ physReg = getFreePhysReg(virtReg);
}
- bool inserted = v2pMap_.insert(std::make_pair(virtReg, physReg)).second;
- assert (inserted && "attempt to allocate already allocated register");
- markReg(virtReg);
+ allocateVirt2PhysReg(virtReg, physReg);
active_.push_back(&*currentInterval_);
++currentInterval_;
}
@@ -295,10 +423,11 @@
// remove expired intervals
if ((*i)->expired(curIndex)) {
DEBUG(std::cerr << "\t\t\tinterval " << **i << " expired\n");
- freeReg(virtReg);
+ clearVirtReg(virtReg);
// remove interval from active
i = active_.erase(i);
}
+ // move not active intervals to inactive list
// else if (!(*i)->overlaps(curIndex)) {
// DEBUG(std::cerr << "\t\t\tinterval " << **i << " inactive\n");
// unmarkReg(virtReg);
@@ -315,30 +444,32 @@
void RA::processInactiveIntervals(unsigned curIndex)
{
- DEBUG(std::cerr << "\t\tprocessing inactive intervals:\n");
- for (IntervalPtrs::iterator i = inactive_.begin(); i != inactive_.end();) {
- unsigned virtReg = (*i)->reg;
- if ((*i)->expired(curIndex)) {
- DEBUG(std::cerr << "\t\t\tinterval " << **i << " expired\n");
- freeReg(virtReg);
- // remove from inactive
- i = inactive_.erase(i);
- }
- else if ((*i)->overlaps(curIndex)) {
- DEBUG(std::cerr << "\t\t\tinterval " << **i << " active\n");
- markReg(virtReg);
- // add to active
- active_.push_back(*i);
- // remove from inactive
- i = inactive_.erase(i);
- }
- else {
- ++i;
- }
- }
+// DEBUG(std::cerr << "\t\tprocessing inactive intervals:\n");
+// for (IntervalPtrs::iterator i = inactive_.begin(); i != inactive_.end();) {
+// unsigned virtReg = (*i)->reg;
+// // remove expired intervals
+// if ((*i)->expired(curIndex)) {
+// DEBUG(std::cerr << "\t\t\tinterval " << **i << " expired\n");
+// freePhysReg(virtReg);
+// // remove from inactive
+// i = inactive_.erase(i);
+// }
+// // move re-activated intervals in active list
+// else if ((*i)->overlaps(curIndex)) {
+// DEBUG(std::cerr << "\t\t\tinterval " << **i << " active\n");
+// markReg(virtReg);
+// // add to active
+// active_.push_back(*i);
+// // remove from inactive
+// i = inactive_.erase(i);
+// }
+// else {
+// ++i;
+// }
+// }
}
-void RA::spill()
+void RA::spillInterval()
{
DEBUG(std::cerr << "\t\tspilling at interval "<< *currentInterval_<< ":\n");
assert(!active_.empty() &&
@@ -361,8 +492,8 @@
DEBUG(std::cerr << "\t\t\tspilling interval " << **lastEnd << "\n");
// spill last in active and inactive
- spillVirtReg((*lastEnd)->reg);
- freeReg((*lastEnd)->reg);
+ unsigned virtReg = (*lastEnd)->reg;
+ spillVirtReg(virtReg);
if (inInactive) {
inactive_.erase(lastEnd);
}
@@ -371,6 +502,35 @@
}
}
+void RA::reservePhysReg(unsigned physReg)
+{
+ DEBUG(std::cerr << "\t\t\treserving physical physical register: "
+ << mri_->getName(physReg) << '\n');
+ // if this register holds a value spill it
+ unsigned virtReg = p2vMap_[physReg];
+ if (virtReg != 0 && virtReg != physReg) {
+ // remove interval from active
+ for (IntervalPtrs::iterator i = active_.begin(), e = active_.end();
+ i != e; ++i) {
+ if ((*i)->reg == virtReg) {
+ active_.erase(i);
+ break;
+ }
+ }
+ spillVirtReg(virtReg);
+ }
+ p2vMap_[physReg] = physReg; // this denotes a reserved physical register
+}
+
+void RA::clearReservedPhysReg(unsigned physReg)
+{
+ DEBUG(std::cerr << "\t\t\tclearing reserved physical physical register: "
+ << mri_->getName(physReg) << '\n');
+ assert(p2vMap_[physReg] == physReg &&
+ "attempt to clear a non reserved physical register");
+ p2vMap_[physReg] = 0;
+}
+
bool RA::physRegAvailable(unsigned physReg)
{
if (p2vMap_[physReg]) {
@@ -387,9 +547,9 @@
return true;
}
-unsigned RA::getFreeReg(unsigned virtReg)
+unsigned RA::getFreePhysReg(unsigned virtReg)
{
- DEBUG(std::cerr << "\t\t\tgetting free register: ");
+ DEBUG(std::cerr << "\t\t\tgetting free physical register: ");
const TargetRegisterClass* rc = mf_->getSSARegMap()->getRegClass(virtReg);
TargetRegisterClass::iterator reg = rc->allocation_order_begin(*mf_);
TargetRegisterClass::iterator regEnd = rc->allocation_order_end(*mf_);
@@ -406,37 +566,37 @@
return 0;
}
-void RA::freeReg(unsigned virtReg)
-{
- unmarkReg(virtReg);
-}
-
-void RA::markReg(unsigned virtReg)
+void RA::allocateVirt2PhysReg(unsigned virtReg, unsigned physReg)
{
+ assert(physRegAvailable(physReg) &&
+ "attempt to allocate to a not available physical register");
Virt2PhysMap::iterator it = v2pMap_.find(virtReg);
- assert(it != v2pMap_.end() &&
- "attempting to mark an already disassociated register");
- unsigned physReg = it->second;
- DEBUG(std::cerr << "\t\t\t\tmarked registster " << mri_->getName(physReg)
- << " used by " << virtReg << '\n');
+ bool inserted = v2pMap_.insert(std::make_pair(virtReg, physReg)).second;
+ assert(inserted &&
+ "attempt to allocate an already allocated virtual register");
p2vMap_[physReg] = virtReg;
+ DEBUG(std::cerr << "\t\t\t\tallocated register " << virtReg << " to "
+ << mri_->getName(physReg) << '\n');
}
-void RA::unmarkReg(unsigned virtReg)
+void RA::clearVirtReg(unsigned virtReg)
{
Virt2PhysMap::iterator it = v2pMap_.find(virtReg);
assert(it != v2pMap_.end() &&
- "attempting to unmark an already disassociated register");
+ "attempting to clear a not allocated virtual register");
unsigned physReg = it->second;
- DEBUG(std::cerr << "\t\t\t\tmarked registster " << mri_->getName(physReg)
- << " free\n");
+ assert(p2vMap_[physReg] == virtReg &&
+ "virt2physMap and phys2virtMap mismatch");
p2vMap_[physReg] = 0;
v2pMap_.erase(it);
+ DEBUG(std::cerr << "\t\t\t\tcleared register " << mri_->getName(physReg)
+ << "\n");
}
int RA::findOrCreateStackSlot(unsigned virtReg)
{
- // use lower_bound so that we can do a O(1) insert later if necessary
+ // use lower_bound so that we can do a possibly O(1) insert later
+ // if necessary
Virt2StackSlotMap::iterator it = v2ssMap_.lower_bound(virtReg);
if (it != v2ssMap_.end() && it->first == virtReg) {
return it->second;
@@ -451,25 +611,26 @@
void RA::spillVirtReg(unsigned virtReg)
{
- DEBUG(std::cerr << "\t\t\tspilling register: " << virtReg << '\n');
+ DEBUG(std::cerr << "\t\t\tspilling register: " << virtReg);
const TargetRegisterClass* rc = mf_->getSSARegMap()->getRegClass(virtReg);
int frameIndex = findOrCreateStackSlot(virtReg);
+ DEBUG(std::cerr << " to stack slot #" << frameIndex << '\n');
++numSpilled;
instrAdded_ += mri_->storeRegToStackSlot(*currentMbb_, currentInstr_,
v2pMap_[virtReg], frameIndex, rc);
- unmarkReg(virtReg);
+ clearVirtReg(virtReg);
}
-void RA::loadPhysReg(unsigned physReg, unsigned virtReg)
+void RA::loadVirt2PhysReg(unsigned virtReg, unsigned physReg)
{
+ DEBUG(std::cerr << "\t\t\tloading register: " << virtReg);
const TargetRegisterClass* rc = mf_->getSSARegMap()->getRegClass(virtReg);
int frameIndex = findOrCreateStackSlot(virtReg);
+ DEBUG(std::cerr << " from stack slot #" << frameIndex << '\n');
++numReloaded;
instrAdded_ += mri_->loadRegFromStackSlot(*currentMbb_, currentInstr_,
physReg, frameIndex, rc);
- bool inserted = v2pMap_.insert(std::make_pair(virtReg, physReg)).second;
- assert (inserted && "attempt to allocate already allocated register");
- markReg(virtReg);
+ allocateVirt2PhysReg(virtReg, physReg);
}
unsigned RA::getInstructionIndex() const
@@ -480,6 +641,6 @@
return it->second + (currentInstr_ - currentMbb_->begin()) - instrAdded_;
}
-FunctionPass *createLinearScanRegisterAllocator() {
+FunctionPass* llvm::createLinearScanRegisterAllocator() {
return new RA();
}
Index: llvm/lib/CodeGen/LiveIntervals.cpp
diff -u llvm/lib/CodeGen/LiveIntervals.cpp:1.1.2.8 llvm/lib/CodeGen/LiveIntervals.cpp:1.1.2.9
--- llvm/lib/CodeGen/LiveIntervals.cpp:1.1.2.8 Fri Nov 7 18:23:03 2003
+++ llvm/lib/CodeGen/LiveIntervals.cpp Wed Nov 12 00:49:55 2003
@@ -34,6 +34,8 @@
#include "Support/Statistic.h"
#include <iostream>
+using namespace llvm;
+
namespace {
RegisterAnalysis<LiveIntervals> X("liveintervals",
"Live Interval Analysis");
More information about the llvm-commits
mailing list