significantly simplify the VirtRegMap code by pulling the SpillSlotsAvailable

and PhysRegsAvailable maps out into a new AvailableSpills struct.  No
functionality change.

This paves the way for a bugfix, coming up next.


git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@25947 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Chris Lattner 2006-02-03 23:13:58 +00:00
parent 244d1dccd1
commit 66cf80f226

View File

@ -231,38 +231,92 @@ namespace {
}; };
} }
void LocalSpiller::ClobberPhysRegOnly(unsigned PhysReg, /// AvailableSpills - As the local spiller is scanning and rewriting an MBB from
std::map<int, unsigned> &SpillSlots, /// top down, keep track of which spills slots are available in each register.
std::multimap<unsigned, int> &PhysRegsAvailable) { class AvailableSpills {
std::multimap<unsigned, int>::iterator I = PhysRegsAvailable.lower_bound(PhysReg); const MRegisterInfo *MRI;
const TargetInstrInfo *TII;
// SpillSlotsAvailable - This map keeps track of all of the spilled virtual
// register values that are still available, due to being loaded or stored to,
// but not invalidated yet.
std::map<int, unsigned> SpillSlotsAvailable;
// PhysRegsAvailable - This is the inverse of SpillSlotsAvailable, indicating
// which stack slot values are currently held by a physreg. This is used to
// invalidate entries in SpillSlotsAvailable when a physreg is modified.
std::multimap<unsigned, int> PhysRegsAvailable;
void ClobberPhysRegOnly(unsigned PhysReg);
public:
AvailableSpills(const MRegisterInfo *mri, const TargetInstrInfo *tii)
: MRI(mri), TII(tii) {
}
/// getSpillSlotPhysReg - If the specified stack slot is available in a
/// physical register, return that PhysReg, otherwise return 0.
unsigned getSpillSlotPhysReg(int Slot) const {
std::map<int, unsigned>::const_iterator I = SpillSlotsAvailable.find(Slot);
if (I != SpillSlotsAvailable.end())
return I->second;
return 0;
}
/// addAvailable - Mark that the specified stack slot is available in the
/// specified physreg.
void addAvailable(int Slot, unsigned Reg) {
PhysRegsAvailable.insert(std::make_pair(Reg, Slot));
SpillSlotsAvailable[Slot] = Reg;
DEBUG(std::cerr << "Remembering SS#" << Slot << " in physreg "
<< MRI->getName(Reg) << "\n");
}
/// 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.
void ClobberPhysReg(unsigned PhysReg);
/// ModifyStackSlot - This method is called when the value in a stack slot
/// changes. This removes information about which register the previous value
/// for this slot lives in (as the previous value is dead now).
void ModifyStackSlot(int Slot);
};
/// 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) {
std::multimap<unsigned, int>::iterator I =
PhysRegsAvailable.lower_bound(PhysReg);
while (I != PhysRegsAvailable.end() && I->first == PhysReg) { while (I != PhysRegsAvailable.end() && I->first == PhysReg) {
int Slot = I->second; int Slot = I->second;
PhysRegsAvailable.erase(I++); PhysRegsAvailable.erase(I++);
assert(SpillSlots[Slot] == PhysReg && "Bidirectional map mismatch!"); assert(SpillSlotsAvailable[Slot] == PhysReg &&
SpillSlots.erase(Slot); "Bidirectional map mismatch!");
SpillSlotsAvailable.erase(Slot);
DEBUG(std::cerr << "PhysReg " << MRI->getName(PhysReg) DEBUG(std::cerr << "PhysReg " << MRI->getName(PhysReg)
<< " clobbered, invalidating SS#" << Slot << "\n"); << " clobbered, invalidating SS#" << Slot << "\n");
} }
} }
void LocalSpiller::ClobberPhysReg(unsigned PhysReg, /// ClobberPhysReg - This is called when the specified physreg changes
std::map<int, unsigned> &SpillSlots, /// value. We use this to invalidate any info about stuff we thing lives in
std::multimap<unsigned, int> &PhysRegsAvailable) { /// it and any of its aliases.
void AvailableSpills::ClobberPhysReg(unsigned PhysReg) {
for (const unsigned *AS = MRI->getAliasSet(PhysReg); *AS; ++AS) for (const unsigned *AS = MRI->getAliasSet(PhysReg); *AS; ++AS)
ClobberPhysRegOnly(*AS, SpillSlots, PhysRegsAvailable); ClobberPhysRegOnly(*AS);
ClobberPhysRegOnly(PhysReg, SpillSlots, PhysRegsAvailable); ClobberPhysRegOnly(PhysReg);
} }
/// ModifyStackSlot - This method is called when the value in a stack slot /// ModifyStackSlot - This method is called when the value in a stack slot
/// changes. This removes information about which register the previous value /// changes. This removes information about which register the previous value
/// for this slot lives in (as the previous value is dead now). /// for this slot lives in (as the previous value is dead now).
void LocalSpiller::ModifyStackSlot(int Slot, std::map<int,unsigned> &SpillSlots, void AvailableSpills::ModifyStackSlot(int Slot) {
std::multimap<unsigned, int> &PhysRegsAvailable) { std::map<int, unsigned>::iterator It = SpillSlotsAvailable.find(Slot);
std::map<int, unsigned>::iterator It = SpillSlots.find(Slot); if (It == SpillSlotsAvailable.end()) return;
if (It == SpillSlots.end()) return;
unsigned Reg = It->second; unsigned Reg = It->second;
SpillSlots.erase(It); SpillSlotsAvailable.erase(It);
// This register may hold the value of multiple stack slots, only remove this // This register may hold the value of multiple stack slots, only remove this
// stack slot from the set of values the register contains. // stack slot from the set of values the register contains.
@ -308,18 +362,12 @@ namespace {
/// register allocator is done with them. If possible, avoid reloading vregs. /// register allocator is done with them. If possible, avoid reloading vregs.
void LocalSpiller::RewriteMBB(MachineBasicBlock &MBB, const VirtRegMap &VRM) { void LocalSpiller::RewriteMBB(MachineBasicBlock &MBB, const VirtRegMap &VRM) {
// SpillSlotsAvailable - This map keeps track of all of the spilled virtual
// register values that are still available, due to being loaded or stored to,
// but not invalidated yet.
std::map<int, unsigned> SpillSlotsAvailable;
// PhysRegsAvailable - This is the inverse of SpillSlotsAvailable, indicating
// which stack slot values are currently held by a physreg. This is used to
// invalidate entries in SpillSlotsAvailable when a physreg is modified.
std::multimap<unsigned, int> PhysRegsAvailable;
DEBUG(std::cerr << MBB.getBasicBlock()->getName() << ":\n"); DEBUG(std::cerr << MBB.getBasicBlock()->getName() << ":\n");
// Spills - Keep track of which spilled values are available in physregs so
// that we can choose to reuse the physregs instead of emitting reloads.
AvailableSpills Spills(MRI, TII);
std::vector<ReusedOp> ReusedOperands; std::vector<ReusedOp> ReusedOperands;
// DefAndUseVReg - When we see a def&use operand that is spilled, keep track // DefAndUseVReg - When we see a def&use operand that is spilled, keep track
@ -387,15 +435,12 @@ void LocalSpiller::RewriteMBB(MachineBasicBlock &MBB, const VirtRegMap &VRM) {
unsigned PhysReg; unsigned PhysReg;
// Check to see if this stack slot is available. // Check to see if this stack slot is available.
std::map<int, unsigned>::iterator SSI = if ((PhysReg = Spills.getSpillSlotPhysReg(StackSlot))) {
SpillSlotsAvailable.find(StackSlot); // If this stack slot value is already available, reuse it!
if (SSI != SpillSlotsAvailable.end()) {
DEBUG(std::cerr << "Reusing SS#" << StackSlot << " from physreg " DEBUG(std::cerr << "Reusing SS#" << StackSlot << " from physreg "
<< MRI->getName(SSI->second) << " for vreg" << MRI->getName(PhysReg) << " for vreg"
<< VirtReg <<" instead of reloading into physreg " << VirtReg <<" instead of reloading into physreg "
<< MRI->getName(VRM.getPhys(VirtReg)) << "\n"); << MRI->getName(VRM.getPhys(VirtReg)) << "\n");
// If this stack slot value is already available, reuse it!
PhysReg = SSI->second;
MI.SetMachineOperandReg(i, PhysReg); MI.SetMachineOperandReg(i, PhysReg);
// The only technical detail we have is that we don't know that // The only technical detail we have is that we don't know that
@ -446,20 +491,15 @@ void LocalSpiller::RewriteMBB(MachineBasicBlock &MBB, const VirtRegMap &VRM) {
MBB.getParent()->getSSARegMap()->getRegClass(Op.VirtReg); MBB.getParent()->getSSARegMap()->getRegClass(Op.VirtReg);
MRI->loadRegFromStackSlot(MBB, &MI, Op.AssignedPhysReg, MRI->loadRegFromStackSlot(MBB, &MI, Op.AssignedPhysReg,
Op.StackSlot, AliasRC); Op.StackSlot, AliasRC);
ClobberPhysReg(Op.AssignedPhysReg, SpillSlotsAvailable, Spills.ClobberPhysReg(Op.AssignedPhysReg);
PhysRegsAvailable); Spills.ClobberPhysReg(Op.PhysRegReused);
// Any stores to this stack slot are not dead anymore. // Any stores to this stack slot are not dead anymore.
MaybeDeadStores.erase(Op.StackSlot); MaybeDeadStores.erase(Op.StackSlot);
MI.SetMachineOperandReg(Op.Operand, Op.AssignedPhysReg); MI.SetMachineOperandReg(Op.Operand, Op.AssignedPhysReg);
PhysRegsAvailable.insert(std::make_pair(Op.AssignedPhysReg,
Op.StackSlot)); Spills.addAvailable(Op.StackSlot, Op.AssignedPhysReg);
SpillSlotsAvailable[Op.StackSlot] = Op.AssignedPhysReg;
PhysRegsAvailable.erase(Op.PhysRegReused);
DEBUG(std::cerr << "Remembering SS#" << Op.StackSlot
<< " in physreg "
<< MRI->getName(Op.AssignedPhysReg) << "\n");
++NumLoads; ++NumLoads;
DEBUG(std::cerr << '\t' << *prior(MII)); DEBUG(std::cerr << '\t' << *prior(MII));
@ -473,17 +513,13 @@ void LocalSpiller::RewriteMBB(MachineBasicBlock &MBB, const VirtRegMap &VRM) {
PhysRegsUsed[PhysReg] = true; PhysRegsUsed[PhysReg] = true;
MRI->loadRegFromStackSlot(MBB, &MI, PhysReg, StackSlot, RC); MRI->loadRegFromStackSlot(MBB, &MI, PhysReg, StackSlot, RC);
// This invalidates PhysReg. // This invalidates PhysReg.
ClobberPhysReg(PhysReg, SpillSlotsAvailable, PhysRegsAvailable); Spills.ClobberPhysReg(PhysReg);
// Any stores to this stack slot are not dead anymore. // Any stores to this stack slot are not dead anymore.
MaybeDeadStores.erase(StackSlot); MaybeDeadStores.erase(StackSlot);
Spills.addAvailable(StackSlot, PhysReg);
MI.SetMachineOperandReg(i, PhysReg);
PhysRegsAvailable.insert(std::make_pair(PhysReg, StackSlot));
SpillSlotsAvailable[StackSlot] = PhysReg;
DEBUG(std::cerr << "Remembering SS#" << StackSlot <<" in physreg "
<< MRI->getName(PhysReg) << "\n");
++NumLoads; ++NumLoads;
MI.SetMachineOperandReg(i, PhysReg);
DEBUG(std::cerr << '\t' << *prior(MII)); DEBUG(std::cerr << '\t' << *prior(MII));
} }
@ -492,7 +528,7 @@ void LocalSpiller::RewriteMBB(MachineBasicBlock &MBB, const VirtRegMap &VRM) {
for (const unsigned *ImpDef = TII->getImplicitDefs(MI.getOpcode()); for (const unsigned *ImpDef = TII->getImplicitDefs(MI.getOpcode());
*ImpDef; ++ImpDef) { *ImpDef; ++ImpDef) {
PhysRegsUsed[*ImpDef] = true; PhysRegsUsed[*ImpDef] = true;
ClobberPhysReg(*ImpDef, SpillSlotsAvailable, PhysRegsAvailable); Spills.ClobberPhysReg(*ImpDef);
} }
DEBUG(std::cerr << '\t' << MI); DEBUG(std::cerr << '\t' << MI);
@ -520,12 +556,12 @@ void LocalSpiller::RewriteMBB(MachineBasicBlock &MBB, const VirtRegMap &VRM) {
if (unsigned DestReg = TII->isLoadFromStackSlot(&MI, FrameIdx)) { if (unsigned DestReg = TII->isLoadFromStackSlot(&MI, FrameIdx)) {
// If this spill slot is available, turn it into a copy (or nothing) // If this spill slot is available, turn it into a copy (or nothing)
// instead of leaving it as a load! // instead of leaving it as a load!
std::map<int, unsigned>::iterator It = SpillSlotsAvailable.find(SS); unsigned InReg;
if (FrameIdx == SS && It != SpillSlotsAvailable.end()) { if (FrameIdx == SS && (InReg = Spills.getSpillSlotPhysReg(SS))) {
DEBUG(std::cerr << "Promoted Load To Copy: " << MI); DEBUG(std::cerr << "Promoted Load To Copy: " << MI);
MachineFunction &MF = *MBB.getParent(); MachineFunction &MF = *MBB.getParent();
if (DestReg != It->second) { if (DestReg != InReg) {
MRI->copyRegToReg(MBB, &MI, DestReg, It->second, MRI->copyRegToReg(MBB, &MI, DestReg, InReg,
MF.getSSARegMap()->getRegClass(VirtReg)); MF.getSSARegMap()->getRegClass(VirtReg));
// Revisit the copy so we make sure to notice the effects of the // Revisit the copy so we make sure to notice the effects of the
// operation on the destreg (either needing to RA it if it's // operation on the destreg (either needing to RA it if it's
@ -558,7 +594,7 @@ void LocalSpiller::RewriteMBB(MachineBasicBlock &MBB, const VirtRegMap &VRM) {
// the value, the value is not available anymore. // the value, the value is not available anymore.
if (MR & VirtRegMap::isMod) { if (MR & VirtRegMap::isMod) {
// Notice that the value in this stack slot has been modified. // Notice that the value in this stack slot has been modified.
ModifyStackSlot(SS, SpillSlotsAvailable, PhysRegsAvailable); Spills.ModifyStackSlot(SS);
// If this is *just* a mod of the value, check to see if this is just a // If this is *just* a mod of the value, check to see if this is just a
// store to the spill slot (i.e. the spill got merged into the copy). If // store to the spill slot (i.e. the spill got merged into the copy). If
@ -577,11 +613,7 @@ void LocalSpiller::RewriteMBB(MachineBasicBlock &MBB, const VirtRegMap &VRM) {
// If the stack slot value was previously available in some other // If the stack slot value was previously available in some other
// register, change it now. Otherwise, make the register available, // register, change it now. Otherwise, make the register available,
// in PhysReg. // in PhysReg.
SpillSlotsAvailable[StackSlot] = SrcReg; Spills.addAvailable(StackSlot, SrcReg);
PhysRegsAvailable.insert(std::make_pair(SrcReg, StackSlot));
DEBUG(std::cerr << "Updating SS#" << StackSlot << " in physreg "
<< MRI->getName(SrcReg) << " for virtreg #"
<< VirtReg << "\n" << MI);
} }
} }
} }
@ -616,7 +648,7 @@ void LocalSpiller::RewriteMBB(MachineBasicBlock &MBB, const VirtRegMap &VRM) {
MBB.erase(&MI); MBB.erase(&MI);
goto ProcessNextInst; goto ProcessNextInst;
} }
ClobberPhysReg(VirtReg, SpillSlotsAvailable, PhysRegsAvailable); Spills.ClobberPhysReg(VirtReg);
continue; continue;
} }
} }
@ -664,14 +696,10 @@ void LocalSpiller::RewriteMBB(MachineBasicBlock &MBB, const VirtRegMap &VRM) {
// If the stack slot value was previously available in some other // If the stack slot value was previously available in some other
// register, change it now. Otherwise, make the register available, // register, change it now. Otherwise, make the register available,
// in PhysReg. // in PhysReg.
ModifyStackSlot(StackSlot, SpillSlotsAvailable, PhysRegsAvailable); Spills.ModifyStackSlot(StackSlot);
ClobberPhysReg(PhysReg, SpillSlotsAvailable, PhysRegsAvailable); Spills.ClobberPhysReg(PhysReg);
PhysRegsAvailable.insert(std::make_pair(PhysReg, StackSlot)); Spills.addAvailable(StackSlot, PhysReg);
SpillSlotsAvailable[StackSlot] = PhysReg;
DEBUG(std::cerr << "Updating SS#" << StackSlot <<" in physreg "
<< MRI->getName(PhysReg) << " for virtreg #"
<< VirtReg << "\n");
++NumStores; ++NumStores;
} }
} }