From e077ef6e85fe0c18f135e6c2c78572a44f689b14 Mon Sep 17 00:00:00 2001 From: Evan Cheng Date: Sat, 4 Nov 2006 00:21:55 +0000 Subject: [PATCH] Fixed some spiller bugs exposed by the recent two-address code changes. Now there may be other def(s) apart from the use&def two-address operand. We need to check if the register reuse for a use&def operand may conflicts with another def. Provide a mean to recover from the conflict if it is detected when the defs are processed later. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@31439 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/CodeGen/VirtRegMap.cpp | 74 +++++++++++++++++++++++++++----------- 1 file changed, 53 insertions(+), 21 deletions(-) diff --git a/lib/CodeGen/VirtRegMap.cpp b/lib/CodeGen/VirtRegMap.cpp index 522590a1a9e..7ee139f9a8e 100644 --- a/lib/CodeGen/VirtRegMap.cpp +++ b/lib/CodeGen/VirtRegMap.cpp @@ -394,8 +394,15 @@ namespace { class VISIBILITY_HIDDEN ReuseInfo { MachineInstr &MI; std::vector Reuses; + bool *PhysRegsClobbered; public: - ReuseInfo(MachineInstr &mi) : MI(mi) {} + ReuseInfo(MachineInstr &mi, const MRegisterInfo *mri) : MI(mi) { + PhysRegsClobbered = new bool[mri->getNumRegs()]; + std::fill(PhysRegsClobbered, PhysRegsClobbered+mri->getNumRegs(), false); + } + ~ReuseInfo() { + delete[] PhysRegsClobbered; + } bool hasReuses() const { return !Reuses.empty(); @@ -414,6 +421,14 @@ namespace { Reuses.push_back(ReusedOp(OpNo, StackSlot, PhysRegReused, AssignedPhysReg, VirtReg)); } + + void markClobbered(unsigned PhysReg) { + PhysRegsClobbered[PhysReg] = true; + } + + bool isClobbered(unsigned PhysReg) const { + return PhysRegsClobbered[PhysReg]; + } /// GetRegForReload - We are about to emit a reload into PhysReg. If there /// is some other operand that is using the specified register, either pick @@ -430,11 +445,7 @@ namespace { // register. if (Op.PhysRegReused == PhysReg) { // Yup, use the reload register that we didn't use before. - unsigned NewReg = Op.AssignedPhysReg; - - // Remove the record for the previous reuse. We know it can never be - // invalidated now. - Reuses.erase(Reuses.begin()+ro); + unsigned NewReg = Op.AssignedPhysReg; return GetRegForReload(NewReg, MI, Spills, MaybeDeadStores); } else { // Otherwise, we might also have a problem if a previously reused @@ -518,8 +529,19 @@ void LocalSpiller::RewriteMBB(MachineBasicBlock &MBB, VirtRegMap &VRM) { /// ReusedOperands - Keep track of operand reuse in case we need to undo /// reuse. - ReuseInfo ReusedOperands(MI); - + ReuseInfo ReusedOperands(MI, MRI); + + // Loop over all of the implicit defs, clearing them from our available + // sets. + const unsigned *ImpDef = TII->getImplicitDefs(MI.getOpcode()); + if (ImpDef) { + for ( ; *ImpDef; ++ImpDef) { + PhysRegsUsed[*ImpDef] = true; + ReusedOperands.markClobbered(*ImpDef); + Spills.ClobberPhysReg(*ImpDef); + } + } + // Process all of the spilled uses and all non spilled reg references. for (unsigned i = 0, e = MI.getNumOperands(); i != e; ++i) { MachineOperand &MO = MI.getOperand(i); @@ -530,6 +552,7 @@ void LocalSpiller::RewriteMBB(MachineBasicBlock &MBB, VirtRegMap &VRM) { // Ignore physregs for spilling, but remember that it is used by this // function. PhysRegsUsed[MO.getReg()] = true; + ReusedOperands.markClobbered(MO.getReg()); continue; } @@ -541,6 +564,8 @@ void LocalSpiller::RewriteMBB(MachineBasicBlock &MBB, VirtRegMap &VRM) { // This virtual register was assigned a physreg! unsigned Phys = VRM.getPhys(VirtReg); PhysRegsUsed[Phys] = true; + if (MO.isDef()) + ReusedOperands.markClobbered(Phys); MI.getOperand(i).setReg(Phys); continue; } @@ -567,8 +592,10 @@ void LocalSpiller::RewriteMBB(MachineBasicBlock &MBB, VirtRegMap &VRM) { MI.getOperand(ti).isReg() && MI.getOperand(ti).getReg() == VirtReg) { // Okay, we have a two address operand. We can reuse this physreg as - // long as we are allowed to clobber the value. - CanReuse = Spills.canClobberPhysReg(StackSlot); + // long as we are allowed to clobber the value and there is an earlier + // def that has already clobbered the physreg. + CanReuse = Spills.canClobberPhysReg(StackSlot) && + !ReusedOperands.isClobbered(PhysReg); } if (CanReuse) { @@ -595,6 +622,9 @@ void LocalSpiller::RewriteMBB(MachineBasicBlock &MBB, VirtRegMap &VRM) { // we can get at R0 or its alias. ReusedOperands.addReuse(i, StackSlot, PhysReg, VRM.getPhys(VirtReg), VirtReg); + if (ti != -1) + // Only mark it clobbered if this is a use&def operand. + ReusedOperands.markClobbered(PhysReg); ++NumReused; continue; } @@ -629,6 +659,7 @@ void LocalSpiller::RewriteMBB(MachineBasicBlock &MBB, VirtRegMap &VRM) { << VirtReg << " instead of reloading into same physreg.\n"); MI.getOperand(i).setReg(PhysReg); + ReusedOperands.markClobbered(PhysReg); ++NumReused; continue; } @@ -637,6 +668,7 @@ void LocalSpiller::RewriteMBB(MachineBasicBlock &MBB, VirtRegMap &VRM) { MBB.getParent()->getSSARegMap()->getRegClass(VirtReg); PhysRegsUsed[DesignatedReg] = true; + ReusedOperands.markClobbered(DesignatedReg); MRI->copyRegToReg(MBB, &MI, DesignatedReg, PhysReg, RC); // This invalidates DesignatedReg. @@ -664,6 +696,7 @@ void LocalSpiller::RewriteMBB(MachineBasicBlock &MBB, VirtRegMap &VRM) { Spills, MaybeDeadStores); PhysRegsUsed[PhysReg] = true; + ReusedOperands.markClobbered(PhysReg); MRI->loadRegFromStackSlot(MBB, &MI, PhysReg, StackSlot, RC); // This invalidates PhysReg. Spills.ClobberPhysReg(PhysReg); @@ -676,16 +709,6 @@ void LocalSpiller::RewriteMBB(MachineBasicBlock &MBB, VirtRegMap &VRM) { DEBUG(std::cerr << '\t' << *prior(MII)); } - // Loop over all of the implicit defs, clearing them from our available - // sets. - const unsigned *ImpDef = TII->getImplicitDefs(MI.getOpcode()); - if (ImpDef) { - for ( ; *ImpDef; ++ImpDef) { - PhysRegsUsed[*ImpDef] = true; - Spills.ClobberPhysReg(*ImpDef); - } - } - DEBUG(std::cerr << '\t' << MI); // If we have folded references to memory operands, make sure we clear all @@ -798,6 +821,7 @@ void LocalSpiller::RewriteMBB(MachineBasicBlock &MBB, VirtRegMap &VRM) { // If it's not a no-op copy, it clobbers the value in the destreg. Spills.ClobberPhysReg(VirtReg); + ReusedOperands.markClobbered(VirtReg); // Check to see if this instruction is a load from a stack slot into // a register. If so, this provides the stack slot value in the reg. @@ -824,10 +848,18 @@ void LocalSpiller::RewriteMBB(MachineBasicBlock &MBB, VirtRegMap &VRM) { int TiedOp = TII->findTiedToSrcOperand(MI.getOpcode(), i); if (TiedOp != -1) PhysReg = MI.getOperand(TiedOp).getReg(); - else + else { PhysReg = VRM.getPhys(VirtReg); + if (ReusedOperands.isClobbered(PhysReg)) { + // Another def has taken the assigned physreg. It must have been a + // use&def which got it due to reuse. Undo the reuse! + PhysReg = ReusedOperands.GetRegForReload(PhysReg, &MI, + Spills, MaybeDeadStores); + } + } PhysRegsUsed[PhysReg] = true; + ReusedOperands.markClobbered(PhysReg); MRI->storeRegToStackSlot(MBB, next(MII), PhysReg, StackSlot, RC); DEBUG(std::cerr << "Store:\t" << *next(MII)); MI.getOperand(i).setReg(PhysReg); -- 2.34.1