1 //===------- X86ExpandPseudo.cpp - Expand pseudo instructions -------------===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 // 10 // This file contains a pass that expands pseudo instructions into target 11 // instructions to allow proper scheduling, if-conversion, other late 12 // optimizations, or simply the encoding of the instructions. 13 // 14 //===----------------------------------------------------------------------===// 15 16 #include "X86.h" 17 #include "X86FrameLowering.h" 18 #include "X86InstrBuilder.h" 19 #include "X86InstrInfo.h" 20 #include "X86MachineFunctionInfo.h" 21 #include "X86Subtarget.h" 22 #include "llvm/Analysis/EHPersonalities.h" 23 #include "llvm/CodeGen/MachineFunctionPass.h" 24 #include "llvm/CodeGen/MachineInstrBuilder.h" 25 #include "llvm/CodeGen/Passes.h" // For IDs of passes that are preserved. 26 #include "llvm/IR/GlobalValue.h" 27 using namespace llvm; 28 29 #define DEBUG_TYPE "x86-pseudo" 30 31 namespace { 32 class X86ExpandPseudo : public MachineFunctionPass { 33 public: 34 static char ID; 35 X86ExpandPseudo() : MachineFunctionPass(ID) {} 36 37 void getAnalysisUsage(AnalysisUsage &AU) const override { 38 AU.setPreservesCFG(); 39 AU.addPreservedID(MachineLoopInfoID); 40 AU.addPreservedID(MachineDominatorsID); 41 MachineFunctionPass::getAnalysisUsage(AU); 42 } 43 44 const X86Subtarget *STI; 45 const X86InstrInfo *TII; 46 const X86RegisterInfo *TRI; 47 const X86MachineFunctionInfo *X86FI; 48 const X86FrameLowering *X86FL; 49 50 bool runOnMachineFunction(MachineFunction &Fn) override; 51 52 MachineFunctionProperties getRequiredProperties() const override { 53 return MachineFunctionProperties().set( 54 MachineFunctionProperties::Property::NoVRegs); 55 } 56 57 StringRef getPassName() const override { 58 return "X86 pseudo instruction expansion pass"; 59 } 60 61 private: 62 bool ExpandMI(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI); 63 bool ExpandMBB(MachineBasicBlock &MBB); 64 }; 65 char X86ExpandPseudo::ID = 0; 66 } // End anonymous namespace. 67 68 /// If \p MBBI is a pseudo instruction, this method expands 69 /// it to the corresponding (sequence of) actual instruction(s). 70 /// \returns true if \p MBBI has been expanded. 71 bool X86ExpandPseudo::ExpandMI(MachineBasicBlock &MBB, 72 MachineBasicBlock::iterator MBBI) { 73 MachineInstr &MI = *MBBI; 74 unsigned Opcode = MI.getOpcode(); 75 DebugLoc DL = MBBI->getDebugLoc(); 76 switch (Opcode) { 77 default: 78 return false; 79 case X86::TCRETURNdi: 80 case X86::TCRETURNdicc: 81 case X86::TCRETURNri: 82 case X86::TCRETURNmi: 83 case X86::TCRETURNdi64: 84 case X86::TCRETURNdi64cc: 85 case X86::TCRETURNri64: 86 case X86::TCRETURNmi64: { 87 bool isMem = Opcode == X86::TCRETURNmi || Opcode == X86::TCRETURNmi64; 88 MachineOperand &JumpTarget = MBBI->getOperand(0); 89 MachineOperand &StackAdjust = MBBI->getOperand(isMem ? 5 : 1); 90 assert(StackAdjust.isImm() && "Expecting immediate value."); 91 92 // Adjust stack pointer. 93 int StackAdj = StackAdjust.getImm(); 94 int MaxTCDelta = X86FI->getTCReturnAddrDelta(); 95 int Offset = 0; 96 assert(MaxTCDelta <= 0 && "MaxTCDelta should never be positive"); 97 98 // Incoporate the retaddr area. 99 Offset = StackAdj - MaxTCDelta; 100 assert(Offset >= 0 && "Offset should never be negative"); 101 102 if (Opcode == X86::TCRETURNdicc || Opcode == X86::TCRETURNdi64cc) { 103 assert(Offset == 0 && "Conditional tail call cannot adjust the stack."); 104 } 105 106 if (Offset) { 107 // Check for possible merge with preceding ADD instruction. 108 Offset += X86FL->mergeSPUpdates(MBB, MBBI, true); 109 X86FL->emitSPUpdate(MBB, MBBI, Offset, /*InEpilogue=*/true); 110 } 111 112 // Jump to label or value in register. 113 bool IsWin64 = STI->isTargetWin64(); 114 if (Opcode == X86::TCRETURNdi || Opcode == X86::TCRETURNdicc || 115 Opcode == X86::TCRETURNdi64 || Opcode == X86::TCRETURNdi64cc) { 116 unsigned Op; 117 switch (Opcode) { 118 case X86::TCRETURNdi: 119 Op = X86::TAILJMPd; 120 break; 121 case X86::TCRETURNdicc: 122 Op = X86::TAILJMPd_CC; 123 break; 124 case X86::TCRETURNdi64cc: 125 assert(!MBB.getParent()->hasWinCFI() && 126 "Conditional tail calls confuse " 127 "the Win64 unwinder."); 128 Op = X86::TAILJMPd64_CC; 129 break; 130 default: 131 // Note: Win64 uses REX prefixes indirect jumps out of functions, but 132 // not direct ones. 133 Op = X86::TAILJMPd64; 134 break; 135 } 136 MachineInstrBuilder MIB = BuildMI(MBB, MBBI, DL, TII->get(Op)); 137 if (JumpTarget.isGlobal()) { 138 MIB.addGlobalAddress(JumpTarget.getGlobal(), JumpTarget.getOffset(), 139 JumpTarget.getTargetFlags()); 140 } else { 141 assert(JumpTarget.isSymbol()); 142 MIB.addExternalSymbol(JumpTarget.getSymbolName(), 143 JumpTarget.getTargetFlags()); 144 } 145 if (Op == X86::TAILJMPd_CC || Op == X86::TAILJMPd64_CC) { 146 MIB.addImm(MBBI->getOperand(2).getImm()); 147 } 148 149 } else if (Opcode == X86::TCRETURNmi || Opcode == X86::TCRETURNmi64) { 150 unsigned Op = (Opcode == X86::TCRETURNmi) 151 ? X86::TAILJMPm 152 : (IsWin64 ? X86::TAILJMPm64_REX : X86::TAILJMPm64); 153 MachineInstrBuilder MIB = BuildMI(MBB, MBBI, DL, TII->get(Op)); 154 for (unsigned i = 0; i != 5; ++i) 155 MIB.add(MBBI->getOperand(i)); 156 } else if (Opcode == X86::TCRETURNri64) { 157 BuildMI(MBB, MBBI, DL, 158 TII->get(IsWin64 ? X86::TAILJMPr64_REX : X86::TAILJMPr64)) 159 .addReg(JumpTarget.getReg(), RegState::Kill); 160 } else { 161 BuildMI(MBB, MBBI, DL, TII->get(X86::TAILJMPr)) 162 .addReg(JumpTarget.getReg(), RegState::Kill); 163 } 164 165 MachineInstr &NewMI = *std::prev(MBBI); 166 NewMI.copyImplicitOps(*MBBI->getParent()->getParent(), *MBBI); 167 168 // Delete the pseudo instruction TCRETURN. 169 MBB.erase(MBBI); 170 171 return true; 172 } 173 case X86::EH_RETURN: 174 case X86::EH_RETURN64: { 175 MachineOperand &DestAddr = MBBI->getOperand(0); 176 assert(DestAddr.isReg() && "Offset should be in register!"); 177 const bool Uses64BitFramePtr = 178 STI->isTarget64BitLP64() || STI->isTargetNaCl64(); 179 unsigned StackPtr = TRI->getStackRegister(); 180 BuildMI(MBB, MBBI, DL, 181 TII->get(Uses64BitFramePtr ? X86::MOV64rr : X86::MOV32rr), StackPtr) 182 .addReg(DestAddr.getReg()); 183 // The EH_RETURN pseudo is really removed during the MC Lowering. 184 return true; 185 } 186 case X86::IRET: { 187 // Adjust stack to erase error code 188 int64_t StackAdj = MBBI->getOperand(0).getImm(); 189 X86FL->emitSPUpdate(MBB, MBBI, StackAdj, true); 190 // Replace pseudo with machine iret 191 BuildMI(MBB, MBBI, DL, 192 TII->get(STI->is64Bit() ? X86::IRET64 : X86::IRET32)); 193 MBB.erase(MBBI); 194 return true; 195 } 196 case X86::RET: { 197 // Adjust stack to erase error code 198 int64_t StackAdj = MBBI->getOperand(0).getImm(); 199 MachineInstrBuilder MIB; 200 if (StackAdj == 0) { 201 MIB = BuildMI(MBB, MBBI, DL, 202 TII->get(STI->is64Bit() ? X86::RETQ : X86::RETL)); 203 } else if (isUInt<16>(StackAdj)) { 204 MIB = BuildMI(MBB, MBBI, DL, 205 TII->get(STI->is64Bit() ? X86::RETIQ : X86::RETIL)) 206 .addImm(StackAdj); 207 } else { 208 assert(!STI->is64Bit() && 209 "shouldn't need to do this for x86_64 targets!"); 210 // A ret can only handle immediates as big as 2**16-1. If we need to pop 211 // off bytes before the return address, we must do it manually. 212 BuildMI(MBB, MBBI, DL, TII->get(X86::POP32r)).addReg(X86::ECX, RegState::Define); 213 X86FL->emitSPUpdate(MBB, MBBI, StackAdj, /*InEpilogue=*/true); 214 BuildMI(MBB, MBBI, DL, TII->get(X86::PUSH32r)).addReg(X86::ECX); 215 MIB = BuildMI(MBB, MBBI, DL, TII->get(X86::RETL)); 216 } 217 for (unsigned I = 1, E = MBBI->getNumOperands(); I != E; ++I) 218 MIB.add(MBBI->getOperand(I)); 219 MBB.erase(MBBI); 220 return true; 221 } 222 case X86::EH_RESTORE: { 223 // Restore ESP and EBP, and optionally ESI if required. 224 bool IsSEH = isAsynchronousEHPersonality(classifyEHPersonality( 225 MBB.getParent()->getFunction()->getPersonalityFn())); 226 X86FL->restoreWin32EHStackPointers(MBB, MBBI, DL, /*RestoreSP=*/IsSEH); 227 MBBI->eraseFromParent(); 228 return true; 229 } 230 case X86::LCMPXCHG8B_SAVE_EBX: 231 case X86::LCMPXCHG16B_SAVE_RBX: { 232 // Perform the following transformation. 233 // SaveRbx = pseudocmpxchg Addr, <4 opds for the address>, InArg, SaveRbx 234 // => 235 // [E|R]BX = InArg 236 // actualcmpxchg Addr 237 // [E|R]BX = SaveRbx 238 const MachineOperand &InArg = MBBI->getOperand(6); 239 unsigned SaveRbx = MBBI->getOperand(7).getReg(); 240 241 unsigned ActualInArg = 242 Opcode == X86::LCMPXCHG8B_SAVE_EBX ? X86::EBX : X86::RBX; 243 // Copy the input argument of the pseudo into the argument of the 244 // actual instruction. 245 TII->copyPhysReg(MBB, MBBI, DL, ActualInArg, InArg.getReg(), 246 InArg.isKill()); 247 // Create the actual instruction. 248 unsigned ActualOpc = 249 Opcode == X86::LCMPXCHG8B_SAVE_EBX ? X86::LCMPXCHG8B : X86::LCMPXCHG16B; 250 MachineInstr *NewInstr = BuildMI(MBB, MBBI, DL, TII->get(ActualOpc)); 251 // Copy the operands related to the address. 252 for (unsigned Idx = 1; Idx < 6; ++Idx) 253 NewInstr->addOperand(MBBI->getOperand(Idx)); 254 // Finally, restore the value of RBX. 255 TII->copyPhysReg(MBB, MBBI, DL, ActualInArg, SaveRbx, 256 /*SrcIsKill*/ true); 257 258 // Delete the pseudo. 259 MBBI->eraseFromParent(); 260 return true; 261 } 262 } 263 llvm_unreachable("Previous switch has a fallthrough?"); 264 } 265 266 /// Expand all pseudo instructions contained in \p MBB. 267 /// \returns true if any expansion occurred for \p MBB. 268 bool X86ExpandPseudo::ExpandMBB(MachineBasicBlock &MBB) { 269 bool Modified = false; 270 271 // MBBI may be invalidated by the expansion. 272 MachineBasicBlock::iterator MBBI = MBB.begin(), E = MBB.end(); 273 while (MBBI != E) { 274 MachineBasicBlock::iterator NMBBI = std::next(MBBI); 275 Modified |= ExpandMI(MBB, MBBI); 276 MBBI = NMBBI; 277 } 278 279 return Modified; 280 } 281 282 bool X86ExpandPseudo::runOnMachineFunction(MachineFunction &MF) { 283 STI = &static_cast<const X86Subtarget &>(MF.getSubtarget()); 284 TII = STI->getInstrInfo(); 285 TRI = STI->getRegisterInfo(); 286 X86FI = MF.getInfo<X86MachineFunctionInfo>(); 287 X86FL = STI->getFrameLowering(); 288 289 bool Modified = false; 290 for (MachineBasicBlock &MBB : MF) 291 Modified |= ExpandMBB(MBB); 292 return Modified; 293 } 294 295 /// Returns an instance of the pseudo instruction expansion pass. 296 FunctionPass *llvm::createX86ExpandPseudoPass() { 297 return new X86ExpandPseudo(); 298 } 299