Fix a long-standing spiller bug:

If a spillslot value is available in a register, and there is a noop copy that
targets that register, the spiller correctly decide not to invalidate the
spillslot register.

However, even though the noop copy does not clobbers the value. It does start a
new intersecting live range. That means the spillslot register is available for
use but should not be reused for a two-address instruction modref operand which
would clobber the new live range.

When we remove the noop copy, update the available information by clearing the
canClobber bit.

llvm-svn: 32576
This commit is contained in:
Evan Cheng 2006-12-14 07:54:05 +00:00
parent b8817b9b6e
commit 4c306ae0c2
1 changed files with 35 additions and 1 deletions

View File

@ -272,6 +272,8 @@ class VISIBILITY_HIDDEN AvailableSpills {
// invalidate entries in SpillSlotsAvailable when a physreg is modified.
std::multimap<unsigned, int> PhysRegsAvailable;
void disallowClobberPhysRegOnly(unsigned PhysReg);
void ClobberPhysRegOnly(unsigned PhysReg);
public:
AvailableSpills(const MRegisterInfo *mri, const TargetInstrInfo *tii)
@ -312,6 +314,11 @@ public:
return SpillSlotsAvailable.find(Slot)->second & 1;
}
/// disallowClobberPhysReg - Unset the CanClobber bit of the specified
/// stackslot register. The register is still available but is no longer
/// allowed to be modifed.
void disallowClobberPhysReg(unsigned PhysReg);
/// ClobberPhysReg - This is called when the specified physreg changes
/// value. We use this to invalidate any info about stuff we thing lives in
/// it and any of its aliases.
@ -324,6 +331,32 @@ public:
};
}
/// disallowClobberPhysRegOnly - Unset the CanClobber bit of the specified
/// stackslot register. The register is still available but is no longer
/// allowed to be modifed.
void AvailableSpills::disallowClobberPhysRegOnly(unsigned PhysReg) {
std::multimap<unsigned, int>::iterator I =
PhysRegsAvailable.lower_bound(PhysReg);
while (I != PhysRegsAvailable.end() && I->first == PhysReg) {
int Slot = I->second;
I++;
assert((SpillSlotsAvailable[Slot] >> 1) == PhysReg &&
"Bidirectional map mismatch!");
SpillSlotsAvailable[Slot] &= ~1;
DOUT << "PhysReg " << MRI->getName(PhysReg)
<< " copied, it is available for use but can no longer be modified\n";
}
}
/// disallowClobberPhysReg - Unset the CanClobber bit of the specified
/// stackslot register and its aliases. The register and its aliases may
/// still available but is no longer allowed to be modifed.
void AvailableSpills::disallowClobberPhysReg(unsigned PhysReg) {
for (const unsigned *AS = MRI->getAliasSet(PhysReg); *AS; ++AS)
disallowClobberPhysRegOnly(*AS);
disallowClobberPhysRegOnly(PhysReg);
}
/// ClobberPhysRegOnly - This is called when the specified physreg changes
/// value. We use this to invalidate any info about stuff we thing lives in it.
void AvailableSpills::ClobberPhysRegOnly(unsigned PhysReg) {
@ -822,6 +855,7 @@ void LocalSpiller::RewriteMBB(MachineBasicBlock &MBB, VirtRegMap &VRM) {
DOUT << "Removing now-noop copy: " << MI;
MBB.erase(&MI);
VRM.RemoveFromFoldedVirtMap(&MI);
Spills.disallowClobberPhysReg(VirtReg);
goto ProcessNextInst;
}