Fix some scavenger performance issues.

- Don't call malloc+free in the very hot forward().
- Don't call isTiedToDefOperand().
- Don't create BitVector temporaries.
- Merge DeadRegs into KillRegs.
- Eliminate the early clobber checks, they were irrelevant to scavenging.
- Remove unnecessary code from -Asserts builds.

This speeds up ARM PEI by 3.4x and overall llc -O0 codegen time by 11%.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@149189 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Jakob Stoklund Olesen 2012-01-29 01:29:28 +00:00
parent 685c23e758
commit 9f946a24d9
2 changed files with 13 additions and 24 deletions

View File

@ -68,6 +68,10 @@ class RegScavenger {
/// available, unset means the register is currently being used. /// available, unset means the register is currently being used.
BitVector RegsAvailable; BitVector RegsAvailable;
// These BitVectors are only used internally to forward(). They are members
// to avoid frequent reallocations.
BitVector KillRegs, DefRegs;
public: public:
RegScavenger() RegScavenger()
: MBB(NULL), NumPhysRegs(0), Tracking(false), : MBB(NULL), NumPhysRegs(0), Tracking(false),
@ -139,7 +143,7 @@ private:
/// setUsed / setUnused - Mark the state of one or a number of registers. /// setUsed / setUnused - Mark the state of one or a number of registers.
/// ///
void setUsed(BitVector &Regs) { void setUsed(BitVector &Regs) {
RegsAvailable &= ~Regs; RegsAvailable.reset(Regs);
} }
void setUnused(BitVector &Regs) { void setUnused(BitVector &Regs) {
RegsAvailable |= Regs; RegsAvailable |= Regs;
@ -148,9 +152,6 @@ private:
/// Add Reg and all its sub-registers to BV. /// Add Reg and all its sub-registers to BV.
void addRegWithSubRegs(BitVector &BV, unsigned Reg); void addRegWithSubRegs(BitVector &BV, unsigned Reg);
/// Add Reg and its aliases to BV.
void addRegWithAliases(BitVector &BV, unsigned Reg);
/// findSurvivorReg - Return the candidate register that is unused for the /// findSurvivorReg - Return the candidate register that is unused for the
/// longest after StartMI. UseMI is set to the instruction where the search /// longest after StartMI. UseMI is set to the instruction where the search
/// stopped. /// stopped.

View File

@ -90,6 +90,8 @@ void RegScavenger::enterBasicBlock(MachineBasicBlock *mbb) {
if (!MBB) { if (!MBB) {
NumPhysRegs = TRI->getNumRegs(); NumPhysRegs = TRI->getNumRegs();
RegsAvailable.resize(NumPhysRegs); RegsAvailable.resize(NumPhysRegs);
KillRegs.resize(NumPhysRegs);
DefRegs.resize(NumPhysRegs);
// Create reserved registers bitvector. // Create reserved registers bitvector.
ReservedRegs = TRI->getReservedRegs(MF); ReservedRegs = TRI->getReservedRegs(MF);
@ -114,12 +116,6 @@ void RegScavenger::addRegWithSubRegs(BitVector &BV, unsigned Reg) {
BV.set(*R); BV.set(*R);
} }
void RegScavenger::addRegWithAliases(BitVector &BV, unsigned Reg) {
BV.set(Reg);
for (const unsigned *R = TRI->getAliasSet(Reg); *R; R++)
BV.set(*R);
}
void RegScavenger::forward() { void RegScavenger::forward() {
// Move ptr forward. // Move ptr forward.
if (!Tracking) { if (!Tracking) {
@ -148,10 +144,8 @@ void RegScavenger::forward() {
// predicated, conservatively assume "kill" markers do not actually kill the // predicated, conservatively assume "kill" markers do not actually kill the
// register. Similarly ignores "dead" markers. // register. Similarly ignores "dead" markers.
bool isPred = TII->isPredicated(MI); bool isPred = TII->isPredicated(MI);
BitVector EarlyClobberRegs(NumPhysRegs); KillRegs.reset();
BitVector KillRegs(NumPhysRegs); DefRegs.reset();
BitVector DefRegs(NumPhysRegs);
BitVector DeadRegs(NumPhysRegs);
for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) { for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) {
const MachineOperand &MO = MI->getOperand(i); const MachineOperand &MO = MI->getOperand(i);
if (!MO.isReg()) if (!MO.isReg())
@ -164,21 +158,19 @@ void RegScavenger::forward() {
// Ignore undef uses. // Ignore undef uses.
if (MO.isUndef()) if (MO.isUndef())
continue; continue;
// Two-address operands implicitly kill. if (!isPred && MO.isKill())
if (!isPred && (MO.isKill() || MI->isRegTiedToDefOperand(i)))
addRegWithSubRegs(KillRegs, Reg); addRegWithSubRegs(KillRegs, Reg);
} else { } else {
assert(MO.isDef()); assert(MO.isDef());
if (!isPred && MO.isDead()) if (!isPred && MO.isDead())
addRegWithSubRegs(DeadRegs, Reg); addRegWithSubRegs(KillRegs, Reg);
else else
addRegWithSubRegs(DefRegs, Reg); addRegWithSubRegs(DefRegs, Reg);
if (MO.isEarlyClobber())
addRegWithAliases(EarlyClobberRegs, Reg);
} }
} }
// Verify uses and defs. // Verify uses and defs.
#ifndef NDEBUG
for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) { for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) {
const MachineOperand &MO = MI->getOperand(i); const MachineOperand &MO = MI->getOperand(i);
if (!MO.isReg()) if (!MO.isReg())
@ -205,16 +197,12 @@ void RegScavenger::forward() {
SubUsed = true; SubUsed = true;
break; break;
} }
#ifndef NDEBUG
if (!SubUsed) { if (!SubUsed) {
MBB->getParent()->verify(NULL, "In Register Scavenger"); MBB->getParent()->verify(NULL, "In Register Scavenger");
llvm_unreachable("Using an undefined register!"); llvm_unreachable("Using an undefined register!");
} }
#endif
(void)SubUsed; (void)SubUsed;
} }
assert((!EarlyClobberRegs.test(Reg) || MI->isRegTiedToDefOperand(i)) &&
"Using an early clobbered register!");
} else { } else {
assert(MO.isDef()); assert(MO.isDef());
#if 0 #if 0
@ -226,10 +214,10 @@ void RegScavenger::forward() {
#endif #endif
} }
} }
#endif // NDEBUG
// Commit the changes. // Commit the changes.
setUnused(KillRegs); setUnused(KillRegs);
setUnused(DeadRegs);
setUsed(DefRegs); setUsed(DefRegs);
} }