Changes in directory llvm/lib/CodeGen:
VirtRegMap.cpp updated: 1.58 -> 1.59 --- Log message: When we have a two-address instruction where the input cannot be clobbered and is already available, instead of falling back to emitting a load, fall back to emitting a reg-reg copy. This generates significantly better code for some SSE testcases, as SSE has lots of two-address instructions and none of them are read/modify/write. As one example, this change does: pshufd %XMM5, XMMWORD PTR [%ESP + 84], 255 xorps %XMM2, %XMM5 cmpltps %XMM1, %XMM0 - movaps XMMWORD PTR [%ESP + 52], %XMM0 - movapd %XMM6, XMMWORD PTR [%ESP + 52] + movaps %XMM6, %XMM0 cmpltps %XMM6, XMMWORD PTR [%ESP + 68] movapd XMMWORD PTR [%ESP + 52], %XMM6 movaps %XMM6, %XMM0 cmpltps %XMM6, XMMWORD PTR [%ESP + 36] cmpltps %XMM3, %XMM0 - movaps XMMWORD PTR [%ESP + 20], %XMM0 - movapd %XMM7, XMMWORD PTR [%ESP + 20] + movaps %XMM7, %XMM0 cmpltps %XMM7, XMMWORD PTR [%ESP + 4] movapd XMMWORD PTR [%ESP + 20], %XMM7 cmpltps %XMM4, %XMM0 ... which is far better than a store followed by a load! --- Diffs of the changes: (+63 -25) VirtRegMap.cpp | 88 ++++++++++++++++++++++++++++++++++++++++----------------- 1 files changed, 63 insertions(+), 25 deletions(-) Index: llvm/lib/CodeGen/VirtRegMap.cpp diff -u llvm/lib/CodeGen/VirtRegMap.cpp:1.58 llvm/lib/CodeGen/VirtRegMap.cpp:1.59 --- llvm/lib/CodeGen/VirtRegMap.cpp:1.58 Fri Feb 24 20:17:31 2006 +++ llvm/lib/CodeGen/VirtRegMap.cpp Thu Apr 27 20:46:50 2006 @@ -558,33 +558,71 @@ unsigned PhysReg; // Check to see if this stack slot is available. - if ((PhysReg = Spills.getSpillSlotPhysReg(StackSlot)) && - // Don't reuse it for a def&use operand if we aren't allowed to change - // the physreg! - (!MO.isDef() || Spills.canClobberPhysReg(StackSlot))) { - // If this stack slot value is already available, reuse it! - DEBUG(std::cerr << "Reusing SS#" << StackSlot << " from physreg " - << MRI->getName(PhysReg) << " for vreg" - << VirtReg <<" instead of reloading into physreg " - << MRI->getName(VRM.getPhys(VirtReg)) << "\n"); - MI.SetMachineOperandReg(i, PhysReg); + if ((PhysReg = Spills.getSpillSlotPhysReg(StackSlot))) { - // The only technical detail we have is that we don't know that - // PhysReg won't be clobbered by a reloaded stack slot that occurs - // later in the instruction. In particular, consider 'op V1, V2'. - // If V1 is available in physreg R0, we would choose to reuse it - // here, instead of reloading it into the register the allocator - // indicated (say R1). However, V2 might have to be reloaded - // later, and it might indicate that it needs to live in R0. When - // this occurs, we need to have information available that - // indicates it is safe to use R1 for the reload instead of R0. + // Don't reuse it for a def&use operand if we aren't allowed to change + // the physreg! + if (!MO.isDef() || Spills.canClobberPhysReg(StackSlot)) { + // If this stack slot value is already available, reuse it! + DEBUG(std::cerr << "Reusing SS#" << StackSlot << " from physreg " + << MRI->getName(PhysReg) << " for vreg" + << VirtReg <<" instead of reloading into physreg " + << MRI->getName(VRM.getPhys(VirtReg)) << "\n"); + MI.SetMachineOperandReg(i, PhysReg); + + // The only technical detail we have is that we don't know that + // PhysReg won't be clobbered by a reloaded stack slot that occurs + // later in the instruction. In particular, consider 'op V1, V2'. + // If V1 is available in physreg R0, we would choose to reuse it + // here, instead of reloading it into the register the allocator + // indicated (say R1). However, V2 might have to be reloaded + // later, and it might indicate that it needs to live in R0. When + // this occurs, we need to have information available that + // indicates it is safe to use R1 for the reload instead of R0. + // + // To further complicate matters, we might conflict with an alias, + // or R0 and R1 might not be compatible with each other. In this + // case, we actually insert a reload for V1 in R1, ensuring that + // we can get at R0 or its alias. + ReusedOperands.addReuse(i, StackSlot, PhysReg, + VRM.getPhys(VirtReg), VirtReg); + ++NumReused; + continue; + } + + // Otherwise we have a situation where we have a two-address instruction + // whose mod/ref operand needs to be reloaded. This reload is already + // available in some register "PhysReg", but if we used PhysReg as the + // operand to our 2-addr instruction, the instruction would modify + // PhysReg. This isn't cool if something later uses PhysReg and expects + // to get its initial value. // - // To further complicate matters, we might conflict with an alias, - // or R0 and R1 might not be compatible with each other. In this - // case, we actually insert a reload for V1 in R1, ensuring that - // we can get at R0 or its alias. - ReusedOperands.addReuse(i, StackSlot, PhysReg, - VRM.getPhys(VirtReg), VirtReg); + // To avoid this problem, and to avoid doing a load right after a store, + // we emit a copy from PhysReg into the designated register for this + // operand. + unsigned DesignatedReg = VRM.getPhys(VirtReg); + assert(DesignatedReg && "Must map virtreg to physreg!"); + + // Note that, if we reused a register for a previous operand, the + // register we want to reload into might not actually be + // available. If this occurs, use the register indicated by the + // reuser. + if (ReusedOperands.hasReuses()) + DesignatedReg = ReusedOperands.GetRegForReload(DesignatedReg, &MI, + Spills, MaybeDeadStores); + + const TargetRegisterClass* RC = + MBB.getParent()->getSSARegMap()->getRegClass(VirtReg); + + PhysRegsUsed[DesignatedReg] = true; + MRI->copyRegToReg(MBB, &MI, DesignatedReg, PhysReg, RC); + + // This invalidates DesignatedReg. + Spills.ClobberPhysReg(DesignatedReg); + + Spills.addAvailable(StackSlot, DesignatedReg); + MI.SetMachineOperandReg(i, DesignatedReg); + DEBUG(std::cerr << '\t' << *prior(MII)); ++NumReused; continue; } _______________________________________________ llvm-commits mailing list llvm-commits@cs.uiuc.edu http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits