[llvm-commits] [regalloc_linearscan] CVS: llvm/lib/CodeGen/RegAllocLinearScan.cpp LiveIntervals.cpp
Alkis Evlogimenos
alkis at cs.uiuc.edu
Fri Nov 7 18:24:02 PST 2003
Changes in directory llvm/lib/CodeGen:
RegAllocLinearScan.cpp updated: 1.1.2.9 -> 1.1.2.10
LiveIntervals.cpp updated: 1.1.2.7 -> 1.1.2.8
---
Log message:
LiveIntervals:
- be a little stricter in terms of constness
- make runOnMachineFunction reentrant
- make debugging output prettier
- fix wrong interval computation of variables that get killed in
their defining basic block
RegAlloc:
- disable inactive interval processing, handle the simple case for
now (ignore holes)
- improve debugging output
- succeed in register allocating a simple hello world llvm assembly file
---
Diffs of the changes: (+214 -96)
Index: llvm/lib/CodeGen/RegAllocLinearScan.cpp
diff -u llvm/lib/CodeGen/RegAllocLinearScan.cpp:1.1.2.9 llvm/lib/CodeGen/RegAllocLinearScan.cpp:1.1.2.10
--- llvm/lib/CodeGen/RegAllocLinearScan.cpp:1.1.2.9 Thu Nov 6 03:59:26 2003
+++ llvm/lib/CodeGen/RegAllocLinearScan.cpp Fri Nov 7 18:23:03 2003
@@ -35,7 +35,7 @@
class RA : public MachineFunctionPass {
public:
- typedef std::vector<LiveIntervals::Interval*> IntervalPtrs;
+ typedef std::vector<const LiveIntervals::Interval*> IntervalPtrs;
private:
MachineFunction* mf_;
@@ -45,8 +45,8 @@
MachineBasicBlock::iterator currentInstr_;
typedef LiveIntervals::Intervals Intervals;
- Intervals* li_;
-
+ const Intervals* li_;
+ Intervals::const_iterator currentInterval_;
IntervalPtrs active_, inactive_;
typedef LiveIntervals::MiIndex2MbbMap MiIndex2MbbMap;
@@ -55,6 +55,9 @@
typedef LiveIntervals::Mbb2MiIndexMap Mbb2MiIndexMap;
Mbb2MiIndexMap* mbb2miiMap_;
+ typedef LiveIntervals::MachineBasicBlockPtrs MachineBasicBlockPtrs;
+ MachineBasicBlockPtrs mbbs_;
+
typedef std::map<MachineInstr*, unsigned> Instr2IndexMap;
Instr2IndexMap i2iMap_;
@@ -83,18 +86,22 @@
/// 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
+ void processInterval(unsigned curIndex);
+
/// processActiveIntervals - expire old intervals and move
/// non-overlapping ones to the incative list
- void processActiveIntervals(Intervals::iterator cur);
+ void processActiveIntervals(unsigned curIndex);
/// expireOldInterval - expire old intervals and move
/// overlapping ones to the active list
- void processInactiveIntervals(Intervals::iterator cur);
+ void processInactiveIntervals(unsigned curIndex);
- /// spillAtInterval - choose and spill at the specified
+ /// 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 spillAtInterval(Intervals::iterator cur);
+ void spill();
/// getFreeReg - return a free register for this virtual
/// register if we have one, otherwise return 0
@@ -129,23 +136,29 @@
/// the virtual register specifed
void loadPhysReg(unsigned physReg, unsigned virtReg);
- /// getMbbMbbIteratorPair - returns a pair of the
- /// MachineBasicBlock this instruction is on and the iterator
- /// pointing to the instruction
- std::pair<MachineBasicBlock*, MachineBasicBlock::iterator>
- getMbbMbbIteratorPair(unsigned miIndex) const;
- };
-}
-
-namespace {
- void printIntervals(const char* const str,
- RA::IntervalPtrs::const_iterator i,
- RA::IntervalPtrs::const_iterator e) {
- if (str) std::cerr << str << " intervals:\n";
- for (; i != e; ++i) {
- std::cerr << "\t\t" << **i << '\n';
+ /// getInstructionIndex() - returns the instruction index as
+ /// it was computed by the live interval analysis (adjusts for
+ /// inserted instructions.
+ unsigned getInstructionIndex() const;
+
+ void printVirt2PhysMap() const {
+ std::cerr << "\tallocated registers: ";
+ for (Virt2PhysMap::const_iterator
+ i = v2pMap_.begin(), e = v2pMap_.end(); i != e; ++i) {
+ std::cerr << '[' << i->first << ','
+ << mri_->getName(i->second) << "] ";
+ }
+ std::cerr << '\n';
+ }
+ void printIntervals(const char* const str,
+ RA::IntervalPtrs::const_iterator i,
+ RA::IntervalPtrs::const_iterator e) const {
+ if (str) std::cerr << str << " intervals:\n";
+ for (; i != e; ++i) {
+ std::cerr << "\t\t" << **i << '\n';
+ }
}
- }
+ };
}
bool RA::runOnMachineFunction(MachineFunction &fn) {
@@ -153,83 +166,165 @@
tm_ = &fn.getTarget();
mri_ = tm_->getRegisterInfo();
li_ = &getAnalysis<LiveIntervals>().getIntervals();
+ currentInterval_ = li_->begin();
active_.clear();
inactive_.clear();
mii2mbbMap_ = &getAnalysis<LiveIntervals>().getMiIndex2MbbMap();
mbb2miiMap_ = &getAnalysis<LiveIntervals>().getMbb2MiIndexMap();
+ mbbs_ = getAnalysis<LiveIntervals>().getOrderedMachineBasicBlockPtrs();
p2vMap_.resize(MRegisterInfo::FirstVirtualRegister-1);
p2vMap_.clear();
v2pMap_.clear();
v2ssMap_.clear();
- instrAdded_ = 0;
-
- // liner scan algorithm
- DEBUG(std::cerr << "Processing " << li_->size() << " instervals\n");
- for (Intervals::iterator i = li_->begin(), e = li_->end(); i != e; ++i) {
- tie(currentMbb_, currentInstr_) = getMbbMbbIteratorPair(i->start());
- DEBUG(std::cerr << "instruction[" << i->start() << "]: "
- << **currentInstr_);
- assert(currentInstr_ >= currentMbb_->begin() &&
- currentInstr_ < currentMbb_->end() &&
- "current instruction/machine basic block mismatch");
- DEBUG(printIntervals("\tactive", active_.begin(), active_.end()));
- DEBUG(printIntervals("\tinactive", inactive_.begin(), inactive_.end()));
- processActiveIntervals(i);
- processInactiveIntervals(i);
+ for (MachineBasicBlockPtrs::iterator
+ mbbi = mbbs_.begin(), mbbe = mbbs_.end(); mbbi != mbbe; ++mbbi) {
+ instrAdded_ = 0;
+ currentMbb_ = *mbbi;
+ for (currentInstr_ = currentMbb_->begin();
+ currentInstr_ != currentMbb_->end(); ++currentInstr_) {
+
+ assert(currentInstr_ >= currentMbb_->begin() &&
+ currentInstr_ < currentMbb_->end() &&
+ "current instruction/machine basic block mismatch");
+ unsigned curIndex = getInstructionIndex();
+ DEBUG(std::cerr << "instruction[" << curIndex << "]: ";
+ (*currentInstr_)->print(std::cerr, *tm_));
+ DEBUG(std::cerr << "\tcurrent interval: ";
+ if (currentInterval_ == li_->end()) std::cerr << "NONE\n";
+ else std::cerr << *currentInterval_ << '\n');
+ DEBUG(printIntervals("\tactive", active_.begin(), active_.end()));
+ DEBUG(printIntervals("\tinactive",
+ inactive_.begin(),
+ inactive_.end()));
+ DEBUG(printVirt2PhysMap());
+
+ // process the active intervals (this will potentially
+ // free physical registers)
+ processActiveIntervals(curIndex);
+ // processInactiveIntervals(curIndex);
+
+
+ // get used operands into registers
+ DEBUG(std::cerr << "\t\tprocessing 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);
+ if (it == v2pMap_.end()) {
+ unsigned physReg = it->second;
+ loadPhysReg(physReg, 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);
+
+ for (unsigned i = 0, e = (*currentInstr_)->getNumOperands();
+ i != e; ++i) {
+ MachineOperand& op = (*currentInstr_)->getOperand(i);
+ if (op.isVirtualRegister()) {
+ unsigned virtReg = op.getAllocatedRegNum();
+ unsigned physReg = v2pMap_[virtReg];
+ assert(physReg && "should not have virtual registers here");
+ (*currentInstr_)->SetMachineOperandReg(i, physReg);
+ }
+ }
- unsigned physReg = getFreeReg(i->reg);
- if (!physReg) {
- spillAtInterval(i);
- physReg = getFreeReg(i->reg);
+ DEBUG(std::cerr << "instruction[" << curIndex << "]: ";
+ (*currentInstr_)->print(std::cerr, *tm_));
}
- loadPhysReg(physReg, i->reg);
- active_.push_back(&*i);
}
return true;
}
-void RA::processActiveIntervals(Intervals::iterator cur)
+void RA::processInterval(unsigned curIndex)
+{
+ // liner scan algorithm
+ assert((currentInterval_ == li_->end() ||
+ currentInterval_->start() >= curIndex)
+ && "skipping intervals?");
+
+ if (currentInterval_ != li_->end() &&
+ currentInterval_->start() == curIndex) {
+ DEBUG(std::cerr << "\t\tprocessing current interval:\n");
+ unsigned virtReg = currentInterval_->reg;
+ unsigned physReg = getFreeReg(virtReg);
+ if (!physReg) {
+ spill();
+ physReg = getFreeReg(virtReg);
+ }
+ bool inserted = v2pMap_.insert(std::make_pair(virtReg, physReg)).second;
+ assert (inserted && "attempt to allocate already allocated register");
+ markReg(virtReg);
+ active_.push_back(&*currentInterval_);
+ ++currentInterval_;
+ }
+}
+
+void RA::processActiveIntervals(unsigned curIndex)
{
DEBUG(std::cerr << "\t\tprocessing active intervals:\n");
- unsigned curInstrIndex = cur->start();
for (IntervalPtrs::iterator i = active_.begin(); i != active_.end();) {
unsigned virtReg = (*i)->reg;
// remove expired intervals
- if ((*i)->expired(curInstrIndex)) {
+ if ((*i)->expired(curIndex)) {
DEBUG(std::cerr << "\t\t\tinterval " << **i << " expired\n");
freeReg(virtReg);
// remove interval from active
i = active_.erase(i);
}
- else if (!(*i)->overlaps(curInstrIndex)) {
- DEBUG(std::cerr << "\t\t\tinterval " << **i << " inactive\n");
- unmarkReg(virtReg);
- // add interval to inactive
- inactive_.push_back(*i);
- // remove interval from active
- i = active_.erase(i);
- }
+// else if (!(*i)->overlaps(curIndex)) {
+// DEBUG(std::cerr << "\t\t\tinterval " << **i << " inactive\n");
+// unmarkReg(virtReg);
+// // add interval to inactive
+// inactive_.push_back(*i);
+// // remove interval from active
+// i = active_.erase(i);
+// }
else {
++i;
}
}
}
-void RA::processInactiveIntervals(Intervals::iterator cur)
+void RA::processInactiveIntervals(unsigned curIndex)
{
DEBUG(std::cerr << "\t\tprocessing inactive intervals:\n");
- unsigned curInstrIndex = cur->start();
for (IntervalPtrs::iterator i = inactive_.begin(); i != inactive_.end();) {
unsigned virtReg = (*i)->reg;
- if ((*i)->expired(curInstrIndex)) {
+ 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(curInstrIndex)) {
+ else if ((*i)->overlaps(curIndex)) {
DEBUG(std::cerr << "\t\t\tinterval " << **i << " active\n");
markReg(virtReg);
// add to active
@@ -243,9 +338,9 @@
}
}
-void RA::spillAtInterval(Intervals::iterator cur)
+void RA::spill()
{
- DEBUG(std::cerr << "\t\tspilling at interval " << *cur << ":\n");
+ DEBUG(std::cerr << "\t\tspilling at interval "<< *currentInterval_<< ":\n");
assert(!active_.empty() &&
"active set cannot be empty when choosing a register to spill");
IntervalPtrs::iterator lastEnd = active_.begin();
@@ -294,7 +389,7 @@
unsigned RA::getFreeReg(unsigned virtReg)
{
- DEBUG(std::cerr << "\t\tgetting free register: ");
+ DEBUG(std::cerr << "\t\t\tgetting free register: ");
const TargetRegisterClass* rc = mf_->getSSARegMap()->getRegClass(virtReg);
TargetRegisterClass::iterator reg = rc->allocation_order_begin(*mf_);
TargetRegisterClass::iterator regEnd = rc->allocation_order_end(*mf_);
@@ -314,7 +409,6 @@
void RA::freeReg(unsigned virtReg)
{
unmarkReg(virtReg);
- v2pMap_.erase(v2pMap_.find(virtReg));
}
void RA::markReg(unsigned virtReg)
@@ -323,6 +417,8 @@
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');
p2vMap_[physReg] = virtReg;
}
@@ -330,9 +426,12 @@
{
Virt2PhysMap::iterator it = v2pMap_.find(virtReg);
assert(it != v2pMap_.end() &&
- "attempting to mark an already disassociated register");
+ "attempting to unmark an already disassociated register");
unsigned physReg = it->second;
+ DEBUG(std::cerr << "\t\t\t\tmarked registster " << mri_->getName(physReg)
+ << " free\n");
p2vMap_[physReg] = 0;
+ v2pMap_.erase(it);
}
int RA::findOrCreateStackSlot(unsigned virtReg)
@@ -352,11 +451,13 @@
void RA::spillVirtReg(unsigned virtReg)
{
+ DEBUG(std::cerr << "\t\t\tspilling register: " << virtReg << '\n');
const TargetRegisterClass* rc = mf_->getSSARegMap()->getRegClass(virtReg);
int frameIndex = findOrCreateStackSlot(virtReg);
++numSpilled;
instrAdded_ += mri_->storeRegToStackSlot(*currentMbb_, currentInstr_,
v2pMap_[virtReg], frameIndex, rc);
+ unmarkReg(virtReg);
}
void RA::loadPhysReg(unsigned physReg, unsigned virtReg)
@@ -366,17 +467,17 @@
++numReloaded;
instrAdded_ += mri_->loadRegFromStackSlot(*currentMbb_, currentInstr_,
physReg, frameIndex, rc);
- v2pMap_[virtReg] = physReg;
- p2vMap_[physReg] = virtReg;
+ bool inserted = v2pMap_.insert(std::make_pair(virtReg, physReg)).second;
+ assert (inserted && "attempt to allocate already allocated register");
+ markReg(virtReg);
}
-std::pair<MachineBasicBlock*, MachineBasicBlock::iterator>
-RA::getMbbMbbIteratorPair(unsigned miIndex) const
+unsigned RA::getInstructionIndex() const
{
- MachineBasicBlock* mbb = (*mii2mbbMap_)[miIndex];
- MachineBasicBlock::iterator instr =
- mbb->begin() + instrAdded_ + miIndex - (*mbb2miiMap_)[mbb];
- return std::make_pair(mbb, instr);
+ Mbb2MiIndexMap::const_iterator it = mbb2miiMap_->find(currentMbb_);
+ assert(it != mbb2miiMap_->end() &&
+ "no MachineInstruction index for basic block?");
+ return it->second + (currentInstr_ - currentMbb_->begin()) - instrAdded_;
}
FunctionPass *createLinearScanRegisterAllocator() {
Index: llvm/lib/CodeGen/LiveIntervals.cpp
diff -u llvm/lib/CodeGen/LiveIntervals.cpp:1.1.2.7 llvm/lib/CodeGen/LiveIntervals.cpp:1.1.2.8
--- llvm/lib/CodeGen/LiveIntervals.cpp:1.1.2.7 Wed Nov 5 20:58:12 2003
+++ llvm/lib/CodeGen/LiveIntervals.cpp Fri Nov 7 18:23:03 2003
@@ -57,6 +57,13 @@
tm_ = &fn.getTarget();
mri_ = tm_->getRegisterInfo();
lv_ = &getAnalysis<LiveVariables>();
+ mbbi2mbbMap_.clear();
+ mi2iMap_.clear();
+ r2iMap_.clear();
+ r2iMap_.clear();
+ intervals_.clear();
+ mii2mbbMap_.clear();
+ mbb2miiMap_.clear();
// number MachineInstrs
unsigned miIndex = 0;
@@ -86,21 +93,19 @@
return true;
}
-namespace {
- void printRegName(const MRegisterInfo* mri, int reg) {
- DEBUG(
- if (reg < MRegisterInfo::FirstVirtualRegister)
- std::cerr << mri->getName(reg);
- else
- std::cerr << '%' << reg);
- }
+void LiveIntervals::printRegName(unsigned reg) const
+{
+ if (reg < MRegisterInfo::FirstVirtualRegister)
+ std::cerr << mri_->getName(reg);
+ else
+ std::cerr << '%' << reg;
}
void LiveIntervals::handleRegisterDef(MachineBasicBlock* mbb,
MachineInstr* instr,
unsigned reg)
{
- DEBUG(std::cerr << "\t\t\tregister: "; printRegName(mri_, reg));
+ DEBUG(std::cerr << "\t\t\tregister: ";printRegName(reg); std::cerr << '\n');
unsigned instrIndex = getInstructionIndex(instr);
@@ -113,8 +118,10 @@
unsigned ii = r2iit->second;
Interval& interval = intervals_[ii];
unsigned end = getInstructionIndex(mbb->back()) + 1;
+ DEBUG(std::cerr << "\t\t\t\tadding range: ["
+ << instrIndex << ',' << end << "]\n");
interval.addRange(instrIndex, end);
- DEBUG(std::cerr << " -> " << interval << '\n');
+ DEBUG(std::cerr << "\t\t\t\t" << interval << '\n');
}
else {
// add new interval
@@ -130,28 +137,38 @@
MachineBasicBlock* liveBlock = it->second;
if (liveBlockIndex < vi.AliveBlocks.size() &&
vi.AliveBlocks[liveBlockIndex]) {
- unsigned start = mbb == liveBlock ?
- instrIndex :
- getInstructionIndex(liveBlock->front());
- interval.addRange(start,
- getInstructionIndex(liveBlock->back()) + 1);
+ unsigned start = getInstructionIndex(liveBlock->front());
+ unsigned end = getInstructionIndex(liveBlock->back()) + 1;
+ DEBUG(std::cerr << "\t\t\t\tadding range: ["
+ << start << ',' << end << "]\n");
+ interval.addRange(start, end);
}
}
+ bool killedInDefiningBasicBlock = false;
for (int i = 0, e = vi.Kills.size(); i != e; ++i) {
MachineBasicBlock* killerBlock = vi.Kills[i].first;
MachineInstr* killerInstr = vi.Kills[i].second;
- unsigned start = mbb == killerBlock ?
- instrIndex :
- getInstructionIndex(killerBlock->front());
- interval.addRange(start,
- getInstructionIndex(killerInstr) + 1);
+ killedInDefiningBasicBlock |= mbb == killerBlock;
+ unsigned start = (mbb == killerBlock ?
+ instrIndex :
+ getInstructionIndex(killerBlock->front()));
+ unsigned end = getInstructionIndex(killerInstr) + 1;
+ DEBUG(std::cerr << "\t\t\t\tadding range: ["
+ << start << ',' << end << "]\n");
+ interval.addRange(start, end);
}
- DEBUG(std::cerr << " -> " << interval << '\n');
+
+ if (!killedInDefiningBasicBlock) {
+ unsigned end = getInstructionIndex(mbb->back()) + 1;
+ interval.addRange(instrIndex, end);
+ }
+
+ DEBUG(std::cerr << "\t\t\t\t" << interval << '\n');
}
}
-unsigned LiveIntervals::getInstructionIndex(MachineInstr* instr)
+unsigned LiveIntervals::getInstructionIndex(MachineInstr* instr) const
{
assert(mi2iMap_.find(instr) != mi2iMap_.end() &&
"instruction not assigned a number");
@@ -178,8 +195,8 @@
const TargetInstrDescriptor& tid =
tm_->getInstrInfo().get(instr->getOpcode());
DEBUG(std::cerr << "\t\tinstruction["
- << mi2iMap_.find(instr)->second << "]: "
- << *instr << '\n');
+ << getInstructionIndex(instr) << "]: ";
+ instr->print(std::cerr, *tm_););
for (int i = instr->getNumOperands() - 1; i >= 0; --i) {
MachineOperand& mop = instr->getOperand(i);
More information about the llvm-commits
mailing list