Skip to content

Commit cbb936b

Browse files
committed
Implement Import Call Optimization for x64
1 parent 71478ec commit cbb936b

24 files changed

+567
-30
lines changed

llvm/include/llvm/Transforms/CFGuard.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
namespace llvm {
1717

1818
class FunctionPass;
19+
class GlobalValue;
1920

2021
class CFGuardPass : public PassInfoMixin<CFGuardPass> {
2122
public:
@@ -34,6 +35,8 @@ FunctionPass *createCFGuardCheckPass();
3435
/// Insert Control FLow Guard dispatches on indirect function calls.
3536
FunctionPass *createCFGuardDispatchPass();
3637

38+
bool isCFGuardFunction(const GlobalValue *GV);
39+
3740
} // namespace llvm
3841

3942
#endif

llvm/lib/MC/MCObjectFileInfo.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -599,6 +599,11 @@ void MCObjectFileInfo::initCOFFMCObjectFileInfo(const Triple &T) {
599599
if (T.getArch() == Triple::aarch64) {
600600
ImportCallSection =
601601
Ctx->getCOFFSection(".impcall", COFF::IMAGE_SCN_LNK_INFO);
602+
} else if (T.getArch() == Triple::x86_64) {
603+
// Import Call Optimization on x64 leverages the same metadata as the
604+
// retpoline mitigation, hence the unusual section name.
605+
ImportCallSection =
606+
Ctx->getCOFFSection(".retplne", COFF::IMAGE_SCN_LNK_INFO);
602607
}
603608

604609
// Debug info.

llvm/lib/Target/X86/X86AsmPrinter.cpp

Lines changed: 34 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -457,7 +457,8 @@ static bool isIndirectBranchOrTailCall(const MachineInstr &MI) {
457457
Opc == X86::TAILJMPr64 || Opc == X86::TAILJMPm64 ||
458458
Opc == X86::TCRETURNri || Opc == X86::TCRETURNmi ||
459459
Opc == X86::TCRETURNri64 || Opc == X86::TCRETURNmi64 ||
460-
Opc == X86::TAILJMPr64_REX || Opc == X86::TAILJMPm64_REX;
460+
Opc == X86::TCRETURNri64_ImpCall || Opc == X86::TAILJMPr64_REX ||
461+
Opc == X86::TAILJMPm64_REX;
461462
}
462463

463464
void X86AsmPrinter::emitBasicBlockEnd(const MachineBasicBlock &MBB) {
@@ -941,6 +942,9 @@ void X86AsmPrinter::emitStartOfAsmFile(Module &M) {
941942
OutStreamer->emitSymbolAttribute(S, MCSA_Global);
942943
OutStreamer->emitAssignment(
943944
S, MCConstantExpr::create(Feat00Value, MMI->getContext()));
945+
946+
if (M.getModuleFlag("import-call-optimization"))
947+
EnableImportCallOptimization = true;
944948
}
945949
OutStreamer->emitSyntaxDirective();
946950

@@ -1042,6 +1046,35 @@ void X86AsmPrinter::emitEndOfAsmFile(Module &M) {
10421046
// safe to set.
10431047
OutStreamer->emitAssemblerFlag(MCAF_SubsectionsViaSymbols);
10441048
} else if (TT.isOSBinFormatCOFF()) {
1049+
// If import call optimization is enabled, emit the appropriate section.
1050+
// We do this whether or not we recorded any items.
1051+
if (EnableImportCallOptimization) {
1052+
OutStreamer->switchSection(getObjFileLowering().getImportCallSection());
1053+
1054+
// Section always starts with some magic.
1055+
constexpr char ImpCallMagic[12] = "RetpolineV1";
1056+
OutStreamer->emitBytes(StringRef{ImpCallMagic, sizeof(ImpCallMagic)});
1057+
1058+
// Layout of this section is:
1059+
// Per section that contains an item to record:
1060+
// uint32_t SectionSize: Size in bytes for information in this section.
1061+
// uint32_t Section Number
1062+
// Per call to imported function in section:
1063+
// uint32_t Kind: the kind of item.
1064+
// uint32_t InstOffset: the offset of the instr in its parent section.
1065+
for (auto &[Section, CallsToImportedFuncs] :
1066+
SectionToImportedFunctionCalls) {
1067+
unsigned SectionSize =
1068+
sizeof(uint32_t) * (2 + 2 * CallsToImportedFuncs.size());
1069+
OutStreamer->emitInt32(SectionSize);
1070+
OutStreamer->emitCOFFSecNumber(Section->getBeginSymbol());
1071+
for (auto &[CallsiteSymbol, Kind] : CallsToImportedFuncs) {
1072+
OutStreamer->emitInt32(Kind);
1073+
OutStreamer->emitCOFFSecOffset(CallsiteSymbol);
1074+
}
1075+
}
1076+
}
1077+
10451078
if (usesMSVCFloatingPoint(TT, M)) {
10461079
// In Windows' libcmt.lib, there is a file which is linked in only if the
10471080
// symbol _fltused is referenced. Linking this in causes some

llvm/lib/Target/X86/X86AsmPrinter.h

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,26 @@ class LLVM_LIBRARY_VISIBILITY X86AsmPrinter : public AsmPrinter {
3131
bool EmitFPOData = false;
3232
bool ShouldEmitWeakSwiftAsyncExtendedFramePointerFlags = false;
3333
bool IndCSPrefix = false;
34+
bool EnableImportCallOptimization = false;
35+
36+
enum ImportCallKind : unsigned {
37+
IMAGE_RETPOLINE_AMD64_IMPORT_BR = 0x02,
38+
IMAGE_RETPOLINE_AMD64_IMPORT_CALL = 0x03,
39+
IMAGE_RETPOLINE_AMD64_INDIR_BR = 0x04,
40+
IMAGE_RETPOLINE_AMD64_INDIR_CALL = 0x05,
41+
IMAGE_RETPOLINE_AMD64_INDIR_BR_REX = 0x06,
42+
IMAGE_RETPOLINE_AMD64_CFG_BR = 0x08,
43+
IMAGE_RETPOLINE_AMD64_CFG_CALL = 0x09,
44+
IMAGE_RETPOLINE_AMD64_CFG_BR_REX = 0x0A,
45+
IMAGE_RETPOLINE_AMD64_SWITCHTABLE_FIRST = 0x010,
46+
IMAGE_RETPOLINE_AMD64_SWITCHTABLE_LAST = 0x01F,
47+
};
48+
struct ImportCallInfo {
49+
MCSymbol *CalleeSymbol;
50+
ImportCallKind Kind;
51+
};
52+
DenseMap<MCSection *, std::vector<ImportCallInfo>>
53+
SectionToImportedFunctionCalls;
3454

3555
// This utility class tracks the length of a stackmap instruction's 'shadow'.
3656
// It is used by the X86AsmPrinter to ensure that the stackmap shadow
@@ -45,7 +65,7 @@ class LLVM_LIBRARY_VISIBILITY X86AsmPrinter : public AsmPrinter {
4565
void startFunction(MachineFunction &MF) {
4666
this->MF = &MF;
4767
}
48-
void count(MCInst &Inst, const MCSubtargetInfo &STI,
68+
void count(const MCInst &Inst, const MCSubtargetInfo &STI,
4969
MCCodeEmitter *CodeEmitter);
5070

5171
// Called to signal the start of a shadow of RequiredSize bytes.
@@ -126,6 +146,12 @@ class LLVM_LIBRARY_VISIBILITY X86AsmPrinter : public AsmPrinter {
126146
void emitMachOIFuncStubHelperBody(Module &M, const GlobalIFunc &GI,
127147
MCSymbol *LazyPointer) override;
128148

149+
void emitCallInstruction(const llvm::MCInst &MCI);
150+
151+
// Emits a label to mark the next instruction as being relevant to Import Call
152+
// Optimization.
153+
void emitLabelAndRecordForImportCallOptimization(ImportCallKind Kind);
154+
129155
public:
130156
X86AsmPrinter(TargetMachine &TM, std::unique_ptr<MCStreamer> Streamer);
131157

llvm/lib/Target/X86/X86ExpandPseudo.cpp

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -274,6 +274,7 @@ bool X86ExpandPseudo::expandMI(MachineBasicBlock &MBB,
274274
case X86::TCRETURNdi64:
275275
case X86::TCRETURNdi64cc:
276276
case X86::TCRETURNri64:
277+
case X86::TCRETURNri64_ImpCall:
277278
case X86::TCRETURNmi64: {
278279
bool isMem = Opcode == X86::TCRETURNmi || Opcode == X86::TCRETURNmi64;
279280
MachineOperand &JumpTarget = MBBI->getOperand(0);
@@ -345,12 +346,14 @@ bool X86ExpandPseudo::expandMI(MachineBasicBlock &MBB,
345346
MachineInstrBuilder MIB = BuildMI(MBB, MBBI, DL, TII->get(Op));
346347
for (unsigned i = 0; i != X86::AddrNumOperands; ++i)
347348
MIB.add(MBBI->getOperand(i));
348-
} else if (Opcode == X86::TCRETURNri64) {
349+
} else if ((Opcode == X86::TCRETURNri64) ||
350+
(Opcode == X86::TCRETURNri64_ImpCall)) {
349351
JumpTarget.setIsKill();
350352
BuildMI(MBB, MBBI, DL,
351353
TII->get(IsWin64 ? X86::TAILJMPr64_REX : X86::TAILJMPr64))
352354
.add(JumpTarget);
353355
} else {
356+
assert(!IsWin64 && "Win64 requires REX for indirect jumps.");
354357
JumpTarget.setIsKill();
355358
BuildMI(MBB, MBBI, DL, TII->get(X86::TAILJMPr))
356359
.add(JumpTarget);
@@ -865,6 +868,9 @@ bool X86ExpandPseudo::expandMI(MachineBasicBlock &MBB,
865868
case X86::CALL64m_RVMARKER:
866869
expandCALL_RVMARKER(MBB, MBBI);
867870
return true;
871+
case X86::CALL64r_ImpCall:
872+
MI.setDesc(TII->get(X86::CALL64r));
873+
return true;
868874
case X86::ADD32mi_ND:
869875
case X86::ADD64mi32_ND:
870876
case X86::SUB32mi_ND:

llvm/lib/Target/X86/X86FastISel.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
#include "llvm/IR/Instructions.h"
3535
#include "llvm/IR/IntrinsicInst.h"
3636
#include "llvm/IR/IntrinsicsX86.h"
37+
#include "llvm/IR/Module.h"
3738
#include "llvm/IR/Operator.h"
3839
#include "llvm/MC/MCAsmInfo.h"
3940
#include "llvm/MC/MCSymbol.h"
@@ -3280,6 +3281,11 @@ bool X86FastISel::fastLowerCall(CallLoweringInfo &CLI) {
32803281
if (Flag.isSwiftError() || Flag.isPreallocated())
32813282
return false;
32823283

3284+
// Can't handle import call optimization.
3285+
if (Is64Bit &&
3286+
MF->getFunction().getParent()->getModuleFlag("import-call-optimization"))
3287+
return false;
3288+
32833289
SmallVector<MVT, 16> OutVTs;
32843290
SmallVector<unsigned, 16> ArgRegs;
32853291

llvm/lib/Target/X86/X86FrameLowering.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2399,7 +2399,8 @@ X86FrameLowering::getWinEHFuncletFrameSize(const MachineFunction &MF) const {
23992399
static bool isTailCallOpcode(unsigned Opc) {
24002400
return Opc == X86::TCRETURNri || Opc == X86::TCRETURNdi ||
24012401
Opc == X86::TCRETURNmi || Opc == X86::TCRETURNri64 ||
2402-
Opc == X86::TCRETURNdi64 || Opc == X86::TCRETURNmi64;
2402+
Opc == X86::TCRETURNri64_ImpCall || Opc == X86::TCRETURNdi64 ||
2403+
Opc == X86::TCRETURNmi64;
24032404
}
24042405

24052406
void X86FrameLowering::emitEpilogue(MachineFunction &MF,

llvm/lib/Target/X86/X86ISelLowering.cpp

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18940,7 +18940,7 @@ SDValue X86TargetLowering::LowerJumpTable(SDValue Op, SelectionDAG &DAG) const {
1894018940

1894118941
SDValue X86TargetLowering::LowerExternalSymbol(SDValue Op,
1894218942
SelectionDAG &DAG) const {
18943-
return LowerGlobalOrExternal(Op, DAG, /*ForCall=*/false);
18943+
return LowerGlobalOrExternal(Op, DAG, /*ForCall=*/false, nullptr);
1894418944
}
1894518945

1894618946
SDValue
@@ -18968,7 +18968,8 @@ X86TargetLowering::LowerBlockAddress(SDValue Op, SelectionDAG &DAG) const {
1896818968
/// Creates target global address or external symbol nodes for calls or
1896918969
/// other uses.
1897018970
SDValue X86TargetLowering::LowerGlobalOrExternal(SDValue Op, SelectionDAG &DAG,
18971-
bool ForCall) const {
18971+
bool ForCall,
18972+
bool *IsImpCall) const {
1897218973
// Unpack the global address or external symbol.
1897318974
SDLoc dl(Op);
1897418975
const GlobalValue *GV = nullptr;
@@ -19018,6 +19019,16 @@ SDValue X86TargetLowering::LowerGlobalOrExternal(SDValue Op, SelectionDAG &DAG,
1901819019
if (ForCall && !NeedsLoad && !HasPICReg && Offset == 0)
1901919020
return Result;
1902019021

19022+
// If Import Call Optimization is enabled and this is an imported function
19023+
// then make a note of it and return the global address without wrapping.
19024+
if (IsImpCall && (OpFlags == X86II::MO_DLLIMPORT) &&
19025+
Mod.getModuleFlag("import-call-optimization")) {
19026+
assert(ForCall && "Should only enable import call optimization if we are "
19027+
"lowering a call");
19028+
*IsImpCall = true;
19029+
return Result;
19030+
}
19031+
1902119032
Result = DAG.getNode(getGlobalWrapperKind(GV, OpFlags), dl, PtrVT, Result);
1902219033

1902319034
// With PIC, the address is actually $g + Offset.
@@ -19043,7 +19054,7 @@ SDValue X86TargetLowering::LowerGlobalOrExternal(SDValue Op, SelectionDAG &DAG,
1904319054

1904419055
SDValue
1904519056
X86TargetLowering::LowerGlobalAddress(SDValue Op, SelectionDAG &DAG) const {
19046-
return LowerGlobalOrExternal(Op, DAG, /*ForCall=*/false);
19057+
return LowerGlobalOrExternal(Op, DAG, /*ForCall=*/false, nullptr);
1904719058
}
1904819059

1904919060
static SDValue GetTLSADDR(SelectionDAG &DAG, GlobalAddressSDNode *GA,
@@ -34582,6 +34593,7 @@ const char *X86TargetLowering::getTargetNodeName(unsigned Opcode) const {
3458234593
NODE_NAME_CASE(FST)
3458334594
NODE_NAME_CASE(CALL)
3458434595
NODE_NAME_CASE(CALL_RVMARKER)
34596+
NODE_NAME_CASE(IMP_CALL)
3458534597
NODE_NAME_CASE(BT)
3458634598
NODE_NAME_CASE(CMP)
3458734599
NODE_NAME_CASE(FCMP)
@@ -60992,6 +61004,7 @@ X86TargetLowering::EmitKCFICheck(MachineBasicBlock &MBB,
6099261004
Register TargetReg;
6099361005
switch (MBBI->getOpcode()) {
6099461006
case X86::CALL64r:
61007+
case X86::CALL64r_ImpCall:
6099561008
case X86::CALL64r_NT:
6099661009
case X86::TAILJMPr64:
6099761010
case X86::TAILJMPr64_REX:

llvm/lib/Target/X86/X86ISelLowering.h

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,10 @@ namespace llvm {
8181
// marker instruction.
8282
CALL_RVMARKER,
8383

84+
// Pseudo for a call to an imported function to ensure the correct machine
85+
// instruction is emitted for Import Call Optimization.
86+
IMP_CALL,
87+
8488
/// X86 compare and logical compare instructions.
8589
CMP,
8690
FCMP,
@@ -1733,8 +1737,8 @@ namespace llvm {
17331737

17341738
/// Creates target global address or external symbol nodes for calls or
17351739
/// other uses.
1736-
SDValue LowerGlobalOrExternal(SDValue Op, SelectionDAG &DAG,
1737-
bool ForCall) const;
1740+
SDValue LowerGlobalOrExternal(SDValue Op, SelectionDAG &DAG, bool ForCall,
1741+
bool *IsImpCall) const;
17381742

17391743
SDValue LowerSINT_TO_FP(SDValue Op, SelectionDAG &DAG) const;
17401744
SDValue LowerUINT_TO_FP(SDValue Op, SelectionDAG &DAG) const;

llvm/lib/Target/X86/X86ISelLoweringCall.cpp

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2031,6 +2031,10 @@ X86TargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI,
20312031
if (CallConv == CallingConv::X86_INTR)
20322032
report_fatal_error("X86 interrupts may not be called directly");
20332033

2034+
if (IsIndirectCall && !IsWin64 &&
2035+
M->getModuleFlag("import-call-optimization"))
2036+
errorUnsupported(DAG, dl, "Indirect calls must have a normal calling convention if Import Call Optimization is enabled");
2037+
20342038
// Analyze operands of the call, assigning locations to each operand.
20352039
SmallVector<CCValAssign, 16> ArgLocs;
20362040
CCState CCInfo(CallConv, isVarArg, MF, ArgLocs, *DAG.getContext());
@@ -2402,6 +2406,7 @@ X86TargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI,
24022406
InGlue = Chain.getValue(1);
24032407
}
24042408

2409+
bool IsImpCall = false;
24052410
if (DAG.getTarget().getCodeModel() == CodeModel::Large) {
24062411
assert(Is64Bit && "Large code model is only legal in 64-bit mode.");
24072412
// In the 64-bit large code model, we have to make all calls
@@ -2414,7 +2419,7 @@ X86TargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI,
24142419
// ForCall to true here has the effect of removing WrapperRIP when possible
24152420
// to allow direct calls to be selected without first materializing the
24162421
// address into a register.
2417-
Callee = LowerGlobalOrExternal(Callee, DAG, /*ForCall=*/true);
2422+
Callee = LowerGlobalOrExternal(Callee, DAG, /*ForCall=*/true, &IsImpCall);
24182423
} else if (Subtarget.isTarget64BitILP32() &&
24192424
Callee.getValueType() == MVT::i32) {
24202425
// Zero-extend the 32-bit Callee address into a 64-bit according to x32 ABI
@@ -2536,7 +2541,9 @@ X86TargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI,
25362541

25372542
// Returns a chain & a glue for retval copy to use.
25382543
SDVTList NodeTys = DAG.getVTList(MVT::Other, MVT::Glue);
2539-
if (HasNoCfCheck && IsCFProtectionSupported && IsIndirectCall) {
2544+
if (IsImpCall) {
2545+
Chain = DAG.getNode(X86ISD::IMP_CALL, dl, NodeTys, Ops);
2546+
} else if (HasNoCfCheck && IsCFProtectionSupported && IsIndirectCall) {
25402547
Chain = DAG.getNode(X86ISD::NT_CALL, dl, NodeTys, Ops);
25412548
} else if (CLI.CB && objcarc::hasAttachedCallOpBundle(CLI.CB)) {
25422549
// Calls with a "clang.arc.attachedcall" bundle are special. They should be

llvm/lib/Target/X86/X86InstrCompiler.td

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1309,6 +1309,8 @@ def : Pat<(X86call_rvmarker (i64 tglobaladdr:$rvfunc), (i64 texternalsym:$dst)),
13091309
def : Pat<(X86call_rvmarker (i64 tglobaladdr:$rvfunc), (i64 tglobaladdr:$dst)),
13101310
(CALL64pcrel32_RVMARKER tglobaladdr:$rvfunc, tglobaladdr:$dst)>;
13111311

1312+
def : Pat<(X86imp_call (i64 tglobaladdr:$dst)),
1313+
(CALL64pcrel32 tglobaladdr:$dst)>;
13121314

13131315
// Tailcall stuff. The TCRETURN instructions execute after the epilog, so they
13141316
// can never use callee-saved registers. That is the purpose of the GR64_TC
@@ -1340,7 +1342,11 @@ def : Pat<(X86tcret (i32 texternalsym:$dst), timm:$off),
13401342

13411343
def : Pat<(X86tcret ptr_rc_tailcall:$dst, timm:$off),
13421344
(TCRETURNri64 ptr_rc_tailcall:$dst, timm:$off)>,
1343-
Requires<[In64BitMode, NotUseIndirectThunkCalls]>;
1345+
Requires<[In64BitMode, NotUseIndirectThunkCalls, ImportCallOptimizationDisabled]>;
1346+
1347+
def : Pat<(X86tcret ptr_rc_tailcall:$dst, timm:$off),
1348+
(TCRETURNri64_ImpCall ptr_rc_tailcall:$dst, timm:$off)>,
1349+
Requires<[In64BitMode, NotUseIndirectThunkCalls, ImportCallOptimizationEnabled]>;
13441350

13451351
// Don't fold loads into X86tcret requiring more than 6 regs.
13461352
// There wouldn't be enough scratch registers for base+index.

llvm/lib/Target/X86/X86InstrControl.td

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -324,7 +324,7 @@ let isCall = 1, Uses = [RSP, SSP], SchedRW = [WriteJump] in {
324324
Requires<[In64BitMode]>;
325325
def CALL64r : I<0xFF, MRM2r, (outs), (ins GR64:$dst),
326326
"call{q}\t{*}$dst", [(X86call GR64:$dst)]>,
327-
Requires<[In64BitMode,NotUseIndirectThunkCalls]>;
327+
Requires<[In64BitMode,NotUseIndirectThunkCalls,ImportCallOptimizationDisabled]>;
328328
def CALL64m : I<0xFF, MRM2m, (outs), (ins i64mem:$dst),
329329
"call{q}\t{*}$dst", [(X86call (loadi64 addr:$dst))]>,
330330
Requires<[In64BitMode,FavorMemIndirectCall,
@@ -354,6 +354,10 @@ let isCall = 1, isTerminator = 1, isReturn = 1, isBarrier = 1,
354354
def TCRETURNri64 : PseudoI<(outs),
355355
(ins ptr_rc_tailcall:$dst, i32imm:$offset),
356356
[]>, Sched<[WriteJump]>;
357+
def TCRETURNri64_ImpCall : PseudoI<(outs),
358+
(ins GR64_A:$dst, i32imm:$offset),
359+
[]>, Sched<[WriteJump]>;
360+
357361
let mayLoad = 1 in
358362
def TCRETURNmi64 : PseudoI<(outs),
359363
(ins i64mem_TC:$dst, i32imm:$offset),
@@ -415,6 +419,10 @@ let isPseudo = 1, isCall = 1, isCodeGenOnly = 1,
415419
def CALL64pcrel32_RVMARKER :
416420
PseudoI<(outs), (ins i64imm:$rvfunc, i64i32imm_brtarget:$dst), []>,
417421
Requires<[In64BitMode]>;
422+
423+
def CALL64r_ImpCall :
424+
PseudoI<(outs), (ins GR64_A:$dst), [(X86call GR64_A:$dst)]>,
425+
Requires<[In64BitMode,NotUseIndirectThunkCalls,ImportCallOptimizationEnabled]>;
418426
}
419427

420428
// Conditional tail calls are similar to the above, but they are branches

llvm/lib/Target/X86/X86InstrFragments.td

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -210,6 +210,9 @@ def X86call_rvmarker : SDNode<"X86ISD::CALL_RVMARKER", SDT_X86Call,
210210
[SDNPHasChain, SDNPOutGlue, SDNPOptInGlue,
211211
SDNPVariadic]>;
212212

213+
def X86imp_call : SDNode<"X86ISD::IMP_CALL", SDT_X86Call,
214+
[SDNPHasChain, SDNPOutGlue, SDNPOptInGlue,
215+
SDNPVariadic]>;
213216

214217
def X86NoTrackCall : SDNode<"X86ISD::NT_CALL", SDT_X86Call,
215218
[SDNPHasChain, SDNPOutGlue, SDNPOptInGlue,

0 commit comments

Comments
 (0)