mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-08-09 11:25:55 +00:00
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
This commit is contained in:
@@ -272,6 +272,8 @@ class VISIBILITY_HIDDEN AvailableSpills {
|
|||||||
// invalidate entries in SpillSlotsAvailable when a physreg is modified.
|
// invalidate entries in SpillSlotsAvailable when a physreg is modified.
|
||||||
std::multimap<unsigned, int> PhysRegsAvailable;
|
std::multimap<unsigned, int> PhysRegsAvailable;
|
||||||
|
|
||||||
|
void disallowClobberPhysRegOnly(unsigned PhysReg);
|
||||||
|
|
||||||
void ClobberPhysRegOnly(unsigned PhysReg);
|
void ClobberPhysRegOnly(unsigned PhysReg);
|
||||||
public:
|
public:
|
||||||
AvailableSpills(const MRegisterInfo *mri, const TargetInstrInfo *tii)
|
AvailableSpills(const MRegisterInfo *mri, const TargetInstrInfo *tii)
|
||||||
@@ -303,7 +305,7 @@ public:
|
|||||||
DOUT << "Remembering SS#" << Slot << " in physreg "
|
DOUT << "Remembering SS#" << Slot << " in physreg "
|
||||||
<< MRI->getName(Reg) << "\n";
|
<< MRI->getName(Reg) << "\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
/// canClobberPhysReg - Return true if the spiller is allowed to change the
|
/// canClobberPhysReg - Return true if the spiller is allowed to change the
|
||||||
/// value of the specified stackslot register if it desires. The specified
|
/// 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.
|
/// 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;
|
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
|
/// ClobberPhysReg - This is called when the specified physreg changes
|
||||||
/// value. We use this to invalidate any info about stuff we thing lives in
|
/// value. We use this to invalidate any info about stuff we thing lives in
|
||||||
/// it and any of its aliases.
|
/// 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
|
/// ClobberPhysRegOnly - This is called when the specified physreg changes
|
||||||
/// value. We use this to invalidate any info about stuff we thing lives in it.
|
/// value. We use this to invalidate any info about stuff we thing lives in it.
|
||||||
void AvailableSpills::ClobberPhysRegOnly(unsigned PhysReg) {
|
void AvailableSpills::ClobberPhysRegOnly(unsigned PhysReg) {
|
||||||
@@ -822,6 +855,7 @@ void LocalSpiller::RewriteMBB(MachineBasicBlock &MBB, VirtRegMap &VRM) {
|
|||||||
DOUT << "Removing now-noop copy: " << MI;
|
DOUT << "Removing now-noop copy: " << MI;
|
||||||
MBB.erase(&MI);
|
MBB.erase(&MI);
|
||||||
VRM.RemoveFromFoldedVirtMap(&MI);
|
VRM.RemoveFromFoldedVirtMap(&MI);
|
||||||
|
Spills.disallowClobberPhysReg(VirtReg);
|
||||||
goto ProcessNextInst;
|
goto ProcessNextInst;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user