mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-06-21 02:24:22 +00:00
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! git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@28001 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
@ -558,10 +558,11 @@ void LocalSpiller::RewriteMBB(MachineBasicBlock &MBB, const VirtRegMap &VRM) {
|
||||
unsigned PhysReg;
|
||||
|
||||
// Check to see if this stack slot is available.
|
||||
if ((PhysReg = Spills.getSpillSlotPhysReg(StackSlot)) &&
|
||||
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 (!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"
|
||||
@ -589,6 +590,43 @@ void LocalSpiller::RewriteMBB(MachineBasicBlock &MBB, const VirtRegMap &VRM) {
|
||||
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 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;
|
||||
}
|
||||
|
||||
// Otherwise, reload it and remember that we have it.
|
||||
PhysReg = VRM.getPhys(VirtReg);
|
||||
assert(PhysReg && "Must map virtreg to physreg!");
|
||||
|
Reference in New Issue
Block a user