diff options
author | Alkis Evlogimenos <alkis@evlogimenos.com> | 2004-05-30 07:24:39 +0000 |
---|---|---|
committer | Alkis Evlogimenos <alkis@evlogimenos.com> | 2004-05-30 07:24:39 +0000 |
commit | 26f5a69e52b64e035d26c135979a39b39fd6ba3e (patch) | |
tree | 271929c25d879599e107f41f0f1577433b22d59d /lib/CodeGen | |
parent | 25d4b54f93b121d0f6beb387e85e8b2670c02b48 (diff) |
When spilling an register, introduce a new temporary for each of its
spills. This allows for more flexibility when allocating registers for
spill code.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@13907 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/CodeGen')
-rw-r--r-- | lib/CodeGen/LiveIntervalAnalysis.cpp | 45 | ||||
-rw-r--r-- | lib/CodeGen/LiveIntervalAnalysis.h | 10 | ||||
-rw-r--r-- | lib/CodeGen/RegAllocLinearScan.cpp | 86 |
3 files changed, 84 insertions, 57 deletions
diff --git a/lib/CodeGen/LiveIntervalAnalysis.cpp b/lib/CodeGen/LiveIntervalAnalysis.cpp index 1dda527c85..e77babb136 100644 --- a/lib/CodeGen/LiveIntervalAnalysis.cpp +++ b/lib/CodeGen/LiveIntervalAnalysis.cpp @@ -186,19 +186,23 @@ bool LiveIntervals::runOnMachineFunction(MachineFunction &fn) { return true; } -void LiveIntervals::updateSpilledInterval(Interval& li, - VirtRegMap& vrm, - int slot) +std::vector<LiveIntervals::Interval*> +LiveIntervals::addIntervalsForSpills(const Interval& li, + VirtRegMap& vrm, + int slot) { + std::vector<Interval*> added; + assert(li.weight != HUGE_VAL && "attempt to spill already spilled interval!"); - Interval::Ranges oldRanges; - swap(oldRanges, li.ranges); - DEBUG(std::cerr << "\t\t\t\tupdating interval: " << li); + DEBUG(std::cerr << "\t\t\t\tadding intervals for spills for interval: " + << li << '\n'); + + const TargetRegisterClass* rc = mf_->getSSARegMap()->getRegClass(li.reg); - for (Interval::Ranges::iterator i = oldRanges.begin(), e = oldRanges.end(); - i != e; ++i) { + for (Interval::Ranges::const_iterator + i = li.ranges.begin(), e = li.ranges.end(); i != e; ++i) { unsigned index = getBaseIndex(i->first); unsigned end = getBaseIndex(i->second-1) + InstrSlots::NUM; for (; index < end; index += InstrSlots::NUM) { @@ -240,16 +244,31 @@ void LiveIntervals::updateSpilledInterval(Interval& li, unsigned end = 1 + (mop.isDef() ? getUseIndex(index+InstrSlots::NUM) : getUseIndex(index)); - li.addRange(start, end); + + // create a new register for this spill + unsigned nReg = + mf_->getSSARegMap()->createVirtualRegister(rc); + mi->SetMachineOperandReg(i, nReg); + vrm.grow(); + vrm.assignVirt2StackSlot(nReg, slot); + Interval& nI = getOrCreateInterval(nReg); + assert(nI.empty()); + // the spill weight is now infinity as it + // cannot be spilled again + nI.weight = HUGE_VAL; + nI.addRange(start, end); + added.push_back(&nI); + // update live variables + lv_->addVirtualRegisterKilled(nReg, mi->getParent(),mi); + DEBUG(std::cerr << "\t\t\t\tadded new interval: " + << nI << '\n'); } } } } } - // the new spill weight is now infinity as it cannot be spilled again - li.weight = HUGE_VAL; - DEBUG(std::cerr << '\n'); - DEBUG(std::cerr << "\t\t\t\tupdated interval: " << li << '\n'); + + return added; } void LiveIntervals::printRegName(unsigned reg) const diff --git a/lib/CodeGen/LiveIntervalAnalysis.h b/lib/CodeGen/LiveIntervalAnalysis.h index ee28cf6bd8..dda1637984 100644 --- a/lib/CodeGen/LiveIntervalAnalysis.h +++ b/lib/CodeGen/LiveIntervalAnalysis.h @@ -80,9 +80,9 @@ namespace llvm { } }; - struct EndPointComp { - bool operator()(const Interval& lhs, const Interval& rhs) { - return lhs.ranges.back().second < rhs.ranges.back().second; + struct StartPointPtrComp { + bool operator()(const Interval* lhs, const Interval* rhs) { + return lhs->ranges.front().first < rhs->ranges.front().first; } }; @@ -164,7 +164,9 @@ namespace llvm { Intervals& getIntervals() { return intervals_; } - void updateSpilledInterval(Interval& i, VirtRegMap& vrm, int slot); + std::vector<Interval*> addIntervalsForSpills(const Interval& i, + VirtRegMap& vrm, + int slot); private: /// computeIntervals - compute live intervals diff --git a/lib/CodeGen/RegAllocLinearScan.cpp b/lib/CodeGen/RegAllocLinearScan.cpp index ed7da0f8c8..d8dfaf90c3 100644 --- a/lib/CodeGen/RegAllocLinearScan.cpp +++ b/lib/CodeGen/RegAllocLinearScan.cpp @@ -27,6 +27,7 @@ #include <algorithm> #include <cmath> #include <iostream> +#include <set> using namespace llvm; @@ -366,24 +367,26 @@ void RA::assignRegOrStackSlotAtInterval(IntervalPtrs::value_type cur) DEBUG(std::cerr << "\t\tregister with min weight: " << mri_->getName(minReg) << " (" << minWeight << ")\n"); - // if the current has the minimum weight, we need to modify it, - // push it back in unhandled and let the linear scan algorithm run - // again + // 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); - li_->updateSpilledInterval(*cur, *vrm_, slot); - - // if we didn't eliminate the interval find where to add it - // back to unhandled. We need to scan since unhandled are - // sorted on earliest start point and we may have changed our - // start point. - if (!cur->empty()) { - IntervalPtrs::iterator it = unhandled_.begin(); - while (it != unhandled_.end() && (*it)->start() < cur->start()) - ++it; - unhandled_.insert(it, cur); + std::vector<LiveIntervals::Interval*> added = + li_->addIntervalsForSpills(*cur, *vrm_, slot); + + // merge added with unhandled + std::vector<LiveIntervals::Interval*>::iterator addedIt = added.begin(); + std::vector<LiveIntervals::Interval*>::iterator addedItEnd = added.end(); + for (IntervalPtrs::iterator i = unhandled_.begin(), e = unhandled_.end(); + i != e && addedIt != addedItEnd; ++i) { + if ((*i)->start() > (*addedIt)->start()) + i = unhandled_.insert(i, *(addedIt++)); } + while (addedIt != addedItEnd) + unhandled_.push_back(*(addedIt++)); + return; } @@ -395,6 +398,7 @@ void RA::assignRegOrStackSlotAtInterval(IntervalPtrs::value_type 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<LiveIntervals::Interval*> added; assert(MRegisterInfo::isPhysicalRegister(minReg) && "did not choose a register to spill?"); std::vector<bool> toSpill(mri_->getNumRegs(), false); @@ -403,6 +407,8 @@ void RA::assignRegOrStackSlotAtInterval(IntervalPtrs::value_type cur) toSpill[*as] = true; unsigned earliestStart = cur->start(); + std::set<unsigned> spilled; + for (IntervalPtrs::iterator i = active_.begin(); i != active_.end(); ++i) { unsigned reg = (*i)->reg; if (MRegisterInfo::isVirtualRegister(reg) && @@ -411,7 +417,10 @@ void RA::assignRegOrStackSlotAtInterval(IntervalPtrs::value_type cur) DEBUG(std::cerr << "\t\t\tspilling(a): " << **i << '\n'); earliestStart = std::min(earliestStart, (*i)->start()); int slot = vrm_->assignVirt2StackSlot((*i)->reg); - li_->updateSpilledInterval(**i, *vrm_, slot); + std::vector<LiveIntervals::Interval*> 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(); @@ -423,7 +432,10 @@ void RA::assignRegOrStackSlotAtInterval(IntervalPtrs::value_type cur) DEBUG(std::cerr << "\t\t\tspilling(i): " << **i << '\n'); earliestStart = std::min(earliestStart, (*i)->start()); int slot = vrm_->assignVirt2StackSlot((*i)->reg); - li_->updateSpilledInterval(**i, *vrm_, slot); + std::vector<LiveIntervals::Interval*> newIs = + li_->addIntervalsForSpills(**i, *vrm_, slot); + std::copy(newIs.begin(), newIs.end(), std::back_inserter(added)); + spilled.insert(reg); } } @@ -433,7 +445,7 @@ void RA::assignRegOrStackSlotAtInterval(IntervalPtrs::value_type cur) while (!handled_.empty()) { IntervalPtrs::value_type i = handled_.back(); // if this interval starts before t we are done - if (!i->empty() && i->start() < earliestStart) + if (i->start() < earliestStart) break; DEBUG(std::cerr << "\t\t\tundo changes for: " << *i << '\n'); handled_.pop_back(); @@ -445,20 +457,10 @@ void RA::assignRegOrStackSlotAtInterval(IntervalPtrs::value_type cur) unhandled_.push_front(i); } else { + if (!spilled.count(i->reg)) + unhandled_.push_front(i); prt_->delRegUse(vrm_->getPhys(i->reg)); vrm_->clearVirt(i->reg); - if (i->spilled()) { - if (!i->empty()) { - IntervalPtrs::iterator it = unhandled_.begin(); - while (it != unhandled_.end() && - (*it)->start() < i->start()) - ++it; - unhandled_.insert(it, i); - } - } - else - unhandled_.push_front(i); - } } else if ((it = find(inactive_.begin(), inactive_.end(), i)) != inactive_.end()) { @@ -466,18 +468,9 @@ void RA::assignRegOrStackSlotAtInterval(IntervalPtrs::value_type cur) if (MRegisterInfo::isPhysicalRegister(i->reg)) unhandled_.push_front(i); else { - vrm_->clearVirt(i->reg); - if (i->spilled()) { - if (!i->empty()) { - IntervalPtrs::iterator it = unhandled_.begin(); - while (it != unhandled_.end() && - (*it)->start() < i->start()) - ++it; - unhandled_.insert(it, i); - } - } - else + if (!spilled.count(i->reg)) unhandled_.push_front(i); + vrm_->clearVirt(i->reg); } } else { @@ -501,6 +494,19 @@ void RA::assignRegOrStackSlotAtInterval(IntervalPtrs::value_type cur) prt_->addRegUse(vrm_->getPhys((*i)->reg)); } } + + std::sort(added.begin(), added.end(), LiveIntervals::StartPointPtrComp()); + // merge added with unhandled + std::vector<LiveIntervals::Interval*>::iterator addedIt = added.begin(); + std::vector<LiveIntervals::Interval*>::iterator addedItEnd = added.end(); + for (IntervalPtrs::iterator i = unhandled_.begin(), e = unhandled_.end(); + i != e && addedIt != addedItEnd; ++i) { + if ((*i)->start() > (*addedIt)->start()) + i = unhandled_.insert(i, *(addedIt++)); + } + while (addedIt != addedItEnd) + unhandled_.push_back(*(addedIt++)); + } unsigned RA::getFreePhysReg(IntervalPtrs::value_type cur) |