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"
2181ad6265SDimitry Andric #include "llvm/CodeGen/LivePhysRegs.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.
2506c3fb27SDimitry Andric #include "llvm/IR/EHPersonalities.h"
260b57cec5SDimitry Andric #include "llvm/IR/GlobalValue.h"
27fe6060f1SDimitry Andric #include "llvm/Target/TargetMachine.h"
280b57cec5SDimitry Andric using namespace llvm;
290b57cec5SDimitry Andric
300b57cec5SDimitry Andric #define DEBUG_TYPE "x86-pseudo"
310b57cec5SDimitry Andric #define X86_EXPAND_PSEUDO_NAME "X86 pseudo instruction expansion pass"
320b57cec5SDimitry Andric
330b57cec5SDimitry Andric namespace {
340b57cec5SDimitry Andric class X86ExpandPseudo : public MachineFunctionPass {
350b57cec5SDimitry Andric public:
360b57cec5SDimitry Andric static char ID;
X86ExpandPseudo()370b57cec5SDimitry Andric X86ExpandPseudo() : MachineFunctionPass(ID) {}
380b57cec5SDimitry Andric
getAnalysisUsage(AnalysisUsage & AU) const390b57cec5SDimitry Andric void getAnalysisUsage(AnalysisUsage &AU) const override {
400b57cec5SDimitry Andric AU.setPreservesCFG();
410b57cec5SDimitry Andric AU.addPreservedID(MachineLoopInfoID);
420b57cec5SDimitry Andric AU.addPreservedID(MachineDominatorsID);
430b57cec5SDimitry Andric MachineFunctionPass::getAnalysisUsage(AU);
440b57cec5SDimitry Andric }
450b57cec5SDimitry Andric
46480093f4SDimitry Andric const X86Subtarget *STI = nullptr;
47480093f4SDimitry Andric const X86InstrInfo *TII = nullptr;
48480093f4SDimitry Andric const X86RegisterInfo *TRI = nullptr;
49480093f4SDimitry Andric const X86MachineFunctionInfo *X86FI = nullptr;
50480093f4SDimitry Andric const X86FrameLowering *X86FL = nullptr;
510b57cec5SDimitry Andric
5206c3fb27SDimitry Andric bool runOnMachineFunction(MachineFunction &MF) override;
530b57cec5SDimitry Andric
getRequiredProperties() const540b57cec5SDimitry Andric MachineFunctionProperties getRequiredProperties() const override {
550b57cec5SDimitry Andric return MachineFunctionProperties().set(
560b57cec5SDimitry Andric MachineFunctionProperties::Property::NoVRegs);
570b57cec5SDimitry Andric }
580b57cec5SDimitry Andric
getPassName() const590b57cec5SDimitry Andric StringRef getPassName() const override {
600b57cec5SDimitry Andric return "X86 pseudo instruction expansion pass";
610b57cec5SDimitry Andric }
620b57cec5SDimitry Andric
630b57cec5SDimitry Andric private:
64*0fca6ea1SDimitry Andric void expandICallBranchFunnel(MachineBasicBlock *MBB,
650b57cec5SDimitry Andric MachineBasicBlock::iterator MBBI);
66fe6060f1SDimitry Andric void expandCALL_RVMARKER(MachineBasicBlock &MBB,
67fe6060f1SDimitry Andric MachineBasicBlock::iterator MBBI);
68*0fca6ea1SDimitry Andric bool expandMI(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI);
69*0fca6ea1SDimitry Andric bool expandMBB(MachineBasicBlock &MBB);
70fe6060f1SDimitry Andric
71fe6060f1SDimitry Andric /// This function expands pseudos which affects control flow.
72fe6060f1SDimitry Andric /// It is done in separate pass to simplify blocks navigation in main
73*0fca6ea1SDimitry Andric /// pass(calling expandMBB).
74*0fca6ea1SDimitry Andric bool expandPseudosWhichAffectControlFlow(MachineFunction &MF);
75fe6060f1SDimitry Andric
76fe6060f1SDimitry Andric /// Expand X86::VASTART_SAVE_XMM_REGS into set of xmm copying instructions,
77fe6060f1SDimitry Andric /// placed into separate block guarded by check for al register(for SystemV
78fe6060f1SDimitry Andric /// abi).
79*0fca6ea1SDimitry Andric void expandVastartSaveXmmRegs(
8006c3fb27SDimitry Andric MachineBasicBlock *EntryBlk,
81fe6060f1SDimitry Andric MachineBasicBlock::iterator VAStartPseudoInstr) const;
820b57cec5SDimitry Andric };
830b57cec5SDimitry Andric char X86ExpandPseudo::ID = 0;
840b57cec5SDimitry Andric
850b57cec5SDimitry Andric } // End anonymous namespace.
860b57cec5SDimitry Andric
INITIALIZE_PASS(X86ExpandPseudo,DEBUG_TYPE,X86_EXPAND_PSEUDO_NAME,false,false)870b57cec5SDimitry Andric INITIALIZE_PASS(X86ExpandPseudo, DEBUG_TYPE, X86_EXPAND_PSEUDO_NAME, false,
880b57cec5SDimitry Andric false)
890b57cec5SDimitry Andric
90*0fca6ea1SDimitry Andric void X86ExpandPseudo::expandICallBranchFunnel(
910b57cec5SDimitry Andric MachineBasicBlock *MBB, MachineBasicBlock::iterator MBBI) {
920b57cec5SDimitry Andric MachineBasicBlock *JTMBB = MBB;
930b57cec5SDimitry Andric MachineInstr *JTInst = &*MBBI;
940b57cec5SDimitry Andric MachineFunction *MF = MBB->getParent();
950b57cec5SDimitry Andric const BasicBlock *BB = MBB->getBasicBlock();
960b57cec5SDimitry Andric auto InsPt = MachineFunction::iterator(MBB);
970b57cec5SDimitry Andric ++InsPt;
980b57cec5SDimitry Andric
990b57cec5SDimitry Andric std::vector<std::pair<MachineBasicBlock *, unsigned>> TargetMBBs;
100fe6060f1SDimitry Andric const DebugLoc &DL = JTInst->getDebugLoc();
1010b57cec5SDimitry Andric MachineOperand Selector = JTInst->getOperand(0);
1020b57cec5SDimitry Andric const GlobalValue *CombinedGlobal = JTInst->getOperand(1).getGlobal();
1030b57cec5SDimitry Andric
1040b57cec5SDimitry Andric auto CmpTarget = [&](unsigned Target) {
1050b57cec5SDimitry Andric if (Selector.isReg())
1060b57cec5SDimitry Andric MBB->addLiveIn(Selector.getReg());
1070b57cec5SDimitry Andric BuildMI(*MBB, MBBI, DL, TII->get(X86::LEA64r), X86::R11)
1080b57cec5SDimitry Andric .addReg(X86::RIP)
1090b57cec5SDimitry Andric .addImm(1)
1100b57cec5SDimitry Andric .addReg(0)
1110b57cec5SDimitry Andric .addGlobalAddress(CombinedGlobal,
1120b57cec5SDimitry Andric JTInst->getOperand(2 + 2 * Target).getImm())
1130b57cec5SDimitry Andric .addReg(0);
1140b57cec5SDimitry Andric BuildMI(*MBB, MBBI, DL, TII->get(X86::CMP64rr))
1150b57cec5SDimitry Andric .add(Selector)
1160b57cec5SDimitry Andric .addReg(X86::R11);
1170b57cec5SDimitry Andric };
1180b57cec5SDimitry Andric
1190b57cec5SDimitry Andric auto CreateMBB = [&]() {
1200b57cec5SDimitry Andric auto *NewMBB = MF->CreateMachineBasicBlock(BB);
1210b57cec5SDimitry Andric MBB->addSuccessor(NewMBB);
1220b57cec5SDimitry Andric if (!MBB->isLiveIn(X86::EFLAGS))
1230b57cec5SDimitry Andric MBB->addLiveIn(X86::EFLAGS);
1240b57cec5SDimitry Andric return NewMBB;
1250b57cec5SDimitry Andric };
1260b57cec5SDimitry Andric
1270b57cec5SDimitry Andric auto EmitCondJump = [&](unsigned CC, MachineBasicBlock *ThenMBB) {
1280b57cec5SDimitry Andric BuildMI(*MBB, MBBI, DL, TII->get(X86::JCC_1)).addMBB(ThenMBB).addImm(CC);
1290b57cec5SDimitry Andric
1300b57cec5SDimitry Andric auto *ElseMBB = CreateMBB();
1310b57cec5SDimitry Andric MF->insert(InsPt, ElseMBB);
1320b57cec5SDimitry Andric MBB = ElseMBB;
1330b57cec5SDimitry Andric MBBI = MBB->end();
1340b57cec5SDimitry Andric };
1350b57cec5SDimitry Andric
1360b57cec5SDimitry Andric auto EmitCondJumpTarget = [&](unsigned CC, unsigned Target) {
1370b57cec5SDimitry Andric auto *ThenMBB = CreateMBB();
1380b57cec5SDimitry Andric TargetMBBs.push_back({ThenMBB, Target});
1390b57cec5SDimitry Andric EmitCondJump(CC, ThenMBB);
1400b57cec5SDimitry Andric };
1410b57cec5SDimitry Andric
1420b57cec5SDimitry Andric auto EmitTailCall = [&](unsigned Target) {
1430b57cec5SDimitry Andric BuildMI(*MBB, MBBI, DL, TII->get(X86::TAILJMPd64))
1440b57cec5SDimitry Andric .add(JTInst->getOperand(3 + 2 * Target));
1450b57cec5SDimitry Andric };
1460b57cec5SDimitry Andric
1470b57cec5SDimitry Andric std::function<void(unsigned, unsigned)> EmitBranchFunnel =
1480b57cec5SDimitry Andric [&](unsigned FirstTarget, unsigned NumTargets) {
1490b57cec5SDimitry Andric if (NumTargets == 1) {
1500b57cec5SDimitry Andric EmitTailCall(FirstTarget);
1510b57cec5SDimitry Andric return;
1520b57cec5SDimitry Andric }
1530b57cec5SDimitry Andric
1540b57cec5SDimitry Andric if (NumTargets == 2) {
1550b57cec5SDimitry Andric CmpTarget(FirstTarget + 1);
1560b57cec5SDimitry Andric EmitCondJumpTarget(X86::COND_B, FirstTarget);
1570b57cec5SDimitry Andric EmitTailCall(FirstTarget + 1);
1580b57cec5SDimitry Andric return;
1590b57cec5SDimitry Andric }
1600b57cec5SDimitry Andric
1610b57cec5SDimitry Andric if (NumTargets < 6) {
1620b57cec5SDimitry Andric CmpTarget(FirstTarget + 1);
1630b57cec5SDimitry Andric EmitCondJumpTarget(X86::COND_B, FirstTarget);
1640b57cec5SDimitry Andric EmitCondJumpTarget(X86::COND_E, FirstTarget + 1);
1650b57cec5SDimitry Andric EmitBranchFunnel(FirstTarget + 2, NumTargets - 2);
1660b57cec5SDimitry Andric return;
1670b57cec5SDimitry Andric }
1680b57cec5SDimitry Andric
1690b57cec5SDimitry Andric auto *ThenMBB = CreateMBB();
1700b57cec5SDimitry Andric CmpTarget(FirstTarget + (NumTargets / 2));
1710b57cec5SDimitry Andric EmitCondJump(X86::COND_B, ThenMBB);
1720b57cec5SDimitry Andric EmitCondJumpTarget(X86::COND_E, FirstTarget + (NumTargets / 2));
1730b57cec5SDimitry Andric EmitBranchFunnel(FirstTarget + (NumTargets / 2) + 1,
1740b57cec5SDimitry Andric NumTargets - (NumTargets / 2) - 1);
1750b57cec5SDimitry Andric
1760b57cec5SDimitry Andric MF->insert(InsPt, ThenMBB);
1770b57cec5SDimitry Andric MBB = ThenMBB;
1780b57cec5SDimitry Andric MBBI = MBB->end();
1790b57cec5SDimitry Andric EmitBranchFunnel(FirstTarget, NumTargets / 2);
1800b57cec5SDimitry Andric };
1810b57cec5SDimitry Andric
1820b57cec5SDimitry Andric EmitBranchFunnel(0, (JTInst->getNumOperands() - 2) / 2);
1830b57cec5SDimitry Andric for (auto P : TargetMBBs) {
1840b57cec5SDimitry Andric MF->insert(InsPt, P.first);
1850b57cec5SDimitry Andric BuildMI(P.first, DL, TII->get(X86::TAILJMPd64))
1860b57cec5SDimitry Andric .add(JTInst->getOperand(3 + 2 * P.second));
1870b57cec5SDimitry Andric }
1880b57cec5SDimitry Andric JTMBB->erase(JTInst);
1890b57cec5SDimitry Andric }
1900b57cec5SDimitry Andric
expandCALL_RVMARKER(MachineBasicBlock & MBB,MachineBasicBlock::iterator MBBI)191fe6060f1SDimitry Andric void X86ExpandPseudo::expandCALL_RVMARKER(MachineBasicBlock &MBB,
192fe6060f1SDimitry Andric MachineBasicBlock::iterator MBBI) {
193fe6060f1SDimitry Andric // Expand CALL_RVMARKER pseudo to call instruction, followed by the special
194fe6060f1SDimitry Andric //"movq %rax, %rdi" marker.
195fe6060f1SDimitry Andric MachineInstr &MI = *MBBI;
196fe6060f1SDimitry Andric
197fe6060f1SDimitry Andric MachineInstr *OriginalCall;
198fe6060f1SDimitry Andric assert((MI.getOperand(1).isGlobal() || MI.getOperand(1).isReg()) &&
199fe6060f1SDimitry Andric "invalid operand for regular call");
200fe6060f1SDimitry Andric unsigned Opc = -1;
201fe6060f1SDimitry Andric if (MI.getOpcode() == X86::CALL64m_RVMARKER)
202fe6060f1SDimitry Andric Opc = X86::CALL64m;
203fe6060f1SDimitry Andric else if (MI.getOpcode() == X86::CALL64r_RVMARKER)
204fe6060f1SDimitry Andric Opc = X86::CALL64r;
205fe6060f1SDimitry Andric else if (MI.getOpcode() == X86::CALL64pcrel32_RVMARKER)
206fe6060f1SDimitry Andric Opc = X86::CALL64pcrel32;
207fe6060f1SDimitry Andric else
208fe6060f1SDimitry Andric llvm_unreachable("unexpected opcode");
209fe6060f1SDimitry Andric
210fe6060f1SDimitry Andric OriginalCall = BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(Opc)).getInstr();
211fe6060f1SDimitry Andric bool RAXImplicitDead = false;
2124824e7fdSDimitry Andric for (MachineOperand &Op : llvm::drop_begin(MI.operands())) {
213fe6060f1SDimitry Andric // RAX may be 'implicit dead', if there are no other users of the return
214fe6060f1SDimitry Andric // value. We introduce a new use, so change it to 'implicit def'.
215fe6060f1SDimitry Andric if (Op.isReg() && Op.isImplicit() && Op.isDead() &&
216fe6060f1SDimitry Andric TRI->regsOverlap(Op.getReg(), X86::RAX)) {
217fe6060f1SDimitry Andric Op.setIsDead(false);
218fe6060f1SDimitry Andric Op.setIsDef(true);
219fe6060f1SDimitry Andric RAXImplicitDead = true;
220fe6060f1SDimitry Andric }
221fe6060f1SDimitry Andric OriginalCall->addOperand(Op);
222fe6060f1SDimitry Andric }
223fe6060f1SDimitry Andric
224fe6060f1SDimitry Andric // Emit marker "movq %rax, %rdi". %rdi is not callee-saved, so it cannot be
225fe6060f1SDimitry Andric // live across the earlier call. The call to the ObjC runtime function returns
226fe6060f1SDimitry Andric // the first argument, so the value of %rax is unchanged after the ObjC
227bdd1243dSDimitry Andric // runtime call. On Windows targets, the runtime call follows the regular
228bdd1243dSDimitry Andric // x64 calling convention and expects the first argument in %rcx.
229bdd1243dSDimitry Andric auto TargetReg = STI->getTargetTriple().isOSWindows() ? X86::RCX : X86::RDI;
230fe6060f1SDimitry Andric auto *Marker = BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(X86::MOV64rr))
231bdd1243dSDimitry Andric .addReg(TargetReg, RegState::Define)
232fe6060f1SDimitry Andric .addReg(X86::RAX)
233fe6060f1SDimitry Andric .getInstr();
234fe6060f1SDimitry Andric if (MI.shouldUpdateCallSiteInfo())
235fe6060f1SDimitry Andric MBB.getParent()->moveCallSiteInfo(&MI, Marker);
236fe6060f1SDimitry Andric
237fe6060f1SDimitry Andric // Emit call to ObjC runtime.
238fe6060f1SDimitry Andric const uint32_t *RegMask =
239fe6060f1SDimitry Andric TRI->getCallPreservedMask(*MBB.getParent(), CallingConv::C);
2400eae32dcSDimitry Andric MachineInstr *RtCall =
241fe6060f1SDimitry Andric BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(X86::CALL64pcrel32))
242349cc55cSDimitry Andric .addGlobalAddress(MI.getOperand(0).getGlobal(), 0, 0)
243fe6060f1SDimitry Andric .addRegMask(RegMask)
244fe6060f1SDimitry Andric .addReg(X86::RAX,
245fe6060f1SDimitry Andric RegState::Implicit |
246fe6060f1SDimitry Andric (RAXImplicitDead ? (RegState::Dead | RegState::Define)
247fe6060f1SDimitry Andric : RegState::Define))
248fe6060f1SDimitry Andric .getInstr();
249fe6060f1SDimitry Andric MI.eraseFromParent();
2500eae32dcSDimitry Andric
2510eae32dcSDimitry Andric auto &TM = MBB.getParent()->getTarget();
2520eae32dcSDimitry Andric // On Darwin platforms, wrap the expanded sequence in a bundle to prevent
2530eae32dcSDimitry Andric // later optimizations from breaking up the sequence.
2540eae32dcSDimitry Andric if (TM.getTargetTriple().isOSDarwin())
2550eae32dcSDimitry Andric finalizeBundle(MBB, OriginalCall->getIterator(),
2560eae32dcSDimitry Andric std::next(RtCall->getIterator()));
257fe6060f1SDimitry Andric }
258fe6060f1SDimitry Andric
2590b57cec5SDimitry Andric /// If \p MBBI is a pseudo instruction, this method expands
2600b57cec5SDimitry Andric /// it to the corresponding (sequence of) actual instruction(s).
2610b57cec5SDimitry Andric /// \returns true if \p MBBI has been expanded.
expandMI(MachineBasicBlock & MBB,MachineBasicBlock::iterator MBBI)262*0fca6ea1SDimitry Andric bool X86ExpandPseudo::expandMI(MachineBasicBlock &MBB,
2630b57cec5SDimitry Andric MachineBasicBlock::iterator MBBI) {
2640b57cec5SDimitry Andric MachineInstr &MI = *MBBI;
2650b57cec5SDimitry Andric unsigned Opcode = MI.getOpcode();
266fe6060f1SDimitry Andric const DebugLoc &DL = MBBI->getDebugLoc();
267*0fca6ea1SDimitry Andric #define GET_EGPR_IF_ENABLED(OPC) (STI->hasEGPR() ? OPC##_EVEX : OPC)
2680b57cec5SDimitry Andric switch (Opcode) {
2690b57cec5SDimitry Andric default:
2700b57cec5SDimitry Andric return false;
2710b57cec5SDimitry Andric case X86::TCRETURNdi:
2720b57cec5SDimitry Andric case X86::TCRETURNdicc:
2730b57cec5SDimitry Andric case X86::TCRETURNri:
2740b57cec5SDimitry Andric case X86::TCRETURNmi:
2750b57cec5SDimitry Andric case X86::TCRETURNdi64:
2760b57cec5SDimitry Andric case X86::TCRETURNdi64cc:
2770b57cec5SDimitry Andric case X86::TCRETURNri64:
2780b57cec5SDimitry Andric case X86::TCRETURNmi64: {
2790b57cec5SDimitry Andric bool isMem = Opcode == X86::TCRETURNmi || Opcode == X86::TCRETURNmi64;
2800b57cec5SDimitry Andric MachineOperand &JumpTarget = MBBI->getOperand(0);
2818bcb0991SDimitry Andric MachineOperand &StackAdjust = MBBI->getOperand(isMem ? X86::AddrNumOperands
2828bcb0991SDimitry Andric : 1);
2830b57cec5SDimitry Andric assert(StackAdjust.isImm() && "Expecting immediate value.");
2840b57cec5SDimitry Andric
2850b57cec5SDimitry Andric // Adjust stack pointer.
2860b57cec5SDimitry Andric int StackAdj = StackAdjust.getImm();
2870b57cec5SDimitry Andric int MaxTCDelta = X86FI->getTCReturnAddrDelta();
2880b57cec5SDimitry Andric int Offset = 0;
2890b57cec5SDimitry Andric assert(MaxTCDelta <= 0 && "MaxTCDelta should never be positive");
2900b57cec5SDimitry Andric
2910b57cec5SDimitry Andric // Incoporate the retaddr area.
2920b57cec5SDimitry Andric Offset = StackAdj - MaxTCDelta;
2930b57cec5SDimitry Andric assert(Offset >= 0 && "Offset should never be negative");
2940b57cec5SDimitry Andric
2950b57cec5SDimitry Andric if (Opcode == X86::TCRETURNdicc || Opcode == X86::TCRETURNdi64cc) {
2960b57cec5SDimitry Andric assert(Offset == 0 && "Conditional tail call cannot adjust the stack.");
2970b57cec5SDimitry Andric }
2980b57cec5SDimitry Andric
2990b57cec5SDimitry Andric if (Offset) {
3000b57cec5SDimitry Andric // Check for possible merge with preceding ADD instruction.
3010b57cec5SDimitry Andric Offset += X86FL->mergeSPUpdates(MBB, MBBI, true);
3020b57cec5SDimitry Andric X86FL->emitSPUpdate(MBB, MBBI, DL, Offset, /*InEpilogue=*/true);
3030b57cec5SDimitry Andric }
3040b57cec5SDimitry Andric
3050b57cec5SDimitry Andric // Jump to label or value in register.
3060b57cec5SDimitry Andric bool IsWin64 = STI->isTargetWin64();
3070b57cec5SDimitry Andric if (Opcode == X86::TCRETURNdi || Opcode == X86::TCRETURNdicc ||
3080b57cec5SDimitry Andric Opcode == X86::TCRETURNdi64 || Opcode == X86::TCRETURNdi64cc) {
3090b57cec5SDimitry Andric unsigned Op;
3100b57cec5SDimitry Andric switch (Opcode) {
3110b57cec5SDimitry Andric case X86::TCRETURNdi:
3120b57cec5SDimitry Andric Op = X86::TAILJMPd;
3130b57cec5SDimitry Andric break;
3140b57cec5SDimitry Andric case X86::TCRETURNdicc:
3150b57cec5SDimitry Andric Op = X86::TAILJMPd_CC;
3160b57cec5SDimitry Andric break;
3170b57cec5SDimitry Andric case X86::TCRETURNdi64cc:
3180b57cec5SDimitry Andric assert(!MBB.getParent()->hasWinCFI() &&
3190b57cec5SDimitry Andric "Conditional tail calls confuse "
3200b57cec5SDimitry Andric "the Win64 unwinder.");
3210b57cec5SDimitry Andric Op = X86::TAILJMPd64_CC;
3220b57cec5SDimitry Andric break;
3230b57cec5SDimitry Andric default:
3240b57cec5SDimitry Andric // Note: Win64 uses REX prefixes indirect jumps out of functions, but
3250b57cec5SDimitry Andric // not direct ones.
3260b57cec5SDimitry Andric Op = X86::TAILJMPd64;
3270b57cec5SDimitry Andric break;
3280b57cec5SDimitry Andric }
3290b57cec5SDimitry Andric MachineInstrBuilder MIB = BuildMI(MBB, MBBI, DL, TII->get(Op));
3300b57cec5SDimitry Andric if (JumpTarget.isGlobal()) {
3310b57cec5SDimitry Andric MIB.addGlobalAddress(JumpTarget.getGlobal(), JumpTarget.getOffset(),
3320b57cec5SDimitry Andric JumpTarget.getTargetFlags());
3330b57cec5SDimitry Andric } else {
3340b57cec5SDimitry Andric assert(JumpTarget.isSymbol());
3350b57cec5SDimitry Andric MIB.addExternalSymbol(JumpTarget.getSymbolName(),
3360b57cec5SDimitry Andric JumpTarget.getTargetFlags());
3370b57cec5SDimitry Andric }
3380b57cec5SDimitry Andric if (Op == X86::TAILJMPd_CC || Op == X86::TAILJMPd64_CC) {
3390b57cec5SDimitry Andric MIB.addImm(MBBI->getOperand(2).getImm());
3400b57cec5SDimitry Andric }
3410b57cec5SDimitry Andric
3420b57cec5SDimitry Andric } else if (Opcode == X86::TCRETURNmi || Opcode == X86::TCRETURNmi64) {
3430b57cec5SDimitry Andric unsigned Op = (Opcode == X86::TCRETURNmi)
3440b57cec5SDimitry Andric ? X86::TAILJMPm
3450b57cec5SDimitry Andric : (IsWin64 ? X86::TAILJMPm64_REX : X86::TAILJMPm64);
3460b57cec5SDimitry Andric MachineInstrBuilder MIB = BuildMI(MBB, MBBI, DL, TII->get(Op));
3478bcb0991SDimitry Andric for (unsigned i = 0; i != X86::AddrNumOperands; ++i)
3480b57cec5SDimitry Andric MIB.add(MBBI->getOperand(i));
3490b57cec5SDimitry Andric } else if (Opcode == X86::TCRETURNri64) {
3500b57cec5SDimitry Andric JumpTarget.setIsKill();
3510b57cec5SDimitry Andric BuildMI(MBB, MBBI, DL,
3520b57cec5SDimitry Andric TII->get(IsWin64 ? X86::TAILJMPr64_REX : X86::TAILJMPr64))
3530b57cec5SDimitry Andric .add(JumpTarget);
3540b57cec5SDimitry Andric } else {
3550b57cec5SDimitry Andric JumpTarget.setIsKill();
3560b57cec5SDimitry Andric BuildMI(MBB, MBBI, DL, TII->get(X86::TAILJMPr))
3570b57cec5SDimitry Andric .add(JumpTarget);
3580b57cec5SDimitry Andric }
3590b57cec5SDimitry Andric
3600b57cec5SDimitry Andric MachineInstr &NewMI = *std::prev(MBBI);
3610b57cec5SDimitry Andric NewMI.copyImplicitOps(*MBBI->getParent()->getParent(), *MBBI);
362bdd1243dSDimitry Andric NewMI.setCFIType(*MBB.getParent(), MI.getCFIType());
3635ffd83dbSDimitry Andric
3645ffd83dbSDimitry Andric // Update the call site info.
3655ffd83dbSDimitry Andric if (MBBI->isCandidateForCallSiteEntry())
3668bcb0991SDimitry Andric MBB.getParent()->moveCallSiteInfo(&*MBBI, &NewMI);
3670b57cec5SDimitry Andric
3680b57cec5SDimitry Andric // Delete the pseudo instruction TCRETURN.
3690b57cec5SDimitry Andric MBB.erase(MBBI);
3700b57cec5SDimitry Andric
3710b57cec5SDimitry Andric return true;
3720b57cec5SDimitry Andric }
3730b57cec5SDimitry Andric case X86::EH_RETURN:
3740b57cec5SDimitry Andric case X86::EH_RETURN64: {
3750b57cec5SDimitry Andric MachineOperand &DestAddr = MBBI->getOperand(0);
3760b57cec5SDimitry Andric assert(DestAddr.isReg() && "Offset should be in register!");
3770b57cec5SDimitry Andric const bool Uses64BitFramePtr =
3780b57cec5SDimitry Andric STI->isTarget64BitLP64() || STI->isTargetNaCl64();
3798bcb0991SDimitry Andric Register StackPtr = TRI->getStackRegister();
3800b57cec5SDimitry Andric BuildMI(MBB, MBBI, DL,
3810b57cec5SDimitry Andric TII->get(Uses64BitFramePtr ? X86::MOV64rr : X86::MOV32rr), StackPtr)
3820b57cec5SDimitry Andric .addReg(DestAddr.getReg());
3830b57cec5SDimitry Andric // The EH_RETURN pseudo is really removed during the MC Lowering.
3840b57cec5SDimitry Andric return true;
3850b57cec5SDimitry Andric }
3860b57cec5SDimitry Andric case X86::IRET: {
3870b57cec5SDimitry Andric // Adjust stack to erase error code
3880b57cec5SDimitry Andric int64_t StackAdj = MBBI->getOperand(0).getImm();
3890b57cec5SDimitry Andric X86FL->emitSPUpdate(MBB, MBBI, DL, StackAdj, true);
3900b57cec5SDimitry Andric // Replace pseudo with machine iret
391fe6060f1SDimitry Andric unsigned RetOp = STI->is64Bit() ? X86::IRET64 : X86::IRET32;
392fe6060f1SDimitry Andric // Use UIRET if UINTR is present (except for building kernel)
393fe6060f1SDimitry Andric if (STI->is64Bit() && STI->hasUINTR() &&
394fe6060f1SDimitry Andric MBB.getParent()->getTarget().getCodeModel() != CodeModel::Kernel)
395fe6060f1SDimitry Andric RetOp = X86::UIRET;
396fe6060f1SDimitry Andric BuildMI(MBB, MBBI, DL, TII->get(RetOp));
3970b57cec5SDimitry Andric MBB.erase(MBBI);
3980b57cec5SDimitry Andric return true;
3990b57cec5SDimitry Andric }
4000b57cec5SDimitry Andric case X86::RET: {
4010b57cec5SDimitry Andric // Adjust stack to erase error code
4020b57cec5SDimitry Andric int64_t StackAdj = MBBI->getOperand(0).getImm();
4030b57cec5SDimitry Andric MachineInstrBuilder MIB;
4040b57cec5SDimitry Andric if (StackAdj == 0) {
4050b57cec5SDimitry Andric MIB = BuildMI(MBB, MBBI, DL,
406349cc55cSDimitry Andric TII->get(STI->is64Bit() ? X86::RET64 : X86::RET32));
4070b57cec5SDimitry Andric } else if (isUInt<16>(StackAdj)) {
4080b57cec5SDimitry Andric MIB = BuildMI(MBB, MBBI, DL,
409349cc55cSDimitry Andric TII->get(STI->is64Bit() ? X86::RETI64 : X86::RETI32))
4100b57cec5SDimitry Andric .addImm(StackAdj);
4110b57cec5SDimitry Andric } else {
4120b57cec5SDimitry Andric assert(!STI->is64Bit() &&
4130b57cec5SDimitry Andric "shouldn't need to do this for x86_64 targets!");
4140b57cec5SDimitry Andric // A ret can only handle immediates as big as 2**16-1. If we need to pop
4150b57cec5SDimitry Andric // off bytes before the return address, we must do it manually.
4160b57cec5SDimitry Andric BuildMI(MBB, MBBI, DL, TII->get(X86::POP32r)).addReg(X86::ECX, RegState::Define);
4170b57cec5SDimitry Andric X86FL->emitSPUpdate(MBB, MBBI, DL, StackAdj, /*InEpilogue=*/true);
4180b57cec5SDimitry Andric BuildMI(MBB, MBBI, DL, TII->get(X86::PUSH32r)).addReg(X86::ECX);
419349cc55cSDimitry Andric MIB = BuildMI(MBB, MBBI, DL, TII->get(X86::RET32));
4200b57cec5SDimitry Andric }
4210b57cec5SDimitry Andric for (unsigned I = 1, E = MBBI->getNumOperands(); I != E; ++I)
4220b57cec5SDimitry Andric MIB.add(MBBI->getOperand(I));
4230b57cec5SDimitry Andric MBB.erase(MBBI);
4240b57cec5SDimitry Andric return true;
4250b57cec5SDimitry Andric }
4260b57cec5SDimitry Andric case X86::LCMPXCHG16B_SAVE_RBX: {
4270b57cec5SDimitry Andric // Perform the following transformation.
4280b57cec5SDimitry Andric // SaveRbx = pseudocmpxchg Addr, <4 opds for the address>, InArg, SaveRbx
4290b57cec5SDimitry Andric // =>
430e8d8bef9SDimitry Andric // RBX = InArg
4310b57cec5SDimitry Andric // actualcmpxchg Addr
432e8d8bef9SDimitry Andric // RBX = SaveRbx
4330b57cec5SDimitry Andric const MachineOperand &InArg = MBBI->getOperand(6);
4348bcb0991SDimitry Andric Register SaveRbx = MBBI->getOperand(7).getReg();
4350b57cec5SDimitry Andric
4360b57cec5SDimitry Andric // Copy the input argument of the pseudo into the argument of the
4370b57cec5SDimitry Andric // actual instruction.
438e8d8bef9SDimitry Andric // NOTE: We don't copy the kill flag since the input might be the same reg
439e8d8bef9SDimitry Andric // as one of the other operands of LCMPXCHG16B.
440e8d8bef9SDimitry Andric TII->copyPhysReg(MBB, MBBI, DL, X86::RBX, InArg.getReg(), false);
4410b57cec5SDimitry Andric // Create the actual instruction.
442e8d8bef9SDimitry Andric MachineInstr *NewInstr = BuildMI(MBB, MBBI, DL, TII->get(X86::LCMPXCHG16B));
4430b57cec5SDimitry Andric // Copy the operands related to the address.
4440b57cec5SDimitry Andric for (unsigned Idx = 1; Idx < 6; ++Idx)
4450b57cec5SDimitry Andric NewInstr->addOperand(MBBI->getOperand(Idx));
4460b57cec5SDimitry Andric // Finally, restore the value of RBX.
447e8d8bef9SDimitry Andric TII->copyPhysReg(MBB, MBBI, DL, X86::RBX, SaveRbx,
4480b57cec5SDimitry Andric /*SrcIsKill*/ true);
4490b57cec5SDimitry Andric
4500b57cec5SDimitry Andric // Delete the pseudo.
4510b57cec5SDimitry Andric MBBI->eraseFromParent();
4520b57cec5SDimitry Andric return true;
4530b57cec5SDimitry Andric }
4545ffd83dbSDimitry Andric // Loading/storing mask pairs requires two kmov operations. The second one of
4555ffd83dbSDimitry Andric // these needs a 2 byte displacement relative to the specified address (with
4565ffd83dbSDimitry Andric // 32 bit spill size). The pairs of 1bit masks up to 16 bit masks all use the
4575ffd83dbSDimitry Andric // same spill size, they all are stored using MASKPAIR16STORE, loaded using
4585ffd83dbSDimitry Andric // MASKPAIR16LOAD.
4595ffd83dbSDimitry Andric //
4605ffd83dbSDimitry Andric // The displacement value might wrap around in theory, thus the asserts in
4615ffd83dbSDimitry Andric // both cases.
4625ffd83dbSDimitry Andric case X86::MASKPAIR16LOAD: {
4635ffd83dbSDimitry Andric int64_t Disp = MBBI->getOperand(1 + X86::AddrDisp).getImm();
4645ffd83dbSDimitry Andric assert(Disp >= 0 && Disp <= INT32_MAX - 2 && "Unexpected displacement");
4655ffd83dbSDimitry Andric Register Reg = MBBI->getOperand(0).getReg();
4665ffd83dbSDimitry Andric bool DstIsDead = MBBI->getOperand(0).isDead();
4675ffd83dbSDimitry Andric Register Reg0 = TRI->getSubReg(Reg, X86::sub_mask_0);
4685ffd83dbSDimitry Andric Register Reg1 = TRI->getSubReg(Reg, X86::sub_mask_1);
4695ffd83dbSDimitry Andric
4705f757f3fSDimitry Andric auto MIBLo =
471*0fca6ea1SDimitry Andric BuildMI(MBB, MBBI, DL, TII->get(GET_EGPR_IF_ENABLED(X86::KMOVWkm)))
4725ffd83dbSDimitry Andric .addReg(Reg0, RegState::Define | getDeadRegState(DstIsDead));
4735f757f3fSDimitry Andric auto MIBHi =
474*0fca6ea1SDimitry Andric BuildMI(MBB, MBBI, DL, TII->get(GET_EGPR_IF_ENABLED(X86::KMOVWkm)))
4755ffd83dbSDimitry Andric .addReg(Reg1, RegState::Define | getDeadRegState(DstIsDead));
4765ffd83dbSDimitry Andric
4775ffd83dbSDimitry Andric for (int i = 0; i < X86::AddrNumOperands; ++i) {
4785ffd83dbSDimitry Andric MIBLo.add(MBBI->getOperand(1 + i));
4795ffd83dbSDimitry Andric if (i == X86::AddrDisp)
4805ffd83dbSDimitry Andric MIBHi.addImm(Disp + 2);
4815ffd83dbSDimitry Andric else
4825ffd83dbSDimitry Andric MIBHi.add(MBBI->getOperand(1 + i));
4835ffd83dbSDimitry Andric }
4845ffd83dbSDimitry Andric
4855ffd83dbSDimitry Andric // Split the memory operand, adjusting the offset and size for the halves.
4865ffd83dbSDimitry Andric MachineMemOperand *OldMMO = MBBI->memoperands().front();
4875ffd83dbSDimitry Andric MachineFunction *MF = MBB.getParent();
4885ffd83dbSDimitry Andric MachineMemOperand *MMOLo = MF->getMachineMemOperand(OldMMO, 0, 2);
4895ffd83dbSDimitry Andric MachineMemOperand *MMOHi = MF->getMachineMemOperand(OldMMO, 2, 2);
4905ffd83dbSDimitry Andric
4915ffd83dbSDimitry Andric MIBLo.setMemRefs(MMOLo);
4925ffd83dbSDimitry Andric MIBHi.setMemRefs(MMOHi);
4935ffd83dbSDimitry Andric
4945ffd83dbSDimitry Andric // Delete the pseudo.
4955ffd83dbSDimitry Andric MBB.erase(MBBI);
4965ffd83dbSDimitry Andric return true;
4975ffd83dbSDimitry Andric }
4985ffd83dbSDimitry Andric case X86::MASKPAIR16STORE: {
4995ffd83dbSDimitry Andric int64_t Disp = MBBI->getOperand(X86::AddrDisp).getImm();
5005ffd83dbSDimitry Andric assert(Disp >= 0 && Disp <= INT32_MAX - 2 && "Unexpected displacement");
5015ffd83dbSDimitry Andric Register Reg = MBBI->getOperand(X86::AddrNumOperands).getReg();
5025ffd83dbSDimitry Andric bool SrcIsKill = MBBI->getOperand(X86::AddrNumOperands).isKill();
5035ffd83dbSDimitry Andric Register Reg0 = TRI->getSubReg(Reg, X86::sub_mask_0);
5045ffd83dbSDimitry Andric Register Reg1 = TRI->getSubReg(Reg, X86::sub_mask_1);
5055ffd83dbSDimitry Andric
506*0fca6ea1SDimitry Andric auto MIBLo =
507*0fca6ea1SDimitry Andric BuildMI(MBB, MBBI, DL, TII->get(GET_EGPR_IF_ENABLED(X86::KMOVWmk)));
508*0fca6ea1SDimitry Andric auto MIBHi =
509*0fca6ea1SDimitry Andric BuildMI(MBB, MBBI, DL, TII->get(GET_EGPR_IF_ENABLED(X86::KMOVWmk)));
5105ffd83dbSDimitry Andric
5115ffd83dbSDimitry Andric for (int i = 0; i < X86::AddrNumOperands; ++i) {
5125ffd83dbSDimitry Andric MIBLo.add(MBBI->getOperand(i));
5135ffd83dbSDimitry Andric if (i == X86::AddrDisp)
5145ffd83dbSDimitry Andric MIBHi.addImm(Disp + 2);
5155ffd83dbSDimitry Andric else
5165ffd83dbSDimitry Andric MIBHi.add(MBBI->getOperand(i));
5175ffd83dbSDimitry Andric }
5185ffd83dbSDimitry Andric MIBLo.addReg(Reg0, getKillRegState(SrcIsKill));
5195ffd83dbSDimitry Andric MIBHi.addReg(Reg1, getKillRegState(SrcIsKill));
5205ffd83dbSDimitry Andric
5215ffd83dbSDimitry Andric // Split the memory operand, adjusting the offset and size for the halves.
5225ffd83dbSDimitry Andric MachineMemOperand *OldMMO = MBBI->memoperands().front();
5235ffd83dbSDimitry Andric MachineFunction *MF = MBB.getParent();
5245ffd83dbSDimitry Andric MachineMemOperand *MMOLo = MF->getMachineMemOperand(OldMMO, 0, 2);
5255ffd83dbSDimitry Andric MachineMemOperand *MMOHi = MF->getMachineMemOperand(OldMMO, 2, 2);
5265ffd83dbSDimitry Andric
5275ffd83dbSDimitry Andric MIBLo.setMemRefs(MMOLo);
5285ffd83dbSDimitry Andric MIBHi.setMemRefs(MMOHi);
5295ffd83dbSDimitry Andric
5305ffd83dbSDimitry Andric // Delete the pseudo.
5315ffd83dbSDimitry Andric MBB.erase(MBBI);
5325ffd83dbSDimitry Andric return true;
5335ffd83dbSDimitry Andric }
534e8d8bef9SDimitry Andric case X86::MWAITX_SAVE_RBX: {
535e8d8bef9SDimitry Andric // Perform the following transformation.
536e8d8bef9SDimitry Andric // SaveRbx = pseudomwaitx InArg, SaveRbx
537e8d8bef9SDimitry Andric // =>
538e8d8bef9SDimitry Andric // [E|R]BX = InArg
539e8d8bef9SDimitry Andric // actualmwaitx
540e8d8bef9SDimitry Andric // [E|R]BX = SaveRbx
541e8d8bef9SDimitry Andric const MachineOperand &InArg = MBBI->getOperand(1);
542e8d8bef9SDimitry Andric // Copy the input argument of the pseudo into the argument of the
543e8d8bef9SDimitry Andric // actual instruction.
544e8d8bef9SDimitry Andric TII->copyPhysReg(MBB, MBBI, DL, X86::EBX, InArg.getReg(), InArg.isKill());
545e8d8bef9SDimitry Andric // Create the actual instruction.
546e8d8bef9SDimitry Andric BuildMI(MBB, MBBI, DL, TII->get(X86::MWAITXrrr));
547e8d8bef9SDimitry Andric // Finally, restore the value of RBX.
548e8d8bef9SDimitry Andric Register SaveRbx = MBBI->getOperand(2).getReg();
549e8d8bef9SDimitry Andric TII->copyPhysReg(MBB, MBBI, DL, X86::RBX, SaveRbx, /*SrcIsKill*/ true);
550e8d8bef9SDimitry Andric // Delete the pseudo.
551e8d8bef9SDimitry Andric MBBI->eraseFromParent();
552e8d8bef9SDimitry Andric return true;
553e8d8bef9SDimitry Andric }
5540b57cec5SDimitry Andric case TargetOpcode::ICALL_BRANCH_FUNNEL:
555*0fca6ea1SDimitry Andric expandICallBranchFunnel(&MBB, MBBI);
5560b57cec5SDimitry Andric return true;
557fe6060f1SDimitry Andric case X86::PLDTILECFGV: {
5587a6dacacSDimitry Andric MI.setDesc(TII->get(GET_EGPR_IF_ENABLED(X86::LDTILECFG)));
559e8d8bef9SDimitry Andric return true;
560e8d8bef9SDimitry Andric }
561fe6060f1SDimitry Andric case X86::PTILELOADDV:
562fe6060f1SDimitry Andric case X86::PTILELOADDT1V: {
563e8d8bef9SDimitry Andric for (unsigned i = 2; i > 0; --i)
56481ad6265SDimitry Andric MI.removeOperand(i);
5657a6dacacSDimitry Andric unsigned Opc = Opcode == X86::PTILELOADDV
5667a6dacacSDimitry Andric ? GET_EGPR_IF_ENABLED(X86::TILELOADD)
5677a6dacacSDimitry Andric : GET_EGPR_IF_ENABLED(X86::TILELOADDT1);
568fe6060f1SDimitry Andric MI.setDesc(TII->get(Opc));
569e8d8bef9SDimitry Andric return true;
570e8d8bef9SDimitry Andric }
57106c3fb27SDimitry Andric case X86::PTCMMIMFP16PSV:
57206c3fb27SDimitry Andric case X86::PTCMMRLFP16PSV:
573fe6060f1SDimitry Andric case X86::PTDPBSSDV:
574fe6060f1SDimitry Andric case X86::PTDPBSUDV:
575fe6060f1SDimitry Andric case X86::PTDPBUSDV:
576fe6060f1SDimitry Andric case X86::PTDPBUUDV:
577bdd1243dSDimitry Andric case X86::PTDPBF16PSV:
578bdd1243dSDimitry Andric case X86::PTDPFP16PSV: {
579e8d8bef9SDimitry Andric MI.untieRegOperand(4);
580e8d8bef9SDimitry Andric for (unsigned i = 3; i > 0; --i)
58181ad6265SDimitry Andric MI.removeOperand(i);
582fe6060f1SDimitry Andric unsigned Opc;
583fe6060f1SDimitry Andric switch (Opcode) {
58406c3fb27SDimitry Andric case X86::PTCMMIMFP16PSV: Opc = X86::TCMMIMFP16PS; break;
58506c3fb27SDimitry Andric case X86::PTCMMRLFP16PSV: Opc = X86::TCMMRLFP16PS; break;
586fe6060f1SDimitry Andric case X86::PTDPBSSDV: Opc = X86::TDPBSSD; break;
587fe6060f1SDimitry Andric case X86::PTDPBSUDV: Opc = X86::TDPBSUD; break;
588fe6060f1SDimitry Andric case X86::PTDPBUSDV: Opc = X86::TDPBUSD; break;
589fe6060f1SDimitry Andric case X86::PTDPBUUDV: Opc = X86::TDPBUUD; break;
590fe6060f1SDimitry Andric case X86::PTDPBF16PSV: Opc = X86::TDPBF16PS; break;
591bdd1243dSDimitry Andric case X86::PTDPFP16PSV: Opc = X86::TDPFP16PS; break;
592fe6060f1SDimitry Andric default: llvm_unreachable("Impossible Opcode!");
593fe6060f1SDimitry Andric }
594fe6060f1SDimitry Andric MI.setDesc(TII->get(Opc));
595e8d8bef9SDimitry Andric MI.tieOperands(0, 1);
596e8d8bef9SDimitry Andric return true;
597e8d8bef9SDimitry Andric }
598e8d8bef9SDimitry Andric case X86::PTILESTOREDV: {
599e8d8bef9SDimitry Andric for (int i = 1; i >= 0; --i)
60081ad6265SDimitry Andric MI.removeOperand(i);
6017a6dacacSDimitry Andric MI.setDesc(TII->get(GET_EGPR_IF_ENABLED(X86::TILESTORED)));
602e8d8bef9SDimitry Andric return true;
603e8d8bef9SDimitry Andric }
6047a6dacacSDimitry Andric #undef GET_EGPR_IF_ENABLED
605e8d8bef9SDimitry Andric case X86::PTILEZEROV: {
606fe6060f1SDimitry Andric for (int i = 2; i > 0; --i) // Remove row, col
60781ad6265SDimitry Andric MI.removeOperand(i);
608e8d8bef9SDimitry Andric MI.setDesc(TII->get(X86::TILEZERO));
609e8d8bef9SDimitry Andric return true;
610e8d8bef9SDimitry Andric }
611fe6060f1SDimitry Andric case X86::CALL64pcrel32_RVMARKER:
612fe6060f1SDimitry Andric case X86::CALL64r_RVMARKER:
613fe6060f1SDimitry Andric case X86::CALL64m_RVMARKER:
614fe6060f1SDimitry Andric expandCALL_RVMARKER(MBB, MBBI);
615fe6060f1SDimitry Andric return true;
616*0fca6ea1SDimitry Andric case X86::ADD32mi_ND:
617*0fca6ea1SDimitry Andric case X86::ADD64mi32_ND:
618*0fca6ea1SDimitry Andric case X86::SUB32mi_ND:
619*0fca6ea1SDimitry Andric case X86::SUB64mi32_ND:
620*0fca6ea1SDimitry Andric case X86::AND32mi_ND:
621*0fca6ea1SDimitry Andric case X86::AND64mi32_ND:
622*0fca6ea1SDimitry Andric case X86::OR32mi_ND:
623*0fca6ea1SDimitry Andric case X86::OR64mi32_ND:
624*0fca6ea1SDimitry Andric case X86::XOR32mi_ND:
625*0fca6ea1SDimitry Andric case X86::XOR64mi32_ND:
626*0fca6ea1SDimitry Andric case X86::ADC32mi_ND:
627*0fca6ea1SDimitry Andric case X86::ADC64mi32_ND:
628*0fca6ea1SDimitry Andric case X86::SBB32mi_ND:
629*0fca6ea1SDimitry Andric case X86::SBB64mi32_ND: {
630*0fca6ea1SDimitry Andric // It's possible for an EVEX-encoded legacy instruction to reach the 15-byte
631*0fca6ea1SDimitry Andric // instruction length limit: 4 bytes of EVEX prefix + 1 byte of opcode + 1
632*0fca6ea1SDimitry Andric // byte of ModRM + 1 byte of SIB + 4 bytes of displacement + 4 bytes of
633*0fca6ea1SDimitry Andric // immediate = 15 bytes in total, e.g.
634*0fca6ea1SDimitry Andric //
635*0fca6ea1SDimitry Andric // subq $184, %fs:257(%rbx, %rcx), %rax
636*0fca6ea1SDimitry Andric //
637*0fca6ea1SDimitry Andric // In such a case, no additional (ADSIZE or segment override) prefix can be
638*0fca6ea1SDimitry Andric // used. To resolve the issue, we split the “long” instruction into 2
639*0fca6ea1SDimitry Andric // instructions:
640*0fca6ea1SDimitry Andric //
641*0fca6ea1SDimitry Andric // movq %fs:257(%rbx, %rcx),%rax
642*0fca6ea1SDimitry Andric // subq $184, %rax
643*0fca6ea1SDimitry Andric //
644*0fca6ea1SDimitry Andric // Therefore we consider the OPmi_ND to be a pseudo instruction to some
645*0fca6ea1SDimitry Andric // extent.
646*0fca6ea1SDimitry Andric const MachineOperand &ImmOp =
647*0fca6ea1SDimitry Andric MI.getOperand(MI.getNumExplicitOperands() - 1);
648*0fca6ea1SDimitry Andric // If the immediate is a expr, conservatively estimate 4 bytes.
649*0fca6ea1SDimitry Andric if (ImmOp.isImm() && isInt<8>(ImmOp.getImm()))
650*0fca6ea1SDimitry Andric return false;
651*0fca6ea1SDimitry Andric int MemOpNo = X86::getFirstAddrOperandIdx(MI);
652*0fca6ea1SDimitry Andric const MachineOperand &DispOp = MI.getOperand(MemOpNo + X86::AddrDisp);
653*0fca6ea1SDimitry Andric Register Base = MI.getOperand(MemOpNo + X86::AddrBaseReg).getReg();
654*0fca6ea1SDimitry Andric // If the displacement is a expr, conservatively estimate 4 bytes.
655*0fca6ea1SDimitry Andric if (Base && DispOp.isImm() && isInt<8>(DispOp.getImm()))
656*0fca6ea1SDimitry Andric return false;
657*0fca6ea1SDimitry Andric // There can only be one of three: SIB, segment override register, ADSIZE
658*0fca6ea1SDimitry Andric Register Index = MI.getOperand(MemOpNo + X86::AddrIndexReg).getReg();
659*0fca6ea1SDimitry Andric unsigned Count = !!MI.getOperand(MemOpNo + X86::AddrSegmentReg).getReg();
660*0fca6ea1SDimitry Andric if (X86II::needSIB(Base, Index, /*In64BitMode=*/true))
661*0fca6ea1SDimitry Andric ++Count;
662*0fca6ea1SDimitry Andric if (X86MCRegisterClasses[X86::GR32RegClassID].contains(Base) ||
663*0fca6ea1SDimitry Andric X86MCRegisterClasses[X86::GR32RegClassID].contains(Index))
664*0fca6ea1SDimitry Andric ++Count;
665*0fca6ea1SDimitry Andric if (Count < 2)
666*0fca6ea1SDimitry Andric return false;
667*0fca6ea1SDimitry Andric unsigned Opc, LoadOpc;
668*0fca6ea1SDimitry Andric switch (Opcode) {
669*0fca6ea1SDimitry Andric #define MI_TO_RI(OP) \
670*0fca6ea1SDimitry Andric case X86::OP##32mi_ND: \
671*0fca6ea1SDimitry Andric Opc = X86::OP##32ri; \
672*0fca6ea1SDimitry Andric LoadOpc = X86::MOV32rm; \
673*0fca6ea1SDimitry Andric break; \
674*0fca6ea1SDimitry Andric case X86::OP##64mi32_ND: \
675*0fca6ea1SDimitry Andric Opc = X86::OP##64ri32; \
676*0fca6ea1SDimitry Andric LoadOpc = X86::MOV64rm; \
677*0fca6ea1SDimitry Andric break;
678*0fca6ea1SDimitry Andric
679*0fca6ea1SDimitry Andric default:
680*0fca6ea1SDimitry Andric llvm_unreachable("Unexpected Opcode");
681*0fca6ea1SDimitry Andric MI_TO_RI(ADD);
682*0fca6ea1SDimitry Andric MI_TO_RI(SUB);
683*0fca6ea1SDimitry Andric MI_TO_RI(AND);
684*0fca6ea1SDimitry Andric MI_TO_RI(OR);
685*0fca6ea1SDimitry Andric MI_TO_RI(XOR);
686*0fca6ea1SDimitry Andric MI_TO_RI(ADC);
687*0fca6ea1SDimitry Andric MI_TO_RI(SBB);
688*0fca6ea1SDimitry Andric #undef MI_TO_RI
689*0fca6ea1SDimitry Andric }
690*0fca6ea1SDimitry Andric // Insert OPri.
691*0fca6ea1SDimitry Andric Register DestReg = MI.getOperand(0).getReg();
692*0fca6ea1SDimitry Andric BuildMI(MBB, std::next(MBBI), DL, TII->get(Opc), DestReg)
693*0fca6ea1SDimitry Andric .addReg(DestReg)
694*0fca6ea1SDimitry Andric .add(ImmOp);
695*0fca6ea1SDimitry Andric // Change OPmi_ND to MOVrm.
696*0fca6ea1SDimitry Andric for (unsigned I = MI.getNumImplicitOperands() + 1; I != 0; --I)
697*0fca6ea1SDimitry Andric MI.removeOperand(MI.getNumOperands() - 1);
698*0fca6ea1SDimitry Andric MI.setDesc(TII->get(LoadOpc));
699*0fca6ea1SDimitry Andric return true;
700*0fca6ea1SDimitry Andric }
7010b57cec5SDimitry Andric }
7020b57cec5SDimitry Andric llvm_unreachable("Previous switch has a fallthrough?");
7030b57cec5SDimitry Andric }
7040b57cec5SDimitry Andric
705fe6060f1SDimitry Andric // This function creates additional block for storing varargs guarded
706fe6060f1SDimitry Andric // registers. It adds check for %al into entry block, to skip
707fe6060f1SDimitry Andric // GuardedRegsBlk if xmm registers should not be stored.
708fe6060f1SDimitry Andric //
709fe6060f1SDimitry Andric // EntryBlk[VAStartPseudoInstr] EntryBlk
710fe6060f1SDimitry Andric // | | .
711fe6060f1SDimitry Andric // | | .
712fe6060f1SDimitry Andric // | | GuardedRegsBlk
713fe6060f1SDimitry Andric // | => | .
714fe6060f1SDimitry Andric // | | .
715fe6060f1SDimitry Andric // | TailBlk
716fe6060f1SDimitry Andric // | |
717fe6060f1SDimitry Andric // | |
718fe6060f1SDimitry Andric //
expandVastartSaveXmmRegs(MachineBasicBlock * EntryBlk,MachineBasicBlock::iterator VAStartPseudoInstr) const719*0fca6ea1SDimitry Andric void X86ExpandPseudo::expandVastartSaveXmmRegs(
720fe6060f1SDimitry Andric MachineBasicBlock *EntryBlk,
721fe6060f1SDimitry Andric MachineBasicBlock::iterator VAStartPseudoInstr) const {
722fe6060f1SDimitry Andric assert(VAStartPseudoInstr->getOpcode() == X86::VASTART_SAVE_XMM_REGS);
723fe6060f1SDimitry Andric
724fe6060f1SDimitry Andric MachineFunction *Func = EntryBlk->getParent();
725fe6060f1SDimitry Andric const TargetInstrInfo *TII = STI->getInstrInfo();
726fe6060f1SDimitry Andric const DebugLoc &DL = VAStartPseudoInstr->getDebugLoc();
727fe6060f1SDimitry Andric Register CountReg = VAStartPseudoInstr->getOperand(0).getReg();
728fe6060f1SDimitry Andric
729fe6060f1SDimitry Andric // Calculate liveins for newly created blocks.
730fe6060f1SDimitry Andric LivePhysRegs LiveRegs(*STI->getRegisterInfo());
731fe6060f1SDimitry Andric SmallVector<std::pair<MCPhysReg, const MachineOperand *>, 8> Clobbers;
732fe6060f1SDimitry Andric
733fe6060f1SDimitry Andric LiveRegs.addLiveIns(*EntryBlk);
734fe6060f1SDimitry Andric for (MachineInstr &MI : EntryBlk->instrs()) {
735fe6060f1SDimitry Andric if (MI.getOpcode() == VAStartPseudoInstr->getOpcode())
736fe6060f1SDimitry Andric break;
737fe6060f1SDimitry Andric
738fe6060f1SDimitry Andric LiveRegs.stepForward(MI, Clobbers);
739fe6060f1SDimitry Andric }
740fe6060f1SDimitry Andric
741fe6060f1SDimitry Andric // Create the new basic blocks. One block contains all the XMM stores,
742fe6060f1SDimitry Andric // and another block is the final destination regardless of whether any
743fe6060f1SDimitry Andric // stores were performed.
744fe6060f1SDimitry Andric const BasicBlock *LLVMBlk = EntryBlk->getBasicBlock();
745fe6060f1SDimitry Andric MachineFunction::iterator EntryBlkIter = ++EntryBlk->getIterator();
746fe6060f1SDimitry Andric MachineBasicBlock *GuardedRegsBlk = Func->CreateMachineBasicBlock(LLVMBlk);
747fe6060f1SDimitry Andric MachineBasicBlock *TailBlk = Func->CreateMachineBasicBlock(LLVMBlk);
748fe6060f1SDimitry Andric Func->insert(EntryBlkIter, GuardedRegsBlk);
749fe6060f1SDimitry Andric Func->insert(EntryBlkIter, TailBlk);
750fe6060f1SDimitry Andric
751fe6060f1SDimitry Andric // Transfer the remainder of EntryBlk and its successor edges to TailBlk.
752fe6060f1SDimitry Andric TailBlk->splice(TailBlk->begin(), EntryBlk,
753fe6060f1SDimitry Andric std::next(MachineBasicBlock::iterator(VAStartPseudoInstr)),
754fe6060f1SDimitry Andric EntryBlk->end());
755fe6060f1SDimitry Andric TailBlk->transferSuccessorsAndUpdatePHIs(EntryBlk);
756fe6060f1SDimitry Andric
757349cc55cSDimitry Andric uint64_t FrameOffset = VAStartPseudoInstr->getOperand(4).getImm();
758349cc55cSDimitry Andric uint64_t VarArgsRegsOffset = VAStartPseudoInstr->getOperand(6).getImm();
759fe6060f1SDimitry Andric
760fe6060f1SDimitry Andric // TODO: add support for YMM and ZMM here.
761fe6060f1SDimitry Andric unsigned MOVOpc = STI->hasAVX() ? X86::VMOVAPSmr : X86::MOVAPSmr;
762fe6060f1SDimitry Andric
763fe6060f1SDimitry Andric // In the XMM save block, save all the XMM argument registers.
764349cc55cSDimitry Andric for (int64_t OpndIdx = 7, RegIdx = 0;
765fe6060f1SDimitry Andric OpndIdx < VAStartPseudoInstr->getNumOperands() - 1;
766fe6060f1SDimitry Andric OpndIdx++, RegIdx++) {
767349cc55cSDimitry Andric auto NewMI = BuildMI(GuardedRegsBlk, DL, TII->get(MOVOpc));
768349cc55cSDimitry Andric for (int i = 0; i < X86::AddrNumOperands; ++i) {
769349cc55cSDimitry Andric if (i == X86::AddrDisp)
770349cc55cSDimitry Andric NewMI.addImm(FrameOffset + VarArgsRegsOffset + RegIdx * 16);
771349cc55cSDimitry Andric else
772349cc55cSDimitry Andric NewMI.add(VAStartPseudoInstr->getOperand(i + 1));
773349cc55cSDimitry Andric }
774349cc55cSDimitry Andric NewMI.addReg(VAStartPseudoInstr->getOperand(OpndIdx).getReg());
775bdd1243dSDimitry Andric assert(VAStartPseudoInstr->getOperand(OpndIdx).getReg().isPhysical());
776fe6060f1SDimitry Andric }
777fe6060f1SDimitry Andric
778fe6060f1SDimitry Andric // The original block will now fall through to the GuardedRegsBlk.
779fe6060f1SDimitry Andric EntryBlk->addSuccessor(GuardedRegsBlk);
780fe6060f1SDimitry Andric // The GuardedRegsBlk will fall through to the TailBlk.
781fe6060f1SDimitry Andric GuardedRegsBlk->addSuccessor(TailBlk);
782fe6060f1SDimitry Andric
783fe6060f1SDimitry Andric if (!STI->isCallingConvWin64(Func->getFunction().getCallingConv())) {
784fe6060f1SDimitry Andric // If %al is 0, branch around the XMM save block.
785fe6060f1SDimitry Andric BuildMI(EntryBlk, DL, TII->get(X86::TEST8rr))
786fe6060f1SDimitry Andric .addReg(CountReg)
787fe6060f1SDimitry Andric .addReg(CountReg);
788fe6060f1SDimitry Andric BuildMI(EntryBlk, DL, TII->get(X86::JCC_1))
789fe6060f1SDimitry Andric .addMBB(TailBlk)
790fe6060f1SDimitry Andric .addImm(X86::COND_E);
791fe6060f1SDimitry Andric EntryBlk->addSuccessor(TailBlk);
792fe6060f1SDimitry Andric }
793fe6060f1SDimitry Andric
794fe6060f1SDimitry Andric // Add liveins to the created block.
795fe6060f1SDimitry Andric addLiveIns(*GuardedRegsBlk, LiveRegs);
796fe6060f1SDimitry Andric addLiveIns(*TailBlk, LiveRegs);
797fe6060f1SDimitry Andric
798fe6060f1SDimitry Andric // Delete the pseudo.
799fe6060f1SDimitry Andric VAStartPseudoInstr->eraseFromParent();
800fe6060f1SDimitry Andric }
801fe6060f1SDimitry Andric
8020b57cec5SDimitry Andric /// Expand all pseudo instructions contained in \p MBB.
8030b57cec5SDimitry Andric /// \returns true if any expansion occurred for \p MBB.
expandMBB(MachineBasicBlock & MBB)804*0fca6ea1SDimitry Andric bool X86ExpandPseudo::expandMBB(MachineBasicBlock &MBB) {
8050b57cec5SDimitry Andric bool Modified = false;
8060b57cec5SDimitry Andric
8070b57cec5SDimitry Andric // MBBI may be invalidated by the expansion.
8080b57cec5SDimitry Andric MachineBasicBlock::iterator MBBI = MBB.begin(), E = MBB.end();
8090b57cec5SDimitry Andric while (MBBI != E) {
8100b57cec5SDimitry Andric MachineBasicBlock::iterator NMBBI = std::next(MBBI);
811*0fca6ea1SDimitry Andric Modified |= expandMI(MBB, MBBI);
8120b57cec5SDimitry Andric MBBI = NMBBI;
8130b57cec5SDimitry Andric }
8140b57cec5SDimitry Andric
8150b57cec5SDimitry Andric return Modified;
8160b57cec5SDimitry Andric }
8170b57cec5SDimitry Andric
expandPseudosWhichAffectControlFlow(MachineFunction & MF)818*0fca6ea1SDimitry Andric bool X86ExpandPseudo::expandPseudosWhichAffectControlFlow(MachineFunction &MF) {
819fe6060f1SDimitry Andric // Currently pseudo which affects control flow is only
820fe6060f1SDimitry Andric // X86::VASTART_SAVE_XMM_REGS which is located in Entry block.
821fe6060f1SDimitry Andric // So we do not need to evaluate other blocks.
822fe6060f1SDimitry Andric for (MachineInstr &Instr : MF.front().instrs()) {
823fe6060f1SDimitry Andric if (Instr.getOpcode() == X86::VASTART_SAVE_XMM_REGS) {
824*0fca6ea1SDimitry Andric expandVastartSaveXmmRegs(&(MF.front()), Instr);
825fe6060f1SDimitry Andric return true;
826fe6060f1SDimitry Andric }
827fe6060f1SDimitry Andric }
828fe6060f1SDimitry Andric
829fe6060f1SDimitry Andric return false;
830fe6060f1SDimitry Andric }
831fe6060f1SDimitry Andric
runOnMachineFunction(MachineFunction & MF)8320b57cec5SDimitry Andric bool X86ExpandPseudo::runOnMachineFunction(MachineFunction &MF) {
83381ad6265SDimitry Andric STI = &MF.getSubtarget<X86Subtarget>();
8340b57cec5SDimitry Andric TII = STI->getInstrInfo();
8350b57cec5SDimitry Andric TRI = STI->getRegisterInfo();
8360b57cec5SDimitry Andric X86FI = MF.getInfo<X86MachineFunctionInfo>();
8370b57cec5SDimitry Andric X86FL = STI->getFrameLowering();
8380b57cec5SDimitry Andric
839*0fca6ea1SDimitry Andric bool Modified = expandPseudosWhichAffectControlFlow(MF);
840fe6060f1SDimitry Andric
8410b57cec5SDimitry Andric for (MachineBasicBlock &MBB : MF)
842*0fca6ea1SDimitry Andric Modified |= expandMBB(MBB);
8430b57cec5SDimitry Andric return Modified;
8440b57cec5SDimitry Andric }
8450b57cec5SDimitry Andric
8460b57cec5SDimitry Andric /// Returns an instance of the pseudo instruction expansion pass.
createX86ExpandPseudoPass()8470b57cec5SDimitry Andric FunctionPass *llvm::createX86ExpandPseudoPass() {
8480b57cec5SDimitry Andric return new X86ExpandPseudo();
8490b57cec5SDimitry Andric }
850