diff options
Diffstat (limited to 'llvm/lib/Target/X86/X86ExpandPseudo.cpp')
-rw-r--r-- | llvm/lib/Target/X86/X86ExpandPseudo.cpp | 32 |
1 files changed, 32 insertions, 0 deletions
diff --git a/llvm/lib/Target/X86/X86ExpandPseudo.cpp b/llvm/lib/Target/X86/X86ExpandPseudo.cpp index 2af2be621ff..d7d0d3cb561 100644 --- a/llvm/lib/Target/X86/X86ExpandPseudo.cpp +++ b/llvm/lib/Target/X86/X86ExpandPseudo.cpp @@ -186,6 +186,38 @@ bool X86ExpandPseudo::ExpandMI(MachineBasicBlock &MBB, MBBI->eraseFromParent(); return true; } + case X86::LCMPXCHG8B_SAVE_EBX: + case X86::LCMPXCHG16B_SAVE_RBX: { + // Perform the following transformation. + // SaveRbx = pseudocmpxchg Addr, <4 opds for the address>, InArg, SaveRbx + // => + // [E|R]BX = InArg + // actualcmpxchg Addr + // [E|R]BX = SaveRbx + const MachineOperand &InArg = MBBI->getOperand(6); + unsigned SaveRbx = MBBI->getOperand(7).getReg(); + + unsigned ActualInArg = + Opcode == X86::LCMPXCHG8B_SAVE_EBX ? X86::EBX : X86::RBX; + // Copy the input argument of the pseudo into the argument of the + // actual instruction. + TII->copyPhysReg(MBB, MBBI, DL, ActualInArg, InArg.getReg(), + InArg.isKill()); + // Create the actual instruction. + unsigned ActualOpc = + Opcode == X86::LCMPXCHG8B_SAVE_EBX ? X86::LCMPXCHG8B : X86::LCMPXCHG16B; + MachineInstr *NewInstr = BuildMI(MBB, MBBI, DL, TII->get(ActualOpc)); + // Copy the operands related to the address. + for (unsigned Idx = 1; Idx < 6; ++Idx) + NewInstr->addOperand(MBBI->getOperand(Idx)); + // Finally, restore the value of RBX. + TII->copyPhysReg(MBB, MBBI, DL, ActualInArg, SaveRbx, + /*SrcIsKill*/ true); + + // Delete the pseudo. + MBBI->eraseFromParent(); + return true; + } } llvm_unreachable("Previous switch has a fallthrough?"); } |