xref: /freebsd/contrib/llvm-project/llvm/lib/Target/X86/X86ExpandPseudo.cpp (revision 480093f4440d54b30b3025afeac24b48f2ba7a2e)
10b57cec5SDimitry Andric //===------- X86ExpandPseudo.cpp - Expand pseudo instructions -------------===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric //
90b57cec5SDimitry Andric // This file contains a pass that expands pseudo instructions into target
100b57cec5SDimitry Andric // instructions to allow proper scheduling, if-conversion, other late
110b57cec5SDimitry Andric // optimizations, or simply the encoding of the instructions.
120b57cec5SDimitry Andric //
130b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
140b57cec5SDimitry Andric 
150b57cec5SDimitry Andric #include "X86.h"
160b57cec5SDimitry Andric #include "X86FrameLowering.h"
170b57cec5SDimitry Andric #include "X86InstrBuilder.h"
180b57cec5SDimitry Andric #include "X86InstrInfo.h"
190b57cec5SDimitry Andric #include "X86MachineFunctionInfo.h"
200b57cec5SDimitry Andric #include "X86Subtarget.h"
210b57cec5SDimitry Andric #include "llvm/Analysis/EHPersonalities.h"
220b57cec5SDimitry Andric #include "llvm/CodeGen/MachineFunctionPass.h"
230b57cec5SDimitry Andric #include "llvm/CodeGen/MachineInstrBuilder.h"
240b57cec5SDimitry Andric #include "llvm/CodeGen/Passes.h" // For IDs of passes that are preserved.
250b57cec5SDimitry Andric #include "llvm/IR/GlobalValue.h"
260b57cec5SDimitry Andric using namespace llvm;
270b57cec5SDimitry Andric 
280b57cec5SDimitry Andric #define DEBUG_TYPE "x86-pseudo"
290b57cec5SDimitry Andric #define X86_EXPAND_PSEUDO_NAME "X86 pseudo instruction expansion pass"
300b57cec5SDimitry Andric 
310b57cec5SDimitry Andric namespace {
320b57cec5SDimitry Andric class X86ExpandPseudo : public MachineFunctionPass {
330b57cec5SDimitry Andric public:
340b57cec5SDimitry Andric   static char ID;
350b57cec5SDimitry Andric   X86ExpandPseudo() : MachineFunctionPass(ID) {}
360b57cec5SDimitry Andric 
370b57cec5SDimitry Andric   void getAnalysisUsage(AnalysisUsage &AU) const override {
380b57cec5SDimitry Andric     AU.setPreservesCFG();
390b57cec5SDimitry Andric     AU.addPreservedID(MachineLoopInfoID);
400b57cec5SDimitry Andric     AU.addPreservedID(MachineDominatorsID);
410b57cec5SDimitry Andric     MachineFunctionPass::getAnalysisUsage(AU);
420b57cec5SDimitry Andric   }
430b57cec5SDimitry Andric 
44*480093f4SDimitry Andric   const X86Subtarget *STI = nullptr;
45*480093f4SDimitry Andric   const X86InstrInfo *TII = nullptr;
46*480093f4SDimitry Andric   const X86RegisterInfo *TRI = nullptr;
47*480093f4SDimitry Andric   const X86MachineFunctionInfo *X86FI = nullptr;
48*480093f4SDimitry Andric   const X86FrameLowering *X86FL = nullptr;
490b57cec5SDimitry Andric 
500b57cec5SDimitry Andric   bool runOnMachineFunction(MachineFunction &Fn) override;
510b57cec5SDimitry Andric 
520b57cec5SDimitry Andric   MachineFunctionProperties getRequiredProperties() const override {
530b57cec5SDimitry Andric     return MachineFunctionProperties().set(
540b57cec5SDimitry Andric         MachineFunctionProperties::Property::NoVRegs);
550b57cec5SDimitry Andric   }
560b57cec5SDimitry Andric 
570b57cec5SDimitry Andric   StringRef getPassName() const override {
580b57cec5SDimitry Andric     return "X86 pseudo instruction expansion pass";
590b57cec5SDimitry Andric   }
600b57cec5SDimitry Andric 
610b57cec5SDimitry Andric private:
620b57cec5SDimitry Andric   void ExpandICallBranchFunnel(MachineBasicBlock *MBB,
630b57cec5SDimitry Andric                                MachineBasicBlock::iterator MBBI);
640b57cec5SDimitry Andric 
650b57cec5SDimitry Andric   bool ExpandMI(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI);
660b57cec5SDimitry Andric   bool ExpandMBB(MachineBasicBlock &MBB);
670b57cec5SDimitry Andric };
680b57cec5SDimitry Andric char X86ExpandPseudo::ID = 0;
690b57cec5SDimitry Andric 
700b57cec5SDimitry Andric } // End anonymous namespace.
710b57cec5SDimitry Andric 
720b57cec5SDimitry Andric INITIALIZE_PASS(X86ExpandPseudo, DEBUG_TYPE, X86_EXPAND_PSEUDO_NAME, false,
730b57cec5SDimitry Andric                 false)
740b57cec5SDimitry Andric 
750b57cec5SDimitry Andric void X86ExpandPseudo::ExpandICallBranchFunnel(
760b57cec5SDimitry Andric     MachineBasicBlock *MBB, MachineBasicBlock::iterator MBBI) {
770b57cec5SDimitry Andric   MachineBasicBlock *JTMBB = MBB;
780b57cec5SDimitry Andric   MachineInstr *JTInst = &*MBBI;
790b57cec5SDimitry Andric   MachineFunction *MF = MBB->getParent();
800b57cec5SDimitry Andric   const BasicBlock *BB = MBB->getBasicBlock();
810b57cec5SDimitry Andric   auto InsPt = MachineFunction::iterator(MBB);
820b57cec5SDimitry Andric   ++InsPt;
830b57cec5SDimitry Andric 
840b57cec5SDimitry Andric   std::vector<std::pair<MachineBasicBlock *, unsigned>> TargetMBBs;
850b57cec5SDimitry Andric   DebugLoc DL = JTInst->getDebugLoc();
860b57cec5SDimitry Andric   MachineOperand Selector = JTInst->getOperand(0);
870b57cec5SDimitry Andric   const GlobalValue *CombinedGlobal = JTInst->getOperand(1).getGlobal();
880b57cec5SDimitry Andric 
890b57cec5SDimitry Andric   auto CmpTarget = [&](unsigned Target) {
900b57cec5SDimitry Andric     if (Selector.isReg())
910b57cec5SDimitry Andric       MBB->addLiveIn(Selector.getReg());
920b57cec5SDimitry Andric     BuildMI(*MBB, MBBI, DL, TII->get(X86::LEA64r), X86::R11)
930b57cec5SDimitry Andric         .addReg(X86::RIP)
940b57cec5SDimitry Andric         .addImm(1)
950b57cec5SDimitry Andric         .addReg(0)
960b57cec5SDimitry Andric         .addGlobalAddress(CombinedGlobal,
970b57cec5SDimitry Andric                           JTInst->getOperand(2 + 2 * Target).getImm())
980b57cec5SDimitry Andric         .addReg(0);
990b57cec5SDimitry Andric     BuildMI(*MBB, MBBI, DL, TII->get(X86::CMP64rr))
1000b57cec5SDimitry Andric         .add(Selector)
1010b57cec5SDimitry Andric         .addReg(X86::R11);
1020b57cec5SDimitry Andric   };
1030b57cec5SDimitry Andric 
1040b57cec5SDimitry Andric   auto CreateMBB = [&]() {
1050b57cec5SDimitry Andric     auto *NewMBB = MF->CreateMachineBasicBlock(BB);
1060b57cec5SDimitry Andric     MBB->addSuccessor(NewMBB);
1070b57cec5SDimitry Andric     if (!MBB->isLiveIn(X86::EFLAGS))
1080b57cec5SDimitry Andric       MBB->addLiveIn(X86::EFLAGS);
1090b57cec5SDimitry Andric     return NewMBB;
1100b57cec5SDimitry Andric   };
1110b57cec5SDimitry Andric 
1120b57cec5SDimitry Andric   auto EmitCondJump = [&](unsigned CC, MachineBasicBlock *ThenMBB) {
1130b57cec5SDimitry Andric     BuildMI(*MBB, MBBI, DL, TII->get(X86::JCC_1)).addMBB(ThenMBB).addImm(CC);
1140b57cec5SDimitry Andric 
1150b57cec5SDimitry Andric     auto *ElseMBB = CreateMBB();
1160b57cec5SDimitry Andric     MF->insert(InsPt, ElseMBB);
1170b57cec5SDimitry Andric     MBB = ElseMBB;
1180b57cec5SDimitry Andric     MBBI = MBB->end();
1190b57cec5SDimitry Andric   };
1200b57cec5SDimitry Andric 
1210b57cec5SDimitry Andric   auto EmitCondJumpTarget = [&](unsigned CC, unsigned Target) {
1220b57cec5SDimitry Andric     auto *ThenMBB = CreateMBB();
1230b57cec5SDimitry Andric     TargetMBBs.push_back({ThenMBB, Target});
1240b57cec5SDimitry Andric     EmitCondJump(CC, ThenMBB);
1250b57cec5SDimitry Andric   };
1260b57cec5SDimitry Andric 
1270b57cec5SDimitry Andric   auto EmitTailCall = [&](unsigned Target) {
1280b57cec5SDimitry Andric     BuildMI(*MBB, MBBI, DL, TII->get(X86::TAILJMPd64))
1290b57cec5SDimitry Andric         .add(JTInst->getOperand(3 + 2 * Target));
1300b57cec5SDimitry Andric   };
1310b57cec5SDimitry Andric 
1320b57cec5SDimitry Andric   std::function<void(unsigned, unsigned)> EmitBranchFunnel =
1330b57cec5SDimitry Andric       [&](unsigned FirstTarget, unsigned NumTargets) {
1340b57cec5SDimitry Andric     if (NumTargets == 1) {
1350b57cec5SDimitry Andric       EmitTailCall(FirstTarget);
1360b57cec5SDimitry Andric       return;
1370b57cec5SDimitry Andric     }
1380b57cec5SDimitry Andric 
1390b57cec5SDimitry Andric     if (NumTargets == 2) {
1400b57cec5SDimitry Andric       CmpTarget(FirstTarget + 1);
1410b57cec5SDimitry Andric       EmitCondJumpTarget(X86::COND_B, FirstTarget);
1420b57cec5SDimitry Andric       EmitTailCall(FirstTarget + 1);
1430b57cec5SDimitry Andric       return;
1440b57cec5SDimitry Andric     }
1450b57cec5SDimitry Andric 
1460b57cec5SDimitry Andric     if (NumTargets < 6) {
1470b57cec5SDimitry Andric       CmpTarget(FirstTarget + 1);
1480b57cec5SDimitry Andric       EmitCondJumpTarget(X86::COND_B, FirstTarget);
1490b57cec5SDimitry Andric       EmitCondJumpTarget(X86::COND_E, FirstTarget + 1);
1500b57cec5SDimitry Andric       EmitBranchFunnel(FirstTarget + 2, NumTargets - 2);
1510b57cec5SDimitry Andric       return;
1520b57cec5SDimitry Andric     }
1530b57cec5SDimitry Andric 
1540b57cec5SDimitry Andric     auto *ThenMBB = CreateMBB();
1550b57cec5SDimitry Andric     CmpTarget(FirstTarget + (NumTargets / 2));
1560b57cec5SDimitry Andric     EmitCondJump(X86::COND_B, ThenMBB);
1570b57cec5SDimitry Andric     EmitCondJumpTarget(X86::COND_E, FirstTarget + (NumTargets / 2));
1580b57cec5SDimitry Andric     EmitBranchFunnel(FirstTarget + (NumTargets / 2) + 1,
1590b57cec5SDimitry Andric                   NumTargets - (NumTargets / 2) - 1);
1600b57cec5SDimitry Andric 
1610b57cec5SDimitry Andric     MF->insert(InsPt, ThenMBB);
1620b57cec5SDimitry Andric     MBB = ThenMBB;
1630b57cec5SDimitry Andric     MBBI = MBB->end();
1640b57cec5SDimitry Andric     EmitBranchFunnel(FirstTarget, NumTargets / 2);
1650b57cec5SDimitry Andric   };
1660b57cec5SDimitry Andric 
1670b57cec5SDimitry Andric   EmitBranchFunnel(0, (JTInst->getNumOperands() - 2) / 2);
1680b57cec5SDimitry Andric   for (auto P : TargetMBBs) {
1690b57cec5SDimitry Andric     MF->insert(InsPt, P.first);
1700b57cec5SDimitry Andric     BuildMI(P.first, DL, TII->get(X86::TAILJMPd64))
1710b57cec5SDimitry Andric         .add(JTInst->getOperand(3 + 2 * P.second));
1720b57cec5SDimitry Andric   }
1730b57cec5SDimitry Andric   JTMBB->erase(JTInst);
1740b57cec5SDimitry Andric }
1750b57cec5SDimitry Andric 
1760b57cec5SDimitry Andric /// If \p MBBI is a pseudo instruction, this method expands
1770b57cec5SDimitry Andric /// it to the corresponding (sequence of) actual instruction(s).
1780b57cec5SDimitry Andric /// \returns true if \p MBBI has been expanded.
1790b57cec5SDimitry Andric bool X86ExpandPseudo::ExpandMI(MachineBasicBlock &MBB,
1800b57cec5SDimitry Andric                                MachineBasicBlock::iterator MBBI) {
1810b57cec5SDimitry Andric   MachineInstr &MI = *MBBI;
1820b57cec5SDimitry Andric   unsigned Opcode = MI.getOpcode();
1830b57cec5SDimitry Andric   DebugLoc DL = MBBI->getDebugLoc();
1840b57cec5SDimitry Andric   switch (Opcode) {
1850b57cec5SDimitry Andric   default:
1860b57cec5SDimitry Andric     return false;
1870b57cec5SDimitry Andric   case X86::TCRETURNdi:
1880b57cec5SDimitry Andric   case X86::TCRETURNdicc:
1890b57cec5SDimitry Andric   case X86::TCRETURNri:
1900b57cec5SDimitry Andric   case X86::TCRETURNmi:
1910b57cec5SDimitry Andric   case X86::TCRETURNdi64:
1920b57cec5SDimitry Andric   case X86::TCRETURNdi64cc:
1930b57cec5SDimitry Andric   case X86::TCRETURNri64:
1940b57cec5SDimitry Andric   case X86::TCRETURNmi64: {
1950b57cec5SDimitry Andric     bool isMem = Opcode == X86::TCRETURNmi || Opcode == X86::TCRETURNmi64;
1960b57cec5SDimitry Andric     MachineOperand &JumpTarget = MBBI->getOperand(0);
1978bcb0991SDimitry Andric     MachineOperand &StackAdjust = MBBI->getOperand(isMem ? X86::AddrNumOperands
1988bcb0991SDimitry Andric                                                          : 1);
1990b57cec5SDimitry Andric     assert(StackAdjust.isImm() && "Expecting immediate value.");
2000b57cec5SDimitry Andric 
2010b57cec5SDimitry Andric     // Adjust stack pointer.
2020b57cec5SDimitry Andric     int StackAdj = StackAdjust.getImm();
2030b57cec5SDimitry Andric     int MaxTCDelta = X86FI->getTCReturnAddrDelta();
2040b57cec5SDimitry Andric     int Offset = 0;
2050b57cec5SDimitry Andric     assert(MaxTCDelta <= 0 && "MaxTCDelta should never be positive");
2060b57cec5SDimitry Andric 
2070b57cec5SDimitry Andric     // Incoporate the retaddr area.
2080b57cec5SDimitry Andric     Offset = StackAdj - MaxTCDelta;
2090b57cec5SDimitry Andric     assert(Offset >= 0 && "Offset should never be negative");
2100b57cec5SDimitry Andric 
2110b57cec5SDimitry Andric     if (Opcode == X86::TCRETURNdicc || Opcode == X86::TCRETURNdi64cc) {
2120b57cec5SDimitry Andric       assert(Offset == 0 && "Conditional tail call cannot adjust the stack.");
2130b57cec5SDimitry Andric     }
2140b57cec5SDimitry Andric 
2150b57cec5SDimitry Andric     if (Offset) {
2160b57cec5SDimitry Andric       // Check for possible merge with preceding ADD instruction.
2170b57cec5SDimitry Andric       Offset += X86FL->mergeSPUpdates(MBB, MBBI, true);
2180b57cec5SDimitry Andric       X86FL->emitSPUpdate(MBB, MBBI, DL, Offset, /*InEpilogue=*/true);
2190b57cec5SDimitry Andric     }
2200b57cec5SDimitry Andric 
2210b57cec5SDimitry Andric     // Jump to label or value in register.
2220b57cec5SDimitry Andric     bool IsWin64 = STI->isTargetWin64();
2230b57cec5SDimitry Andric     if (Opcode == X86::TCRETURNdi || Opcode == X86::TCRETURNdicc ||
2240b57cec5SDimitry Andric         Opcode == X86::TCRETURNdi64 || Opcode == X86::TCRETURNdi64cc) {
2250b57cec5SDimitry Andric       unsigned Op;
2260b57cec5SDimitry Andric       switch (Opcode) {
2270b57cec5SDimitry Andric       case X86::TCRETURNdi:
2280b57cec5SDimitry Andric         Op = X86::TAILJMPd;
2290b57cec5SDimitry Andric         break;
2300b57cec5SDimitry Andric       case X86::TCRETURNdicc:
2310b57cec5SDimitry Andric         Op = X86::TAILJMPd_CC;
2320b57cec5SDimitry Andric         break;
2330b57cec5SDimitry Andric       case X86::TCRETURNdi64cc:
2340b57cec5SDimitry Andric         assert(!MBB.getParent()->hasWinCFI() &&
2350b57cec5SDimitry Andric                "Conditional tail calls confuse "
2360b57cec5SDimitry Andric                "the Win64 unwinder.");
2370b57cec5SDimitry Andric         Op = X86::TAILJMPd64_CC;
2380b57cec5SDimitry Andric         break;
2390b57cec5SDimitry Andric       default:
2400b57cec5SDimitry Andric         // Note: Win64 uses REX prefixes indirect jumps out of functions, but
2410b57cec5SDimitry Andric         // not direct ones.
2420b57cec5SDimitry Andric         Op = X86::TAILJMPd64;
2430b57cec5SDimitry Andric         break;
2440b57cec5SDimitry Andric       }
2450b57cec5SDimitry Andric       MachineInstrBuilder MIB = BuildMI(MBB, MBBI, DL, TII->get(Op));
2460b57cec5SDimitry Andric       if (JumpTarget.isGlobal()) {
2470b57cec5SDimitry Andric         MIB.addGlobalAddress(JumpTarget.getGlobal(), JumpTarget.getOffset(),
2480b57cec5SDimitry Andric                              JumpTarget.getTargetFlags());
2490b57cec5SDimitry Andric       } else {
2500b57cec5SDimitry Andric         assert(JumpTarget.isSymbol());
2510b57cec5SDimitry Andric         MIB.addExternalSymbol(JumpTarget.getSymbolName(),
2520b57cec5SDimitry Andric                               JumpTarget.getTargetFlags());
2530b57cec5SDimitry Andric       }
2540b57cec5SDimitry Andric       if (Op == X86::TAILJMPd_CC || Op == X86::TAILJMPd64_CC) {
2550b57cec5SDimitry Andric         MIB.addImm(MBBI->getOperand(2).getImm());
2560b57cec5SDimitry Andric       }
2570b57cec5SDimitry Andric 
2580b57cec5SDimitry Andric     } else if (Opcode == X86::TCRETURNmi || Opcode == X86::TCRETURNmi64) {
2590b57cec5SDimitry Andric       unsigned Op = (Opcode == X86::TCRETURNmi)
2600b57cec5SDimitry Andric                         ? X86::TAILJMPm
2610b57cec5SDimitry Andric                         : (IsWin64 ? X86::TAILJMPm64_REX : X86::TAILJMPm64);
2620b57cec5SDimitry Andric       MachineInstrBuilder MIB = BuildMI(MBB, MBBI, DL, TII->get(Op));
2638bcb0991SDimitry Andric       for (unsigned i = 0; i != X86::AddrNumOperands; ++i)
2640b57cec5SDimitry Andric         MIB.add(MBBI->getOperand(i));
2650b57cec5SDimitry Andric     } else if (Opcode == X86::TCRETURNri64) {
2660b57cec5SDimitry Andric       JumpTarget.setIsKill();
2670b57cec5SDimitry Andric       BuildMI(MBB, MBBI, DL,
2680b57cec5SDimitry Andric               TII->get(IsWin64 ? X86::TAILJMPr64_REX : X86::TAILJMPr64))
2690b57cec5SDimitry Andric           .add(JumpTarget);
2700b57cec5SDimitry Andric     } else {
2710b57cec5SDimitry Andric       JumpTarget.setIsKill();
2720b57cec5SDimitry Andric       BuildMI(MBB, MBBI, DL, TII->get(X86::TAILJMPr))
2730b57cec5SDimitry Andric           .add(JumpTarget);
2740b57cec5SDimitry Andric     }
2750b57cec5SDimitry Andric 
2760b57cec5SDimitry Andric     MachineInstr &NewMI = *std::prev(MBBI);
2770b57cec5SDimitry Andric     NewMI.copyImplicitOps(*MBBI->getParent()->getParent(), *MBBI);
2788bcb0991SDimitry Andric     MBB.getParent()->moveCallSiteInfo(&*MBBI, &NewMI);
2790b57cec5SDimitry Andric 
2800b57cec5SDimitry Andric     // Delete the pseudo instruction TCRETURN.
2810b57cec5SDimitry Andric     MBB.erase(MBBI);
2820b57cec5SDimitry Andric 
2830b57cec5SDimitry Andric     return true;
2840b57cec5SDimitry Andric   }
2850b57cec5SDimitry Andric   case X86::EH_RETURN:
2860b57cec5SDimitry Andric   case X86::EH_RETURN64: {
2870b57cec5SDimitry Andric     MachineOperand &DestAddr = MBBI->getOperand(0);
2880b57cec5SDimitry Andric     assert(DestAddr.isReg() && "Offset should be in register!");
2890b57cec5SDimitry Andric     const bool Uses64BitFramePtr =
2900b57cec5SDimitry Andric         STI->isTarget64BitLP64() || STI->isTargetNaCl64();
2918bcb0991SDimitry Andric     Register StackPtr = TRI->getStackRegister();
2920b57cec5SDimitry Andric     BuildMI(MBB, MBBI, DL,
2930b57cec5SDimitry Andric             TII->get(Uses64BitFramePtr ? X86::MOV64rr : X86::MOV32rr), StackPtr)
2940b57cec5SDimitry Andric         .addReg(DestAddr.getReg());
2950b57cec5SDimitry Andric     // The EH_RETURN pseudo is really removed during the MC Lowering.
2960b57cec5SDimitry Andric     return true;
2970b57cec5SDimitry Andric   }
2980b57cec5SDimitry Andric   case X86::IRET: {
2990b57cec5SDimitry Andric     // Adjust stack to erase error code
3000b57cec5SDimitry Andric     int64_t StackAdj = MBBI->getOperand(0).getImm();
3010b57cec5SDimitry Andric     X86FL->emitSPUpdate(MBB, MBBI, DL, StackAdj, true);
3020b57cec5SDimitry Andric     // Replace pseudo with machine iret
3030b57cec5SDimitry Andric     BuildMI(MBB, MBBI, DL,
3040b57cec5SDimitry Andric             TII->get(STI->is64Bit() ? X86::IRET64 : X86::IRET32));
3050b57cec5SDimitry Andric     MBB.erase(MBBI);
3060b57cec5SDimitry Andric     return true;
3070b57cec5SDimitry Andric   }
3080b57cec5SDimitry Andric   case X86::RET: {
3090b57cec5SDimitry Andric     // Adjust stack to erase error code
3100b57cec5SDimitry Andric     int64_t StackAdj = MBBI->getOperand(0).getImm();
3110b57cec5SDimitry Andric     MachineInstrBuilder MIB;
3120b57cec5SDimitry Andric     if (StackAdj == 0) {
3130b57cec5SDimitry Andric       MIB = BuildMI(MBB, MBBI, DL,
3140b57cec5SDimitry Andric                     TII->get(STI->is64Bit() ? X86::RETQ : X86::RETL));
3150b57cec5SDimitry Andric     } else if (isUInt<16>(StackAdj)) {
3160b57cec5SDimitry Andric       MIB = BuildMI(MBB, MBBI, DL,
3170b57cec5SDimitry Andric                     TII->get(STI->is64Bit() ? X86::RETIQ : X86::RETIL))
3180b57cec5SDimitry Andric                 .addImm(StackAdj);
3190b57cec5SDimitry Andric     } else {
3200b57cec5SDimitry Andric       assert(!STI->is64Bit() &&
3210b57cec5SDimitry Andric              "shouldn't need to do this for x86_64 targets!");
3220b57cec5SDimitry Andric       // A ret can only handle immediates as big as 2**16-1.  If we need to pop
3230b57cec5SDimitry Andric       // off bytes before the return address, we must do it manually.
3240b57cec5SDimitry Andric       BuildMI(MBB, MBBI, DL, TII->get(X86::POP32r)).addReg(X86::ECX, RegState::Define);
3250b57cec5SDimitry Andric       X86FL->emitSPUpdate(MBB, MBBI, DL, StackAdj, /*InEpilogue=*/true);
3260b57cec5SDimitry Andric       BuildMI(MBB, MBBI, DL, TII->get(X86::PUSH32r)).addReg(X86::ECX);
3270b57cec5SDimitry Andric       MIB = BuildMI(MBB, MBBI, DL, TII->get(X86::RETL));
3280b57cec5SDimitry Andric     }
3290b57cec5SDimitry Andric     for (unsigned I = 1, E = MBBI->getNumOperands(); I != E; ++I)
3300b57cec5SDimitry Andric       MIB.add(MBBI->getOperand(I));
3310b57cec5SDimitry Andric     MBB.erase(MBBI);
3320b57cec5SDimitry Andric     return true;
3330b57cec5SDimitry Andric   }
3340b57cec5SDimitry Andric   case X86::EH_RESTORE: {
3350b57cec5SDimitry Andric     // Restore ESP and EBP, and optionally ESI if required.
3360b57cec5SDimitry Andric     bool IsSEH = isAsynchronousEHPersonality(classifyEHPersonality(
3370b57cec5SDimitry Andric         MBB.getParent()->getFunction().getPersonalityFn()));
3380b57cec5SDimitry Andric     X86FL->restoreWin32EHStackPointers(MBB, MBBI, DL, /*RestoreSP=*/IsSEH);
3390b57cec5SDimitry Andric     MBBI->eraseFromParent();
3400b57cec5SDimitry Andric     return true;
3410b57cec5SDimitry Andric   }
3420b57cec5SDimitry Andric   case X86::LCMPXCHG8B_SAVE_EBX:
3430b57cec5SDimitry Andric   case X86::LCMPXCHG16B_SAVE_RBX: {
3440b57cec5SDimitry Andric     // Perform the following transformation.
3450b57cec5SDimitry Andric     // SaveRbx = pseudocmpxchg Addr, <4 opds for the address>, InArg, SaveRbx
3460b57cec5SDimitry Andric     // =>
3470b57cec5SDimitry Andric     // [E|R]BX = InArg
3480b57cec5SDimitry Andric     // actualcmpxchg Addr
3490b57cec5SDimitry Andric     // [E|R]BX = SaveRbx
3500b57cec5SDimitry Andric     const MachineOperand &InArg = MBBI->getOperand(6);
3518bcb0991SDimitry Andric     Register SaveRbx = MBBI->getOperand(7).getReg();
3520b57cec5SDimitry Andric 
3530b57cec5SDimitry Andric     unsigned ActualInArg =
3540b57cec5SDimitry Andric         Opcode == X86::LCMPXCHG8B_SAVE_EBX ? X86::EBX : X86::RBX;
3550b57cec5SDimitry Andric     // Copy the input argument of the pseudo into the argument of the
3560b57cec5SDimitry Andric     // actual instruction.
3570b57cec5SDimitry Andric     TII->copyPhysReg(MBB, MBBI, DL, ActualInArg, InArg.getReg(),
3580b57cec5SDimitry Andric                      InArg.isKill());
3590b57cec5SDimitry Andric     // Create the actual instruction.
3600b57cec5SDimitry Andric     unsigned ActualOpc =
3610b57cec5SDimitry Andric         Opcode == X86::LCMPXCHG8B_SAVE_EBX ? X86::LCMPXCHG8B : X86::LCMPXCHG16B;
3620b57cec5SDimitry Andric     MachineInstr *NewInstr = BuildMI(MBB, MBBI, DL, TII->get(ActualOpc));
3630b57cec5SDimitry Andric     // Copy the operands related to the address.
3640b57cec5SDimitry Andric     for (unsigned Idx = 1; Idx < 6; ++Idx)
3650b57cec5SDimitry Andric       NewInstr->addOperand(MBBI->getOperand(Idx));
3660b57cec5SDimitry Andric     // Finally, restore the value of RBX.
3670b57cec5SDimitry Andric     TII->copyPhysReg(MBB, MBBI, DL, ActualInArg, SaveRbx,
3680b57cec5SDimitry Andric                      /*SrcIsKill*/ true);
3690b57cec5SDimitry Andric 
3700b57cec5SDimitry Andric     // Delete the pseudo.
3710b57cec5SDimitry Andric     MBBI->eraseFromParent();
3720b57cec5SDimitry Andric     return true;
3730b57cec5SDimitry Andric   }
3740b57cec5SDimitry Andric   case TargetOpcode::ICALL_BRANCH_FUNNEL:
3750b57cec5SDimitry Andric     ExpandICallBranchFunnel(&MBB, MBBI);
3760b57cec5SDimitry Andric     return true;
3770b57cec5SDimitry Andric   }
3780b57cec5SDimitry Andric   llvm_unreachable("Previous switch has a fallthrough?");
3790b57cec5SDimitry Andric }
3800b57cec5SDimitry Andric 
3810b57cec5SDimitry Andric /// Expand all pseudo instructions contained in \p MBB.
3820b57cec5SDimitry Andric /// \returns true if any expansion occurred for \p MBB.
3830b57cec5SDimitry Andric bool X86ExpandPseudo::ExpandMBB(MachineBasicBlock &MBB) {
3840b57cec5SDimitry Andric   bool Modified = false;
3850b57cec5SDimitry Andric 
3860b57cec5SDimitry Andric   // MBBI may be invalidated by the expansion.
3870b57cec5SDimitry Andric   MachineBasicBlock::iterator MBBI = MBB.begin(), E = MBB.end();
3880b57cec5SDimitry Andric   while (MBBI != E) {
3890b57cec5SDimitry Andric     MachineBasicBlock::iterator NMBBI = std::next(MBBI);
3900b57cec5SDimitry Andric     Modified |= ExpandMI(MBB, MBBI);
3910b57cec5SDimitry Andric     MBBI = NMBBI;
3920b57cec5SDimitry Andric   }
3930b57cec5SDimitry Andric 
3940b57cec5SDimitry Andric   return Modified;
3950b57cec5SDimitry Andric }
3960b57cec5SDimitry Andric 
3970b57cec5SDimitry Andric bool X86ExpandPseudo::runOnMachineFunction(MachineFunction &MF) {
3980b57cec5SDimitry Andric   STI = &static_cast<const X86Subtarget &>(MF.getSubtarget());
3990b57cec5SDimitry Andric   TII = STI->getInstrInfo();
4000b57cec5SDimitry Andric   TRI = STI->getRegisterInfo();
4010b57cec5SDimitry Andric   X86FI = MF.getInfo<X86MachineFunctionInfo>();
4020b57cec5SDimitry Andric   X86FL = STI->getFrameLowering();
4030b57cec5SDimitry Andric 
4040b57cec5SDimitry Andric   bool Modified = false;
4050b57cec5SDimitry Andric   for (MachineBasicBlock &MBB : MF)
4060b57cec5SDimitry Andric     Modified |= ExpandMBB(MBB);
4070b57cec5SDimitry Andric   return Modified;
4080b57cec5SDimitry Andric }
4090b57cec5SDimitry Andric 
4100b57cec5SDimitry Andric /// Returns an instance of the pseudo instruction expansion pass.
4110b57cec5SDimitry Andric FunctionPass *llvm::createX86ExpandPseudoPass() {
4120b57cec5SDimitry Andric   return new X86ExpandPseudo();
4130b57cec5SDimitry Andric }
414