LLVM  6.0.0svn
X86ExpandPseudo.cpp
Go to the documentation of this file.
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"
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();
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 {
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,
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();
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.
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.
297  return new X86ExpandPseudo();
298 }
unsigned getTargetFlags() const
const MachineInstrBuilder & add(const MachineOperand &MO) const
Compute iterated dominance frontiers using a linear time algorithm.
Definition: AllocatorList.h:24
char & MachineDominatorsID
MachineDominators - This pass is a machine dominators analysis pass.
unsigned getReg() const
getReg - Returns the register number.
A debug info location.
Definition: DebugLoc.h:34
const MachineInstrBuilder & addGlobalAddress(const GlobalValue *GV, int64_t Offset=0, unsigned char TargetFlags=0) const
bool isImm() const
isImm - Tests if this is a MO_Immediate operand.
X86MachineFunctionInfo - This class is derived from MachineFunction and contains private X86 target-s...
char & MachineLoopInfoID
MachineLoopInfo - This pass is a loop analysis pass.
instr_iterator erase(instr_iterator I)
Remove an instruction from the instruction list and delete it.
MachineFunctionPass - This class adapts the FunctionPass interface to allow convenient creation of pa...
const HexagonInstrInfo * TII
unsigned getOpcode() const
Returns the opcode of this MachineInstr.
Definition: MachineInstr.h:290
const char * getSymbolName() const
static bool isMem(const MachineInstr &MI, unsigned Op)
Definition: X86InstrInfo.h:137
Return from interrupt. Operand 0 is the number of bytes to pop.
AnalysisUsage & addPreservedID(const void *ID)
MachineInstrBuilder BuildMI(MachineFunction &MF, const DebugLoc &DL, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
void getAnalysisUsage(AnalysisUsage &AU) const override
getAnalysisUsage - Subclasses that override getAnalysisUsage must call this.
FunctionPass * createX86ExpandPseudoPass()
Return a Machine IR pass that expands X86-specific pseudo instructions into a sequence of actual inst...
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
const GlobalValue * getGlobal() const
EHPersonality classifyEHPersonality(const Value *Pers)
See if the given exception handling personality function is one that we understand.
Represent the analysis usage information of a pass.
Ty * getInfo()
getInfo - Keep track of various per-function pieces of information for backends that would like to do...
FunctionPass class - This class is used to implement most global optimizations.
Definition: Pass.h:285
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
void addOperand(MachineFunction &MF, const MachineOperand &Op)
Add the specified operand to the instruction.
bool isGlobal() const
isGlobal - Tests if this is a MO_GlobalAddress operand.
MachineOperand class - Representation of each machine instruction operand.
void setPreservesCFG()
This function should be called by the pass, iff they do not:
Definition: Pass.cpp:285
int64_t getImm() const
void copyPhysReg(MachineBasicBlock &MBB, MachineBasicBlock::iterator I, const DebugLoc &DL, unsigned DestReg, unsigned SrcReg, bool KillSrc) const override
Emit instructions to copy a pair of physical registers.
MachineFunctionProperties & set(Property P)
Representation of each machine instruction.
Definition: MachineInstr.h:59
const MachineFunction * getParent() const
Return the MachineFunction containing this basic block.
const MachineInstrBuilder & addImm(int64_t Val) const
Add a new immediate operand.
int64_t getOffset() const
Return the offset from the symbol in this operand.
const MachineInstrBuilder & addExternalSymbol(const char *FnName, unsigned char TargetFlags=0) const
#define I(x, y, z)
Definition: MD5.cpp:58
constexpr bool isUInt< 16 >(uint64_t x)
Definition: MathExtras.h:338
bool isSymbol() const
isSymbol - Tests if this is a MO_ExternalSymbol operand.
bool isReg() const
isReg - Tests if this is a MO_Register operand.
OUTCHAIN = EH_RETURN(INCHAIN, OFFSET, HANDLER) - This node represents &#39;eh_return&#39; gcc dwarf builtin...
Definition: ISDOpcodes.h:102
const Function * getFunction() const
getFunction - Return the LLVM function that this machine code represents
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
bool isAsynchronousEHPersonality(EHPersonality Pers)
Returns true if this personality function catches asynchronous exceptions.
Constant * getPersonalityFn() const
Get the personality function associated with this function.
Definition: Function.cpp:1260
IRTranslator LLVM IR MI
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:49
Properties which a MachineFunction may have at a given point in time.