From 7a0d51c8e3d6cdc6d961f6525f97f8926fb76c83 Mon Sep 17 00:00:00 2001 From: Evan Cheng Date: Thu, 14 Dec 2006 07:54:05 +0000 Subject: [PATCH] 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. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@32576 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/CodeGen/VirtRegMap.cpp | 36 +++++++++++++++++++++++++++++++++++- 1 file changed, 35 insertions(+), 1 deletion(-) diff --git a/lib/CodeGen/VirtRegMap.cpp b/lib/CodeGen/VirtRegMap.cpp index c51d4ab9aad..04a6cf13073 100644 --- a/lib/CodeGen/VirtRegMap.cpp +++ b/lib/CodeGen/VirtRegMap.cpp @@ -272,6 +272,8 @@ class VISIBILITY_HIDDEN AvailableSpills { // invalidate entries in SpillSlotsAvailable when a physreg is modified. std::multimap PhysRegsAvailable; + void disallowClobberPhysRegOnly(unsigned PhysReg); + void ClobberPhysRegOnly(unsigned PhysReg); public: AvailableSpills(const MRegisterInfo *mri, const TargetInstrInfo *tii) @@ -303,7 +305,7 @@ public: DOUT << "Remembering SS#" << Slot << " in physreg " << MRI->getName(Reg) << "\n"; } - + /// canClobberPhysReg - Return true if the spiller is allowed to change the /// value of the specified stackslot register if it desires. The specified /// stack slot must be available in a physreg for this query to make sense. @@ -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::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; }