[llvm-commits] CVS: llvm/lib/CodeGen/RegAllocLinearScan.cpp
Alkis Evlogimenos
alkis at cs.uiuc.edu
Tue Dec 23 12:01:01 PST 2003
Changes in directory llvm/lib/CodeGen:
RegAllocLinearScan.cpp updated: 1.17 -> 1.18
---
Log message:
Change the way free regusters are computed and perform better
allocation in the presence of preallocated intervals.
---
Diffs of the changes: (+77 -130)
Index: llvm/lib/CodeGen/RegAllocLinearScan.cpp
diff -u llvm/lib/CodeGen/RegAllocLinearScan.cpp:1.17 llvm/lib/CodeGen/RegAllocLinearScan.cpp:1.18
--- llvm/lib/CodeGen/RegAllocLinearScan.cpp:1.17 Sun Dec 21 14:41:26 2003
+++ llvm/lib/CodeGen/RegAllocLinearScan.cpp Tue Dec 23 12:00:33 2003
@@ -55,6 +55,7 @@
RegMask reserved_;
unsigned regUse_[MRegisterInfo::FirstVirtualRegister];
+ unsigned regUseBackup_[MRegisterInfo::FirstVirtualRegister];
typedef LiveIntervals::MachineBasicBlockPtrs MachineBasicBlockPtrs;
MachineBasicBlockPtrs mbbs_;
@@ -105,14 +106,6 @@
/// 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
/// virtual register interval if we have one, otherwise return
/// 0
@@ -159,6 +152,14 @@
void markPhysRegFree(unsigned physReg);
void markPhysRegNotFree(unsigned physReg);
+ void backupRegUse() {
+ memcpy(regUseBackup_, regUse_, sizeof(regUseBackup_));
+ }
+
+ void restoreRegUse() {
+ memcpy(regUse_, regUseBackup_, sizeof(regUseBackup_));
+ }
+
void printVirt2PhysMap() const {
std::cerr << "allocated registers:\n";
for (Virt2PhysMap::const_iterator
@@ -212,6 +213,7 @@
v2pMap_.clear();
v2ssMap_.clear();
memset(regUse_, 0, sizeof(regUse_));
+ memset(regUseBackup_, 0, sizeof(regUseBackup_));
DEBUG(
unsigned i = 0;
@@ -257,19 +259,37 @@
DEBUG(printIntervals("\tactive", active_.begin(), active_.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);
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");
// if this register is preallocated reserve it
if (i->reg < MRegisterInfo::FirstVirtualRegister) {
- reservePhysReg(i->reg);
+ restoreRegUse();
+ markPhysRegNotFree(i->reg);
active_.push_back(&*i);
}
// otherwise we are allocating a virtual register. try to find
@@ -281,6 +301,7 @@
assignStackSlotAtInterval(i);
}
else {
+ restoreRegUse();
assignVirt2PhysReg(i->reg, physReg);
active_.push_back(&*i);
}
@@ -290,24 +311,10 @@
for (IntervalPtrs::iterator i = active_.begin(); i != active_.end(); ++i) {
unsigned reg = (*i)->reg;
DEBUG(std::cerr << "\t\tinterval " << **i << " expired\n");
- if (reg < MRegisterInfo::FirstVirtualRegister) {
- markPhysRegFree(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]);
+ if (reg >= MRegisterInfo::FirstVirtualRegister) {
+ reg = v2pMap_[reg];
}
+ markPhysRegFree(reg);
}
DEBUG(std::cerr << "finished register allocation\n");
@@ -413,18 +420,20 @@
// instruction
if ((*i)->expiredAt(cur->start() + 1)) {
DEBUG(std::cerr << "\t\tinterval " << **i << " expired\n");
- if (reg < MRegisterInfo::FirstVirtualRegister) {
- markPhysRegFree(reg);
- }
- else {
- markPhysRegFree(v2pMap_[reg]);
+ if (reg >= MRegisterInfo::FirstVirtualRegister) {
+ reg = v2pMap_[reg];
}
+ markPhysRegFree(reg);
// remove from active
i = active_.erase(i);
}
// move inactive intervals to inactive list
else if (!(*i)->liveAt(cur->start())) {
DEBUG(std::cerr << "\t\t\tinterval " << **i << " inactive\n");
+ if (reg >= MRegisterInfo::FirstVirtualRegister) {
+ reg = v2pMap_[reg];
+ }
+ markPhysRegFree(reg);
// add to inactive
inactive_.push_back(*i);
// remove from active
@@ -448,18 +457,16 @@
// instruction
if ((*i)->expiredAt(cur->start() + 1)) {
DEBUG(std::cerr << "\t\t\tinterval " << **i << " expired\n");
- if (reg < MRegisterInfo::FirstVirtualRegister) {
- markPhysRegFree(reg);
- }
- else {
- markPhysRegFree(v2pMap_[reg]);
- }
// remove from inactive
i = inactive_.erase(i);
}
// move re-activated intervals in active list
else if ((*i)->liveAt(cur->start())) {
DEBUG(std::cerr << "\t\t\tinterval " << **i << " active\n");
+ if (reg >= MRegisterInfo::FirstVirtualRegister) {
+ reg = v2pMap_[reg];
+ }
+ markPhysRegNotFree(reg);
// add to active
active_.push_back(*i);
// remove from inactive
@@ -487,18 +494,16 @@
{
DEBUG(std::cerr << "\t\tassigning stack slot at interval "
<< *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
float regWeight[MRegisterInfo::FirstVirtualRegister];
for (unsigned i = 0; i < MRegisterInfo::FirstVirtualRegister; ++i)
regWeight[i] = 0.0F;
+ // for each interval in active that overlaps
for (IntervalPtrs::iterator i = active_.begin(); i != active_.end(); ++i) {
-// if (!cur->overlaps(**i))
-// continue;
+ if (!cur->overlaps(**i))
+ continue;
unsigned reg = (*i)->reg;
if (reg >= MRegisterInfo::FirstVirtualRegister) {
@@ -509,10 +514,11 @@
updateWeight(regWeight, *as, (*i)->weight);
}
+ // for each interval in inactive that overlaps
for (IntervalPtrs::iterator i = inactive_.begin();
i != inactive_.end(); ++i) {
-// if (!cur->overlaps(**i))
-// continue;
+ if (!cur->overlaps(**i))
+ continue;
unsigned reg = (*i)->reg;
if (reg >= MRegisterInfo::FirstVirtualRegister) {
@@ -523,6 +529,15 @@
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();
unsigned minReg = 0;
const TargetRegisterClass* rc = mf_->getSSARegMap()->getRegClass(cur->reg);
@@ -536,6 +551,7 @@
}
if (cur->weight < minWeight) {
+ restoreRegUse();
DEBUG(std::cerr << "\t\t\t\tspilling : " << mri_->getName(minReg)
<< ", weight: " << cur->weight << '\n');
assignVirt2StackSlot(cur->reg);
@@ -546,11 +562,14 @@
for (const unsigned* as = mri_->getAliasSet(minReg); *as; ++as)
toSpill.insert(*as);
+ std::vector<unsigned> spilled;
for (IntervalPtrs::iterator i = active_.begin();
i != active_.end(); ) {
unsigned reg = (*i)->reg;
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 : "
<< mri_->getName(minReg) << ", weight: "
<< (*i)->weight << '\n');
@@ -565,7 +584,8 @@
i != inactive_.end(); ) {
unsigned reg = (*i)->reg;
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 : "
<< mri_->getName(minReg) << ", weight: "
<< (*i)->weight << '\n');
@@ -579,67 +599,14 @@
unsigned physReg = getFreePhysReg(cur);
assert(physReg && "no free physical register after spill?");
- assignVirt2PhysReg(cur->reg, physReg);
- 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;
- }
+ restoreRegUse();
+ for (unsigned i = 0; i < spilled.size(); ++i)
+ markPhysRegFree(spilled[i]);
- 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;
- }
+ assignVirt2PhysReg(cur->reg, physReg);
+ active_.push_back(&*cur);
}
-
- 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)
@@ -654,37 +621,17 @@
{
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);
for (TargetRegisterClass::iterator i = rc->allocation_order_begin(*mf_);
i != rc->allocation_order_end(*mf_); ++i) {
unsigned reg = *i;
if (!reserved_[reg] && !regUse_[reg]) {
DEBUG(std::cerr << mri_->getName(reg) << '\n');
- memcpy(regUse_, regUseBackup, sizeof(regUseBackup));
return reg;
}
}
DEBUG(std::cerr << "no free register\n");
- memcpy(regUse_, regUseBackup, sizeof(regUseBackup));
return 0;
}
More information about the llvm-commits
mailing list