28 #define DEBUG_TYPE "x86-pseudo" 57 return "X86 pseudo instruction expansion pass";
70 void X86ExpandPseudo::ExpandICallBranchFunnel(
79 std::vector<std::pair<MachineBasicBlock *, unsigned>> TargetMBBs;
84 auto CmpTarget = [&](
unsigned Target) {
85 BuildMI(*MBB, MBBI, DL,
TII->get(X86::LEA64r), X86::R11)
92 BuildMI(*MBB, MBBI, DL,
TII->get(X86::CMP64rr))
97 auto CreateMBB = [&]() {
104 BuildMI(*MBB, MBBI, DL,
TII->get(Opcode)).addMBB(ThenMBB);
106 auto *ElseMBB = CreateMBB();
107 MF->
insert(InsPt, ElseMBB);
112 auto EmitCondJumpTarget = [&](
unsigned Opcode,
unsigned Target) {
113 auto *ThenMBB = CreateMBB();
114 TargetMBBs.push_back({ThenMBB,
Target});
115 EmitCondJump(Opcode, ThenMBB);
118 auto EmitTailCall = [&](
unsigned Target) {
119 BuildMI(*MBB, MBBI, DL,
TII->get(X86::TAILJMPd64))
123 std::function<void(unsigned, unsigned)> EmitBranchFunnel =
125 if (NumTargets == 1) {
126 EmitTailCall(FirstTarget);
130 if (NumTargets == 2) {
131 CmpTarget(FirstTarget + 1);
132 EmitCondJumpTarget(X86::JB_1, FirstTarget);
133 EmitTailCall(FirstTarget + 1);
137 if (NumTargets < 6) {
138 CmpTarget(FirstTarget + 1);
139 EmitCondJumpTarget(X86::JB_1, FirstTarget);
140 EmitCondJumpTarget(X86::JE_1, FirstTarget + 1);
141 EmitBranchFunnel(FirstTarget + 2, NumTargets - 2);
145 auto *ThenMBB = CreateMBB();
146 CmpTarget(FirstTarget + (NumTargets / 2));
147 EmitCondJump(X86::JB_1, ThenMBB);
148 EmitCondJumpTarget(X86::JE_1, FirstTarget + (NumTargets / 2));
149 EmitBranchFunnel(FirstTarget + (NumTargets / 2) + 1,
150 NumTargets - (NumTargets / 2) - 1);
152 MF->
insert(InsPt, ThenMBB);
155 EmitBranchFunnel(FirstTarget, NumTargets / 2);
159 for (
auto P : TargetMBBs) {
164 JTMBB->
erase(JTInst);
178 case X86::TCRETURNdi:
179 case X86::TCRETURNdicc:
180 case X86::TCRETURNri:
181 case X86::TCRETURNmi:
182 case X86::TCRETURNdi64:
183 case X86::TCRETURNdi64cc:
184 case X86::TCRETURNri64:
185 case X86::TCRETURNmi64: {
186 bool isMem = Opcode == X86::TCRETURNmi || Opcode == X86::TCRETURNmi64;
189 assert(StackAdjust.
isImm() &&
"Expecting immediate value.");
192 int StackAdj = StackAdjust.
getImm();
193 int MaxTCDelta = X86FI->getTCReturnAddrDelta();
195 assert(MaxTCDelta <= 0 &&
"MaxTCDelta should never be positive");
198 Offset = StackAdj - MaxTCDelta;
199 assert(Offset >= 0 &&
"Offset should never be negative");
201 if (Opcode == X86::TCRETURNdicc || Opcode == X86::TCRETURNdi64cc) {
202 assert(Offset == 0 &&
"Conditional tail call cannot adjust the stack.");
207 Offset += X86FL->mergeSPUpdates(MBB, MBBI,
true);
208 X86FL->emitSPUpdate(MBB, MBBI, DL, Offset,
true);
212 bool IsWin64 = STI->isTargetWin64();
213 if (Opcode == X86::TCRETURNdi || Opcode == X86::TCRETURNdicc ||
214 Opcode == X86::TCRETURNdi64 || Opcode == X86::TCRETURNdi64cc) {
217 case X86::TCRETURNdi:
220 case X86::TCRETURNdicc:
221 Op = X86::TAILJMPd_CC;
223 case X86::TCRETURNdi64cc:
225 "Conditional tail calls confuse " 226 "the Win64 unwinder.");
227 Op = X86::TAILJMPd64_CC;
232 Op = X86::TAILJMPd64;
244 if (Op == X86::TAILJMPd_CC || Op == X86::TAILJMPd64_CC) {
245 MIB.
addImm(MBBI->getOperand(2).getImm());
248 }
else if (Opcode == X86::TCRETURNmi || Opcode == X86::TCRETURNmi64) {
249 unsigned Op = (Opcode == X86::TCRETURNmi)
251 : (IsWin64 ? X86::TAILJMPm64_REX : X86::TAILJMPm64);
253 for (
unsigned i = 0; i != 5; ++i)
254 MIB.
add(MBBI->getOperand(i));
255 }
else if (Opcode == X86::TCRETURNri64) {
257 TII->get(IsWin64 ? X86::TAILJMPr64_REX : X86::TAILJMPr64))
260 BuildMI(MBB, MBBI, DL,
TII->get(X86::TAILJMPr))
265 NewMI.copyImplicitOps(*MBBI->getParent()->getParent(), *MBBI);
273 case X86::EH_RETURN64: {
275 assert(DestAddr.
isReg() &&
"Offset should be in register!");
276 const bool Uses64BitFramePtr =
277 STI->isTarget64BitLP64() || STI->isTargetNaCl64();
278 unsigned StackPtr =
TRI->getStackRegister();
280 TII->get(Uses64BitFramePtr ? X86::MOV64rr : X86::MOV32rr), StackPtr)
281 .addReg(DestAddr.
getReg());
287 int64_t StackAdj = MBBI->getOperand(0).getImm();
288 X86FL->emitSPUpdate(MBB, MBBI, DL, StackAdj,
true);
291 TII->get(STI->is64Bit() ? X86::IRET64 : X86::IRET32));
297 int64_t StackAdj = MBBI->getOperand(0).getImm();
301 TII->get(STI->is64Bit() ? X86::RETQ : X86::RETL));
304 TII->get(STI->is64Bit() ? X86::RETIQ : X86::RETIL))
308 "shouldn't need to do this for x86_64 targets!");
312 X86FL->emitSPUpdate(MBB, MBBI, DL, StackAdj,
true);
314 MIB =
BuildMI(MBB, MBBI, DL,
TII->get(X86::RETL));
316 for (
unsigned I = 1,
E = MBBI->getNumOperands();
I !=
E; ++
I)
317 MIB.
add(MBBI->getOperand(
I));
321 case X86::EH_RESTORE: {
325 X86FL->restoreWin32EHStackPointers(MBB, MBBI, DL, IsSEH);
326 MBBI->eraseFromParent();
329 case X86::LCMPXCHG8B_SAVE_EBX:
330 case X86::LCMPXCHG16B_SAVE_RBX: {
338 unsigned SaveRbx = MBBI->getOperand(7).getReg();
340 unsigned ActualInArg =
341 Opcode == X86::LCMPXCHG8B_SAVE_EBX ?
X86::EBX : X86::RBX;
348 Opcode == X86::LCMPXCHG8B_SAVE_EBX ? X86::LCMPXCHG8B : X86::LCMPXCHG16B;
351 for (
unsigned Idx = 1; Idx < 6; ++Idx)
358 MBBI->eraseFromParent();
361 case TargetOpcode::ICALL_BRANCH_FUNNEL:
362 ExpandICallBranchFunnel(&MBB, MBBI);
377 Modified |= ExpandMI(MBB, MBBI);
386 TII = STI->getInstrInfo();
387 TRI = STI->getRegisterInfo();
389 X86FL = STI->getFrameLowering();
393 Modified |= ExpandMBB(MBB);
399 return new X86ExpandPseudo();
unsigned getTargetFlags() const
const MachineInstrBuilder & add(const MachineOperand &MO) const
This class represents lattice values for constants.
const DebugLoc & getDebugLoc() const
Returns the debug location id of this MachineInstr.
char & MachineDominatorsID
MachineDominators - This pass is a machine dominators analysis pass.
unsigned getReg() const
getReg - Returns the register number.
unsigned const TargetRegisterInfo * TRI
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 getNumOperands() const
Retuns the total number of operands.
unsigned getOpcode() const
Returns the opcode of this MachineInstr.
const char * getSymbolName() const
static bool isMem(const MachineInstr &MI, unsigned Op)
Return from interrupt. Operand 0 is the number of bytes to pop.
AnalysisUsage & addPreservedID(const void *ID)
MachineBasicBlock * CreateMachineBasicBlock(const BasicBlock *bb=nullptr)
CreateMachineBasicBlock - Allocate a new MachineBasicBlock.
BasicBlockListType::iterator iterator
MachineInstrBuilder BuildMI(MachineFunction &MF, const DebugLoc &DL, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
LLVM Basic Block Representation.
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.
static Target * FirstTarget
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
void addSuccessor(MachineBasicBlock *Succ, BranchProbability Prob=BranchProbability::getUnknown())
Add Succ as a successor of this MachineBasicBlock.
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:
const Function & getFunction() const
Return the LLVM function that this machine code represents.
Target - Wrapper for Target specific information.
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.
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
const BasicBlock * getBasicBlock() const
Return the LLVM basic block that this instance corresponded to originally.
const MachineInstrBuilder & addReg(unsigned RegNo, unsigned flags=0, unsigned SubReg=0) const
Add a new virtual register operand.
constexpr bool isUInt< 16 >(uint64_t x)
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 'eh_return' gcc dwarf builtin...
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
void insert(iterator MBBI, MachineBasicBlock *MBB)
bool isAsynchronousEHPersonality(EHPersonality Pers)
Returns true if this personality function catches asynchronous exceptions.
Constant * getPersonalityFn() const
Get the personality function associated with this function.
StringRef - Represent a constant reference to a string, i.e.
const MachineOperand & getOperand(unsigned i) const
Properties which a MachineFunction may have at a given point in time.