Create an object for tracking physical register usage. This will look

much better when I get rid of the reserved registers.


git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@11066 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Alkis Evlogimenos
2004-02-02 07:30:36 +00:00
parent c8a35817fc
commit 22b7e44bb0

View File

@ -35,6 +35,69 @@ namespace {
Statistic<> numPeep ("ra-linearscan", Statistic<> numPeep ("ra-linearscan",
"Number of identity moves eliminated"); "Number of identity moves eliminated");
class PhysRegTracker {
private:
const MRegisterInfo* mri_;
std::vector<bool> reserved_;
std::vector<unsigned> regUse_;
public:
PhysRegTracker(MachineFunction* mf)
: mri_(mf ? mf->getTarget().getRegisterInfo() : NULL) {
if (mri_) {
reserved_.assign(mri_->getNumRegs(), false);
regUse_.assign(mri_->getNumRegs(), 0);
}
}
PhysRegTracker(const PhysRegTracker& rhs)
: mri_(rhs.mri_),
reserved_(rhs.reserved_),
regUse_(rhs.regUse_) {
}
const PhysRegTracker& operator=(const PhysRegTracker& rhs) {
mri_ = rhs.mri_;
reserved_ = rhs.reserved_;
regUse_ = rhs.regUse_;
return *this;
}
void reservePhysReg(unsigned physReg) {
reserved_[physReg] = true;
}
void addPhysRegUse(unsigned physReg) {
++regUse_[physReg];
for (const unsigned* as = mri_->getAliasSet(physReg); *as; ++as) {
physReg = *as;
++regUse_[physReg];
}
}
void delPhysRegUse(unsigned physReg) {
assert(regUse_[physReg] != 0);
--regUse_[physReg];
for (const unsigned* as = mri_->getAliasSet(physReg); *as; ++as) {
physReg = *as;
assert(regUse_[physReg] != 0);
--regUse_[physReg];
}
}
bool isPhysRegReserved(unsigned physReg) const {
return reserved_[physReg];
}
bool isPhysRegAvail(unsigned physReg) const {
return regUse_[physReg] == 0 && !isPhysRegReserved(physReg);
}
bool isReservedPhysRegAvail(unsigned physReg) const {
return regUse_[physReg] == 0 && isPhysRegReserved(physReg);
}
};
class RA : public MachineFunctionPass { class RA : public MachineFunctionPass {
private: private:
MachineFunction* mf_; MachineFunction* mf_;
@ -50,11 +113,7 @@ namespace {
Regs tempUseOperands_; Regs tempUseOperands_;
Regs tempDefOperands_; Regs tempDefOperands_;
typedef std::vector<bool> RegMask; PhysRegTracker prt_;
RegMask reserved_;
unsigned regUse_[MRegisterInfo::FirstVirtualRegister];
unsigned regUseBackup_[MRegisterInfo::FirstVirtualRegister];
typedef std::map<unsigned, unsigned> Virt2PhysMap; typedef std::map<unsigned, unsigned> Virt2PhysMap;
Virt2PhysMap v2pMap_; Virt2PhysMap v2pMap_;
@ -65,6 +124,11 @@ namespace {
int instrAdded_; int instrAdded_;
public: public:
RA()
: prt_(NULL) {
}
virtual const char* getPassName() const { virtual const char* getPassName() const {
return "Linear Scan Register Allocator"; return "Linear Scan Register Allocator";
} }
@ -97,7 +161,8 @@ namespace {
/// interval. Currently we spill the interval with the last /// interval. Currently we spill the interval with the last
/// end point in the active and inactive lists and the current /// end point in the active and inactive lists and the current
/// interval /// interval
void assignStackSlotAtInterval(IntervalPtrs::value_type cur); void assignStackSlotAtInterval(IntervalPtrs::value_type cur,
const PhysRegTracker& backupPtr);
/// ///
/// register handling helpers /// register handling helpers
@ -108,14 +173,6 @@ namespace {
/// 0 /// 0
unsigned getFreePhysReg(IntervalPtrs::value_type cur); unsigned getFreePhysReg(IntervalPtrs::value_type cur);
/// physRegAvailable - returns true if the specifed physical
/// register is available
bool physRegAvailable(unsigned physReg);
/// tempPhysRegAvailable - returns true if the specifed
/// temporary physical register is available
bool tempPhysRegAvailable(unsigned physReg);
/// getFreeTempPhysReg - return a free temprorary physical /// getFreeTempPhysReg - return a free temprorary physical
/// register for this virtual register if we have one (should /// register for this virtual register if we have one (should
/// never return 0) /// never return 0)
@ -146,19 +203,9 @@ namespace {
/// an assigned stack slot /// an assigned stack slot
void loadVirt2PhysReg(unsigned virtReg, unsigned physReg); void loadVirt2PhysReg(unsigned virtReg, unsigned physReg);
void markPhysRegFree(unsigned physReg);
void markPhysRegNotFree(unsigned physReg);
void backupRegUse() {
memcpy(regUseBackup_, regUse_, sizeof(regUseBackup_));
}
void restoreRegUse() {
memcpy(regUse_, regUseBackup_, sizeof(regUseBackup_));
}
void printVirtRegAssignment() const { void printVirtRegAssignment() const {
std::cerr << "register assignment:\n"; std::cerr << "register assignment:\n";
for (Virt2PhysMap::const_iterator for (Virt2PhysMap::const_iterator
i = v2pMap_.begin(), e = v2pMap_.end(); i != e; ++i) { i = v2pMap_.begin(), e = v2pMap_.end(); i != e; ++i) {
assert(i->second != 0); assert(i->second != 0);
@ -187,20 +234,20 @@ namespace {
} }
} }
void printFreeRegs(const char* const str, // void printFreeRegs(const char* const str,
const TargetRegisterClass* rc) const { // const TargetRegisterClass* rc) const {
if (str) std::cerr << str << ':'; // if (str) std::cerr << str << ':';
for (TargetRegisterClass::iterator i = // for (TargetRegisterClass::iterator i =
rc->allocation_order_begin(*mf_); // 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 (!regUse_[reg]) { // if (!regUse_[reg]) {
std::cerr << ' ' << mri_->getName(reg); // std::cerr << ' ' << mri_->getName(reg);
if (reserved_[reg]) std::cerr << "*"; // if (reserved_[reg]) std::cerr << "*";
} // }
} // }
std::cerr << '\n'; // std::cerr << '\n';
} // }
}; };
} }
@ -220,10 +267,9 @@ bool RA::runOnMachineFunction(MachineFunction &fn) {
tm_ = &fn.getTarget(); tm_ = &fn.getTarget();
mri_ = tm_->getRegisterInfo(); mri_ = tm_->getRegisterInfo();
li_ = &getAnalysis<LiveIntervals>(); li_ = &getAnalysis<LiveIntervals>();
initIntervalSets(li_->getIntervals()); prt_ = PhysRegTracker(mf_);
memset(regUse_, 0, sizeof(regUse_)); initIntervalSets(li_->getIntervals());
memset(regUseBackup_, 0, sizeof(regUseBackup_));
// FIXME: this will work only for the X86 backend. I need to // FIXME: this will work only for the X86 backend. I need to
// device an algorthm to select the minimal (considering register // device an algorthm to select the minimal (considering register
@ -234,15 +280,14 @@ bool RA::runOnMachineFunction(MachineFunction &fn) {
// R16: CX, DI, // R16: CX, DI,
// R32: ECX, EDI, // R32: ECX, EDI,
// RFP: FP5, FP6 // RFP: FP5, FP6
reserved_.assign(MRegisterInfo::FirstVirtualRegister, false); prt_.reservePhysReg( 8); /* CH */
reserved_[ 8] = true; /* CH */ prt_.reservePhysReg( 9); /* CL */
reserved_[ 9] = true; /* CL */ prt_.reservePhysReg(10); /* CX */
reserved_[10] = true; /* CX */ prt_.reservePhysReg(12); /* DI */
reserved_[12] = true; /* DI */ prt_.reservePhysReg(18); /* ECX */
reserved_[18] = true; /* ECX */ prt_.reservePhysReg(19); /* EDI */
reserved_[19] = true; /* EDI */ prt_.reservePhysReg(28); /* FP5 */
reserved_[28] = true; /* FP5 */ prt_.reservePhysReg(29); /* FP6 */
reserved_[29] = true; /* FP6 */
// linear scan algorithm // linear scan algorithm
DEBUG(std::cerr << "Machine Function\n"); DEBUG(std::cerr << "Machine Function\n");
@ -279,14 +324,14 @@ bool RA::runOnMachineFunction(MachineFunction &fn) {
// if this register is fixed we are done // if this register is fixed we are done
if (MRegisterInfo::isPhysicalRegister(cur->reg)) { if (MRegisterInfo::isPhysicalRegister(cur->reg)) {
markPhysRegNotFree(cur->reg); prt_.addPhysRegUse(cur->reg);
active_.push_back(cur); active_.push_back(cur);
} }
// otherwise we are allocating a virtual register. try to find // otherwise we are allocating a virtual register. try to find
// a free physical register or spill an interval in order to // a free physical register or spill an interval in order to
// assign it one (we could spill the current though). // assign it one (we could spill the current though).
else { else {
backupRegUse(); PhysRegTracker backupPrt = prt_;
// for every interval in inactive we overlap with, mark the // for every interval in inactive we overlap with, mark the
// register as not free // register as not free
@ -297,7 +342,7 @@ bool RA::runOnMachineFunction(MachineFunction &fn) {
reg = v2pMap_[reg]; reg = v2pMap_[reg];
if (cur->overlaps(**i)) { if (cur->overlaps(**i)) {
markPhysRegNotFree(reg); prt_.addPhysRegUse(reg);
} }
} }
@ -308,17 +353,17 @@ bool RA::runOnMachineFunction(MachineFunction &fn) {
assert(MRegisterInfo::isPhysicalRegister((*i)->reg) && assert(MRegisterInfo::isPhysicalRegister((*i)->reg) &&
"virtual register interval in fixed set?"); "virtual register interval in fixed set?");
if (cur->overlaps(**i)) if (cur->overlaps(**i))
markPhysRegNotFree((*i)->reg); prt_.addPhysRegUse((*i)->reg);
} }
DEBUG(std::cerr << "\tallocating current interval:\n"); DEBUG(std::cerr << "\tallocating current interval:\n");
unsigned physReg = getFreePhysReg(cur); unsigned physReg = getFreePhysReg(cur);
if (!physReg) { if (!physReg) {
assignStackSlotAtInterval(cur); assignStackSlotAtInterval(cur, backupPrt);
} }
else { else {
restoreRegUse(); prt_ = backupPrt;
assignVirt2PhysReg(cur->reg, physReg); assignVirt2PhysReg(cur->reg, physReg);
active_.push_back(cur); active_.push_back(cur);
} }
@ -334,7 +379,7 @@ bool RA::runOnMachineFunction(MachineFunction &fn) {
if (MRegisterInfo::isVirtualRegister(reg)) { if (MRegisterInfo::isVirtualRegister(reg)) {
reg = v2pMap_[reg]; reg = v2pMap_[reg];
} }
markPhysRegFree(reg); prt_.delPhysRegUse(reg);
} }
typedef LiveIntervals::Reg2RegMap Reg2RegMap; typedef LiveIntervals::Reg2RegMap Reg2RegMap;
@ -514,7 +559,7 @@ void RA::processActiveIntervals(IntervalPtrs::value_type cur)
if (MRegisterInfo::isVirtualRegister(reg)) { if (MRegisterInfo::isVirtualRegister(reg)) {
reg = v2pMap_[reg]; reg = v2pMap_[reg];
} }
markPhysRegFree(reg); prt_.delPhysRegUse(reg);
// remove from active // remove from active
i = active_.erase(i); i = active_.erase(i);
} }
@ -524,7 +569,7 @@ void RA::processActiveIntervals(IntervalPtrs::value_type cur)
if (MRegisterInfo::isVirtualRegister(reg)) { if (MRegisterInfo::isVirtualRegister(reg)) {
reg = v2pMap_[reg]; reg = v2pMap_[reg];
} }
markPhysRegFree(reg); prt_.delPhysRegUse(reg);
// add to inactive // add to inactive
inactive_.push_back(*i); inactive_.push_back(*i);
// remove from active // remove from active
@ -554,7 +599,7 @@ void RA::processInactiveIntervals(IntervalPtrs::value_type cur)
if (MRegisterInfo::isVirtualRegister(reg)) { if (MRegisterInfo::isVirtualRegister(reg)) {
reg = v2pMap_[reg]; reg = v2pMap_[reg];
} }
markPhysRegNotFree(reg); prt_.addPhysRegUse(reg);
// add to active // add to active
active_.push_back(*i); active_.push_back(*i);
// remove from inactive // remove from inactive
@ -578,7 +623,8 @@ namespace {
} }
} }
void RA::assignStackSlotAtInterval(IntervalPtrs::value_type cur) void RA::assignStackSlotAtInterval(IntervalPtrs::value_type cur,
const PhysRegTracker& backupPrt)
{ {
DEBUG(std::cerr << "\t\tassigning stack slot at interval " DEBUG(std::cerr << "\t\tassigning stack slot at interval "
<< *cur << ":\n"); << *cur << ":\n");
@ -631,7 +677,7 @@ void RA::assignStackSlotAtInterval(IntervalPtrs::value_type cur)
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] && minWeight > regWeight[reg]) { if (!prt_.isPhysRegReserved(reg) && minWeight > regWeight[reg]) {
minWeight = regWeight[reg]; minWeight = regWeight[reg];
minReg = reg; minReg = reg;
} }
@ -640,7 +686,7 @@ void RA::assignStackSlotAtInterval(IntervalPtrs::value_type cur)
<< mri_->getName(minReg) << " (" << minWeight << ")\n"); << mri_->getName(minReg) << " (" << minWeight << ")\n");
if (cur->weight < minWeight) { if (cur->weight < minWeight) {
restoreRegUse(); prt_ = backupPrt;
DEBUG(std::cerr << "\t\t\t\tspilling: " << *cur << '\n'); DEBUG(std::cerr << "\t\t\t\tspilling: " << *cur << '\n');
assignVirt2StackSlot(cur->reg); assignVirt2StackSlot(cur->reg);
} }
@ -684,23 +730,15 @@ void RA::assignStackSlotAtInterval(IntervalPtrs::value_type 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(); prt_ = backupPrt;
for (unsigned i = 0; i < spilled.size(); ++i) for (unsigned i = 0; i < spilled.size(); ++i)
markPhysRegFree(spilled[i]); prt_.delPhysRegUse(spilled[i]);
assignVirt2PhysReg(cur->reg, physReg); assignVirt2PhysReg(cur->reg, physReg);
active_.push_back(cur); active_.push_back(cur);
} }
} }
bool RA::physRegAvailable(unsigned physReg)
{
assert(!reserved_[physReg] &&
"cannot call this method with a reserved register");
return !regUse_[physReg];
}
unsigned RA::getFreePhysReg(IntervalPtrs::value_type cur) unsigned RA::getFreePhysReg(IntervalPtrs::value_type cur)
{ {
DEBUG(std::cerr << "\t\tgetting free physical register: "); DEBUG(std::cerr << "\t\tgetting free physical register: ");
@ -709,7 +747,7 @@ unsigned RA::getFreePhysReg(IntervalPtrs::value_type cur)
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 (prt_.isPhysRegAvail(reg)) {
DEBUG(std::cerr << mri_->getName(reg) << '\n'); DEBUG(std::cerr << mri_->getName(reg) << '\n');
return reg; return reg;
} }
@ -719,14 +757,6 @@ unsigned RA::getFreePhysReg(IntervalPtrs::value_type cur)
return 0; return 0;
} }
bool RA::tempPhysRegAvailable(unsigned physReg)
{
assert(reserved_[physReg] &&
"cannot call this method with a not reserved temp register");
return !regUse_[physReg];
}
unsigned RA::getFreeTempPhysReg(unsigned virtReg) unsigned RA::getFreeTempPhysReg(unsigned virtReg)
{ {
DEBUG(std::cerr << "\t\tgetting free temporary physical register: "); DEBUG(std::cerr << "\t\tgetting free temporary physical register: ");
@ -738,7 +768,7 @@ unsigned RA::getFreeTempPhysReg(unsigned virtReg)
i(rc->allocation_order_end(*mf_)), i(rc->allocation_order_end(*mf_)),
e(rc->allocation_order_begin(*mf_)); i != e; ++i) { e(rc->allocation_order_begin(*mf_)); i != e; ++i) {
unsigned reg = *i; unsigned reg = *i;
if (reserved_[reg] && !regUse_[reg]) { if (prt_.isReservedPhysRegAvail(reg)) {
DEBUG(std::cerr << mri_->getName(reg) << '\n'); DEBUG(std::cerr << mri_->getName(reg) << '\n');
return reg; return reg;
} }
@ -753,7 +783,7 @@ void RA::assignVirt2PhysReg(unsigned virtReg, unsigned physReg)
bool inserted = v2pMap_.insert(std::make_pair(virtReg, physReg)).second; bool inserted = v2pMap_.insert(std::make_pair(virtReg, physReg)).second;
assert(inserted && "attempting to assign a virt->phys mapping to an " assert(inserted && "attempting to assign a virt->phys mapping to an "
"already mapped register"); "already mapped register");
markPhysRegNotFree(physReg); prt_.addPhysRegUse(physReg);
} }
void RA::clearVirtReg(unsigned virtReg) void RA::clearVirtReg(unsigned virtReg)
@ -762,7 +792,7 @@ void RA::clearVirtReg(unsigned virtReg)
assert(it != v2pMap_.end() && assert(it != v2pMap_.end() &&
"attempting to clear a not allocated virtual register"); "attempting to clear a not allocated virtual register");
unsigned physReg = it->second; unsigned physReg = it->second;
markPhysRegFree(physReg); prt_.delPhysRegUse(physReg);
v2pMap_.erase(it); v2pMap_.erase(it);
DEBUG(std::cerr << "\t\t\tcleared register " << mri_->getName(physReg) DEBUG(std::cerr << "\t\t\tcleared register " << mri_->getName(physReg)
<< "\n"); << "\n");
@ -817,26 +847,6 @@ void RA::loadVirt2PhysReg(unsigned virtReg, unsigned physReg)
assignVirt2PhysReg(virtReg, physReg); assignVirt2PhysReg(virtReg, physReg);
} }
void RA::markPhysRegFree(unsigned physReg)
{
assert(regUse_[physReg] != 0);
--regUse_[physReg];
for (const unsigned* as = mri_->getAliasSet(physReg); *as; ++as) {
physReg = *as;
assert(regUse_[physReg] != 0);
--regUse_[physReg];
}
}
void RA::markPhysRegNotFree(unsigned physReg)
{
++regUse_[physReg];
for (const unsigned* as = mri_->getAliasSet(physReg); *as; ++as) {
physReg = *as;
++regUse_[physReg];
}
}
FunctionPass* llvm::createLinearScanRegisterAllocator() { FunctionPass* llvm::createLinearScanRegisterAllocator() {
return new RA(); return new RA();
} }