diff --git a/include/llvm/CodeGen/LiveIntervalAnalysis.h b/include/llvm/CodeGen/LiveIntervalAnalysis.h index c9db013d976..c1fa5c591fb 100644 --- a/include/llvm/CodeGen/LiveIntervalAnalysis.h +++ b/include/llvm/CodeGen/LiveIntervalAnalysis.h @@ -22,7 +22,6 @@ #include "llvm/CodeGen/MachineFunctionPass.h" #include "LiveInterval.h" -#include namespace llvm { @@ -30,17 +29,10 @@ namespace llvm { class MRegisterInfo; class VirtRegMap; - class LiveIntervals : public MachineFunctionPass - { - public: - typedef std::list Intervals; - - private: + class LiveIntervals : public MachineFunctionPass { MachineFunction* mf_; const TargetMachine* tm_; const MRegisterInfo* mri_; - MachineBasicBlock* currentMbb_; - MachineBasicBlock::iterator currentInstr_; LiveVariables* lv_; typedef std::map Mi2IndexMap; @@ -49,14 +41,14 @@ namespace llvm { typedef std::vector Index2MiMap; Index2MiMap i2miMap_; - typedef std::map Reg2IntervalMap; - Reg2IntervalMap r2iMap_; + /// r2iMap_ - This map OWNS the interval pointed to by the map. When + /// this map is destroyed or when entries are modified, this intervals + /// should be destroyed or modified as well. + std::map r2iMap_; typedef std::map Reg2RegMap; Reg2RegMap r2rMap_; - Intervals intervals_; - public: struct InstrSlots { @@ -88,15 +80,15 @@ namespace llvm { return getBaseIndex(index) + InstrSlots::STORE; } - virtual void getAnalysisUsage(AnalysisUsage &AU) const; - virtual void releaseMemory(); + typedef std::map::const_iterator iterator; + iterator begin() const { return r2iMap_.begin(); } + iterator end() const { return r2iMap_.end(); } + unsigned getNumIntervals() const { return r2iMap_.size(); } - /// runOnMachineFunction - pass entry point - virtual bool runOnMachineFunction(MachineFunction&); - - LiveInterval& getInterval(unsigned reg) { - Reg2IntervalMap::iterator I = r2iMap_.find(reg); - assert(I != r2iMap_.end()&& "Interval does not exist for register"); + LiveInterval &getInterval(unsigned reg) const { + std::map::const_iterator I = + r2iMap_.find(reg); + assert(I != r2iMap_.end() && "Interval does not exist for register"); return *I->second; } @@ -116,12 +108,16 @@ namespace llvm { return i2miMap_[index]; } - Intervals& getIntervals() { return intervals_; } - 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(); @@ -159,8 +155,14 @@ namespace llvm { bool overlapsAliases(const LiveInterval *lhs, const LiveInterval *rhs) const; + LiveInterval *createInterval(unsigned Reg) const; - LiveInterval& getOrCreateInterval(unsigned reg); + LiveInterval &getOrCreateInterval(unsigned reg) { + LiveInterval *&LI = r2iMap_[reg]; + if (LI == 0) + LI = createInterval(reg); + return *LI; + } /// rep - returns the representative of this register unsigned rep(unsigned reg) { diff --git a/lib/CodeGen/LiveIntervalAnalysis.cpp b/lib/CodeGen/LiveIntervalAnalysis.cpp index 0b31e227cbb..2b1184cf1c1 100644 --- a/lib/CodeGen/LiveIntervalAnalysis.cpp +++ b/lib/CodeGen/LiveIntervalAnalysis.cpp @@ -76,9 +76,12 @@ void LiveIntervals::releaseMemory() { mi2iMap_.clear(); i2miMap_.clear(); + for (std::map::iterator I = r2iMap_.begin(), + E = r2iMap_.end(); I != E; ++I) + delete I->second; // free all intervals. r2iMap_.clear(); + r2rMap_.clear(); - intervals_.clear(); } @@ -104,18 +107,18 @@ bool LiveIntervals::runOnMachineFunction(MachineFunction &fn) { computeIntervals(); - numIntervals += intervals_.size(); + numIntervals += getNumIntervals(); #if 1 DEBUG(std::cerr << "********** INTERVALS **********\n"); - DEBUG(std::copy(intervals_.begin(), intervals_.end(), - std::ostream_iterator(std::cerr, "\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 += intervals_.size(); + numIntervalsAfter += getNumIntervals(); // perform a final pass over the instructions and compute spill // weights, coalesce virtual registers and remove identity moves @@ -130,11 +133,11 @@ bool LiveIntervals::runOnMachineFunction(MachineFunction &fn) { for (MachineBasicBlock::iterator mii = mbb->begin(), mie = mbb->end(); mii != mie; ) { // if the move will be an identity move delete it - unsigned srcReg, dstReg; + unsigned srcReg, dstReg, RegRep; if (tii.isMoveInstr(*mii, srcReg, dstReg) && - rep(srcReg) == rep(dstReg)) { + (RegRep = rep(srcReg)) == rep(dstReg)) { // remove from def list - LiveInterval& interval = getOrCreateInterval(rep(dstReg)); + LiveInterval &interval = getOrCreateInterval(RegRep); // remove index -> MachineInstr and // MachineInstr -> index mappings Mi2IndexMap::iterator mi2i = mi2iMap_.find(mii); @@ -154,9 +157,8 @@ bool LiveIntervals::runOnMachineFunction(MachineFunction &fn) { unsigned reg = rep(mop.getReg()); mii->SetMachineOperandReg(i, reg); - Reg2IntervalMap::iterator r2iit = r2iMap_.find(reg); - assert(r2iit != r2iMap_.end()); - r2iit->second->weight += + LiveInterval &RegInt = getInterval(reg); + RegInt.weight += (mop.isUse() + mop.isDef()) * pow(10.0F, loopDepth); } } @@ -166,8 +168,8 @@ bool LiveIntervals::runOnMachineFunction(MachineFunction &fn) { } DEBUG(std::cerr << "********** INTERVALS **********\n"); - DEBUG(std::copy(intervals_.begin(), intervals_.end(), - std::ostream_iterator(std::cerr, "\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(); @@ -548,6 +550,8 @@ void LiveIntervals::joinIntervalsInMachineBB(MachineBasicBlock *MBB) { assert(IntA.reg == regA && IntB.reg == regB && "Register mapping is horribly broken!"); + // If two intervals contain a single value and are joined by a copy, it + // does not matter if the intervals overlap, they can always be joined. bool TriviallyJoinable = IntA.containsOneValue() && IntB.containsOneValue(); @@ -555,19 +559,18 @@ void LiveIntervals::joinIntervalsInMachineBB(MachineBasicBlock *MBB) { if ((TriviallyJoinable || !IntB.joinable(IntA, MIDefIdx)) && !overlapsAliases(&IntA, &IntB)) { IntB.join(IntA, MIDefIdx); - - // FIXME: Turn 'intervals_' into an ilist so we don't need to do these - // map lookups! - intervals_.erase(r2iMap_[regA]); - r2iMap_[regA] = r2iMap_[regB]; + delete r2iMap_[regA]; // Delete the dead interval if (!MRegisterInfo::isPhysicalRegister(regA)) { + r2iMap_.erase(regA); r2rMap_[regA] = regB; } else { // Otherwise merge the data structures the other way so we don't lose // the physreg information. r2rMap_[regB] = regA; IntB.reg = regA; + r2iMap_[regA] = r2iMap_[regB]; + r2iMap_.erase(regB); } DEBUG(std::cerr << "Joined. Result = " << IntB << "\n"); ++numJoins; @@ -649,25 +652,15 @@ bool LiveIntervals::overlapsAliases(const LiveInterval *LHS, MRegisterInfo::isVirtualRegister(RHS->reg) && "first interval must describe a physical register"); - for (const unsigned *AS = mri_->getAliasSet(LHS->reg); *AS; ++AS) { - Reg2IntervalMap::const_iterator r2i = r2iMap_.find(*AS); - assert(r2i != r2iMap_.end() && "alias does not have interval?"); - if (RHS->overlaps(*r2i->second)) - return true; - } + for (const unsigned *AS = mri_->getAliasSet(LHS->reg); *AS; ++AS) + if (RHS->overlaps(getInterval(*AS))) + return true; - return false; + return false; } -LiveInterval& LiveIntervals::getOrCreateInterval(unsigned reg) -{ - Reg2IntervalMap::iterator r2iit = r2iMap_.lower_bound(reg); - if (r2iit == r2iMap_.end() || r2iit->first != reg) { - float Weight = MRegisterInfo::isPhysicalRegister(reg) ? HUGE_VAL :0.0F; - intervals_.push_back(LiveInterval(reg, Weight)); - r2iit = r2iMap_.insert(r2iit, std::make_pair(reg, --intervals_.end())); - } - - return *r2iit->second; +LiveInterval *LiveIntervals::createInterval(unsigned reg) const { + float Weight = MRegisterInfo::isPhysicalRegister(reg) ? HUGE_VAL :0.0F; + return new LiveInterval(reg, Weight); } diff --git a/lib/CodeGen/LiveIntervalAnalysis.h b/lib/CodeGen/LiveIntervalAnalysis.h index c9db013d976..c1fa5c591fb 100644 --- a/lib/CodeGen/LiveIntervalAnalysis.h +++ b/lib/CodeGen/LiveIntervalAnalysis.h @@ -22,7 +22,6 @@ #include "llvm/CodeGen/MachineFunctionPass.h" #include "LiveInterval.h" -#include namespace llvm { @@ -30,17 +29,10 @@ namespace llvm { class MRegisterInfo; class VirtRegMap; - class LiveIntervals : public MachineFunctionPass - { - public: - typedef std::list Intervals; - - private: + class LiveIntervals : public MachineFunctionPass { MachineFunction* mf_; const TargetMachine* tm_; const MRegisterInfo* mri_; - MachineBasicBlock* currentMbb_; - MachineBasicBlock::iterator currentInstr_; LiveVariables* lv_; typedef std::map Mi2IndexMap; @@ -49,14 +41,14 @@ namespace llvm { typedef std::vector Index2MiMap; Index2MiMap i2miMap_; - typedef std::map Reg2IntervalMap; - Reg2IntervalMap r2iMap_; + /// r2iMap_ - This map OWNS the interval pointed to by the map. When + /// this map is destroyed or when entries are modified, this intervals + /// should be destroyed or modified as well. + std::map r2iMap_; typedef std::map Reg2RegMap; Reg2RegMap r2rMap_; - Intervals intervals_; - public: struct InstrSlots { @@ -88,15 +80,15 @@ namespace llvm { return getBaseIndex(index) + InstrSlots::STORE; } - virtual void getAnalysisUsage(AnalysisUsage &AU) const; - virtual void releaseMemory(); + typedef std::map::const_iterator iterator; + iterator begin() const { return r2iMap_.begin(); } + iterator end() const { return r2iMap_.end(); } + unsigned getNumIntervals() const { return r2iMap_.size(); } - /// runOnMachineFunction - pass entry point - virtual bool runOnMachineFunction(MachineFunction&); - - LiveInterval& getInterval(unsigned reg) { - Reg2IntervalMap::iterator I = r2iMap_.find(reg); - assert(I != r2iMap_.end()&& "Interval does not exist for register"); + LiveInterval &getInterval(unsigned reg) const { + std::map::const_iterator I = + r2iMap_.find(reg); + assert(I != r2iMap_.end() && "Interval does not exist for register"); return *I->second; } @@ -116,12 +108,16 @@ namespace llvm { return i2miMap_[index]; } - Intervals& getIntervals() { return intervals_; } - 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(); @@ -159,8 +155,14 @@ namespace llvm { bool overlapsAliases(const LiveInterval *lhs, const LiveInterval *rhs) const; + LiveInterval *createInterval(unsigned Reg) const; - LiveInterval& getOrCreateInterval(unsigned reg); + LiveInterval &getOrCreateInterval(unsigned reg) { + LiveInterval *&LI = r2iMap_[reg]; + if (LI == 0) + LI = createInterval(reg); + return *LI; + } /// rep - returns the representative of this register unsigned rep(unsigned reg) { diff --git a/lib/CodeGen/RegAllocIterativeScan.cpp b/lib/CodeGen/RegAllocIterativeScan.cpp index 5e62bcad34c..d2f5d5b0bfe 100644 --- a/lib/CodeGen/RegAllocIterativeScan.cpp +++ b/lib/CodeGen/RegAllocIterativeScan.cpp @@ -85,7 +85,7 @@ namespace { /// initIntervalSets - initializes the four interval sets: /// unhandled, fixed, active and inactive - void initIntervalSets(LiveIntervals::Intervals& li); + void initIntervalSets(); /// processActiveIntervals - expire old intervals and move /// non-overlapping ones to the incative list @@ -151,9 +151,9 @@ bool RA::runOnMachineFunction(MachineFunction &fn) { vrm_.reset(new VirtRegMap(*mf_)); if (!spiller_.get()) spiller_.reset(createSpiller()); - initIntervalSets(li_->getIntervals()); + initIntervalSets(); - numIntervals += li_->getIntervals().size(); + numIntervals += li_->getNumIntervals(); while (linearScan()) { // we spilled some registers, so we need to add intervals for @@ -251,17 +251,15 @@ bool RA::linearScan() return !spilled_.empty(); } -void RA::initIntervalSets(LiveIntervals::Intervals& li) -{ +void RA::initIntervalSets() { assert(unhandled_.empty() && fixed_.empty() && active_.empty() && inactive_.empty() && "interval sets should be empty on initialization"); - for (LiveIntervals::Intervals::iterator i = li.begin(), e = li.end(); - i != e; ++i) { - unhandled_.push_back(&*i); - if (MRegisterInfo::isPhysicalRegister(i->reg)) - fixed_.push_back(&*i); + 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); } } diff --git a/lib/CodeGen/RegAllocLinearScan.cpp b/lib/CodeGen/RegAllocLinearScan.cpp index 51b73c690e3..382cff4ad7c 100644 --- a/lib/CodeGen/RegAllocLinearScan.cpp +++ b/lib/CodeGen/RegAllocLinearScan.cpp @@ -82,7 +82,7 @@ namespace { /// initIntervalSets - initializa the four interval sets: /// unhandled, fixed, active and inactive - void initIntervalSets(LiveIntervals::Intervals& li); + void initIntervalSets(); /// processActiveIntervals - expire old intervals and move /// non-overlapping ones to the incative list @@ -146,7 +146,7 @@ bool RA::runOnMachineFunction(MachineFunction &fn) { vrm_.reset(new VirtRegMap(*mf_)); if (!spiller_.get()) spiller_.reset(createSpiller()); - initIntervalSets(li_->getIntervals()); + initIntervalSets(); linearScan(); @@ -193,7 +193,7 @@ void RA::linearScan() DEBUG(printIntervals("active", active_.begin(), active_.end())); DEBUG(printIntervals("inactive", inactive_.begin(), inactive_.end())); } - numIntervals += li_->getIntervals().size(); + numIntervals += li_->getNumIntervals(); efficiency = double(numIterations) / double(numIntervals); // expire any remaining active intervals @@ -217,17 +217,16 @@ void RA::linearScan() DEBUG(std::cerr << *vrm_); } -void RA::initIntervalSets(LiveIntervals::Intervals& li) +void RA::initIntervalSets() { assert(unhandled_.empty() && fixed_.empty() && active_.empty() && inactive_.empty() && "interval sets should be empty on initialization"); - for (LiveIntervals::Intervals::iterator i = li.begin(), e = li.end(); - i != e; ++i) { - unhandled_.push(&*i); - if (MRegisterInfo::isPhysicalRegister(i->reg)) - fixed_.push_back(&*i); + 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); } }