Index: docs/LangRef.rst =================================================================== --- docs/LangRef.rst +++ docs/LangRef.rst @@ -12169,8 +12169,11 @@ Lowering: """"""""" -Lowering for ``@llvm.experimental.deoptimize`` is not yet implemented, -and is a work in progress. +Calls to ``@llvm.experimental.deoptimize`` are lowered to calls to the +symbol ``__llvm_deoptimize`` (it is the frontend's responsibility to +ensure that this symbol is available). The call arguments to the +``@llvm.experimental.deoptimize`` call are passed via a non-varargs +calling convention to ``__llvm_deoptimize``. Stack Map Intrinsics -------------------- Index: include/llvm/CodeGen/RuntimeLibcalls.h =================================================================== --- include/llvm/CodeGen/RuntimeLibcalls.h +++ include/llvm/CodeGen/RuntimeLibcalls.h @@ -401,6 +401,9 @@ // Stack Protector Fail. STACKPROTECTOR_CHECK_FAIL, + // Deoptimization. + DEOPTIMIZE, + UNKNOWN_LIBCALL }; Index: lib/CodeGen/SelectionDAG/SelectionDAGBuilder.h =================================================================== --- lib/CodeGen/SelectionDAG/SelectionDAGBuilder.h +++ lib/CodeGen/SelectionDAG/SelectionDAGBuilder.h @@ -781,6 +781,8 @@ void LowerCallSiteWithDeoptBundle(ImmutableCallSite CS, SDValue Callee, const BasicBlock *EHPadBB); + void LowerDeoptimizeCall(ImmutableCallSite CS); + private: // Terminator instructions. void visitRet(const ReturnInst &I); Index: lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp =================================================================== --- lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp +++ lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp @@ -5460,6 +5460,10 @@ setValue(&I, N); return nullptr; } + + case Intrinsic::experimental_deoptimize: + LowerDeoptimizeCall(&I); + return nullptr; } } Index: lib/CodeGen/SelectionDAG/StatepointLowering.cpp =================================================================== --- lib/CodeGen/SelectionDAG/StatepointLowering.cpp +++ lib/CodeGen/SelectionDAG/StatepointLowering.cpp @@ -920,3 +920,36 @@ assert(SpillLoad.getNode()); setValue(&Relocate, SpillLoad); } + +void SelectionDAGBuilder::LowerDeoptimizeCall(ImmutableCallSite CS) { + const auto &TLI = DAG.getTargetLoweringInfo(); + + SDValue Callee = DAG.getExternalSymbol(TLI.getLibcallName(RTLIB::DEOPTIMIZE), + TLI.getPointerTy(DAG.getDataLayout())); + StatepointLoweringInfo SI(DAG); + unsigned ArgBeginIndex = CS.arg_begin() - CS.getInstruction()->op_begin(); + populateCallLoweringInfo(SI.CLI, CS, ArgBeginIndex, CS.getNumArgOperands(), + Callee, CS.getType(), false); + + // We don't lower calls to __llvm_deoptimize as varargs, but as a + // regular call. + assert(!SI.CLI.IsVarArg && "Expected from populateCallLoweringInfo!"); + + auto DeoptBundle = *CS.getOperandBundle(LLVMContext::OB_deopt); + + unsigned DefaultID = StatepointDirectives::DeoptBundleStatepointID; + + auto SD = parseStatepointDirectivesFromAttrs(CS.getAttributes()); + SI.ID = SD.StatepointID.getValueOr(DefaultID); + SI.NumPatchBytes = SD.NumPatchBytes.getValueOr(0); + + SI.DeoptState = + ArrayRef(DeoptBundle.Inputs.begin(), DeoptBundle.Inputs.end()); + SI.StatepointFlags = static_cast(StatepointFlags::None); + + if (SDValue ReturnVal = LowerAsSTATEPOINT(SI)) { + const Instruction *Inst = CS.getInstruction(); + ReturnVal = lowerRangeToAssertZExt(DAG, *Inst, ReturnVal); + setValue(Inst, ReturnVal); + } +} Index: lib/CodeGen/TargetLoweringBase.cpp =================================================================== --- lib/CodeGen/TargetLoweringBase.cpp +++ lib/CodeGen/TargetLoweringBase.cpp @@ -435,6 +435,8 @@ Names[RTLIB::FPEXT_F16_F32] = "__extendhfsf2"; Names[RTLIB::FPROUND_F32_F16] = "__truncsfhf2"; } + + Names[RTLIB::DEOPTIMIZE] = "__llvm_deoptimize"; } /// InitLibcallCallingConvs - Set default libcall CallingConvs. Index: test/CodeGen/X86/deopt-intrinsic.ll =================================================================== --- /dev/null +++ test/CodeGen/X86/deopt-intrinsic.ll @@ -0,0 +1,44 @@ +; RUN: llc < %s | FileCheck %s +; RUN: llc -debug-only=stackmaps < %s 2>&1 | FileCheck --check-prefix=STACKMAPS %s + +target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128" +target triple = "x86_64-apple-macosx10.11.0" + +declare i32 @llvm.experimental.deoptimize.i32(...) +declare i8 @llvm.experimental.deoptimize.i8(...) + +define i32 @caller_0() { +; CHECK: _caller_0: +; CHECK-NOT: mov +; CHECK: callq ___llvm_deoptimize +entry: + %v = call i32(...) @llvm.experimental.deoptimize.i32() [ "deopt"(i32 0) ] + ret i32 %v +} + +define i8 @caller_1() { +; CHECK: _caller_1 +; CHECK: movss {{[a-zA-Z0-9_]+}}(%rip), %xmm0 ## xmm0 = mem[0],zero,zero,zero +; CHECK-NEXT: movl $42, %edi +; CHECK-NEXT: callq ___llvm_deoptimize + +entry: + %v = call i8(...) @llvm.experimental.deoptimize.i8(i32 42, float 500.0) [ "deopt"(i32 1) ] + ret i8 %v +} + +; STACKMAPS: Stack Maps: callsites: +; STACKMAPS-NEXT: Stack Maps: callsite 2882400015 +; STACKMAPS-NEXT: Stack Maps: has 4 locations +; STACKMAPS-NEXT: Stack Maps: Loc 0: Constant 0 [encoding: .byte 4, .byte 8, .short 0, .int 0] +; STACKMAPS-NEXT: Stack Maps: Loc 1: Constant 0 [encoding: .byte 4, .byte 8, .short 0, .int 0] +; STACKMAPS-NEXT: Stack Maps: Loc 2: Constant 1 [encoding: .byte 4, .byte 8, .short 0, .int 1] +; STACKMAPS-NEXT: Stack Maps: Loc 3: Constant 0 [encoding: .byte 4, .byte 8, .short 0, .int 0] +; STACKMAPS-NEXT: Stack Maps: has 0 live-out registers +; STACKMAPS-NEXT: Stack Maps: callsite 2882400015 +; STACKMAPS-NEXT: Stack Maps: has 4 locations +; STACKMAPS-NEXT: Stack Maps: Loc 0: Constant 0 [encoding: .byte 4, .byte 8, .short 0, .int 0] +; STACKMAPS-NEXT: Stack Maps: Loc 1: Constant 0 [encoding: .byte 4, .byte 8, .short 0, .int 0] +; STACKMAPS-NEXT: Stack Maps: Loc 2: Constant 1 [encoding: .byte 4, .byte 8, .short 0, .int 1] +; STACKMAPS-NEXT: Stack Maps: Loc 3: Constant 1 [encoding: .byte 4, .byte 8, .short 0, .int 1] +; STACKMAPS-NEXT: Stack Maps: has 0 live-out registers