From 1a8ea01f01b30e28e4e3ac0e3a344c4a4d579270 Mon Sep 17 00:00:00 2001 From: Alkis Evlogimenos Date: Wed, 4 Aug 2004 09:46:26 +0000 Subject: [PATCH] Convert indentation to 2 spaces. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@15489 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/CodeGen/LiveIntervalAnalysis.h | 292 +++---- lib/CodeGen/LiveIntervalAnalysis.cpp | 807 +++++++++--------- lib/CodeGen/LiveIntervalAnalysis.h | 292 +++---- lib/CodeGen/RegAllocIterativeScan.cpp | 724 ++++++++--------- lib/CodeGen/RegAllocLinearScan.cpp | 858 ++++++++++---------- 5 files changed, 1486 insertions(+), 1487 deletions(-) diff --git a/include/llvm/CodeGen/LiveIntervalAnalysis.h b/include/llvm/CodeGen/LiveIntervalAnalysis.h index e4e31ec2493..de7cc8001f8 100644 --- a/include/llvm/CodeGen/LiveIntervalAnalysis.h +++ b/include/llvm/CodeGen/LiveIntervalAnalysis.h @@ -25,160 +25,160 @@ namespace llvm { - class LiveVariables; - class MRegisterInfo; - class VirtRegMap; + class LiveVariables; + class MRegisterInfo; + class VirtRegMap; - class LiveIntervals : public MachineFunctionPass { - MachineFunction* mf_; - const TargetMachine* tm_; - const MRegisterInfo* mri_; - LiveVariables* lv_; + class LiveIntervals : public MachineFunctionPass { + MachineFunction* mf_; + const TargetMachine* tm_; + const MRegisterInfo* mri_; + LiveVariables* lv_; - typedef std::map Mi2IndexMap; - Mi2IndexMap mi2iMap_; + typedef std::map Mi2IndexMap; + Mi2IndexMap mi2iMap_; - typedef std::vector Index2MiMap; - Index2MiMap i2miMap_; + typedef std::vector Index2MiMap; + Index2MiMap i2miMap_; - typedef std::map Reg2IntervalMap; - Reg2IntervalMap r2iMap_; + typedef std::map Reg2IntervalMap; + Reg2IntervalMap r2iMap_; - typedef std::map Reg2RegMap; - Reg2RegMap r2rMap_; + typedef std::map Reg2RegMap; + Reg2RegMap r2rMap_; - public: - struct InstrSlots - { - enum { - LOAD = 0, - USE = 1, - DEF = 2, - STORE = 3, - NUM = 4, - }; - }; - - static unsigned getBaseIndex(unsigned index) { - return index - (index % InstrSlots::NUM); - } - static unsigned getBoundaryIndex(unsigned index) { - return getBaseIndex(index + InstrSlots::NUM - 1); - } - static unsigned getLoadIndex(unsigned index) { - return getBaseIndex(index) + InstrSlots::LOAD; - } - static unsigned getUseIndex(unsigned index) { - return getBaseIndex(index) + InstrSlots::USE; - } - static unsigned getDefIndex(unsigned index) { - return getBaseIndex(index) + InstrSlots::DEF; - } - static unsigned getStoreIndex(unsigned index) { - return getBaseIndex(index) + InstrSlots::STORE; - } - - // FIXME: this should really be a const_iterator - typedef Reg2IntervalMap::iterator iterator; - iterator begin() { return r2iMap_.begin(); } - iterator end() { return r2iMap_.end(); } - unsigned getNumIntervals() const { return r2iMap_.size(); } - - LiveInterval &getInterval(unsigned reg) { - Reg2IntervalMap::iterator I = r2iMap_.find(reg); - assert(I != r2iMap_.end() && "Interval does not exist for register"); - return I->second; - } - - const LiveInterval &getInterval(unsigned reg) const { - Reg2IntervalMap::const_iterator I = r2iMap_.find(reg); - assert(I != r2iMap_.end() && "Interval does not exist for register"); - return I->second; - } - - /// getInstructionIndex - returns the base index of instr - unsigned getInstructionIndex(MachineInstr* instr) const { - Mi2IndexMap::const_iterator it = mi2iMap_.find(instr); - assert(it != mi2iMap_.end() && "Invalid instruction!"); - return it->second; - } - - /// getInstructionFromIndex - given an index in any slot of an - /// instruction return a pointer the instruction - MachineInstr* getInstructionFromIndex(unsigned index) const { - index /= InstrSlots::NUM; // convert index to vector index - assert(index < i2miMap_.size() && - "index does not correspond to an instruction"); - return i2miMap_[index]; - } - - std::vector addIntervalsForSpills(const LiveInterval& i, - VirtRegMap& vrm, - int slot); - - virtual void getAnalysisUsage(AnalysisUsage &AU) const; - virtual void releaseMemory(); - - /// runOnMachineFunction - pass entry point - virtual bool runOnMachineFunction(MachineFunction&); - - private: - /// computeIntervals - compute live intervals - void computeIntervals(); - - /// joinIntervals - join compatible live intervals - void joinIntervals(); - - /// joinIntervalsInMachineBB - Join intervals based on move - /// instructions in the specified basic block. - void joinIntervalsInMachineBB(MachineBasicBlock *MBB); - - /// handleRegisterDef - update intervals for a register def - /// (calls handlePhysicalRegisterDef and - /// handleVirtualRegisterDef) - void handleRegisterDef(MachineBasicBlock* mbb, - MachineBasicBlock::iterator mi, - unsigned reg); - - /// handleVirtualRegisterDef - update intervals for a virtual - /// register def - void handleVirtualRegisterDef(MachineBasicBlock* mbb, - MachineBasicBlock::iterator mi, - LiveInterval& interval); - - /// handlePhysicalRegisterDef - update intervals for a - /// physical register def - void handlePhysicalRegisterDef(MachineBasicBlock* mbb, - MachineBasicBlock::iterator mi, - LiveInterval& interval); - - /// Return true if the two specified registers belong to different - /// register classes. The registers may be either phys or virt regs. - bool differingRegisterClasses(unsigned RegA, unsigned RegB) const; - - bool overlapsAliases(const LiveInterval *lhs, - const LiveInterval *rhs) const; - - static LiveInterval createInterval(unsigned Reg); - - LiveInterval &getOrCreateInterval(unsigned reg) { - Reg2IntervalMap::iterator I = r2iMap_.find(reg); - if (I == r2iMap_.end()) - I = r2iMap_.insert(I, std::make_pair(reg, createInterval(reg))); - return I->second; - } - - /// rep - returns the representative of this register - unsigned rep(unsigned reg) { - Reg2RegMap::iterator it = r2rMap_.find(reg); - if (it != r2rMap_.end()) - return it->second = rep(it->second); - return reg; - } - - void printRegName(unsigned reg) const; + public: + struct InstrSlots + { + enum { + LOAD = 0, + USE = 1, + DEF = 2, + STORE = 3, + NUM = 4, + }; }; + static unsigned getBaseIndex(unsigned index) { + return index - (index % InstrSlots::NUM); + } + static unsigned getBoundaryIndex(unsigned index) { + return getBaseIndex(index + InstrSlots::NUM - 1); + } + static unsigned getLoadIndex(unsigned index) { + return getBaseIndex(index) + InstrSlots::LOAD; + } + static unsigned getUseIndex(unsigned index) { + return getBaseIndex(index) + InstrSlots::USE; + } + static unsigned getDefIndex(unsigned index) { + return getBaseIndex(index) + InstrSlots::DEF; + } + static unsigned getStoreIndex(unsigned index) { + return getBaseIndex(index) + InstrSlots::STORE; + } + + // FIXME: this should really be a const_iterator + typedef Reg2IntervalMap::iterator iterator; + iterator begin() { return r2iMap_.begin(); } + iterator end() { return r2iMap_.end(); } + unsigned getNumIntervals() const { return r2iMap_.size(); } + + LiveInterval &getInterval(unsigned reg) { + Reg2IntervalMap::iterator I = r2iMap_.find(reg); + assert(I != r2iMap_.end() && "Interval does not exist for register"); + return I->second; + } + + const LiveInterval &getInterval(unsigned reg) const { + Reg2IntervalMap::const_iterator I = r2iMap_.find(reg); + assert(I != r2iMap_.end() && "Interval does not exist for register"); + return I->second; + } + + /// getInstructionIndex - returns the base index of instr + unsigned getInstructionIndex(MachineInstr* instr) const { + Mi2IndexMap::const_iterator it = mi2iMap_.find(instr); + assert(it != mi2iMap_.end() && "Invalid instruction!"); + return it->second; + } + + /// getInstructionFromIndex - given an index in any slot of an + /// instruction return a pointer the instruction + MachineInstr* getInstructionFromIndex(unsigned index) const { + index /= InstrSlots::NUM; // convert index to vector index + assert(index < i2miMap_.size() && + "index does not correspond to an instruction"); + return i2miMap_[index]; + } + + std::vector addIntervalsForSpills(const LiveInterval& i, + VirtRegMap& vrm, + int slot); + + virtual void getAnalysisUsage(AnalysisUsage &AU) const; + virtual void releaseMemory(); + + /// runOnMachineFunction - pass entry point + virtual bool runOnMachineFunction(MachineFunction&); + + private: + /// computeIntervals - compute live intervals + void computeIntervals(); + + /// joinIntervals - join compatible live intervals + void joinIntervals(); + + /// joinIntervalsInMachineBB - Join intervals based on move + /// instructions in the specified basic block. + void joinIntervalsInMachineBB(MachineBasicBlock *MBB); + + /// handleRegisterDef - update intervals for a register def + /// (calls handlePhysicalRegisterDef and + /// handleVirtualRegisterDef) + void handleRegisterDef(MachineBasicBlock* mbb, + MachineBasicBlock::iterator mi, + unsigned reg); + + /// handleVirtualRegisterDef - update intervals for a virtual + /// register def + void handleVirtualRegisterDef(MachineBasicBlock* mbb, + MachineBasicBlock::iterator mi, + LiveInterval& interval); + + /// handlePhysicalRegisterDef - update intervals for a + /// physical register def + void handlePhysicalRegisterDef(MachineBasicBlock* mbb, + MachineBasicBlock::iterator mi, + LiveInterval& interval); + + /// Return true if the two specified registers belong to different + /// register classes. The registers may be either phys or virt regs. + bool differingRegisterClasses(unsigned RegA, unsigned RegB) const; + + bool overlapsAliases(const LiveInterval *lhs, + const LiveInterval *rhs) const; + + static LiveInterval createInterval(unsigned Reg); + + LiveInterval &getOrCreateInterval(unsigned reg) { + Reg2IntervalMap::iterator I = r2iMap_.find(reg); + if (I == r2iMap_.end()) + I = r2iMap_.insert(I, std::make_pair(reg, createInterval(reg))); + return I->second; + } + + /// rep - returns the representative of this register + unsigned rep(unsigned reg) { + Reg2RegMap::iterator it = r2rMap_.find(reg); + if (it != r2rMap_.end()) + return it->second = rep(it->second); + return reg; + } + + void printRegName(unsigned reg) const; + }; + } // End llvm namespace #endif diff --git a/lib/CodeGen/LiveIntervalAnalysis.cpp b/lib/CodeGen/LiveIntervalAnalysis.cpp index ed90fca3df4..fc65e001380 100644 --- a/lib/CodeGen/LiveIntervalAnalysis.cpp +++ b/lib/CodeGen/LiveIntervalAnalysis.cpp @@ -37,447 +37,446 @@ using namespace llvm; namespace { - RegisterAnalysis X("liveintervals", - "Live Interval Analysis"); + RegisterAnalysis X("liveintervals", "Live Interval Analysis"); - Statistic<> numIntervals - ("liveintervals", "Number of original intervals"); + Statistic<> numIntervals + ("liveintervals", "Number of original intervals"); - Statistic<> numIntervalsAfter - ("liveintervals", "Number of intervals after coalescing"); + Statistic<> numIntervalsAfter + ("liveintervals", "Number of intervals after coalescing"); - Statistic<> numJoins - ("liveintervals", "Number of interval joins performed"); + Statistic<> numJoins + ("liveintervals", "Number of interval joins performed"); - Statistic<> numPeep - ("liveintervals", "Number of identity moves eliminated after coalescing"); + Statistic<> numPeep + ("liveintervals", "Number of identity moves eliminated after coalescing"); - Statistic<> numFolded - ("liveintervals", "Number of loads/stores folded into instructions"); + Statistic<> numFolded + ("liveintervals", "Number of loads/stores folded into instructions"); - cl::opt - EnableJoining("join-liveintervals", - cl::desc("Join compatible live intervals"), - cl::init(true)); + cl::opt + EnableJoining("join-liveintervals", + cl::desc("Join compatible live intervals"), + cl::init(true)); }; void LiveIntervals::getAnalysisUsage(AnalysisUsage &AU) const { - AU.addPreserved(); - AU.addRequired(); - AU.addPreservedID(PHIEliminationID); - AU.addRequiredID(PHIEliminationID); - AU.addRequiredID(TwoAddressInstructionPassID); - AU.addRequired(); - MachineFunctionPass::getAnalysisUsage(AU); + AU.addPreserved(); + AU.addRequired(); + AU.addPreservedID(PHIEliminationID); + AU.addRequiredID(PHIEliminationID); + AU.addRequiredID(TwoAddressInstructionPassID); + AU.addRequired(); + MachineFunctionPass::getAnalysisUsage(AU); } void LiveIntervals::releaseMemory() { - mi2iMap_.clear(); - i2miMap_.clear(); - r2iMap_.clear(); - r2rMap_.clear(); + mi2iMap_.clear(); + i2miMap_.clear(); + r2iMap_.clear(); + r2rMap_.clear(); } /// runOnMachineFunction - Register allocate the whole function /// bool LiveIntervals::runOnMachineFunction(MachineFunction &fn) { - mf_ = &fn; - tm_ = &fn.getTarget(); - mri_ = tm_->getRegisterInfo(); - lv_ = &getAnalysis(); + mf_ = &fn; + tm_ = &fn.getTarget(); + mri_ = tm_->getRegisterInfo(); + lv_ = &getAnalysis(); - // number MachineInstrs - unsigned miIndex = 0; - for (MachineFunction::iterator mbb = mf_->begin(), mbbEnd = mf_->end(); - mbb != mbbEnd; ++mbb) - for (MachineBasicBlock::iterator mi = mbb->begin(), miEnd = mbb->end(); - mi != miEnd; ++mi) { - bool inserted = mi2iMap_.insert(std::make_pair(mi, miIndex)).second; - assert(inserted && "multiple MachineInstr -> index mappings"); - i2miMap_.push_back(mi); - miIndex += InstrSlots::NUM; - } - - computeIntervals(); - - numIntervals += getNumIntervals(); - -#if 1 - DEBUG(std::cerr << "********** INTERVALS **********\n"); - DEBUG(for (iterator I = begin(), E = end(); I != E; ++I) - std::cerr << I->second << "\n"); -#endif - - // join intervals if requested - if (EnableJoining) joinIntervals(); - - numIntervalsAfter += getNumIntervals(); - - // perform a final pass over the instructions and compute spill - // weights, coalesce virtual registers and remove identity moves - const LoopInfo& loopInfo = getAnalysis(); - const TargetInstrInfo& tii = *tm_->getInstrInfo(); - - for (MachineFunction::iterator mbbi = mf_->begin(), mbbe = mf_->end(); - mbbi != mbbe; ++mbbi) { - MachineBasicBlock* mbb = mbbi; - unsigned loopDepth = loopInfo.getLoopDepth(mbb->getBasicBlock()); - - for (MachineBasicBlock::iterator mii = mbb->begin(), mie = mbb->end(); - mii != mie; ) { - // if the move will be an identity move delete it - unsigned srcReg, dstReg, RegRep; - if (tii.isMoveInstr(*mii, srcReg, dstReg) && - (RegRep = rep(srcReg)) == rep(dstReg)) { - // remove from def list - LiveInterval &interval = getOrCreateInterval(RegRep); - // remove index -> MachineInstr and - // MachineInstr -> index mappings - Mi2IndexMap::iterator mi2i = mi2iMap_.find(mii); - if (mi2i != mi2iMap_.end()) { - i2miMap_[mi2i->second/InstrSlots::NUM] = 0; - mi2iMap_.erase(mi2i); - } - mii = mbbi->erase(mii); - ++numPeep; - } - else { - for (unsigned i = 0; i < mii->getNumOperands(); ++i) { - const MachineOperand& mop = mii->getOperand(i); - if (mop.isRegister() && mop.getReg() && - MRegisterInfo::isVirtualRegister(mop.getReg())) { - // replace register with representative register - unsigned reg = rep(mop.getReg()); - mii->SetMachineOperandReg(i, reg); - - LiveInterval &RegInt = getInterval(reg); - RegInt.weight += - (mop.isUse() + mop.isDef()) * pow(10.0F, loopDepth); - } - } - ++mii; - } - } + // number MachineInstrs + unsigned miIndex = 0; + for (MachineFunction::iterator mbb = mf_->begin(), mbbEnd = mf_->end(); + mbb != mbbEnd; ++mbb) + for (MachineBasicBlock::iterator mi = mbb->begin(), miEnd = mbb->end(); + mi != miEnd; ++mi) { + bool inserted = mi2iMap_.insert(std::make_pair(mi, miIndex)).second; + assert(inserted && "multiple MachineInstr -> index mappings"); + i2miMap_.push_back(mi); + miIndex += InstrSlots::NUM; } - DEBUG(std::cerr << "********** INTERVALS **********\n"); - DEBUG (for (iterator I = begin(), E = end(); I != E; ++I) - std::cerr << I->second << "\n"); - DEBUG(std::cerr << "********** MACHINEINSTRS **********\n"); - DEBUG( - for (MachineFunction::iterator mbbi = mf_->begin(), mbbe = mf_->end(); - mbbi != mbbe; ++mbbi) { - std::cerr << ((Value*)mbbi->getBasicBlock())->getName() << ":\n"; - for (MachineBasicBlock::iterator mii = mbbi->begin(), - mie = mbbi->end(); mii != mie; ++mii) { - std::cerr << getInstructionIndex(mii) << '\t'; - mii->print(std::cerr, tm_); - } - }); + computeIntervals(); - return true; + numIntervals += getNumIntervals(); + +#if 1 + DEBUG(std::cerr << "********** INTERVALS **********\n"); + DEBUG(for (iterator I = begin(), E = end(); I != E; ++I) + std::cerr << I->second << "\n"); +#endif + + // join intervals if requested + if (EnableJoining) joinIntervals(); + + numIntervalsAfter += getNumIntervals(); + + // perform a final pass over the instructions and compute spill + // weights, coalesce virtual registers and remove identity moves + const LoopInfo& loopInfo = getAnalysis(); + const TargetInstrInfo& tii = *tm_->getInstrInfo(); + + for (MachineFunction::iterator mbbi = mf_->begin(), mbbe = mf_->end(); + mbbi != mbbe; ++mbbi) { + MachineBasicBlock* mbb = mbbi; + unsigned loopDepth = loopInfo.getLoopDepth(mbb->getBasicBlock()); + + for (MachineBasicBlock::iterator mii = mbb->begin(), mie = mbb->end(); + mii != mie; ) { + // if the move will be an identity move delete it + unsigned srcReg, dstReg, RegRep; + if (tii.isMoveInstr(*mii, srcReg, dstReg) && + (RegRep = rep(srcReg)) == rep(dstReg)) { + // remove from def list + LiveInterval &interval = getOrCreateInterval(RegRep); + // remove index -> MachineInstr and + // MachineInstr -> index mappings + Mi2IndexMap::iterator mi2i = mi2iMap_.find(mii); + if (mi2i != mi2iMap_.end()) { + i2miMap_[mi2i->second/InstrSlots::NUM] = 0; + mi2iMap_.erase(mi2i); + } + mii = mbbi->erase(mii); + ++numPeep; + } + else { + for (unsigned i = 0; i < mii->getNumOperands(); ++i) { + const MachineOperand& mop = mii->getOperand(i); + if (mop.isRegister() && mop.getReg() && + MRegisterInfo::isVirtualRegister(mop.getReg())) { + // replace register with representative register + unsigned reg = rep(mop.getReg()); + mii->SetMachineOperandReg(i, reg); + + LiveInterval &RegInt = getInterval(reg); + RegInt.weight += + (mop.isUse() + mop.isDef()) * pow(10.0F, loopDepth); + } + } + ++mii; + } + } + } + + DEBUG(std::cerr << "********** INTERVALS **********\n"); + DEBUG (for (iterator I = begin(), E = end(); I != E; ++I) + std::cerr << I->second << "\n"); + DEBUG(std::cerr << "********** MACHINEINSTRS **********\n"); + DEBUG( + for (MachineFunction::iterator mbbi = mf_->begin(), mbbe = mf_->end(); + mbbi != mbbe; ++mbbi) { + std::cerr << ((Value*)mbbi->getBasicBlock())->getName() << ":\n"; + for (MachineBasicBlock::iterator mii = mbbi->begin(), + mie = mbbi->end(); mii != mie; ++mii) { + std::cerr << getInstructionIndex(mii) << '\t'; + mii->print(std::cerr, tm_); + } + }); + + return true; } std::vector LiveIntervals::addIntervalsForSpills( - const LiveInterval& li, - VirtRegMap& vrm, - int slot) + const LiveInterval& li, + VirtRegMap& vrm, + int slot) { - std::vector added; + std::vector added; - assert(li.weight != HUGE_VAL && - "attempt to spill already spilled interval!"); + assert(li.weight != HUGE_VAL && + "attempt to spill already spilled interval!"); - DEBUG(std::cerr << "\t\t\t\tadding intervals for spills for interval: " - << li << '\n'); + DEBUG(std::cerr << "\t\t\t\tadding intervals for spills for interval: " + << li << '\n'); - const TargetRegisterClass* rc = mf_->getSSARegMap()->getRegClass(li.reg); + const TargetRegisterClass* rc = mf_->getSSARegMap()->getRegClass(li.reg); - for (LiveInterval::Ranges::const_iterator - i = li.ranges.begin(), e = li.ranges.end(); i != e; ++i) { - unsigned index = getBaseIndex(i->start); - unsigned end = getBaseIndex(i->end-1) + InstrSlots::NUM; - for (; index != end; index += InstrSlots::NUM) { - // skip deleted instructions - while (index != end && !getInstructionFromIndex(index)) - index += InstrSlots::NUM; - if (index == end) break; + for (LiveInterval::Ranges::const_iterator + i = li.ranges.begin(), e = li.ranges.end(); i != e; ++i) { + unsigned index = getBaseIndex(i->start); + unsigned end = getBaseIndex(i->end-1) + InstrSlots::NUM; + for (; index != end; index += InstrSlots::NUM) { + // skip deleted instructions + while (index != end && !getInstructionFromIndex(index)) + index += InstrSlots::NUM; + if (index == end) break; - MachineBasicBlock::iterator mi = getInstructionFromIndex(index); + MachineBasicBlock::iterator mi = getInstructionFromIndex(index); - for_operand: - for (unsigned i = 0; i != mi->getNumOperands(); ++i) { - MachineOperand& mop = mi->getOperand(i); - if (mop.isRegister() && mop.getReg() == li.reg) { - if (MachineInstr* fmi = - mri_->foldMemoryOperand(mi, i, slot)) { - lv_->instructionChanged(mi, fmi); - vrm.virtFolded(li.reg, mi, fmi); - mi2iMap_.erase(mi); - i2miMap_[index/InstrSlots::NUM] = fmi; - mi2iMap_[fmi] = index; - MachineBasicBlock& mbb = *mi->getParent(); - mi = mbb.insert(mbb.erase(mi), fmi); - ++numFolded; - goto for_operand; - } - else { - // This is tricky. We need to add information in - // the interval about the spill code so we have to - // use our extra load/store slots. - // - // If we have a use we are going to have a load so - // we start the interval from the load slot - // onwards. Otherwise we start from the def slot. - unsigned start = (mop.isUse() ? - getLoadIndex(index) : - getDefIndex(index)); - // If we have a def we are going to have a store - // right after it so we end the interval after the - // use of the next instruction. Otherwise we end - // after the use of this instruction. - unsigned end = 1 + (mop.isDef() ? - getStoreIndex(index) : - getUseIndex(index)); + for_operand: + for (unsigned i = 0; i != mi->getNumOperands(); ++i) { + MachineOperand& mop = mi->getOperand(i); + if (mop.isRegister() && mop.getReg() == li.reg) { + if (MachineInstr* fmi = + mri_->foldMemoryOperand(mi, i, slot)) { + lv_->instructionChanged(mi, fmi); + vrm.virtFolded(li.reg, mi, fmi); + mi2iMap_.erase(mi); + i2miMap_[index/InstrSlots::NUM] = fmi; + mi2iMap_[fmi] = index; + MachineBasicBlock& mbb = *mi->getParent(); + mi = mbb.insert(mbb.erase(mi), fmi); + ++numFolded; + goto for_operand; + } + else { + // This is tricky. We need to add information in + // the interval about the spill code so we have to + // use our extra load/store slots. + // + // If we have a use we are going to have a load so + // we start the interval from the load slot + // onwards. Otherwise we start from the def slot. + unsigned start = (mop.isUse() ? + getLoadIndex(index) : + getDefIndex(index)); + // If we have a def we are going to have a store + // right after it so we end the interval after the + // use of the next instruction. Otherwise we end + // after the use of this instruction. + unsigned end = 1 + (mop.isDef() ? + getStoreIndex(index) : + getUseIndex(index)); - // create a new register for this spill - unsigned nReg = - mf_->getSSARegMap()->createVirtualRegister(rc); - mi->SetMachineOperandReg(i, nReg); - vrm.grow(); - vrm.assignVirt2StackSlot(nReg, slot); - LiveInterval& nI = getOrCreateInterval(nReg); - assert(nI.empty()); - // the spill weight is now infinity as it - // cannot be spilled again - nI.weight = HUGE_VAL; - LiveRange LR(start, end, nI.getNextValue()); - DEBUG(std::cerr << " +" << LR); - nI.addRange(LR); - added.push_back(&nI); - // update live variables - lv_->addVirtualRegisterKilled(nReg, mi); - DEBUG(std::cerr << "\t\t\t\tadded new interval: " - << nI << '\n'); - } - } - } + // create a new register for this spill + unsigned nReg = + mf_->getSSARegMap()->createVirtualRegister(rc); + mi->SetMachineOperandReg(i, nReg); + vrm.grow(); + vrm.assignVirt2StackSlot(nReg, slot); + LiveInterval& nI = getOrCreateInterval(nReg); + assert(nI.empty()); + // the spill weight is now infinity as it + // cannot be spilled again + nI.weight = HUGE_VAL; + LiveRange LR(start, end, nI.getNextValue()); + DEBUG(std::cerr << " +" << LR); + nI.addRange(LR); + added.push_back(&nI); + // update live variables + lv_->addVirtualRegisterKilled(nReg, mi); + DEBUG(std::cerr << "\t\t\t\tadded new interval: " + << nI << '\n'); + } } + } } + } - return added; + return added; } void LiveIntervals::printRegName(unsigned reg) const { - if (MRegisterInfo::isPhysicalRegister(reg)) - std::cerr << mri_->getName(reg); - else - std::cerr << "%reg" << reg; + if (MRegisterInfo::isPhysicalRegister(reg)) + std::cerr << mri_->getName(reg); + else + std::cerr << "%reg" << reg; } void LiveIntervals::handleVirtualRegisterDef(MachineBasicBlock* mbb, MachineBasicBlock::iterator mi, LiveInterval& interval) { - DEBUG(std::cerr << "\t\tregister: "; printRegName(interval.reg)); - LiveVariables::VarInfo& vi = lv_->getVarInfo(interval.reg); + DEBUG(std::cerr << "\t\tregister: "; printRegName(interval.reg)); + LiveVariables::VarInfo& vi = lv_->getVarInfo(interval.reg); - // Virtual registers may be defined multiple times (due to phi - // elimination and 2-addr elimination). Much of what we do only has to be - // done once for the vreg. We use an empty interval to detect the first - // time we see a vreg. - if (interval.empty()) { - // Get the Idx of the defining instructions. - unsigned defIndex = getDefIndex(getInstructionIndex(mi)); + // Virtual registers may be defined multiple times (due to phi + // elimination and 2-addr elimination). Much of what we do only has to be + // done once for the vreg. We use an empty interval to detect the first + // time we see a vreg. + if (interval.empty()) { + // Get the Idx of the defining instructions. + unsigned defIndex = getDefIndex(getInstructionIndex(mi)); - unsigned ValNum = interval.getNextValue(); - assert(ValNum == 0 && "First value in interval is not 0?"); - ValNum = 0; // Clue in the optimizer. + unsigned ValNum = interval.getNextValue(); + assert(ValNum == 0 && "First value in interval is not 0?"); + ValNum = 0; // Clue in the optimizer. - // Loop over all of the blocks that the vreg is defined in. There are - // two cases we have to handle here. The most common case is a vreg - // whose lifetime is contained within a basic block. In this case there - // will be a single kill, in MBB, which comes after the definition. - if (vi.Kills.size() == 1 && vi.Kills[0]->getParent() == mbb) { - // FIXME: what about dead vars? - unsigned killIdx; - if (vi.Kills[0] != mi) - killIdx = getUseIndex(getInstructionIndex(vi.Kills[0]))+1; - else - killIdx = defIndex+1; + // Loop over all of the blocks that the vreg is defined in. There are + // two cases we have to handle here. The most common case is a vreg + // whose lifetime is contained within a basic block. In this case there + // will be a single kill, in MBB, which comes after the definition. + if (vi.Kills.size() == 1 && vi.Kills[0]->getParent() == mbb) { + // FIXME: what about dead vars? + unsigned killIdx; + if (vi.Kills[0] != mi) + killIdx = getUseIndex(getInstructionIndex(vi.Kills[0]))+1; + else + killIdx = defIndex+1; - // If the kill happens after the definition, we have an intra-block - // live range. - if (killIdx > defIndex) { - assert(vi.AliveBlocks.empty() && - "Shouldn't be alive across any blocks!"); - LiveRange LR(defIndex, killIdx, ValNum); - interval.addRange(LR); - DEBUG(std::cerr << " +" << LR << "\n"); - return; - } - } - - // The other case we handle is when a virtual register lives to the end - // of the defining block, potentially live across some blocks, then is - // live into some number of blocks, but gets killed. Start by adding a - // range that goes from this definition to the end of the defining block. - LiveRange NewLR(defIndex, getInstructionIndex(&mbb->back()) + - InstrSlots::NUM, ValNum); - DEBUG(std::cerr << " +" << NewLR); - interval.addRange(NewLR); - - // Iterate over all of the blocks that the variable is completely - // live in, adding [insrtIndex(begin), instrIndex(end)+4) to the - // live interval. - for (unsigned i = 0, e = vi.AliveBlocks.size(); i != e; ++i) { - if (vi.AliveBlocks[i]) { - MachineBasicBlock* mbb = mf_->getBlockNumbered(i); - if (!mbb->empty()) { - LiveRange LR(getInstructionIndex(&mbb->front()), - getInstructionIndex(&mbb->back())+InstrSlots::NUM, - ValNum); - interval.addRange(LR); - DEBUG(std::cerr << " +" << LR); - } - } - } - - // Finally, this virtual register is live from the start of any killing - // block to the 'use' slot of the killing instruction. - for (unsigned i = 0, e = vi.Kills.size(); i != e; ++i) { - MachineInstr *Kill = vi.Kills[i]; - LiveRange LR(getInstructionIndex(Kill->getParent()->begin()), - getUseIndex(getInstructionIndex(Kill))+1, ValNum); - interval.addRange(LR); - DEBUG(std::cerr << " +" << LR); - } - - } else { - // If this is the second time we see a virtual register definition, it - // must be due to phi elimination or two addr elimination. If this is - // the result of two address elimination, then the vreg is the first - // operand, and is a def-and-use. - if (mi->getOperand(0).isRegister() && - mi->getOperand(0).getReg() == interval.reg && - mi->getOperand(0).isDef() && mi->getOperand(0).isUse()) { - // If this is a two-address definition, then we have already processed - // the live range. The only problem is that we didn't realize there - // are actually two values in the live interval. Because of this we - // need to take the LiveRegion that defines this register and split it - // into two values. - unsigned DefIndex = getDefIndex(getInstructionIndex(vi.DefInst)); - unsigned RedefIndex = getDefIndex(getInstructionIndex(mi)); - - // Delete the initial value, which should be short and continuous, - // becuase the 2-addr copy must be in the same MBB as the redef. - interval.removeRange(DefIndex, RedefIndex); - - LiveRange LR(DefIndex, RedefIndex, interval.getNextValue()); - DEBUG(std::cerr << " replace range with " << LR); - interval.addRange(LR); - - // If this redefinition is dead, we need to add a dummy unit live - // range covering the def slot. - for (LiveVariables::killed_iterator KI = lv_->dead_begin(mi), - E = lv_->dead_end(mi); KI != E; ++KI) - if (KI->second == interval.reg) { - interval.addRange(LiveRange(RedefIndex, RedefIndex+1, 0)); - break; - } - - DEBUG(std::cerr << "RESULT: " << interval); - - } else { - // Otherwise, this must be because of phi elimination. If this is the - // first redefinition of the vreg that we have seen, go back and change - // the live range in the PHI block to be a different value number. - if (interval.containsOneValue()) { - assert(vi.Kills.size() == 1 && - "PHI elimination vreg should have one kill, the PHI itself!"); - - // Remove the old range that we now know has an incorrect number. - MachineInstr *Killer = vi.Kills[0]; - unsigned Start = getInstructionIndex(Killer->getParent()->begin()); - unsigned End = getUseIndex(getInstructionIndex(Killer))+1; - DEBUG(std::cerr << "Removing [" << Start << "," << End << "] from: " - << interval << "\n"); - interval.removeRange(Start, End); - DEBUG(std::cerr << "RESULT: " << interval); - - // Replace the interval with one of a NEW value number. - LiveRange LR(Start, End, interval.getNextValue()); - DEBUG(std::cerr << " replace range with " << LR); - interval.addRange(LR); - DEBUG(std::cerr << "RESULT: " << interval); - } - - // In the case of PHI elimination, each variable definition is only - // live until the end of the block. We've already taken care of the - // rest of the live range. - unsigned defIndex = getDefIndex(getInstructionIndex(mi)); - LiveRange LR(defIndex, - getInstructionIndex(&mbb->back()) + InstrSlots::NUM, - interval.getNextValue()); - interval.addRange(LR); - DEBUG(std::cerr << " +" << LR); - } + // If the kill happens after the definition, we have an intra-block + // live range. + if (killIdx > defIndex) { + assert(vi.AliveBlocks.empty() && + "Shouldn't be alive across any blocks!"); + LiveRange LR(defIndex, killIdx, ValNum); + interval.addRange(LR); + DEBUG(std::cerr << " +" << LR << "\n"); + return; + } } - DEBUG(std::cerr << '\n'); + // The other case we handle is when a virtual register lives to the end + // of the defining block, potentially live across some blocks, then is + // live into some number of blocks, but gets killed. Start by adding a + // range that goes from this definition to the end of the defining block. + LiveRange NewLR(defIndex, getInstructionIndex(&mbb->back()) + + InstrSlots::NUM, ValNum); + DEBUG(std::cerr << " +" << NewLR); + interval.addRange(NewLR); + + // Iterate over all of the blocks that the variable is completely + // live in, adding [insrtIndex(begin), instrIndex(end)+4) to the + // live interval. + for (unsigned i = 0, e = vi.AliveBlocks.size(); i != e; ++i) { + if (vi.AliveBlocks[i]) { + MachineBasicBlock* mbb = mf_->getBlockNumbered(i); + if (!mbb->empty()) { + LiveRange LR(getInstructionIndex(&mbb->front()), + getInstructionIndex(&mbb->back())+InstrSlots::NUM, + ValNum); + interval.addRange(LR); + DEBUG(std::cerr << " +" << LR); + } + } + } + + // Finally, this virtual register is live from the start of any killing + // block to the 'use' slot of the killing instruction. + for (unsigned i = 0, e = vi.Kills.size(); i != e; ++i) { + MachineInstr *Kill = vi.Kills[i]; + LiveRange LR(getInstructionIndex(Kill->getParent()->begin()), + getUseIndex(getInstructionIndex(Kill))+1, ValNum); + interval.addRange(LR); + DEBUG(std::cerr << " +" << LR); + } + + } else { + // If this is the second time we see a virtual register definition, it + // must be due to phi elimination or two addr elimination. If this is + // the result of two address elimination, then the vreg is the first + // operand, and is a def-and-use. + if (mi->getOperand(0).isRegister() && + mi->getOperand(0).getReg() == interval.reg && + mi->getOperand(0).isDef() && mi->getOperand(0).isUse()) { + // If this is a two-address definition, then we have already processed + // the live range. The only problem is that we didn't realize there + // are actually two values in the live interval. Because of this we + // need to take the LiveRegion that defines this register and split it + // into two values. + unsigned DefIndex = getDefIndex(getInstructionIndex(vi.DefInst)); + unsigned RedefIndex = getDefIndex(getInstructionIndex(mi)); + + // Delete the initial value, which should be short and continuous, + // becuase the 2-addr copy must be in the same MBB as the redef. + interval.removeRange(DefIndex, RedefIndex); + + LiveRange LR(DefIndex, RedefIndex, interval.getNextValue()); + DEBUG(std::cerr << " replace range with " << LR); + interval.addRange(LR); + + // If this redefinition is dead, we need to add a dummy unit live + // range covering the def slot. + for (LiveVariables::killed_iterator KI = lv_->dead_begin(mi), + E = lv_->dead_end(mi); KI != E; ++KI) + if (KI->second == interval.reg) { + interval.addRange(LiveRange(RedefIndex, RedefIndex+1, 0)); + break; + } + + DEBUG(std::cerr << "RESULT: " << interval); + + } else { + // Otherwise, this must be because of phi elimination. If this is the + // first redefinition of the vreg that we have seen, go back and change + // the live range in the PHI block to be a different value number. + if (interval.containsOneValue()) { + assert(vi.Kills.size() == 1 && + "PHI elimination vreg should have one kill, the PHI itself!"); + + // Remove the old range that we now know has an incorrect number. + MachineInstr *Killer = vi.Kills[0]; + unsigned Start = getInstructionIndex(Killer->getParent()->begin()); + unsigned End = getUseIndex(getInstructionIndex(Killer))+1; + DEBUG(std::cerr << "Removing [" << Start << "," << End << "] from: " + << interval << "\n"); + interval.removeRange(Start, End); + DEBUG(std::cerr << "RESULT: " << interval); + + // Replace the interval with one of a NEW value number. + LiveRange LR(Start, End, interval.getNextValue()); + DEBUG(std::cerr << " replace range with " << LR); + interval.addRange(LR); + DEBUG(std::cerr << "RESULT: " << interval); + } + + // In the case of PHI elimination, each variable definition is only + // live until the end of the block. We've already taken care of the + // rest of the live range. + unsigned defIndex = getDefIndex(getInstructionIndex(mi)); + LiveRange LR(defIndex, + getInstructionIndex(&mbb->back()) + InstrSlots::NUM, + interval.getNextValue()); + interval.addRange(LR); + DEBUG(std::cerr << " +" << LR); + } + } + + DEBUG(std::cerr << '\n'); } void LiveIntervals::handlePhysicalRegisterDef(MachineBasicBlock *MBB, MachineBasicBlock::iterator mi, LiveInterval& interval) { - // A physical register cannot be live across basic block, so its - // lifetime must end somewhere in its defining basic block. - DEBUG(std::cerr << "\t\tregister: "; printRegName(interval.reg)); - typedef LiveVariables::killed_iterator KillIter; + // A physical register cannot be live across basic block, so its + // lifetime must end somewhere in its defining basic block. + DEBUG(std::cerr << "\t\tregister: "; printRegName(interval.reg)); + typedef LiveVariables::killed_iterator KillIter; - unsigned baseIndex = getInstructionIndex(mi); - unsigned start = getDefIndex(baseIndex); - unsigned end = start; + unsigned baseIndex = getInstructionIndex(mi); + unsigned start = getDefIndex(baseIndex); + unsigned end = start; - // If it is not used after definition, it is considered dead at - // the instruction defining it. Hence its interval is: - // [defSlot(def), defSlot(def)+1) - for (KillIter ki = lv_->dead_begin(mi), ke = lv_->dead_end(mi); + // If it is not used after definition, it is considered dead at + // the instruction defining it. Hence its interval is: + // [defSlot(def), defSlot(def)+1) + for (KillIter ki = lv_->dead_begin(mi), ke = lv_->dead_end(mi); + ki != ke; ++ki) { + if (interval.reg == ki->second) { + DEBUG(std::cerr << " dead"); + end = getDefIndex(start) + 1; + goto exit; + } + } + + // If it is not dead on definition, it must be killed by a + // subsequent instruction. Hence its interval is: + // [defSlot(def), useSlot(kill)+1) + while (true) { + ++mi; + assert(mi != MBB->end() && "physreg was not killed in defining block!"); + baseIndex += InstrSlots::NUM; + for (KillIter ki = lv_->killed_begin(mi), ke = lv_->killed_end(mi); ki != ke; ++ki) { - if (interval.reg == ki->second) { - DEBUG(std::cerr << " dead"); - end = getDefIndex(start) + 1; - goto exit; - } - } - - // If it is not dead on definition, it must be killed by a - // subsequent instruction. Hence its interval is: - // [defSlot(def), useSlot(kill)+1) - while (true) { - ++mi; - assert(mi != MBB->end() && "physreg was not killed in defining block!"); - baseIndex += InstrSlots::NUM; - for (KillIter ki = lv_->killed_begin(mi), ke = lv_->killed_end(mi); - ki != ke; ++ki) { - if (interval.reg == ki->second) { - DEBUG(std::cerr << " killed"); - end = getUseIndex(baseIndex) + 1; - goto exit; - } - } + if (interval.reg == ki->second) { + DEBUG(std::cerr << " killed"); + end = getUseIndex(baseIndex) + 1; + goto exit; + } } + } exit: - assert(start < end && "did not find end of interval?"); - LiveRange LR(start, end, interval.getNextValue()); - interval.addRange(LR); - DEBUG(std::cerr << " +" << LR << '\n'); + assert(start < end && "did not find end of interval?"); + LiveRange LR(start, end, interval.getNextValue()); + interval.addRange(LR); + DEBUG(std::cerr << " +" << LR << '\n'); } void LiveIntervals::handleRegisterDef(MachineBasicBlock *MBB, @@ -498,35 +497,35 @@ void LiveIntervals::handleRegisterDef(MachineBasicBlock *MBB, /// which a variable is live void LiveIntervals::computeIntervals() { - DEBUG(std::cerr << "********** COMPUTING LIVE INTERVALS **********\n"); - DEBUG(std::cerr << "********** Function: " - << ((Value*)mf_->getFunction())->getName() << '\n'); + DEBUG(std::cerr << "********** COMPUTING LIVE INTERVALS **********\n"); + DEBUG(std::cerr << "********** Function: " + << ((Value*)mf_->getFunction())->getName() << '\n'); - for (MachineFunction::iterator I = mf_->begin(), E = mf_->end(); - I != E; ++I) { - MachineBasicBlock* mbb = I; - DEBUG(std::cerr << ((Value*)mbb->getBasicBlock())->getName() << ":\n"); + for (MachineFunction::iterator I = mf_->begin(), E = mf_->end(); + I != E; ++I) { + MachineBasicBlock* mbb = I; + DEBUG(std::cerr << ((Value*)mbb->getBasicBlock())->getName() << ":\n"); - for (MachineBasicBlock::iterator mi = mbb->begin(), miEnd = mbb->end(); - mi != miEnd; ++mi) { - const TargetInstrDescriptor& tid = - tm_->getInstrInfo()->get(mi->getOpcode()); - DEBUG(std::cerr << getInstructionIndex(mi) << "\t"; - mi->print(std::cerr, tm_)); + for (MachineBasicBlock::iterator mi = mbb->begin(), miEnd = mbb->end(); + mi != miEnd; ++mi) { + const TargetInstrDescriptor& tid = + tm_->getInstrInfo()->get(mi->getOpcode()); + DEBUG(std::cerr << getInstructionIndex(mi) << "\t"; + mi->print(std::cerr, tm_)); - // handle implicit defs - for (const unsigned* id = tid.ImplicitDefs; *id; ++id) - handleRegisterDef(mbb, mi, *id); + // handle implicit defs + for (const unsigned* id = tid.ImplicitDefs; *id; ++id) + handleRegisterDef(mbb, mi, *id); - // handle explicit defs - for (int i = mi->getNumOperands() - 1; i >= 0; --i) { - MachineOperand& mop = mi->getOperand(i); - // handle register defs - build intervals - if (mop.isRegister() && mop.getReg() && mop.isDef()) - handleRegisterDef(mbb, mi, mop.getReg()); - } - } + // handle explicit defs + for (int i = mi->getNumOperands() - 1; i >= 0; --i) { + MachineOperand& mop = mi->getOperand(i); + // handle register defs - build intervals + if (mop.isRegister() && mop.getReg() && mop.isDef()) + handleRegisterDef(mbb, mi, mop.getReg()); + } } + } } void LiveIntervals::joinIntervalsInMachineBB(MachineBasicBlock *MBB) { @@ -543,9 +542,9 @@ void LiveIntervals::joinIntervalsInMachineBB(MachineBasicBlock *MBB) { unsigned regA, regB; if (TII.isMoveInstr(*mi, regA, regB) && (MRegisterInfo::isVirtualRegister(regA) || - lv_->getAllocatablePhysicalRegisters()[regA]) && + lv_->getAllocatablePhysicalRegisters()[regA]) && (MRegisterInfo::isVirtualRegister(regB) || - lv_->getAllocatablePhysicalRegisters()[regB])) { + lv_->getAllocatablePhysicalRegisters()[regB])) { // Get representative registers. regA = rep(regA); @@ -609,7 +608,7 @@ namespace { bool operator()(const DepthMBBPair &LHS, const DepthMBBPair &RHS) const { if (LHS.first > RHS.first) return true; // Deeper loops first return LHS.first == RHS.first && - LHS.second->getNumber() < RHS.second->getNumber(); + LHS.second->getNumber() < RHS.second->getNumber(); } }; } @@ -642,8 +641,8 @@ void LiveIntervals::joinIntervals() { DEBUG(std::cerr << "*** Register mapping ***\n"); DEBUG(for (std::map::iterator I = r2rMap_.begin(), - E = r2rMap_.end(); I != E; ++I) - std::cerr << " reg " << I->first << " -> reg " << I->second << "\n";); + E = r2rMap_.end(); I != E; ++I) + std::cerr << " reg " << I->first << " -> reg " << I->second << "\n";); } /// Return true if the two specified registers belong to different register diff --git a/lib/CodeGen/LiveIntervalAnalysis.h b/lib/CodeGen/LiveIntervalAnalysis.h index e4e31ec2493..de7cc8001f8 100644 --- a/lib/CodeGen/LiveIntervalAnalysis.h +++ b/lib/CodeGen/LiveIntervalAnalysis.h @@ -25,160 +25,160 @@ namespace llvm { - class LiveVariables; - class MRegisterInfo; - class VirtRegMap; + class LiveVariables; + class MRegisterInfo; + class VirtRegMap; - class LiveIntervals : public MachineFunctionPass { - MachineFunction* mf_; - const TargetMachine* tm_; - const MRegisterInfo* mri_; - LiveVariables* lv_; + class LiveIntervals : public MachineFunctionPass { + MachineFunction* mf_; + const TargetMachine* tm_; + const MRegisterInfo* mri_; + LiveVariables* lv_; - typedef std::map Mi2IndexMap; - Mi2IndexMap mi2iMap_; + typedef std::map Mi2IndexMap; + Mi2IndexMap mi2iMap_; - typedef std::vector Index2MiMap; - Index2MiMap i2miMap_; + typedef std::vector Index2MiMap; + Index2MiMap i2miMap_; - typedef std::map Reg2IntervalMap; - Reg2IntervalMap r2iMap_; + typedef std::map Reg2IntervalMap; + Reg2IntervalMap r2iMap_; - typedef std::map Reg2RegMap; - Reg2RegMap r2rMap_; + typedef std::map Reg2RegMap; + Reg2RegMap r2rMap_; - public: - struct InstrSlots - { - enum { - LOAD = 0, - USE = 1, - DEF = 2, - STORE = 3, - NUM = 4, - }; - }; - - static unsigned getBaseIndex(unsigned index) { - return index - (index % InstrSlots::NUM); - } - static unsigned getBoundaryIndex(unsigned index) { - return getBaseIndex(index + InstrSlots::NUM - 1); - } - static unsigned getLoadIndex(unsigned index) { - return getBaseIndex(index) + InstrSlots::LOAD; - } - static unsigned getUseIndex(unsigned index) { - return getBaseIndex(index) + InstrSlots::USE; - } - static unsigned getDefIndex(unsigned index) { - return getBaseIndex(index) + InstrSlots::DEF; - } - static unsigned getStoreIndex(unsigned index) { - return getBaseIndex(index) + InstrSlots::STORE; - } - - // FIXME: this should really be a const_iterator - typedef Reg2IntervalMap::iterator iterator; - iterator begin() { return r2iMap_.begin(); } - iterator end() { return r2iMap_.end(); } - unsigned getNumIntervals() const { return r2iMap_.size(); } - - LiveInterval &getInterval(unsigned reg) { - Reg2IntervalMap::iterator I = r2iMap_.find(reg); - assert(I != r2iMap_.end() && "Interval does not exist for register"); - return I->second; - } - - const LiveInterval &getInterval(unsigned reg) const { - Reg2IntervalMap::const_iterator I = r2iMap_.find(reg); - assert(I != r2iMap_.end() && "Interval does not exist for register"); - return I->second; - } - - /// getInstructionIndex - returns the base index of instr - unsigned getInstructionIndex(MachineInstr* instr) const { - Mi2IndexMap::const_iterator it = mi2iMap_.find(instr); - assert(it != mi2iMap_.end() && "Invalid instruction!"); - return it->second; - } - - /// getInstructionFromIndex - given an index in any slot of an - /// instruction return a pointer the instruction - MachineInstr* getInstructionFromIndex(unsigned index) const { - index /= InstrSlots::NUM; // convert index to vector index - assert(index < i2miMap_.size() && - "index does not correspond to an instruction"); - return i2miMap_[index]; - } - - std::vector addIntervalsForSpills(const LiveInterval& i, - VirtRegMap& vrm, - int slot); - - virtual void getAnalysisUsage(AnalysisUsage &AU) const; - virtual void releaseMemory(); - - /// runOnMachineFunction - pass entry point - virtual bool runOnMachineFunction(MachineFunction&); - - private: - /// computeIntervals - compute live intervals - void computeIntervals(); - - /// joinIntervals - join compatible live intervals - void joinIntervals(); - - /// joinIntervalsInMachineBB - Join intervals based on move - /// instructions in the specified basic block. - void joinIntervalsInMachineBB(MachineBasicBlock *MBB); - - /// handleRegisterDef - update intervals for a register def - /// (calls handlePhysicalRegisterDef and - /// handleVirtualRegisterDef) - void handleRegisterDef(MachineBasicBlock* mbb, - MachineBasicBlock::iterator mi, - unsigned reg); - - /// handleVirtualRegisterDef - update intervals for a virtual - /// register def - void handleVirtualRegisterDef(MachineBasicBlock* mbb, - MachineBasicBlock::iterator mi, - LiveInterval& interval); - - /// handlePhysicalRegisterDef - update intervals for a - /// physical register def - void handlePhysicalRegisterDef(MachineBasicBlock* mbb, - MachineBasicBlock::iterator mi, - LiveInterval& interval); - - /// Return true if the two specified registers belong to different - /// register classes. The registers may be either phys or virt regs. - bool differingRegisterClasses(unsigned RegA, unsigned RegB) const; - - bool overlapsAliases(const LiveInterval *lhs, - const LiveInterval *rhs) const; - - static LiveInterval createInterval(unsigned Reg); - - LiveInterval &getOrCreateInterval(unsigned reg) { - Reg2IntervalMap::iterator I = r2iMap_.find(reg); - if (I == r2iMap_.end()) - I = r2iMap_.insert(I, std::make_pair(reg, createInterval(reg))); - return I->second; - } - - /// rep - returns the representative of this register - unsigned rep(unsigned reg) { - Reg2RegMap::iterator it = r2rMap_.find(reg); - if (it != r2rMap_.end()) - return it->second = rep(it->second); - return reg; - } - - void printRegName(unsigned reg) const; + public: + struct InstrSlots + { + enum { + LOAD = 0, + USE = 1, + DEF = 2, + STORE = 3, + NUM = 4, + }; }; + static unsigned getBaseIndex(unsigned index) { + return index - (index % InstrSlots::NUM); + } + static unsigned getBoundaryIndex(unsigned index) { + return getBaseIndex(index + InstrSlots::NUM - 1); + } + static unsigned getLoadIndex(unsigned index) { + return getBaseIndex(index) + InstrSlots::LOAD; + } + static unsigned getUseIndex(unsigned index) { + return getBaseIndex(index) + InstrSlots::USE; + } + static unsigned getDefIndex(unsigned index) { + return getBaseIndex(index) + InstrSlots::DEF; + } + static unsigned getStoreIndex(unsigned index) { + return getBaseIndex(index) + InstrSlots::STORE; + } + + // FIXME: this should really be a const_iterator + typedef Reg2IntervalMap::iterator iterator; + iterator begin() { return r2iMap_.begin(); } + iterator end() { return r2iMap_.end(); } + unsigned getNumIntervals() const { return r2iMap_.size(); } + + LiveInterval &getInterval(unsigned reg) { + Reg2IntervalMap::iterator I = r2iMap_.find(reg); + assert(I != r2iMap_.end() && "Interval does not exist for register"); + return I->second; + } + + const LiveInterval &getInterval(unsigned reg) const { + Reg2IntervalMap::const_iterator I = r2iMap_.find(reg); + assert(I != r2iMap_.end() && "Interval does not exist for register"); + return I->second; + } + + /// getInstructionIndex - returns the base index of instr + unsigned getInstructionIndex(MachineInstr* instr) const { + Mi2IndexMap::const_iterator it = mi2iMap_.find(instr); + assert(it != mi2iMap_.end() && "Invalid instruction!"); + return it->second; + } + + /// getInstructionFromIndex - given an index in any slot of an + /// instruction return a pointer the instruction + MachineInstr* getInstructionFromIndex(unsigned index) const { + index /= InstrSlots::NUM; // convert index to vector index + assert(index < i2miMap_.size() && + "index does not correspond to an instruction"); + return i2miMap_[index]; + } + + std::vector addIntervalsForSpills(const LiveInterval& i, + VirtRegMap& vrm, + int slot); + + virtual void getAnalysisUsage(AnalysisUsage &AU) const; + virtual void releaseMemory(); + + /// runOnMachineFunction - pass entry point + virtual bool runOnMachineFunction(MachineFunction&); + + private: + /// computeIntervals - compute live intervals + void computeIntervals(); + + /// joinIntervals - join compatible live intervals + void joinIntervals(); + + /// joinIntervalsInMachineBB - Join intervals based on move + /// instructions in the specified basic block. + void joinIntervalsInMachineBB(MachineBasicBlock *MBB); + + /// handleRegisterDef - update intervals for a register def + /// (calls handlePhysicalRegisterDef and + /// handleVirtualRegisterDef) + void handleRegisterDef(MachineBasicBlock* mbb, + MachineBasicBlock::iterator mi, + unsigned reg); + + /// handleVirtualRegisterDef - update intervals for a virtual + /// register def + void handleVirtualRegisterDef(MachineBasicBlock* mbb, + MachineBasicBlock::iterator mi, + LiveInterval& interval); + + /// handlePhysicalRegisterDef - update intervals for a + /// physical register def + void handlePhysicalRegisterDef(MachineBasicBlock* mbb, + MachineBasicBlock::iterator mi, + LiveInterval& interval); + + /// Return true if the two specified registers belong to different + /// register classes. The registers may be either phys or virt regs. + bool differingRegisterClasses(unsigned RegA, unsigned RegB) const; + + bool overlapsAliases(const LiveInterval *lhs, + const LiveInterval *rhs) const; + + static LiveInterval createInterval(unsigned Reg); + + LiveInterval &getOrCreateInterval(unsigned reg) { + Reg2IntervalMap::iterator I = r2iMap_.find(reg); + if (I == r2iMap_.end()) + I = r2iMap_.insert(I, std::make_pair(reg, createInterval(reg))); + return I->second; + } + + /// rep - returns the representative of this register + unsigned rep(unsigned reg) { + Reg2RegMap::iterator it = r2rMap_.find(reg); + if (it != r2rMap_.end()) + return it->second = rep(it->second); + return reg; + } + + void printRegName(unsigned reg) const; + }; + } // End llvm namespace #endif diff --git a/lib/CodeGen/RegAllocIterativeScan.cpp b/lib/CodeGen/RegAllocIterativeScan.cpp index e9e9fd8e136..ddd0451b600 100644 --- a/lib/CodeGen/RegAllocIterativeScan.cpp +++ b/lib/CodeGen/RegAllocIterativeScan.cpp @@ -40,439 +40,439 @@ using namespace llvm; namespace { - Statistic efficiency - ("regalloc", "Ratio of intervals processed over total intervals"); + Statistic efficiency + ("regalloc", "Ratio of intervals processed over total intervals"); - static unsigned numIterations = 0; - static unsigned numIntervals = 0; + static unsigned numIterations = 0; + static unsigned numIntervals = 0; - class RA : public MachineFunctionPass { - private: - MachineFunction* mf_; - const TargetMachine* tm_; - const MRegisterInfo* mri_; - LiveIntervals* li_; - typedef std::vector IntervalPtrs; - IntervalPtrs unhandled_, fixed_, active_, inactive_, handled_, spilled_; + class RA : public MachineFunctionPass { + private: + MachineFunction* mf_; + const TargetMachine* tm_; + const MRegisterInfo* mri_; + LiveIntervals* li_; + typedef std::vector IntervalPtrs; + IntervalPtrs unhandled_, fixed_, active_, inactive_, handled_, spilled_; - std::auto_ptr prt_; - std::auto_ptr vrm_; - std::auto_ptr spiller_; + std::auto_ptr prt_; + std::auto_ptr vrm_; + std::auto_ptr spiller_; - typedef std::vector SpillWeights; - SpillWeights spillWeights_; + typedef std::vector SpillWeights; + SpillWeights spillWeights_; - public: - virtual const char* getPassName() const { - return "Iterative Scan Register Allocator"; + public: + virtual const char* getPassName() const { + return "Iterative Scan Register Allocator"; + } + + virtual void getAnalysisUsage(AnalysisUsage &AU) const { + AU.addRequired(); + AU.addRequired(); + MachineFunctionPass::getAnalysisUsage(AU); + } + + /// runOnMachineFunction - register allocate the whole function + bool runOnMachineFunction(MachineFunction&); + + void releaseMemory(); + + private: + /// linearScan - the linear scan algorithm. Returns a boolean + /// indicating if there were any spills + bool linearScan(); + + /// initIntervalSets - initializes the four interval sets: + /// unhandled, fixed, active and inactive + void initIntervalSets(); + + /// processActiveIntervals - expire old intervals and move + /// non-overlapping ones to the incative list + void processActiveIntervals(IntervalPtrs::value_type cur); + + /// processInactiveIntervals - expire old intervals and move + /// overlapping ones to the active list + void processInactiveIntervals(IntervalPtrs::value_type cur); + + /// updateSpillWeights - updates the spill weights of the + /// specifed physical register and its weight + void updateSpillWeights(unsigned reg, SpillWeights::value_type weight); + + /// assignRegOrStackSlotAtInterval - assign a register if one + /// is available, or spill. + void assignRegOrSpillAtInterval(IntervalPtrs::value_type cur); + + /// + /// register handling helpers + /// + + /// getFreePhysReg - return a free physical register for this + /// virtual register interval if we have one, otherwise return + /// 0 + unsigned getFreePhysReg(IntervalPtrs::value_type cur); + + /// assignVirt2StackSlot - assigns this virtual register to a + /// stack slot. returns the stack slot + int assignVirt2StackSlot(unsigned virtReg); + + 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" << **i << " -> "; + unsigned reg = (*i)->reg; + if (MRegisterInfo::isVirtualRegister(reg)) { + reg = vrm_->getPhys(reg); } - - virtual void getAnalysisUsage(AnalysisUsage &AU) const { - AU.addRequired(); - AU.addRequired(); - MachineFunctionPass::getAnalysisUsage(AU); - } - - /// runOnMachineFunction - register allocate the whole function - bool runOnMachineFunction(MachineFunction&); - - void releaseMemory(); - - private: - /// linearScan - the linear scan algorithm. Returns a boolean - /// indicating if there were any spills - bool linearScan(); - - /// initIntervalSets - initializes the four interval sets: - /// unhandled, fixed, active and inactive - void initIntervalSets(); - - /// processActiveIntervals - expire old intervals and move - /// non-overlapping ones to the incative list - void processActiveIntervals(IntervalPtrs::value_type cur); - - /// processInactiveIntervals - expire old intervals and move - /// overlapping ones to the active list - void processInactiveIntervals(IntervalPtrs::value_type cur); - - /// updateSpillWeights - updates the spill weights of the - /// specifed physical register and its weight - void updateSpillWeights(unsigned reg, SpillWeights::value_type weight); - - /// assignRegOrStackSlotAtInterval - assign a register if one - /// is available, or spill. - void assignRegOrSpillAtInterval(IntervalPtrs::value_type cur); - - /// - /// register handling helpers - /// - - /// getFreePhysReg - return a free physical register for this - /// virtual register interval if we have one, otherwise return - /// 0 - unsigned getFreePhysReg(IntervalPtrs::value_type cur); - - /// assignVirt2StackSlot - assigns this virtual register to a - /// stack slot. returns the stack slot - int assignVirt2StackSlot(unsigned virtReg); - - 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" << **i << " -> "; - unsigned reg = (*i)->reg; - if (MRegisterInfo::isVirtualRegister(reg)) { - reg = vrm_->getPhys(reg); - } - std::cerr << mri_->getName(reg) << '\n'; - } - } - }; + std::cerr << mri_->getName(reg) << '\n'; + } + } + }; } void RA::releaseMemory() { - unhandled_.clear(); - fixed_.clear(); - active_.clear(); - inactive_.clear(); - handled_.clear(); - spilled_.clear(); + unhandled_.clear(); + fixed_.clear(); + active_.clear(); + inactive_.clear(); + handled_.clear(); + spilled_.clear(); } bool RA::runOnMachineFunction(MachineFunction &fn) { - mf_ = &fn; - tm_ = &fn.getTarget(); - mri_ = tm_->getRegisterInfo(); - li_ = &getAnalysis(); - if (!prt_.get()) prt_.reset(new PhysRegTracker(*mri_)); - vrm_.reset(new VirtRegMap(*mf_)); - if (!spiller_.get()) spiller_.reset(createSpiller()); + mf_ = &fn; + tm_ = &fn.getTarget(); + mri_ = tm_->getRegisterInfo(); + li_ = &getAnalysis(); + if (!prt_.get()) prt_.reset(new PhysRegTracker(*mri_)); + vrm_.reset(new VirtRegMap(*mf_)); + if (!spiller_.get()) spiller_.reset(createSpiller()); - initIntervalSets(); + initIntervalSets(); - numIntervals += li_->getNumIntervals(); + numIntervals += li_->getNumIntervals(); - while (linearScan()) { - // we spilled some registers, so we need to add intervals for - // the spill code and restart the algorithm - std::set spilledRegs; - for (IntervalPtrs::iterator - i = spilled_.begin(); i != spilled_.end(); ++i) { - int slot = vrm_->assignVirt2StackSlot((*i)->reg); - std::vector added = - li_->addIntervalsForSpills(**i, *vrm_, slot); - std::copy(added.begin(), added.end(), std::back_inserter(handled_)); - spilledRegs.insert((*i)->reg); - } - spilled_.clear(); - for (IntervalPtrs::iterator - i = handled_.begin(); i != handled_.end(); ) - if (spilledRegs.count((*i)->reg)) - i = handled_.erase(i); - else - ++i; - handled_.swap(unhandled_); - vrm_->clearAllVirt(); + while (linearScan()) { + // we spilled some registers, so we need to add intervals for + // the spill code and restart the algorithm + std::set spilledRegs; + for (IntervalPtrs::iterator + i = spilled_.begin(); i != spilled_.end(); ++i) { + int slot = vrm_->assignVirt2StackSlot((*i)->reg); + std::vector added = + li_->addIntervalsForSpills(**i, *vrm_, slot); + std::copy(added.begin(), added.end(), std::back_inserter(handled_)); + spilledRegs.insert((*i)->reg); } + spilled_.clear(); + for (IntervalPtrs::iterator + i = handled_.begin(); i != handled_.end(); ) + if (spilledRegs.count((*i)->reg)) + i = handled_.erase(i); + else + ++i; + handled_.swap(unhandled_); + vrm_->clearAllVirt(); + } - efficiency = double(numIterations) / double(numIntervals); + efficiency = double(numIterations) / double(numIntervals); - DEBUG(std::cerr << *vrm_); + DEBUG(std::cerr << *vrm_); - spiller_->runOnMachineFunction(*mf_, *vrm_); + spiller_->runOnMachineFunction(*mf_, *vrm_); - return true; + return true; } bool RA::linearScan() { - // linear scan algorithm - DEBUG(std::cerr << "********** LINEAR SCAN **********\n"); - DEBUG(std::cerr << "********** Function: " - << mf_->getFunction()->getName() << '\n'); + // linear scan algorithm + DEBUG(std::cerr << "********** LINEAR SCAN **********\n"); + DEBUG(std::cerr << "********** Function: " + << mf_->getFunction()->getName() << '\n'); - std::sort(unhandled_.begin(), unhandled_.end(), - greater_ptr()); - DEBUG(printIntervals("unhandled", unhandled_.begin(), unhandled_.end())); - DEBUG(printIntervals("fixed", fixed_.begin(), fixed_.end())); + std::sort(unhandled_.begin(), unhandled_.end(), + greater_ptr()); + DEBUG(printIntervals("unhandled", unhandled_.begin(), unhandled_.end())); + DEBUG(printIntervals("fixed", fixed_.begin(), fixed_.end())); + DEBUG(printIntervals("active", active_.begin(), active_.end())); + DEBUG(printIntervals("inactive", inactive_.begin(), inactive_.end())); + + while (!unhandled_.empty()) { + // pick the interval with the earliest start point + IntervalPtrs::value_type cur = unhandled_.back(); + unhandled_.pop_back(); + ++numIterations; + DEBUG(std::cerr << "\n*** CURRENT ***: " << *cur << '\n'); + + processActiveIntervals(cur); + processInactiveIntervals(cur); + + // if this register is fixed we are done + if (MRegisterInfo::isPhysicalRegister(cur->reg)) { + prt_->addRegUse(cur->reg); + active_.push_back(cur); + handled_.push_back(cur); + } + // otherwise we are allocating a virtual register. try to find + // a free physical register or spill an interval in order to + // assign it one (we could spill the current though). + else { + assignRegOrSpillAtInterval(cur); + } + DEBUG(printIntervals("active", active_.begin(), active_.end())); DEBUG(printIntervals("inactive", inactive_.begin(), inactive_.end())); + } - while (!unhandled_.empty()) { - // pick the interval with the earliest start point - IntervalPtrs::value_type cur = unhandled_.back(); - unhandled_.pop_back(); - ++numIterations; - DEBUG(std::cerr << "\n*** CURRENT ***: " << *cur << '\n'); + // expire any remaining active intervals + for (IntervalPtrs::reverse_iterator + i = active_.rbegin(); i != active_.rend(); ) { + unsigned reg = (*i)->reg; + DEBUG(std::cerr << "\tinterval " << **i << " expired\n"); + if (MRegisterInfo::isVirtualRegister(reg)) + reg = vrm_->getPhys(reg); + prt_->delRegUse(reg); + i = IntervalPtrs::reverse_iterator(active_.erase(i.base()-1)); + } - processActiveIntervals(cur); - processInactiveIntervals(cur); + // expire any remaining inactive intervals + for (IntervalPtrs::reverse_iterator + i = inactive_.rbegin(); i != inactive_.rend(); ) { + DEBUG(std::cerr << "\tinterval " << **i << " expired\n"); + i = IntervalPtrs::reverse_iterator(inactive_.erase(i.base()-1)); + } - // if this register is fixed we are done - if (MRegisterInfo::isPhysicalRegister(cur->reg)) { - prt_->addRegUse(cur->reg); - active_.push_back(cur); - handled_.push_back(cur); - } - // otherwise we are allocating a virtual register. try to find - // a free physical register or spill an interval in order to - // assign it one (we could spill the current though). - else { - assignRegOrSpillAtInterval(cur); - } - - DEBUG(printIntervals("active", active_.begin(), active_.end())); - DEBUG(printIntervals("inactive", inactive_.begin(), inactive_.end())); - } - - // expire any remaining active intervals - for (IntervalPtrs::reverse_iterator - i = active_.rbegin(); i != active_.rend(); ) { - unsigned reg = (*i)->reg; - DEBUG(std::cerr << "\tinterval " << **i << " expired\n"); - if (MRegisterInfo::isVirtualRegister(reg)) - reg = vrm_->getPhys(reg); - prt_->delRegUse(reg); - i = IntervalPtrs::reverse_iterator(active_.erase(i.base()-1)); - } - - // expire any remaining inactive intervals - for (IntervalPtrs::reverse_iterator - i = inactive_.rbegin(); i != inactive_.rend(); ) { - DEBUG(std::cerr << "\tinterval " << **i << " expired\n"); - i = IntervalPtrs::reverse_iterator(inactive_.erase(i.base()-1)); - } - - // return true if we spilled anything - return !spilled_.empty(); + // return true if we spilled anything + return !spilled_.empty(); } void RA::initIntervalSets() { - assert(unhandled_.empty() && fixed_.empty() && - active_.empty() && inactive_.empty() && - "interval sets should be empty on initialization"); + assert(unhandled_.empty() && fixed_.empty() && + active_.empty() && inactive_.empty() && + "interval sets should be empty on initialization"); - for (LiveIntervals::iterator i = li_->begin(), e = li_->end(); i != e; ++i){ - unhandled_.push_back(&i->second); - if (MRegisterInfo::isPhysicalRegister(i->second.reg)) - fixed_.push_back(&i->second); - } + for (LiveIntervals::iterator i = li_->begin(), e = li_->end(); i != e; ++i){ + unhandled_.push_back(&i->second); + if (MRegisterInfo::isPhysicalRegister(i->second.reg)) + fixed_.push_back(&i->second); + } } void RA::processActiveIntervals(IntervalPtrs::value_type cur) { - DEBUG(std::cerr << "\tprocessing active intervals:\n"); - for (IntervalPtrs::reverse_iterator - i = active_.rbegin(); i != active_.rend();) { - unsigned reg = (*i)->reg; - // remove expired intervals - if ((*i)->expiredAt(cur->start())) { - DEBUG(std::cerr << "\t\tinterval " << **i << " expired\n"); - if (MRegisterInfo::isVirtualRegister(reg)) - reg = vrm_->getPhys(reg); - prt_->delRegUse(reg); - // remove from active - i = IntervalPtrs::reverse_iterator(active_.erase(i.base()-1)); - } - // move inactive intervals to inactive list - else if (!(*i)->liveAt(cur->start())) { - DEBUG(std::cerr << "\t\tinterval " << **i << " inactive\n"); - if (MRegisterInfo::isVirtualRegister(reg)) - reg = vrm_->getPhys(reg); - prt_->delRegUse(reg); - // add to inactive - inactive_.push_back(*i); - // remove from active - i = IntervalPtrs::reverse_iterator(active_.erase(i.base()-1)); - } - else { - ++i; - } + DEBUG(std::cerr << "\tprocessing active intervals:\n"); + for (IntervalPtrs::reverse_iterator + i = active_.rbegin(); i != active_.rend();) { + unsigned reg = (*i)->reg; + // remove expired intervals + if ((*i)->expiredAt(cur->start())) { + DEBUG(std::cerr << "\t\tinterval " << **i << " expired\n"); + if (MRegisterInfo::isVirtualRegister(reg)) + reg = vrm_->getPhys(reg); + prt_->delRegUse(reg); + // remove from active + i = IntervalPtrs::reverse_iterator(active_.erase(i.base()-1)); } + // move inactive intervals to inactive list + else if (!(*i)->liveAt(cur->start())) { + DEBUG(std::cerr << "\t\tinterval " << **i << " inactive\n"); + if (MRegisterInfo::isVirtualRegister(reg)) + reg = vrm_->getPhys(reg); + prt_->delRegUse(reg); + // add to inactive + inactive_.push_back(*i); + // remove from active + i = IntervalPtrs::reverse_iterator(active_.erase(i.base()-1)); + } + else { + ++i; + } + } } void RA::processInactiveIntervals(IntervalPtrs::value_type cur) { - DEBUG(std::cerr << "\tprocessing inactive intervals:\n"); - for (IntervalPtrs::reverse_iterator - i = inactive_.rbegin(); i != inactive_.rend();) { - unsigned reg = (*i)->reg; + DEBUG(std::cerr << "\tprocessing inactive intervals:\n"); + for (IntervalPtrs::reverse_iterator + i = inactive_.rbegin(); i != inactive_.rend();) { + unsigned reg = (*i)->reg; - // remove expired intervals - if ((*i)->expiredAt(cur->start())) { - DEBUG(std::cerr << "\t\tinterval " << **i << " expired\n"); - // remove from inactive - i = IntervalPtrs::reverse_iterator(inactive_.erase(i.base()-1)); - } - // move re-activated intervals in active list - else if ((*i)->liveAt(cur->start())) { - DEBUG(std::cerr << "\t\tinterval " << **i << " active\n"); - if (MRegisterInfo::isVirtualRegister(reg)) - reg = vrm_->getPhys(reg); - prt_->addRegUse(reg); - // add to active - active_.push_back(*i); - // remove from inactive - i = IntervalPtrs::reverse_iterator(inactive_.erase(i.base()-1)); - } - else { - ++i; - } + // remove expired intervals + if ((*i)->expiredAt(cur->start())) { + DEBUG(std::cerr << "\t\tinterval " << **i << " expired\n"); + // remove from inactive + i = IntervalPtrs::reverse_iterator(inactive_.erase(i.base()-1)); } + // move re-activated intervals in active list + else if ((*i)->liveAt(cur->start())) { + DEBUG(std::cerr << "\t\tinterval " << **i << " active\n"); + if (MRegisterInfo::isVirtualRegister(reg)) + reg = vrm_->getPhys(reg); + prt_->addRegUse(reg); + // add to active + active_.push_back(*i); + // remove from inactive + i = IntervalPtrs::reverse_iterator(inactive_.erase(i.base()-1)); + } + else { + ++i; + } + } } void RA::updateSpillWeights(unsigned reg, SpillWeights::value_type weight) { - spillWeights_[reg] += weight; - for (const unsigned* as = mri_->getAliasSet(reg); *as; ++as) - spillWeights_[*as] += weight; + spillWeights_[reg] += weight; + for (const unsigned* as = mri_->getAliasSet(reg); *as; ++as) + spillWeights_[*as] += weight; } void RA::assignRegOrSpillAtInterval(IntervalPtrs::value_type cur) { - DEBUG(std::cerr << "\tallocating current interval: "); + DEBUG(std::cerr << "\tallocating current interval: "); - PhysRegTracker backupPrt = *prt_; + PhysRegTracker backupPrt = *prt_; - spillWeights_.assign(mri_->getNumRegs(), 0.0); + spillWeights_.assign(mri_->getNumRegs(), 0.0); - // for each interval in active update spill weights - for (IntervalPtrs::const_iterator i = active_.begin(), e = active_.end(); - i != e; ++i) { - unsigned reg = (*i)->reg; - if (MRegisterInfo::isVirtualRegister(reg)) - reg = vrm_->getPhys(reg); - updateSpillWeights(reg, (*i)->weight); + // for each interval in active update spill weights + for (IntervalPtrs::const_iterator i = active_.begin(), e = active_.end(); + i != e; ++i) { + unsigned reg = (*i)->reg; + if (MRegisterInfo::isVirtualRegister(reg)) + reg = vrm_->getPhys(reg); + updateSpillWeights(reg, (*i)->weight); + } + + // for every interval in inactive we overlap with, mark the + // register as not free and update spill weights + for (IntervalPtrs::const_iterator i = inactive_.begin(), + e = inactive_.end(); i != e; ++i) { + if (cur->overlaps(**i)) { + unsigned reg = (*i)->reg; + if (MRegisterInfo::isVirtualRegister(reg)) + reg = vrm_->getPhys(reg); + prt_->addRegUse(reg); + updateSpillWeights(reg, (*i)->weight); } + } - // for every interval in inactive we overlap with, mark the - // register as not free and update spill weights - for (IntervalPtrs::const_iterator i = inactive_.begin(), - e = inactive_.end(); i != e; ++i) { - if (cur->overlaps(**i)) { - unsigned reg = (*i)->reg; - if (MRegisterInfo::isVirtualRegister(reg)) - reg = vrm_->getPhys(reg); - prt_->addRegUse(reg); - updateSpillWeights(reg, (*i)->weight); - } + // for every interval in fixed we overlap with, + // mark the register as not free and update spill weights + for (IntervalPtrs::const_iterator i = fixed_.begin(), + e = fixed_.end(); i != e; ++i) { + if (cur->overlaps(**i)) { + unsigned reg = (*i)->reg; + prt_->addRegUse(reg); + updateSpillWeights(reg, (*i)->weight); } + } - // for every interval in fixed we overlap with, - // mark the register as not free and update spill weights - for (IntervalPtrs::const_iterator i = fixed_.begin(), - e = fixed_.end(); i != e; ++i) { - if (cur->overlaps(**i)) { - unsigned reg = (*i)->reg; - prt_->addRegUse(reg); - updateSpillWeights(reg, (*i)->weight); - } - } - - unsigned physReg = getFreePhysReg(cur); - // restore the physical register tracker - *prt_ = backupPrt; - // if we find a free register, we are done: assign this virtual to - // the free physical register and add this interval to the active - // list. - if (physReg) { - DEBUG(std::cerr << mri_->getName(physReg) << '\n'); - vrm_->assignVirt2Phys(cur->reg, physReg); - prt_->addRegUse(physReg); - active_.push_back(cur); - handled_.push_back(cur); - return; - } - DEBUG(std::cerr << "no free registers\n"); - - DEBUG(std::cerr << "\tassigning stack slot at interval "<< *cur << ":\n"); - - float minWeight = HUGE_VAL; - unsigned minReg = 0; - const TargetRegisterClass* rc = mf_->getSSARegMap()->getRegClass(cur->reg); - for (TargetRegisterClass::iterator i = rc->allocation_order_begin(*mf_); - i != rc->allocation_order_end(*mf_); ++i) { - unsigned reg = *i; - if (minWeight > spillWeights_[reg]) { - minWeight = spillWeights_[reg]; - minReg = reg; - } - } - DEBUG(std::cerr << "\t\tregister with min weight: " - << mri_->getName(minReg) << " (" << minWeight << ")\n"); - - // if the current has the minimum weight, we spill it and move on - if (cur->weight <= minWeight) { - DEBUG(std::cerr << "\t\t\tspilling(c): " << *cur << '\n'); - spilled_.push_back(cur); - return; - } - - // otherwise we spill all intervals aliasing the register with - // minimum weight, assigned the newly cleared register to the - // current interval and continue - assert(MRegisterInfo::isPhysicalRegister(minReg) && - "did not choose a register to spill?"); - std::vector toSpill(mri_->getNumRegs(), false); - toSpill[minReg] = true; - for (const unsigned* as = mri_->getAliasSet(minReg); *as; ++as) - toSpill[*as] = true; - unsigned earliestStart = cur->start(); - - std::set spilled; - - for (IntervalPtrs::iterator i = active_.begin(); i != active_.end(); ) { - unsigned reg = (*i)->reg; - if (MRegisterInfo::isVirtualRegister(reg) && - toSpill[vrm_->getPhys(reg)] && - cur->overlaps(**i)) { - DEBUG(std::cerr << "\t\t\tspilling(a): " << **i << '\n'); - spilled_.push_back(*i); - prt_->delRegUse(vrm_->getPhys(reg)); - vrm_->clearVirt(reg); - i = active_.erase(i); - } - else - ++i; - } - for (IntervalPtrs::iterator i = inactive_.begin(); i != inactive_.end(); ) { - unsigned reg = (*i)->reg; - if (MRegisterInfo::isVirtualRegister(reg) && - toSpill[vrm_->getPhys(reg)] && - cur->overlaps(**i)) { - DEBUG(std::cerr << "\t\t\tspilling(i): " << **i << '\n'); - spilled_.push_back(*i); - vrm_->clearVirt(reg); - i = inactive_.erase(i); - } - else - ++i; - } - - vrm_->assignVirt2Phys(cur->reg, minReg); - prt_->addRegUse(minReg); + unsigned physReg = getFreePhysReg(cur); + // restore the physical register tracker + *prt_ = backupPrt; + // if we find a free register, we are done: assign this virtual to + // the free physical register and add this interval to the active + // list. + if (physReg) { + DEBUG(std::cerr << mri_->getName(physReg) << '\n'); + vrm_->assignVirt2Phys(cur->reg, physReg); + prt_->addRegUse(physReg); active_.push_back(cur); handled_.push_back(cur); + return; + } + DEBUG(std::cerr << "no free registers\n"); + + DEBUG(std::cerr << "\tassigning stack slot at interval "<< *cur << ":\n"); + + float minWeight = HUGE_VAL; + unsigned minReg = 0; + const TargetRegisterClass* rc = mf_->getSSARegMap()->getRegClass(cur->reg); + for (TargetRegisterClass::iterator i = rc->allocation_order_begin(*mf_); + i != rc->allocation_order_end(*mf_); ++i) { + unsigned reg = *i; + if (minWeight > spillWeights_[reg]) { + minWeight = spillWeights_[reg]; + minReg = reg; + } + } + DEBUG(std::cerr << "\t\tregister with min weight: " + << mri_->getName(minReg) << " (" << minWeight << ")\n"); + + // if the current has the minimum weight, we spill it and move on + if (cur->weight <= minWeight) { + DEBUG(std::cerr << "\t\t\tspilling(c): " << *cur << '\n'); + spilled_.push_back(cur); + return; + } + + // otherwise we spill all intervals aliasing the register with + // minimum weight, assigned the newly cleared register to the + // current interval and continue + assert(MRegisterInfo::isPhysicalRegister(minReg) && + "did not choose a register to spill?"); + std::vector toSpill(mri_->getNumRegs(), false); + toSpill[minReg] = true; + for (const unsigned* as = mri_->getAliasSet(minReg); *as; ++as) + toSpill[*as] = true; + unsigned earliestStart = cur->start(); + + std::set spilled; + + for (IntervalPtrs::iterator i = active_.begin(); i != active_.end(); ) { + unsigned reg = (*i)->reg; + if (MRegisterInfo::isVirtualRegister(reg) && + toSpill[vrm_->getPhys(reg)] && + cur->overlaps(**i)) { + DEBUG(std::cerr << "\t\t\tspilling(a): " << **i << '\n'); + spilled_.push_back(*i); + prt_->delRegUse(vrm_->getPhys(reg)); + vrm_->clearVirt(reg); + i = active_.erase(i); + } + else + ++i; + } + for (IntervalPtrs::iterator i = inactive_.begin(); i != inactive_.end(); ) { + unsigned reg = (*i)->reg; + if (MRegisterInfo::isVirtualRegister(reg) && + toSpill[vrm_->getPhys(reg)] && + cur->overlaps(**i)) { + DEBUG(std::cerr << "\t\t\tspilling(i): " << **i << '\n'); + spilled_.push_back(*i); + vrm_->clearVirt(reg); + i = inactive_.erase(i); + } + else + ++i; + } + + vrm_->assignVirt2Phys(cur->reg, minReg); + prt_->addRegUse(minReg); + active_.push_back(cur); + handled_.push_back(cur); } unsigned RA::getFreePhysReg(IntervalPtrs::value_type cur) { - const TargetRegisterClass* rc = mf_->getSSARegMap()->getRegClass(cur->reg); + const TargetRegisterClass* rc = mf_->getSSARegMap()->getRegClass(cur->reg); - for (TargetRegisterClass::iterator i = rc->allocation_order_begin(*mf_); - i != rc->allocation_order_end(*mf_); ++i) { - unsigned reg = *i; - if (prt_->isRegAvail(reg)) - return reg; - } - return 0; + for (TargetRegisterClass::iterator i = rc->allocation_order_begin(*mf_); + i != rc->allocation_order_end(*mf_); ++i) { + unsigned reg = *i; + if (prt_->isRegAvail(reg)) + return reg; + } + return 0; } FunctionPass* llvm::createIterativeScanRegisterAllocator() { - return new RA(); + return new RA(); } diff --git a/lib/CodeGen/RegAllocLinearScan.cpp b/lib/CodeGen/RegAllocLinearScan.cpp index 4c44d9201cb..6858744ba1b 100644 --- a/lib/CodeGen/RegAllocLinearScan.cpp +++ b/lib/CodeGen/RegAllocLinearScan.cpp @@ -35,502 +35,502 @@ using namespace llvm; namespace { - Statistic efficiency - ("regalloc", "Ratio of intervals processed over total intervals"); + Statistic efficiency + ("regalloc", "Ratio of intervals processed over total intervals"); - static unsigned numIterations = 0; - static unsigned numIntervals = 0; + static unsigned numIterations = 0; + static unsigned numIntervals = 0; - class RA : public MachineFunctionPass { - private: - MachineFunction* mf_; - const TargetMachine* tm_; - const MRegisterInfo* mri_; - LiveIntervals* li_; - typedef std::vector IntervalPtrs; - IntervalPtrs handled_, fixed_, active_, inactive_; - typedef std::priority_queue > IntervalHeap; - IntervalHeap unhandled_; - std::auto_ptr prt_; - std::auto_ptr vrm_; - std::auto_ptr spiller_; + class RA : public MachineFunctionPass { + private: + MachineFunction* mf_; + const TargetMachine* tm_; + const MRegisterInfo* mri_; + LiveIntervals* li_; + typedef std::vector IntervalPtrs; + IntervalPtrs handled_, fixed_, active_, inactive_; + typedef std::priority_queue > IntervalHeap; + IntervalHeap unhandled_; + std::auto_ptr prt_; + std::auto_ptr vrm_; + std::auto_ptr spiller_; - typedef std::vector SpillWeights; - SpillWeights spillWeights_; + typedef std::vector SpillWeights; + SpillWeights spillWeights_; - public: - virtual const char* getPassName() const { - return "Linear Scan Register Allocator"; + public: + virtual const char* getPassName() const { + return "Linear Scan Register Allocator"; + } + + virtual void getAnalysisUsage(AnalysisUsage &AU) const { + AU.addRequired(); + AU.addRequired(); + MachineFunctionPass::getAnalysisUsage(AU); + } + + /// runOnMachineFunction - register allocate the whole function + bool runOnMachineFunction(MachineFunction&); + + void releaseMemory(); + + private: + /// linearScan - the linear scan algorithm + void linearScan(); + + /// initIntervalSets - initializa the four interval sets: + /// unhandled, fixed, active and inactive + void initIntervalSets(); + + /// processActiveIntervals - expire old intervals and move + /// non-overlapping ones to the incative list + void processActiveIntervals(LiveInterval* cur); + + /// processInactiveIntervals - expire old intervals and move + /// overlapping ones to the active list + void processInactiveIntervals(LiveInterval* cur); + + /// updateSpillWeights - updates the spill weights of the + /// specifed physical register and its weight + void updateSpillWeights(unsigned reg, SpillWeights::value_type weight); + + /// assignRegOrStackSlotAtInterval - assign a register if one + /// is available, or spill. + void assignRegOrStackSlotAtInterval(LiveInterval* cur); + + /// + /// register handling helpers + /// + + /// getFreePhysReg - return a free physical register for this + /// virtual register interval if we have one, otherwise return + /// 0 + unsigned getFreePhysReg(LiveInterval* cur); + + /// assignVirt2StackSlot - assigns this virtual register to a + /// stack slot. returns the stack slot + int assignVirt2StackSlot(unsigned virtReg); + + template + void printIntervals(const char* const str, ItTy i, ItTy e) const { + if (str) std::cerr << str << " intervals:\n"; + for (; i != e; ++i) { + std::cerr << "\t" << **i << " -> "; + unsigned reg = (*i)->reg; + if (MRegisterInfo::isVirtualRegister(reg)) { + reg = vrm_->getPhys(reg); } - - virtual void getAnalysisUsage(AnalysisUsage &AU) const { - AU.addRequired(); - AU.addRequired(); - MachineFunctionPass::getAnalysisUsage(AU); - } - - /// runOnMachineFunction - register allocate the whole function - bool runOnMachineFunction(MachineFunction&); - - void releaseMemory(); - - private: - /// linearScan - the linear scan algorithm - void linearScan(); - - /// initIntervalSets - initializa the four interval sets: - /// unhandled, fixed, active and inactive - void initIntervalSets(); - - /// processActiveIntervals - expire old intervals and move - /// non-overlapping ones to the incative list - void processActiveIntervals(LiveInterval* cur); - - /// processInactiveIntervals - expire old intervals and move - /// overlapping ones to the active list - void processInactiveIntervals(LiveInterval* cur); - - /// updateSpillWeights - updates the spill weights of the - /// specifed physical register and its weight - void updateSpillWeights(unsigned reg, SpillWeights::value_type weight); - - /// assignRegOrStackSlotAtInterval - assign a register if one - /// is available, or spill. - void assignRegOrStackSlotAtInterval(LiveInterval* cur); - - /// - /// register handling helpers - /// - - /// getFreePhysReg - return a free physical register for this - /// virtual register interval if we have one, otherwise return - /// 0 - unsigned getFreePhysReg(LiveInterval* cur); - - /// assignVirt2StackSlot - assigns this virtual register to a - /// stack slot. returns the stack slot - int assignVirt2StackSlot(unsigned virtReg); - - template - void printIntervals(const char* const str, ItTy i, ItTy e) const { - if (str) std::cerr << str << " intervals:\n"; - for (; i != e; ++i) { - std::cerr << "\t" << **i << " -> "; - unsigned reg = (*i)->reg; - if (MRegisterInfo::isVirtualRegister(reg)) { - reg = vrm_->getPhys(reg); - } - std::cerr << mri_->getName(reg) << '\n'; - } - } - }; + std::cerr << mri_->getName(reg) << '\n'; + } + } + }; } void RA::releaseMemory() { - while (!unhandled_.empty()) unhandled_.pop(); - fixed_.clear(); - active_.clear(); - inactive_.clear(); - handled_.clear(); + while (!unhandled_.empty()) unhandled_.pop(); + fixed_.clear(); + active_.clear(); + inactive_.clear(); + handled_.clear(); } bool RA::runOnMachineFunction(MachineFunction &fn) { - mf_ = &fn; - tm_ = &fn.getTarget(); - mri_ = tm_->getRegisterInfo(); - li_ = &getAnalysis(); - if (!prt_.get()) prt_.reset(new PhysRegTracker(*mri_)); - vrm_.reset(new VirtRegMap(*mf_)); - if (!spiller_.get()) spiller_.reset(createSpiller()); + mf_ = &fn; + tm_ = &fn.getTarget(); + mri_ = tm_->getRegisterInfo(); + li_ = &getAnalysis(); + if (!prt_.get()) prt_.reset(new PhysRegTracker(*mri_)); + vrm_.reset(new VirtRegMap(*mf_)); + if (!spiller_.get()) spiller_.reset(createSpiller()); - initIntervalSets(); + initIntervalSets(); - linearScan(); + linearScan(); - spiller_->runOnMachineFunction(*mf_, *vrm_); + spiller_->runOnMachineFunction(*mf_, *vrm_); - return true; + return true; } void RA::linearScan() { - // linear scan algorithm - DEBUG(std::cerr << "********** LINEAR SCAN **********\n"); - DEBUG(std::cerr << "********** Function: " - << mf_->getFunction()->getName() << '\n'); + // linear scan algorithm + DEBUG(std::cerr << "********** LINEAR SCAN **********\n"); + DEBUG(std::cerr << "********** Function: " + << mf_->getFunction()->getName() << '\n'); + + // DEBUG(printIntervals("unhandled", unhandled_.begin(), unhandled_.end())); + DEBUG(printIntervals("fixed", fixed_.begin(), fixed_.end())); + DEBUG(printIntervals("active", active_.begin(), active_.end())); + DEBUG(printIntervals("inactive", inactive_.begin(), inactive_.end())); + + while (!unhandled_.empty()) { + // pick the interval with the earliest start point + LiveInterval* cur = unhandled_.top(); + unhandled_.pop(); + ++numIterations; + DEBUG(std::cerr << "\n*** CURRENT ***: " << *cur << '\n'); + + processActiveIntervals(cur); + processInactiveIntervals(cur); + + // if this register is fixed we are done + if (MRegisterInfo::isPhysicalRegister(cur->reg)) { + prt_->addRegUse(cur->reg); + active_.push_back(cur); + handled_.push_back(cur); + } + // otherwise we are allocating a virtual register. try to find + // a free physical register or spill an interval in order to + // assign it one (we could spill the current though). + else { + assignRegOrStackSlotAtInterval(cur); + } - // DEBUG(printIntervals("unhandled", unhandled_.begin(), unhandled_.end())); - DEBUG(printIntervals("fixed", fixed_.begin(), fixed_.end())); DEBUG(printIntervals("active", active_.begin(), active_.end())); DEBUG(printIntervals("inactive", inactive_.begin(), inactive_.end())); + } + numIntervals += li_->getNumIntervals(); + efficiency = double(numIterations) / double(numIntervals); - while (!unhandled_.empty()) { - // pick the interval with the earliest start point - LiveInterval* cur = unhandled_.top(); - unhandled_.pop(); - ++numIterations; - DEBUG(std::cerr << "\n*** CURRENT ***: " << *cur << '\n'); + // expire any remaining active intervals + for (IntervalPtrs::reverse_iterator + i = active_.rbegin(); i != active_.rend(); ) { + unsigned reg = (*i)->reg; + DEBUG(std::cerr << "\tinterval " << **i << " expired\n"); + if (MRegisterInfo::isVirtualRegister(reg)) + reg = vrm_->getPhys(reg); + prt_->delRegUse(reg); + i = IntervalPtrs::reverse_iterator(active_.erase(i.base()-1)); + } - processActiveIntervals(cur); - processInactiveIntervals(cur); + // expire any remaining inactive intervals + for (IntervalPtrs::reverse_iterator + i = inactive_.rbegin(); i != inactive_.rend(); ) { + DEBUG(std::cerr << "\tinterval " << **i << " expired\n"); + i = IntervalPtrs::reverse_iterator(inactive_.erase(i.base()-1)); + } - // if this register is fixed we are done - if (MRegisterInfo::isPhysicalRegister(cur->reg)) { - prt_->addRegUse(cur->reg); - active_.push_back(cur); - handled_.push_back(cur); - } - // otherwise we are allocating a virtual register. try to find - // a free physical register or spill an interval in order to - // assign it one (we could spill the current though). - else { - assignRegOrStackSlotAtInterval(cur); - } - - DEBUG(printIntervals("active", active_.begin(), active_.end())); - DEBUG(printIntervals("inactive", inactive_.begin(), inactive_.end())); - } - numIntervals += li_->getNumIntervals(); - efficiency = double(numIterations) / double(numIntervals); - - // expire any remaining active intervals - for (IntervalPtrs::reverse_iterator - i = active_.rbegin(); i != active_.rend(); ) { - unsigned reg = (*i)->reg; - DEBUG(std::cerr << "\tinterval " << **i << " expired\n"); - if (MRegisterInfo::isVirtualRegister(reg)) - reg = vrm_->getPhys(reg); - prt_->delRegUse(reg); - i = IntervalPtrs::reverse_iterator(active_.erase(i.base()-1)); - } - - // expire any remaining inactive intervals - for (IntervalPtrs::reverse_iterator - i = inactive_.rbegin(); i != inactive_.rend(); ) { - DEBUG(std::cerr << "\tinterval " << **i << " expired\n"); - i = IntervalPtrs::reverse_iterator(inactive_.erase(i.base()-1)); - } - - DEBUG(std::cerr << *vrm_); + DEBUG(std::cerr << *vrm_); } void RA::initIntervalSets() { - assert(unhandled_.empty() && fixed_.empty() && - active_.empty() && inactive_.empty() && - "interval sets should be empty on initialization"); + assert(unhandled_.empty() && fixed_.empty() && + active_.empty() && inactive_.empty() && + "interval sets should be empty on initialization"); - for (LiveIntervals::iterator i = li_->begin(), e = li_->end(); i != e; ++i){ - unhandled_.push(&i->second); - if (MRegisterInfo::isPhysicalRegister(i->second.reg)) - fixed_.push_back(&i->second); - } + for (LiveIntervals::iterator i = li_->begin(), e = li_->end(); i != e; ++i){ + unhandled_.push(&i->second); + if (MRegisterInfo::isPhysicalRegister(i->second.reg)) + fixed_.push_back(&i->second); + } } void RA::processActiveIntervals(IntervalPtrs::value_type cur) { - DEBUG(std::cerr << "\tprocessing active intervals:\n"); - for (IntervalPtrs::reverse_iterator - i = active_.rbegin(); i != active_.rend();) { - unsigned reg = (*i)->reg; - // remove expired intervals - if ((*i)->expiredAt(cur->start())) { - DEBUG(std::cerr << "\t\tinterval " << **i << " expired\n"); - if (MRegisterInfo::isVirtualRegister(reg)) - reg = vrm_->getPhys(reg); - prt_->delRegUse(reg); - // remove from active - i = IntervalPtrs::reverse_iterator(active_.erase(i.base()-1)); - } - // move inactive intervals to inactive list - else if (!(*i)->liveAt(cur->start())) { - DEBUG(std::cerr << "\t\tinterval " << **i << " inactive\n"); - if (MRegisterInfo::isVirtualRegister(reg)) - reg = vrm_->getPhys(reg); - prt_->delRegUse(reg); - // add to inactive - inactive_.push_back(*i); - // remove from active - i = IntervalPtrs::reverse_iterator(active_.erase(i.base()-1)); - } - else { - ++i; - } + DEBUG(std::cerr << "\tprocessing active intervals:\n"); + for (IntervalPtrs::reverse_iterator + i = active_.rbegin(); i != active_.rend();) { + unsigned reg = (*i)->reg; + // remove expired intervals + if ((*i)->expiredAt(cur->start())) { + DEBUG(std::cerr << "\t\tinterval " << **i << " expired\n"); + if (MRegisterInfo::isVirtualRegister(reg)) + reg = vrm_->getPhys(reg); + prt_->delRegUse(reg); + // remove from active + i = IntervalPtrs::reverse_iterator(active_.erase(i.base()-1)); } + // move inactive intervals to inactive list + else if (!(*i)->liveAt(cur->start())) { + DEBUG(std::cerr << "\t\tinterval " << **i << " inactive\n"); + if (MRegisterInfo::isVirtualRegister(reg)) + reg = vrm_->getPhys(reg); + prt_->delRegUse(reg); + // add to inactive + inactive_.push_back(*i); + // remove from active + i = IntervalPtrs::reverse_iterator(active_.erase(i.base()-1)); + } + else { + ++i; + } + } } void RA::processInactiveIntervals(IntervalPtrs::value_type cur) { - DEBUG(std::cerr << "\tprocessing inactive intervals:\n"); - for (IntervalPtrs::reverse_iterator - i = inactive_.rbegin(); i != inactive_.rend();) { - unsigned reg = (*i)->reg; + DEBUG(std::cerr << "\tprocessing inactive intervals:\n"); + for (IntervalPtrs::reverse_iterator + i = inactive_.rbegin(); i != inactive_.rend();) { + unsigned reg = (*i)->reg; - // remove expired intervals - if ((*i)->expiredAt(cur->start())) { - DEBUG(std::cerr << "\t\tinterval " << **i << " expired\n"); - // remove from inactive - i = IntervalPtrs::reverse_iterator(inactive_.erase(i.base()-1)); - } - // move re-activated intervals in active list - else if ((*i)->liveAt(cur->start())) { - DEBUG(std::cerr << "\t\tinterval " << **i << " active\n"); - if (MRegisterInfo::isVirtualRegister(reg)) - reg = vrm_->getPhys(reg); - prt_->addRegUse(reg); - // add to active - active_.push_back(*i); - // remove from inactive - i = IntervalPtrs::reverse_iterator(inactive_.erase(i.base()-1)); - } - else { - ++i; - } + // remove expired intervals + if ((*i)->expiredAt(cur->start())) { + DEBUG(std::cerr << "\t\tinterval " << **i << " expired\n"); + // remove from inactive + i = IntervalPtrs::reverse_iterator(inactive_.erase(i.base()-1)); } + // move re-activated intervals in active list + else if ((*i)->liveAt(cur->start())) { + DEBUG(std::cerr << "\t\tinterval " << **i << " active\n"); + if (MRegisterInfo::isVirtualRegister(reg)) + reg = vrm_->getPhys(reg); + prt_->addRegUse(reg); + // add to active + active_.push_back(*i); + // remove from inactive + i = IntervalPtrs::reverse_iterator(inactive_.erase(i.base()-1)); + } + else { + ++i; + } + } } void RA::updateSpillWeights(unsigned reg, SpillWeights::value_type weight) { - spillWeights_[reg] += weight; - for (const unsigned* as = mri_->getAliasSet(reg); *as; ++as) - spillWeights_[*as] += weight; + spillWeights_[reg] += weight; + for (const unsigned* as = mri_->getAliasSet(reg); *as; ++as) + spillWeights_[*as] += weight; } void RA::assignRegOrStackSlotAtInterval(LiveInterval* cur) { - DEBUG(std::cerr << "\tallocating current interval: "); + DEBUG(std::cerr << "\tallocating current interval: "); - PhysRegTracker backupPrt = *prt_; + PhysRegTracker backupPrt = *prt_; - spillWeights_.assign(mri_->getNumRegs(), 0.0); + spillWeights_.assign(mri_->getNumRegs(), 0.0); - // for each interval in active update spill weights - for (IntervalPtrs::const_iterator i = active_.begin(), e = active_.end(); - i != e; ++i) { - unsigned reg = (*i)->reg; - if (MRegisterInfo::isVirtualRegister(reg)) - reg = vrm_->getPhys(reg); - updateSpillWeights(reg, (*i)->weight); + // for each interval in active update spill weights + for (IntervalPtrs::const_iterator i = active_.begin(), e = active_.end(); + i != e; ++i) { + unsigned reg = (*i)->reg; + if (MRegisterInfo::isVirtualRegister(reg)) + reg = vrm_->getPhys(reg); + updateSpillWeights(reg, (*i)->weight); + } + + // for every interval in inactive we overlap with, mark the + // register as not free and update spill weights + for (IntervalPtrs::const_iterator i = inactive_.begin(), + e = inactive_.end(); i != e; ++i) { + if (cur->overlaps(**i)) { + unsigned reg = (*i)->reg; + if (MRegisterInfo::isVirtualRegister(reg)) + reg = vrm_->getPhys(reg); + prt_->addRegUse(reg); + updateSpillWeights(reg, (*i)->weight); } + } - // for every interval in inactive we overlap with, mark the - // register as not free and update spill weights - for (IntervalPtrs::const_iterator i = inactive_.begin(), - e = inactive_.end(); i != e; ++i) { - if (cur->overlaps(**i)) { - unsigned reg = (*i)->reg; - if (MRegisterInfo::isVirtualRegister(reg)) - reg = vrm_->getPhys(reg); - prt_->addRegUse(reg); - updateSpillWeights(reg, (*i)->weight); - } + // for every interval in fixed we overlap with, + // mark the register as not free and update spill weights + for (IntervalPtrs::const_iterator i = fixed_.begin(), + e = fixed_.end(); i != e; ++i) { + if (cur->overlaps(**i)) { + unsigned reg = (*i)->reg; + prt_->addRegUse(reg); + updateSpillWeights(reg, (*i)->weight); } + } - // for every interval in fixed we overlap with, - // mark the register as not free and update spill weights - for (IntervalPtrs::const_iterator i = fixed_.begin(), - e = fixed_.end(); i != e; ++i) { - if (cur->overlaps(**i)) { - unsigned reg = (*i)->reg; - prt_->addRegUse(reg); - updateSpillWeights(reg, (*i)->weight); - } + unsigned physReg = getFreePhysReg(cur); + // restore the physical register tracker + *prt_ = backupPrt; + // if we find a free register, we are done: assign this virtual to + // the free physical register and add this interval to the active + // list. + if (physReg) { + DEBUG(std::cerr << mri_->getName(physReg) << '\n'); + vrm_->assignVirt2Phys(cur->reg, physReg); + prt_->addRegUse(physReg); + active_.push_back(cur); + handled_.push_back(cur); + return; + } + DEBUG(std::cerr << "no free registers\n"); + + DEBUG(std::cerr << "\tassigning stack slot at interval "<< *cur << ":\n"); + + float minWeight = HUGE_VAL; + unsigned minReg = 0; + const TargetRegisterClass* rc = mf_->getSSARegMap()->getRegClass(cur->reg); + for (TargetRegisterClass::iterator i = rc->allocation_order_begin(*mf_); + i != rc->allocation_order_end(*mf_); ++i) { + unsigned reg = *i; + if (minWeight > spillWeights_[reg]) { + minWeight = spillWeights_[reg]; + minReg = reg; } + } + DEBUG(std::cerr << "\t\tregister with min weight: " + << mri_->getName(minReg) << " (" << minWeight << ")\n"); - unsigned physReg = getFreePhysReg(cur); - // restore the physical register tracker - *prt_ = backupPrt; - // if we find a free register, we are done: assign this virtual to - // the free physical register and add this interval to the active - // list. - if (physReg) { - DEBUG(std::cerr << mri_->getName(physReg) << '\n'); - vrm_->assignVirt2Phys(cur->reg, physReg); - prt_->addRegUse(physReg); - active_.push_back(cur); - handled_.push_back(cur); - return; - } - DEBUG(std::cerr << "no free registers\n"); + // if the current has the minimum weight, we need to spill it and + // add any added intervals back to unhandled, and restart + // linearscan. + if (cur->weight <= minWeight) { + DEBUG(std::cerr << "\t\t\tspilling(c): " << *cur << '\n';); + int slot = vrm_->assignVirt2StackSlot(cur->reg); + std::vector added = + li_->addIntervalsForSpills(*cur, *vrm_, slot); + if (added.empty()) + return; // Early exit if all spills were folded. - DEBUG(std::cerr << "\tassigning stack slot at interval "<< *cur << ":\n"); - - float minWeight = HUGE_VAL; - unsigned minReg = 0; - const TargetRegisterClass* rc = mf_->getSSARegMap()->getRegClass(cur->reg); - for (TargetRegisterClass::iterator i = rc->allocation_order_begin(*mf_); - i != rc->allocation_order_end(*mf_); ++i) { - unsigned reg = *i; - if (minWeight > spillWeights_[reg]) { - minWeight = spillWeights_[reg]; - minReg = reg; - } - } - DEBUG(std::cerr << "\t\tregister with min weight: " - << mri_->getName(minReg) << " (" << minWeight << ")\n"); - - // if the current has the minimum weight, we need to spill it and - // add any added intervals back to unhandled, and restart - // linearscan. - if (cur->weight <= minWeight) { - DEBUG(std::cerr << "\t\t\tspilling(c): " << *cur << '\n';); - int slot = vrm_->assignVirt2StackSlot(cur->reg); - std::vector added = - li_->addIntervalsForSpills(*cur, *vrm_, slot); - if (added.empty()) - return; // Early exit if all spills were folded. - - // Merge added with unhandled. Note that we know that - // addIntervalsForSpills returns intervals sorted by their starting - // point. - for (unsigned i = 0, e = added.size(); i != e; ++i) - unhandled_.push(added[i]); - return; - } - - // push the current interval back to unhandled since we are going - // to re-run at least this iteration. Since we didn't modify it it - // should go back right in the front of the list - unhandled_.push(cur); - - // otherwise we spill all intervals aliasing the register with - // minimum weight, rollback to the interval with the earliest - // start point and let the linear scan algorithm run again - std::vector added; - assert(MRegisterInfo::isPhysicalRegister(minReg) && - "did not choose a register to spill?"); - std::vector toSpill(mri_->getNumRegs(), false); - // we are going to spill minReg and all its aliases - toSpill[minReg] = true; - for (const unsigned* as = mri_->getAliasSet(minReg); *as; ++as) - toSpill[*as] = true; - - // the earliest start of a spilled interval indicates up to where - // in handled we need to roll back - unsigned earliestStart = cur->start(); - - // set of spilled vregs (used later to rollback properly) - std::set spilled; - - // spill live intervals of virtual regs mapped to the physical - // register we want to clear (and its aliases). we only spill - // those that overlap with the current interval as the rest do not - // affect its allocation. we also keep track of the earliest start - // of all spilled live intervals since this will mark our rollback - // point - for (IntervalPtrs::iterator - i = active_.begin(); i != active_.end(); ++i) { - unsigned reg = (*i)->reg; - if (MRegisterInfo::isVirtualRegister(reg) && - toSpill[vrm_->getPhys(reg)] && - cur->overlaps(**i)) { - DEBUG(std::cerr << "\t\t\tspilling(a): " << **i << '\n'); - earliestStart = std::min(earliestStart, (*i)->start()); - int slot = vrm_->assignVirt2StackSlot((*i)->reg); - std::vector newIs = - li_->addIntervalsForSpills(**i, *vrm_, slot); - std::copy(newIs.begin(), newIs.end(), std::back_inserter(added)); - spilled.insert(reg); - } - } - for (IntervalPtrs::iterator - i = inactive_.begin(); i != inactive_.end(); ++i) { - unsigned reg = (*i)->reg; - if (MRegisterInfo::isVirtualRegister(reg) && - toSpill[vrm_->getPhys(reg)] && - cur->overlaps(**i)) { - DEBUG(std::cerr << "\t\t\tspilling(i): " << **i << '\n'); - earliestStart = std::min(earliestStart, (*i)->start()); - int slot = vrm_->assignVirt2StackSlot((*i)->reg); - std::vector newIs = - li_->addIntervalsForSpills(**i, *vrm_, slot); - std::copy(newIs.begin(), newIs.end(), std::back_inserter(added)); - spilled.insert(reg); - } - } - - DEBUG(std::cerr << "\t\trolling back to: " << earliestStart << '\n'); - // scan handled in reverse order up to the earliaset start of a - // spilled live interval and undo each one, restoring the state of - // unhandled - while (!handled_.empty()) { - LiveInterval* i = handled_.back(); - // if this interval starts before t we are done - if (i->start() < earliestStart) - break; - DEBUG(std::cerr << "\t\t\tundo changes for: " << *i << '\n'); - handled_.pop_back(); - // when undoing a live interval allocation we must know if it - // is active or inactive to properly update the PhysRegTracker - // and the VirtRegMap - IntervalPtrs::iterator it; - if ((it = find(active_.begin(), active_.end(), i)) != active_.end()) { - active_.erase(it); - if (MRegisterInfo::isPhysicalRegister(i->reg)) { - prt_->delRegUse(i->reg); - unhandled_.push(i); - } - else { - if (!spilled.count(i->reg)) - unhandled_.push(i); - prt_->delRegUse(vrm_->getPhys(i->reg)); - vrm_->clearVirt(i->reg); - } - } - else if ((it = find(inactive_.begin(), inactive_.end(), i)) != inactive_.end()) { - inactive_.erase(it); - if (MRegisterInfo::isPhysicalRegister(i->reg)) - unhandled_.push(i); - else { - if (!spilled.count(i->reg)) - unhandled_.push(i); - vrm_->clearVirt(i->reg); - } - } - else { - if (MRegisterInfo::isVirtualRegister(i->reg)) - vrm_->clearVirt(i->reg); - unhandled_.push(i); - } - } - - // scan the rest and undo each interval that expired after t and - // insert it in active (the next iteration of the algorithm will - // put it in inactive if required) - IntervalPtrs::iterator i = handled_.begin(), e = handled_.end(); - for (; i != e; ++i) { - if (!(*i)->expiredAt(earliestStart) && (*i)->expiredAt(cur->start())) { - DEBUG(std::cerr << "\t\t\tundo changes for: " << **i << '\n'); - active_.push_back(*i); - if (MRegisterInfo::isPhysicalRegister((*i)->reg)) - prt_->addRegUse((*i)->reg); - else - prt_->addRegUse(vrm_->getPhys((*i)->reg)); - } - } - - std::sort(added.begin(), added.end(), less_ptr()); - // merge added with unhandled + // Merge added with unhandled. Note that we know that + // addIntervalsForSpills returns intervals sorted by their starting + // point. for (unsigned i = 0, e = added.size(); i != e; ++i) - unhandled_.push(added[i]); + unhandled_.push(added[i]); + return; + } + + // push the current interval back to unhandled since we are going + // to re-run at least this iteration. Since we didn't modify it it + // should go back right in the front of the list + unhandled_.push(cur); + + // otherwise we spill all intervals aliasing the register with + // minimum weight, rollback to the interval with the earliest + // start point and let the linear scan algorithm run again + std::vector added; + assert(MRegisterInfo::isPhysicalRegister(minReg) && + "did not choose a register to spill?"); + std::vector toSpill(mri_->getNumRegs(), false); + // we are going to spill minReg and all its aliases + toSpill[minReg] = true; + for (const unsigned* as = mri_->getAliasSet(minReg); *as; ++as) + toSpill[*as] = true; + + // the earliest start of a spilled interval indicates up to where + // in handled we need to roll back + unsigned earliestStart = cur->start(); + + // set of spilled vregs (used later to rollback properly) + std::set spilled; + + // spill live intervals of virtual regs mapped to the physical + // register we want to clear (and its aliases). we only spill + // those that overlap with the current interval as the rest do not + // affect its allocation. we also keep track of the earliest start + // of all spilled live intervals since this will mark our rollback + // point + for (IntervalPtrs::iterator + i = active_.begin(); i != active_.end(); ++i) { + unsigned reg = (*i)->reg; + if (MRegisterInfo::isVirtualRegister(reg) && + toSpill[vrm_->getPhys(reg)] && + cur->overlaps(**i)) { + DEBUG(std::cerr << "\t\t\tspilling(a): " << **i << '\n'); + earliestStart = std::min(earliestStart, (*i)->start()); + int slot = vrm_->assignVirt2StackSlot((*i)->reg); + std::vector newIs = + li_->addIntervalsForSpills(**i, *vrm_, slot); + std::copy(newIs.begin(), newIs.end(), std::back_inserter(added)); + spilled.insert(reg); + } + } + for (IntervalPtrs::iterator + i = inactive_.begin(); i != inactive_.end(); ++i) { + unsigned reg = (*i)->reg; + if (MRegisterInfo::isVirtualRegister(reg) && + toSpill[vrm_->getPhys(reg)] && + cur->overlaps(**i)) { + DEBUG(std::cerr << "\t\t\tspilling(i): " << **i << '\n'); + earliestStart = std::min(earliestStart, (*i)->start()); + int slot = vrm_->assignVirt2StackSlot((*i)->reg); + std::vector newIs = + li_->addIntervalsForSpills(**i, *vrm_, slot); + std::copy(newIs.begin(), newIs.end(), std::back_inserter(added)); + spilled.insert(reg); + } + } + + DEBUG(std::cerr << "\t\trolling back to: " << earliestStart << '\n'); + // scan handled in reverse order up to the earliaset start of a + // spilled live interval and undo each one, restoring the state of + // unhandled + while (!handled_.empty()) { + LiveInterval* i = handled_.back(); + // if this interval starts before t we are done + if (i->start() < earliestStart) + break; + DEBUG(std::cerr << "\t\t\tundo changes for: " << *i << '\n'); + handled_.pop_back(); + // when undoing a live interval allocation we must know if it + // is active or inactive to properly update the PhysRegTracker + // and the VirtRegMap + IntervalPtrs::iterator it; + if ((it = find(active_.begin(), active_.end(), i)) != active_.end()) { + active_.erase(it); + if (MRegisterInfo::isPhysicalRegister(i->reg)) { + prt_->delRegUse(i->reg); + unhandled_.push(i); + } + else { + if (!spilled.count(i->reg)) + unhandled_.push(i); + prt_->delRegUse(vrm_->getPhys(i->reg)); + vrm_->clearVirt(i->reg); + } + } + else if ((it = find(inactive_.begin(), inactive_.end(), i)) != inactive_.end()) { + inactive_.erase(it); + if (MRegisterInfo::isPhysicalRegister(i->reg)) + unhandled_.push(i); + else { + if (!spilled.count(i->reg)) + unhandled_.push(i); + vrm_->clearVirt(i->reg); + } + } + else { + if (MRegisterInfo::isVirtualRegister(i->reg)) + vrm_->clearVirt(i->reg); + unhandled_.push(i); + } + } + + // scan the rest and undo each interval that expired after t and + // insert it in active (the next iteration of the algorithm will + // put it in inactive if required) + IntervalPtrs::iterator i = handled_.begin(), e = handled_.end(); + for (; i != e; ++i) { + if (!(*i)->expiredAt(earliestStart) && (*i)->expiredAt(cur->start())) { + DEBUG(std::cerr << "\t\t\tundo changes for: " << **i << '\n'); + active_.push_back(*i); + if (MRegisterInfo::isPhysicalRegister((*i)->reg)) + prt_->addRegUse((*i)->reg); + else + prt_->addRegUse(vrm_->getPhys((*i)->reg)); + } + } + + std::sort(added.begin(), added.end(), less_ptr()); + // merge added with unhandled + for (unsigned i = 0, e = added.size(); i != e; ++i) + unhandled_.push(added[i]); } unsigned RA::getFreePhysReg(LiveInterval* cur) { - const TargetRegisterClass* rc = mf_->getSSARegMap()->getRegClass(cur->reg); + const TargetRegisterClass* rc = mf_->getSSARegMap()->getRegClass(cur->reg); - for (TargetRegisterClass::iterator i = rc->allocation_order_begin(*mf_); - i != rc->allocation_order_end(*mf_); ++i) { - unsigned reg = *i; - if (prt_->isRegAvail(reg)) - return reg; - } - return 0; + for (TargetRegisterClass::iterator i = rc->allocation_order_begin(*mf_); + i != rc->allocation_order_end(*mf_); ++i) { + unsigned reg = *i; + if (prt_->isRegAvail(reg)) + return reg; + } + return 0; } FunctionPass* llvm::createLinearScanRegisterAllocator() { - return new RA(); + return new RA(); }