Change the way free regusters are computed and perform better

allocation in the presence of preallocated intervals.


git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@10595 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Alkis Evlogimenos 2003-12-23 18:00:33 +00:00
parent 1715ce00e4
commit 3bf564a95f

View File

@ -55,6 +55,7 @@ namespace {
RegMask reserved_; RegMask reserved_;
unsigned regUse_[MRegisterInfo::FirstVirtualRegister]; unsigned regUse_[MRegisterInfo::FirstVirtualRegister];
unsigned regUseBackup_[MRegisterInfo::FirstVirtualRegister];
typedef LiveIntervals::MachineBasicBlockPtrs MachineBasicBlockPtrs; typedef LiveIntervals::MachineBasicBlockPtrs MachineBasicBlockPtrs;
MachineBasicBlockPtrs mbbs_; MachineBasicBlockPtrs mbbs_;
@ -105,14 +106,6 @@ namespace {
/// register handling helpers /// register handling helpers
/// ///
/// reservePhysReg - reserves a physical register and spills
/// any value assigned to it if any
void reservePhysReg(unsigned reg);
/// clearReservedPhysReg - marks pysical register as free for
/// use
void clearReservedPhysReg(unsigned reg);
/// getFreePhysReg - return a free physical register for this /// getFreePhysReg - return a free physical register for this
/// virtual register interval if we have one, otherwise return /// virtual register interval if we have one, otherwise return
/// 0 /// 0
@ -159,6 +152,14 @@ namespace {
void markPhysRegFree(unsigned physReg); void markPhysRegFree(unsigned physReg);
void markPhysRegNotFree(unsigned physReg); void markPhysRegNotFree(unsigned physReg);
void backupRegUse() {
memcpy(regUseBackup_, regUse_, sizeof(regUseBackup_));
}
void restoreRegUse() {
memcpy(regUse_, regUseBackup_, sizeof(regUseBackup_));
}
void printVirt2PhysMap() const { void printVirt2PhysMap() const {
std::cerr << "allocated registers:\n"; std::cerr << "allocated registers:\n";
for (Virt2PhysMap::const_iterator for (Virt2PhysMap::const_iterator
@ -212,6 +213,7 @@ bool RA::runOnMachineFunction(MachineFunction &fn) {
v2pMap_.clear(); v2pMap_.clear();
v2ssMap_.clear(); v2ssMap_.clear();
memset(regUse_, 0, sizeof(regUse_)); memset(regUse_, 0, sizeof(regUse_));
memset(regUseBackup_, 0, sizeof(regUseBackup_));
DEBUG( DEBUG(
unsigned i = 0; unsigned i = 0;
@ -257,19 +259,37 @@ bool RA::runOnMachineFunction(MachineFunction &fn) {
DEBUG(printIntervals("\tactive", active_.begin(), active_.end())); DEBUG(printIntervals("\tactive", active_.begin(), active_.end()));
DEBUG(printIntervals("\tinactive", inactive_.begin(), inactive_.end())); DEBUG(printIntervals("\tinactive", inactive_.begin(), inactive_.end()));
for (MRegisterInfo::regclass_iterator c = mri_->regclass_begin();
c != mri_->regclass_end(); ++c) {
const TargetRegisterClass* rc = *c;
DEBUG(printFreeRegs("\tfree registers", rc));
}
processActiveIntervals(i); processActiveIntervals(i);
processInactiveIntervals(i); processInactiveIntervals(i);
backupRegUse();
// for every interval in inactive we overlap mark the register
// as not free
for (IntervalPtrs::iterator j = inactive_.begin();
j != inactive_.end(); ++j) {
unsigned reg = (*j)->reg;
if (reg >= MRegisterInfo::FirstVirtualRegister)
reg = v2pMap_[reg];
if (i->overlaps(**j)) {
markPhysRegNotFree(reg);
}
}
// for every pre-allocated interval in unhandled we overlap
// mark the register as not free
for (Intervals::const_iterator j = i + 1; j != e; ++j) {
if (j->reg < MRegisterInfo::FirstVirtualRegister &&
i->overlaps(*j))
markPhysRegNotFree(j->reg);
}
DEBUG(std::cerr << "\tallocating current interval:\n"); DEBUG(std::cerr << "\tallocating current interval:\n");
// if this register is preallocated reserve it // if this register is preallocated reserve it
if (i->reg < MRegisterInfo::FirstVirtualRegister) { if (i->reg < MRegisterInfo::FirstVirtualRegister) {
reservePhysReg(i->reg); restoreRegUse();
markPhysRegNotFree(i->reg);
active_.push_back(&*i); active_.push_back(&*i);
} }
// otherwise we are allocating a virtual register. try to find // otherwise we are allocating a virtual register. try to find
@ -281,6 +301,7 @@ bool RA::runOnMachineFunction(MachineFunction &fn) {
assignStackSlotAtInterval(i); assignStackSlotAtInterval(i);
} }
else { else {
restoreRegUse();
assignVirt2PhysReg(i->reg, physReg); assignVirt2PhysReg(i->reg, physReg);
active_.push_back(&*i); active_.push_back(&*i);
} }
@ -290,24 +311,10 @@ bool RA::runOnMachineFunction(MachineFunction &fn) {
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;
DEBUG(std::cerr << "\t\tinterval " << **i << " expired\n"); DEBUG(std::cerr << "\t\tinterval " << **i << " expired\n");
if (reg < MRegisterInfo::FirstVirtualRegister) { if (reg >= MRegisterInfo::FirstVirtualRegister) {
markPhysRegFree(reg); reg = v2pMap_[reg];
}
else {
markPhysRegFree(v2pMap_[reg]);
}
}
// expire any remaining inactive intervals
for (IntervalPtrs::iterator i = inactive_.begin(); i != inactive_.end();
++i) {
unsigned reg = (*i)->reg;
DEBUG(std::cerr << "\t\tinterval " << **i << " expired\n");
if (reg < MRegisterInfo::FirstVirtualRegister) {
markPhysRegFree(reg);
}
else {
markPhysRegFree(v2pMap_[reg]);
} }
markPhysRegFree(reg);
} }
DEBUG(std::cerr << "finished register allocation\n"); DEBUG(std::cerr << "finished register allocation\n");
@ -413,18 +420,20 @@ void RA::processActiveIntervals(Intervals::const_iterator cur)
// instruction // instruction
if ((*i)->expiredAt(cur->start() + 1)) { if ((*i)->expiredAt(cur->start() + 1)) {
DEBUG(std::cerr << "\t\tinterval " << **i << " expired\n"); DEBUG(std::cerr << "\t\tinterval " << **i << " expired\n");
if (reg < MRegisterInfo::FirstVirtualRegister) { if (reg >= MRegisterInfo::FirstVirtualRegister) {
markPhysRegFree(reg); reg = v2pMap_[reg];
}
else {
markPhysRegFree(v2pMap_[reg]);
} }
markPhysRegFree(reg);
// remove from active // remove from active
i = active_.erase(i); i = active_.erase(i);
} }
// move inactive intervals to inactive list // move inactive intervals to inactive list
else if (!(*i)->liveAt(cur->start())) { else if (!(*i)->liveAt(cur->start())) {
DEBUG(std::cerr << "\t\t\tinterval " << **i << " inactive\n"); DEBUG(std::cerr << "\t\t\tinterval " << **i << " inactive\n");
if (reg >= MRegisterInfo::FirstVirtualRegister) {
reg = v2pMap_[reg];
}
markPhysRegFree(reg);
// add to inactive // add to inactive
inactive_.push_back(*i); inactive_.push_back(*i);
// remove from active // remove from active
@ -448,18 +457,16 @@ void RA::processInactiveIntervals(Intervals::const_iterator cur)
// instruction // instruction
if ((*i)->expiredAt(cur->start() + 1)) { if ((*i)->expiredAt(cur->start() + 1)) {
DEBUG(std::cerr << "\t\t\tinterval " << **i << " expired\n"); DEBUG(std::cerr << "\t\t\tinterval " << **i << " expired\n");
if (reg < MRegisterInfo::FirstVirtualRegister) {
markPhysRegFree(reg);
}
else {
markPhysRegFree(v2pMap_[reg]);
}
// remove from inactive // remove from inactive
i = inactive_.erase(i); i = inactive_.erase(i);
} }
// move re-activated intervals in active list // move re-activated intervals in active list
else if ((*i)->liveAt(cur->start())) { else if ((*i)->liveAt(cur->start())) {
DEBUG(std::cerr << "\t\t\tinterval " << **i << " active\n"); DEBUG(std::cerr << "\t\t\tinterval " << **i << " active\n");
if (reg >= MRegisterInfo::FirstVirtualRegister) {
reg = v2pMap_[reg];
}
markPhysRegNotFree(reg);
// add to active // add to active
active_.push_back(*i); active_.push_back(*i);
// remove from inactive // remove from inactive
@ -487,18 +494,16 @@ void RA::assignStackSlotAtInterval(Intervals::const_iterator cur)
{ {
DEBUG(std::cerr << "\t\tassigning stack slot at interval " DEBUG(std::cerr << "\t\tassigning stack slot at interval "
<< *cur << ":\n"); << *cur << ":\n");
assert((!active_.empty() || !inactive_.empty()) &&
"active and inactive sets cannot be both empty when choosing "
"a register to spill");
// set all weights to zero // set all weights to zero
float regWeight[MRegisterInfo::FirstVirtualRegister]; float regWeight[MRegisterInfo::FirstVirtualRegister];
for (unsigned i = 0; i < MRegisterInfo::FirstVirtualRegister; ++i) for (unsigned i = 0; i < MRegisterInfo::FirstVirtualRegister; ++i)
regWeight[i] = 0.0F; regWeight[i] = 0.0F;
// for each interval in active that overlaps
for (IntervalPtrs::iterator i = active_.begin(); i != active_.end(); ++i) { for (IntervalPtrs::iterator i = active_.begin(); i != active_.end(); ++i) {
// if (!cur->overlaps(**i)) if (!cur->overlaps(**i))
// continue; continue;
unsigned reg = (*i)->reg; unsigned reg = (*i)->reg;
if (reg >= MRegisterInfo::FirstVirtualRegister) { if (reg >= MRegisterInfo::FirstVirtualRegister) {
@ -509,10 +514,11 @@ void RA::assignStackSlotAtInterval(Intervals::const_iterator cur)
updateWeight(regWeight, *as, (*i)->weight); updateWeight(regWeight, *as, (*i)->weight);
} }
// for each interval in inactive that overlaps
for (IntervalPtrs::iterator i = inactive_.begin(); for (IntervalPtrs::iterator i = inactive_.begin();
i != inactive_.end(); ++i) { i != inactive_.end(); ++i) {
// if (!cur->overlaps(**i)) if (!cur->overlaps(**i))
// continue; continue;
unsigned reg = (*i)->reg; unsigned reg = (*i)->reg;
if (reg >= MRegisterInfo::FirstVirtualRegister) { if (reg >= MRegisterInfo::FirstVirtualRegister) {
@ -523,6 +529,15 @@ void RA::assignStackSlotAtInterval(Intervals::const_iterator cur)
updateWeight(regWeight, *as, (*i)->weight); updateWeight(regWeight, *as, (*i)->weight);
} }
// for each fixed interval in unhandled that overlaps
for (Intervals::const_iterator j = cur + 1; j != li_->end(); ++j) {
if (j->reg >= MRegisterInfo::FirstVirtualRegister)
continue;
updateWeight(regWeight, j->reg, j->weight);
for (const unsigned* as = mri_->getAliasSet(j->reg); *as; ++as)
updateWeight(regWeight, *as, j->weight);
}
float minWeight = std::numeric_limits<float>::max(); float minWeight = std::numeric_limits<float>::max();
unsigned minReg = 0; unsigned minReg = 0;
const TargetRegisterClass* rc = mf_->getSSARegMap()->getRegClass(cur->reg); const TargetRegisterClass* rc = mf_->getSSARegMap()->getRegClass(cur->reg);
@ -536,6 +551,7 @@ void RA::assignStackSlotAtInterval(Intervals::const_iterator cur)
} }
if (cur->weight < minWeight) { if (cur->weight < minWeight) {
restoreRegUse();
DEBUG(std::cerr << "\t\t\t\tspilling : " << mri_->getName(minReg) DEBUG(std::cerr << "\t\t\t\tspilling : " << mri_->getName(minReg)
<< ", weight: " << cur->weight << '\n'); << ", weight: " << cur->weight << '\n');
assignVirt2StackSlot(cur->reg); assignVirt2StackSlot(cur->reg);
@ -546,11 +562,14 @@ void RA::assignStackSlotAtInterval(Intervals::const_iterator cur)
for (const unsigned* as = mri_->getAliasSet(minReg); *as; ++as) for (const unsigned* as = mri_->getAliasSet(minReg); *as; ++as)
toSpill.insert(*as); toSpill.insert(*as);
std::vector<unsigned> spilled;
for (IntervalPtrs::iterator i = active_.begin(); for (IntervalPtrs::iterator i = active_.begin();
i != active_.end(); ) { i != active_.end(); ) {
unsigned reg = (*i)->reg; unsigned reg = (*i)->reg;
if (reg >= MRegisterInfo::FirstVirtualRegister && if (reg >= MRegisterInfo::FirstVirtualRegister &&
toSpill.find(v2pMap_[reg]) != toSpill.end()) { toSpill.find(v2pMap_[reg]) != toSpill.end() &&
cur->overlaps(**i)) {
spilled.push_back(v2pMap_[reg]);
DEBUG(std::cerr << "\t\t\t\tspilling : " DEBUG(std::cerr << "\t\t\t\tspilling : "
<< mri_->getName(minReg) << ", weight: " << mri_->getName(minReg) << ", weight: "
<< (*i)->weight << '\n'); << (*i)->weight << '\n');
@ -565,7 +584,8 @@ void RA::assignStackSlotAtInterval(Intervals::const_iterator cur)
i != inactive_.end(); ) { i != inactive_.end(); ) {
unsigned reg = (*i)->reg; unsigned reg = (*i)->reg;
if (reg >= MRegisterInfo::FirstVirtualRegister && if (reg >= MRegisterInfo::FirstVirtualRegister &&
toSpill.find(v2pMap_[reg]) != toSpill.end()) { toSpill.find(v2pMap_[reg]) != toSpill.end() &&
cur->overlaps(**i)) {
DEBUG(std::cerr << "\t\t\t\tspilling : " DEBUG(std::cerr << "\t\t\t\tspilling : "
<< mri_->getName(minReg) << ", weight: " << mri_->getName(minReg) << ", weight: "
<< (*i)->weight << '\n'); << (*i)->weight << '\n');
@ -579,69 +599,16 @@ void RA::assignStackSlotAtInterval(Intervals::const_iterator cur)
unsigned physReg = getFreePhysReg(cur); unsigned physReg = getFreePhysReg(cur);
assert(physReg && "no free physical register after spill?"); assert(physReg && "no free physical register after spill?");
restoreRegUse();
for (unsigned i = 0; i < spilled.size(); ++i)
markPhysRegFree(spilled[i]);
assignVirt2PhysReg(cur->reg, physReg); assignVirt2PhysReg(cur->reg, physReg);
active_.push_back(&*cur); active_.push_back(&*cur);
} }
} }
void RA::reservePhysReg(unsigned physReg)
{
DEBUG(std::cerr << "\t\t\treserving physical register: "
<< mri_->getName(physReg) << '\n');
Regs clobbered;
clobbered.push_back(physReg);
for (const unsigned* as = mri_->getAliasSet(physReg); *as; ++as) {
clobbered.push_back(*as);
}
// remove interval from active
for (IntervalPtrs::iterator i = active_.begin(), e = active_.end();
i != e; ) {
unsigned reg = (*i)->reg;
if (reg < MRegisterInfo::FirstVirtualRegister) {
++i;
continue;
}
if (find(clobbered.begin(), clobbered.end(), v2pMap_[reg]) !=
clobbered.end()) {
i = active_.erase(i);
assignVirt2StackSlot(reg);
}
else {
++i;
}
}
// or from inactive
for (IntervalPtrs::iterator i = inactive_.begin(), e = inactive_.end();
i != e; ) {
unsigned reg = (*i)->reg;
if (reg < MRegisterInfo::FirstVirtualRegister) {
++i;
continue;
}
if (find(clobbered.begin(), clobbered.end(), v2pMap_[reg]) !=
clobbered.end()) {
i = inactive_.erase(i);
assignVirt2StackSlot(reg);
}
else {
++i;
}
}
markPhysRegNotFree(physReg);
}
void RA::clearReservedPhysReg(unsigned physReg)
{
DEBUG(std::cerr << "\t\t\tclearing reserved physical register: "
<< mri_->getName(physReg) << '\n');
markPhysRegFree(physReg);
}
bool RA::physRegAvailable(unsigned physReg) bool RA::physRegAvailable(unsigned physReg)
{ {
assert(!reserved_[physReg] && assert(!reserved_[physReg] &&
@ -654,37 +621,17 @@ unsigned RA::getFreePhysReg(Intervals::const_iterator cur)
{ {
DEBUG(std::cerr << "\t\tgetting free physical register: "); DEBUG(std::cerr << "\t\tgetting free physical register: ");
// save the regUse counts because we are going to modify them
// specifically for this interval
unsigned regUseBackup[MRegisterInfo::FirstVirtualRegister];
memcpy(regUseBackup, regUse_, sizeof(regUseBackup));
// for every interval in inactive we don't overlap mark the
// register as free
for (IntervalPtrs::iterator i = inactive_.begin(); i != inactive_.end();
++i) {
unsigned reg = (*i)->reg;
if (reg >= MRegisterInfo::FirstVirtualRegister)
reg = v2pMap_[reg];
if (!cur->overlaps(**i)) {
markPhysRegFree(reg);
}
}
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_); for (TargetRegisterClass::iterator i = rc->allocation_order_begin(*mf_);
i != rc->allocation_order_end(*mf_); ++i) { i != rc->allocation_order_end(*mf_); ++i) {
unsigned reg = *i; unsigned reg = *i;
if (!reserved_[reg] && !regUse_[reg]) { if (!reserved_[reg] && !regUse_[reg]) {
DEBUG(std::cerr << mri_->getName(reg) << '\n'); DEBUG(std::cerr << mri_->getName(reg) << '\n');
memcpy(regUse_, regUseBackup, sizeof(regUseBackup));
return reg; return reg;
} }
} }
DEBUG(std::cerr << "no free register\n"); DEBUG(std::cerr << "no free register\n");
memcpy(regUse_, regUseBackup, sizeof(regUseBackup));
return 0; return 0;
} }