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
This commit is contained in:
Alkis Evlogimenos 2004-05-30 07:24:39 +00:00
parent 25d4b54f93
commit 26f5a69e52
4 changed files with 89 additions and 60 deletions

View File

@ -80,9 +80,9 @@ namespace llvm {
} }
}; };
struct EndPointComp { struct StartPointPtrComp {
bool operator()(const Interval& lhs, const Interval& rhs) { bool operator()(const Interval* lhs, const Interval* rhs) {
return lhs.ranges.back().second < rhs.ranges.back().second; return lhs->ranges.front().first < rhs->ranges.front().first;
} }
}; };
@ -164,7 +164,9 @@ namespace llvm {
Intervals& getIntervals() { return intervals_; } Intervals& getIntervals() { return intervals_; }
void updateSpilledInterval(Interval& i, VirtRegMap& vrm, int slot); std::vector<Interval*> addIntervalsForSpills(const Interval& i,
VirtRegMap& vrm,
int slot);
private: private:
/// computeIntervals - compute live intervals /// computeIntervals - compute live intervals

View File

@ -186,19 +186,23 @@ bool LiveIntervals::runOnMachineFunction(MachineFunction &fn) {
return true; return true;
} }
void LiveIntervals::updateSpilledInterval(Interval& li, std::vector<LiveIntervals::Interval*>
LiveIntervals::addIntervalsForSpills(const Interval& li,
VirtRegMap& vrm, VirtRegMap& vrm,
int slot) int slot)
{ {
std::vector<Interval*> added;
assert(li.weight != HUGE_VAL && assert(li.weight != HUGE_VAL &&
"attempt to spill already spilled interval!"); "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');
for (Interval::Ranges::iterator i = oldRanges.begin(), e = oldRanges.end(); const TargetRegisterClass* rc = mf_->getSSARegMap()->getRegClass(li.reg);
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 index = getBaseIndex(i->first);
unsigned end = getBaseIndex(i->second-1) + InstrSlots::NUM; unsigned end = getBaseIndex(i->second-1) + InstrSlots::NUM;
for (; index < end; index += InstrSlots::NUM) { for (; index < end; index += InstrSlots::NUM) {
@ -240,16 +244,31 @@ void LiveIntervals::updateSpilledInterval(Interval& li,
unsigned end = 1 + (mop.isDef() ? unsigned end = 1 + (mop.isDef() ?
getUseIndex(index+InstrSlots::NUM) : getUseIndex(index+InstrSlots::NUM) :
getUseIndex(index)); 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; return added;
DEBUG(std::cerr << '\n');
DEBUG(std::cerr << "\t\t\t\tupdated interval: " << li << '\n');
} }
void LiveIntervals::printRegName(unsigned reg) const void LiveIntervals::printRegName(unsigned reg) const

View File

@ -80,9 +80,9 @@ namespace llvm {
} }
}; };
struct EndPointComp { struct StartPointPtrComp {
bool operator()(const Interval& lhs, const Interval& rhs) { bool operator()(const Interval* lhs, const Interval* rhs) {
return lhs.ranges.back().second < rhs.ranges.back().second; return lhs->ranges.front().first < rhs->ranges.front().first;
} }
}; };
@ -164,7 +164,9 @@ namespace llvm {
Intervals& getIntervals() { return intervals_; } Intervals& getIntervals() { return intervals_; }
void updateSpilledInterval(Interval& i, VirtRegMap& vrm, int slot); std::vector<Interval*> addIntervalsForSpills(const Interval& i,
VirtRegMap& vrm,
int slot);
private: private:
/// computeIntervals - compute live intervals /// computeIntervals - compute live intervals

View File

@ -27,6 +27,7 @@
#include <algorithm> #include <algorithm>
#include <cmath> #include <cmath>
#include <iostream> #include <iostream>
#include <set>
using namespace llvm; using namespace llvm;
@ -366,24 +367,26 @@ void RA::assignRegOrStackSlotAtInterval(IntervalPtrs::value_type cur)
DEBUG(std::cerr << "\t\tregister with min weight: " DEBUG(std::cerr << "\t\tregister with min weight: "
<< mri_->getName(minReg) << " (" << minWeight << ")\n"); << mri_->getName(minReg) << " (" << minWeight << ")\n");
// if the current has the minimum weight, we need to modify it, // if the current has the minimum weight, we need to spill it and
// push it back in unhandled and let the linear scan algorithm run // add any added intervals back to unhandled, and restart
// again // linearscan.
if (cur->weight <= minWeight) { if (cur->weight <= minWeight) {
DEBUG(std::cerr << "\t\t\tspilling(c): " << *cur << '\n';); DEBUG(std::cerr << "\t\t\tspilling(c): " << *cur << '\n';);
int slot = vrm_->assignVirt2StackSlot(cur->reg); int slot = vrm_->assignVirt2StackSlot(cur->reg);
li_->updateSpilledInterval(*cur, *vrm_, slot); std::vector<LiveIntervals::Interval*> added =
li_->addIntervalsForSpills(*cur, *vrm_, slot);
// if we didn't eliminate the interval find where to add it // merge added with unhandled
// back to unhandled. We need to scan since unhandled are std::vector<LiveIntervals::Interval*>::iterator addedIt = added.begin();
// sorted on earliest start point and we may have changed our std::vector<LiveIntervals::Interval*>::iterator addedItEnd = added.end();
// start point. for (IntervalPtrs::iterator i = unhandled_.begin(), e = unhandled_.end();
if (!cur->empty()) { i != e && addedIt != addedItEnd; ++i) {
IntervalPtrs::iterator it = unhandled_.begin(); if ((*i)->start() > (*addedIt)->start())
while (it != unhandled_.end() && (*it)->start() < cur->start()) i = unhandled_.insert(i, *(addedIt++));
++it;
unhandled_.insert(it, cur);
} }
while (addedIt != addedItEnd)
unhandled_.push_back(*(addedIt++));
return; return;
} }
@ -395,6 +398,7 @@ void RA::assignRegOrStackSlotAtInterval(IntervalPtrs::value_type cur)
// otherwise we spill all intervals aliasing the register with // otherwise we spill all intervals aliasing the register with
// minimum weight, rollback to the interval with the earliest // minimum weight, rollback to the interval with the earliest
// start point and let the linear scan algorithm run again // start point and let the linear scan algorithm run again
std::vector<LiveIntervals::Interval*> added;
assert(MRegisterInfo::isPhysicalRegister(minReg) && assert(MRegisterInfo::isPhysicalRegister(minReg) &&
"did not choose a register to spill?"); "did not choose a register to spill?");
std::vector<bool> toSpill(mri_->getNumRegs(), false); std::vector<bool> toSpill(mri_->getNumRegs(), false);
@ -403,6 +407,8 @@ void RA::assignRegOrStackSlotAtInterval(IntervalPtrs::value_type cur)
toSpill[*as] = true; toSpill[*as] = true;
unsigned earliestStart = cur->start(); unsigned earliestStart = cur->start();
std::set<unsigned> spilled;
for (IntervalPtrs::iterator i = active_.begin(); i != active_.end(); ++i) { for (IntervalPtrs::iterator i = active_.begin(); i != active_.end(); ++i) {
unsigned reg = (*i)->reg; unsigned reg = (*i)->reg;
if (MRegisterInfo::isVirtualRegister(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'); DEBUG(std::cerr << "\t\t\tspilling(a): " << **i << '\n');
earliestStart = std::min(earliestStart, (*i)->start()); earliestStart = std::min(earliestStart, (*i)->start());
int slot = vrm_->assignVirt2StackSlot((*i)->reg); 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(); 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'); DEBUG(std::cerr << "\t\t\tspilling(i): " << **i << '\n');
earliestStart = std::min(earliestStart, (*i)->start()); earliestStart = std::min(earliestStart, (*i)->start());
int slot = vrm_->assignVirt2StackSlot((*i)->reg); 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()) { while (!handled_.empty()) {
IntervalPtrs::value_type i = handled_.back(); IntervalPtrs::value_type i = handled_.back();
// if this interval starts before t we are done // if this interval starts before t we are done
if (!i->empty() && i->start() < earliestStart) if (i->start() < earliestStart)
break; break;
DEBUG(std::cerr << "\t\t\tundo changes for: " << *i << '\n'); DEBUG(std::cerr << "\t\t\tundo changes for: " << *i << '\n');
handled_.pop_back(); handled_.pop_back();
@ -445,20 +457,10 @@ void RA::assignRegOrStackSlotAtInterval(IntervalPtrs::value_type cur)
unhandled_.push_front(i); unhandled_.push_front(i);
} }
else { else {
if (!spilled.count(i->reg))
unhandled_.push_front(i);
prt_->delRegUse(vrm_->getPhys(i->reg)); prt_->delRegUse(vrm_->getPhys(i->reg));
vrm_->clearVirt(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()) { 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)) if (MRegisterInfo::isPhysicalRegister(i->reg))
unhandled_.push_front(i); unhandled_.push_front(i);
else { else {
vrm_->clearVirt(i->reg); if (!spilled.count(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); unhandled_.push_front(i);
vrm_->clearVirt(i->reg);
} }
} }
else { else {
@ -501,6 +494,19 @@ void RA::assignRegOrStackSlotAtInterval(IntervalPtrs::value_type cur)
prt_->addRegUse(vrm_->getPhys((*i)->reg)); 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) unsigned RA::getFreePhysReg(IntervalPtrs::value_type cur)