29 #define DEBUG_TYPE "x86-pseudo" 58 return "X86 pseudo instruction expansion pass";
71 void X86ExpandPseudo::ExpandICallBranchFunnel(
80 std::vector<std::pair<MachineBasicBlock *, unsigned>> TargetMBBs;
85 auto CmpTarget = [&](
unsigned Target) {
86 BuildMI(*MBB, MBBI, DL,
TII->get(X86::LEA64r), X86::R11)
93 BuildMI(*MBB, MBBI, DL,
TII->get(X86::CMP64rr))
98 auto CreateMBB = [&]() {
105 BuildMI(*MBB, MBBI, DL,
TII->get(Opcode)).addMBB(ThenMBB);
107 auto *ElseMBB = CreateMBB();
108 MF->
insert(InsPt, ElseMBB);
113 auto EmitCondJumpTarget = [&](
unsigned Opcode,
unsigned Target) {
114 auto *ThenMBB = CreateMBB();
115 TargetMBBs.push_back({ThenMBB,
Target});
116 EmitCondJump(Opcode, ThenMBB);
119 auto EmitTailCall = [&](
unsigned Target) {
120 BuildMI(*MBB, MBBI, DL,
TII->get(X86::TAILJMPd64))
124 std::function<void(unsigned, unsigned)> EmitBranchFunnel =
126 if (NumTargets == 1) {
127 EmitTailCall(FirstTarget);
131 if (NumTargets == 2) {
132 CmpTarget(FirstTarget + 1);
133 EmitCondJumpTarget(X86::JB_1, FirstTarget);
134 EmitTailCall(FirstTarget + 1);
138 if (NumTargets < 6) {
139 CmpTarget(FirstTarget + 1);
140 EmitCondJumpTarget(X86::JB_1, FirstTarget);
141 EmitCondJumpTarget(X86::JE_1, FirstTarget + 1);
142 EmitBranchFunnel(FirstTarget + 2, NumTargets - 2);
146 auto *ThenMBB = CreateMBB();
147 CmpTarget(FirstTarget + (NumTargets / 2));
148 EmitCondJump(X86::JB_1, ThenMBB);
149 EmitCondJumpTarget(X86::JE_1, FirstTarget + (NumTargets / 2));
150 EmitBranchFunnel(FirstTarget + (NumTargets / 2) + 1,
151 NumTargets - (NumTargets / 2) - 1);
153 MF->
insert(InsPt, ThenMBB);
156 EmitBranchFunnel(FirstTarget, NumTargets / 2);
160 for (
auto P : TargetMBBs) {
165 JTMBB->
erase(JTInst);
179 case X86::TCRETURNdi:
180 case X86::TCRETURNdicc:
181 case X86::TCRETURNri:
182 case X86::TCRETURNmi:
183 case X86::TCRETURNdi64:
184 case X86::TCRETURNdi64cc:
185 case X86::TCRETURNri64:
186 case X86::TCRETURNmi64: {
187 bool isMem = Opcode == X86::TCRETURNmi || Opcode == X86::TCRETURNmi64;
190 assert(StackAdjust.
isImm() &&
"Expecting immediate value.");
193 int StackAdj = StackAdjust.
getImm();
194 int MaxTCDelta = X86FI->getTCReturnAddrDelta();
196 assert(MaxTCDelta <= 0 &&
"MaxTCDelta should never be positive");
199 Offset = StackAdj - MaxTCDelta;
200 assert(Offset >= 0 &&
"Offset should never be negative");
202 if (Opcode == X86::TCRETURNdicc || Opcode == X86::TCRETURNdi64cc) {
203 assert(Offset == 0 &&
"Conditional tail call cannot adjust the stack.");
208 Offset += X86FL->mergeSPUpdates(MBB, MBBI,
true);
209 X86FL->emitSPUpdate(MBB, MBBI, DL, Offset,
true);
213 bool IsWin64 = STI->isTargetWin64();
214 if (Opcode == X86::TCRETURNdi || Opcode == X86::TCRETURNdicc ||
215 Opcode == X86::TCRETURNdi64 || Opcode == X86::TCRETURNdi64cc) {
218 case X86::TCRETURNdi:
221 case X86::TCRETURNdicc:
222 Op = X86::TAILJMPd_CC;
224 case X86::TCRETURNdi64cc:
226 "Conditional tail calls confuse " 227 "the Win64 unwinder.");
228 Op = X86::TAILJMPd64_CC;
233 Op = X86::TAILJMPd64;
245 if (Op == X86::TAILJMPd_CC || Op == X86::TAILJMPd64_CC) {
246 MIB.
addImm(MBBI->getOperand(2).getImm());
249 }
else if (Opcode == X86::TCRETURNmi || Opcode == X86::TCRETURNmi64) {
250 unsigned Op = (Opcode == X86::TCRETURNmi)
252 : (IsWin64 ? X86::TAILJMPm64_REX : X86::TAILJMPm64);
254 for (
unsigned i = 0; i != 5; ++i)
255 MIB.
add(MBBI->getOperand(i));
256 }
else if (Opcode == X86::TCRETURNri64) {
258 TII->get(IsWin64 ? X86::TAILJMPr64_REX : X86::TAILJMPr64))
261 BuildMI(MBB, MBBI, DL,
TII->get(X86::TAILJMPr))
266 NewMI.copyImplicitOps(*MBBI->getParent()->getParent(), *MBBI);
274 case X86::EH_RETURN64: {
276 assert(DestAddr.
isReg() &&
"Offset should be in register!");
277 const bool Uses64BitFramePtr =
278 STI->isTarget64BitLP64() || STI->isTargetNaCl64();
279 unsigned StackPtr =
TRI->getStackRegister();
281 TII->get(Uses64BitFramePtr ? X86::MOV64rr : X86::MOV32rr), StackPtr)
282 .addReg(DestAddr.
getReg());
288 int64_t StackAdj = MBBI->getOperand(0).getImm();
289 X86FL->emitSPUpdate(MBB, MBBI, DL, StackAdj,
true);
292 TII->get(STI->is64Bit() ? X86::IRET64 : X86::IRET32));
298 int64_t StackAdj = MBBI->getOperand(0).getImm();
302 TII->get(STI->is64Bit() ? X86::RETQ : X86::RETL));
305 TII->get(STI->is64Bit() ? X86::RETIQ : X86::RETIL))
309 "shouldn't need to do this for x86_64 targets!");
313 X86FL->emitSPUpdate(MBB, MBBI, DL, StackAdj,
true);
315 MIB =
BuildMI(MBB, MBBI, DL,
TII->get(X86::RETL));
317 for (
unsigned I = 1,
E = MBBI->getNumOperands();
I !=
E; ++
I)
318 MIB.
add(MBBI->getOperand(
I));
322 case X86::EH_RESTORE: {
326 X86FL->restoreWin32EHStackPointers(MBB, MBBI, DL, IsSEH);
327 MBBI->eraseFromParent();
330 case X86::LCMPXCHG8B_SAVE_EBX:
331 case X86::LCMPXCHG16B_SAVE_RBX: {
339 unsigned SaveRbx = MBBI->getOperand(7).getReg();
341 unsigned ActualInArg =
342 Opcode == X86::LCMPXCHG8B_SAVE_EBX ?
X86::EBX : X86::RBX;
349 Opcode == X86::LCMPXCHG8B_SAVE_EBX ? X86::LCMPXCHG8B : X86::LCMPXCHG16B;
352 for (
unsigned Idx = 1; Idx < 6; ++Idx)
359 MBBI->eraseFromParent();
362 case TargetOpcode::ICALL_BRANCH_FUNNEL:
363 ExpandICallBranchFunnel(&MBB, MBBI);
378 Modified |= ExpandMI(MBB, MBBI);
387 TII = STI->getInstrInfo();
388 TRI = STI->getRegisterInfo();
390 X86FL = STI->getFrameLowering();
394 Modified |= ExpandMBB(MBB);
400 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.