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; 370b57cec5SDimitry Andric X86ExpandPseudo() : MachineFunctionPass(ID) {} 380b57cec5SDimitry Andric 390b57cec5SDimitry 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 540b57cec5SDimitry Andric MachineFunctionProperties getRequiredProperties() const override { 550b57cec5SDimitry Andric return MachineFunctionProperties().set( 560b57cec5SDimitry Andric MachineFunctionProperties::Property::NoVRegs); 570b57cec5SDimitry Andric } 580b57cec5SDimitry Andric 590b57cec5SDimitry 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 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 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. 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 // 719*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. 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 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 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. 8470b57cec5SDimitry Andric FunctionPass *llvm::createX86ExpandPseudoPass() { 8480b57cec5SDimitry Andric return new X86ExpandPseudo(); 8490b57cec5SDimitry Andric } 850