diff options
-rw-r--r-- | include/llvm/CodeGen/LiveIntervalAnalysis.h | 304 | ||||
-rw-r--r-- | lib/CodeGen/LiveIntervalAnalysis.cpp | 823 | ||||
-rw-r--r-- | lib/CodeGen/LiveIntervalAnalysis.h | 304 | ||||
-rw-r--r-- | lib/CodeGen/RegAllocIterativeScan.cpp | 756 | ||||
-rw-r--r-- | lib/CodeGen/RegAllocLinearScan.cpp | 876 |
5 files changed, 1531 insertions, 1532 deletions
diff --git a/include/llvm/CodeGen/LiveIntervalAnalysis.h b/include/llvm/CodeGen/LiveIntervalAnalysis.h index e4e31ec249..de7cc8001f 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 LiveIntervals : public MachineFunctionPass { - MachineFunction* mf_; - const TargetMachine* tm_; - const MRegisterInfo* mri_; - LiveVariables* lv_; - - typedef std::map<MachineInstr*, unsigned> Mi2IndexMap; - Mi2IndexMap mi2iMap_; - - typedef std::vector<MachineInstr*> Index2MiMap; - Index2MiMap i2miMap_; - - typedef std::map<unsigned, LiveInterval> Reg2IntervalMap; - Reg2IntervalMap r2iMap_; - - typedef std::map<unsigned, unsigned> 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<LiveInterval*> 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; + class LiveVariables; + class MRegisterInfo; + class VirtRegMap; + + class LiveIntervals : public MachineFunctionPass { + MachineFunction* mf_; + const TargetMachine* tm_; + const MRegisterInfo* mri_; + LiveVariables* lv_; + + typedef std::map<MachineInstr*, unsigned> Mi2IndexMap; + Mi2IndexMap mi2iMap_; + + typedef std::vector<MachineInstr*> Index2MiMap; + Index2MiMap i2miMap_; + + typedef std::map<unsigned, LiveInterval> Reg2IntervalMap; + Reg2IntervalMap r2iMap_; + + typedef std::map<unsigned, unsigned> 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<LiveInterval*> 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 ed90fca3df..fc65e00138 100644 --- a/lib/CodeGen/LiveIntervalAnalysis.cpp +++ b/lib/CodeGen/LiveIntervalAnalysis.cpp @@ -37,447 +37,446 @@ using namespace llvm; namespace { - RegisterAnalysis<LiveIntervals> X("liveintervals", - "Live Interval Analysis"); + RegisterAnalysis<LiveIntervals> 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<bool> - EnableJoining("join-liveintervals", - cl::desc("Join compatible live intervals"), - cl::init(true)); + cl::opt<bool> + EnableJoining("join-liveintervals", + cl::desc("Join compatible live intervals"), + cl::init(true)); }; void LiveIntervals::getAnalysisUsage(AnalysisUsage &AU) const { - AU.addPreserved<LiveVariables>(); - AU.addRequired<LiveVariables>(); - AU.addPreservedID(PHIEliminationID); - AU.addRequiredID(PHIEliminationID); - AU.addRequiredID(TwoAddressInstructionPassID); - AU.addRequired<LoopInfo>(); - MachineFunctionPass::getAnalysisUsage(AU); + AU.addPreserved<LiveVariables>(); + AU.addRequired<LiveVariables>(); + AU.addPreservedID(PHIEliminationID); + AU.addRequiredID(PHIEliminationID); + AU.addRequiredID(TwoAddressInstructionPassID); + AU.addRequired<LoopInfo>(); + 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<LiveVariables>(); - - // 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; - } + mf_ = &fn; + tm_ = &fn.getTarget(); + mri_ = tm_->getRegisterInfo(); + lv_ = &getAnalysis<LiveVariables>(); + + // 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(); + computeIntervals(); - numIntervals += getNumIntervals(); + numIntervals += getNumIntervals(); #if 1 - DEBUG(std::cerr << "********** INTERVALS **********\n"); - DEBUG(for (iterator I = begin(), E = end(); I != E; ++I) - std::cerr << I->second << "\n"); + 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<LoopInfo>(); - const TargetInstrInfo& tii = *tm_->getInstrInfo(); + // 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<LoopInfo>(); + 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) { - 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; - } - } - } + 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_); + } + }); - 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; + return true; } std::vector<LiveInterval*> LiveIntervals::addIntervalsForSpills( - const LiveInterval& li, - VirtRegMap& vrm, - int slot) + const LiveInterval& li, + VirtRegMap& vrm, + int slot) { - std::vector<LiveInterval*> added; - - 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'); - - 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; - - 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)); - - // 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'); - } - } - } + std::vector<LiveInterval*> added; + + 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'); + + 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; + + 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)); + + // 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); - - // 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. - - // 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); - } + 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)); + + 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; + + // 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; + } + } - } 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, |