From df9ae70f49a506cddf6bbfdb472b0913567d8010 Mon Sep 17 00:00:00 2001 From: Sanjoy Das Date: Thu, 24 Mar 2016 20:23:29 +0000 Subject: [PATCH] Add lowering support for llvm.experimental.deoptimize Summary: Only adds support for "naked" calls to llvm.experimental.deoptimize. Support for round-tripping through RewriteStatepointsForGC will come as a separate patch (should be simpler than this one). Reviewers: reames Subscribers: sanjoy, mcrosier, llvm-commits Differential Revision: http://reviews.llvm.org/D18429 llvm-svn: 264329 --- llvm/docs/LangRef.rst | 8 +- llvm/include/llvm/CodeGen/RuntimeLibcalls.h | 3 + .../CodeGen/SelectionDAG/SelectionDAGBuilder.cpp | 4 + .../lib/CodeGen/SelectionDAG/SelectionDAGBuilder.h | 2 + .../CodeGen/SelectionDAG/StatepointLowering.cpp | 34 +++++++++ llvm/lib/CodeGen/TargetLoweringBase.cpp | 2 + llvm/test/CodeGen/X86/deopt-intrinsic.ll | 86 ++++++++++++++++++++++ 7 files changed, 137 insertions(+), 2 deletions(-) create mode 100644 llvm/test/CodeGen/X86/deopt-intrinsic.ll diff --git a/llvm/docs/LangRef.rst b/llvm/docs/LangRef.rst index 4316848..01c255d 100644 --- a/llvm/docs/LangRef.rst +++ b/llvm/docs/LangRef.rst @@ -12169,8 +12169,12 @@ intrinsic to return directly from the frame of the function it inlined into. 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 defined). The call arguments to +``@llvm.experimental.deoptimize`` are lowered as if they were formal +arguments of the specified types, and not as varargs. + Stack Map Intrinsics -------------------- diff --git a/llvm/include/llvm/CodeGen/RuntimeLibcalls.h b/llvm/include/llvm/CodeGen/RuntimeLibcalls.h index 8beb55d..bdf8d9c 100644 --- a/llvm/include/llvm/CodeGen/RuntimeLibcalls.h +++ b/llvm/include/llvm/CodeGen/RuntimeLibcalls.h @@ -401,6 +401,9 @@ namespace RTLIB { // Stack Protector Fail. STACKPROTECTOR_CHECK_FAIL, + // Deoptimization. + DEOPTIMIZE, + UNKNOWN_LIBCALL }; diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp index 6f65361..5126bde 100644 --- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp @@ -5460,6 +5460,10 @@ SelectionDAGBuilder::visitIntrinsicCall(const CallInst &I, unsigned Intrinsic) { setValue(&I, N); return nullptr; } + + case Intrinsic::experimental_deoptimize: + LowerDeoptimizeCall(&I); + return nullptr; } } diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.h b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.h index eebae0d..4b222a9 100644 --- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.h +++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.h @@ -781,6 +781,8 @@ public: void LowerCallSiteWithDeoptBundle(ImmutableCallSite CS, SDValue Callee, const BasicBlock *EHPadBB); + void LowerDeoptimizeCall(const CallInst *CI); + private: // Terminator instructions. void visitRet(const ReturnInst &I); diff --git a/llvm/lib/CodeGen/SelectionDAG/StatepointLowering.cpp b/llvm/lib/CodeGen/SelectionDAG/StatepointLowering.cpp index f50d7d0..bf9f1fa 100644 --- a/llvm/lib/CodeGen/SelectionDAG/StatepointLowering.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/StatepointLowering.cpp @@ -923,3 +923,37 @@ void SelectionDAGBuilder::visitGCRelocate(const GCRelocateInst &Relocate) { assert(SpillLoad.getNode()); setValue(&Relocate, SpillLoad); } + +void SelectionDAGBuilder::LowerDeoptimizeCall(const CallInst *CI) { + const auto &TLI = DAG.getTargetLoweringInfo(); + + SDValue Callee = DAG.getExternalSymbol(TLI.getLibcallName(RTLIB::DEOPTIMIZE), + TLI.getPointerTy(DAG.getDataLayout())); + StatepointLoweringInfo SI(DAG); + unsigned ArgBeginIndex = CI->arg_begin() - CI->op_begin(); + populateCallLoweringInfo(SI.CLI, CI, ArgBeginIndex, CI->getNumArgOperands(), + Callee, CI->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 = *CI->getOperandBundle(LLVMContext::OB_deopt); + + unsigned DefaultID = StatepointDirectives::DeoptBundleStatepointID; + + auto SD = parseStatepointDirectivesFromAttrs(CI->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); + + // NB! The GC arguments are specifically left empty. + + if (SDValue ReturnVal = LowerAsSTATEPOINT(SI)) { + ReturnVal = lowerRangeToAssertZExt(DAG, *CI, ReturnVal); + setValue(CI, ReturnVal); + } +} diff --git a/llvm/lib/CodeGen/TargetLoweringBase.cpp b/llvm/lib/CodeGen/TargetLoweringBase.cpp index d714ad1..747950f 100644 --- a/llvm/lib/CodeGen/TargetLoweringBase.cpp +++ b/llvm/lib/CodeGen/TargetLoweringBase.cpp @@ -435,6 +435,8 @@ static void InitLibcallNames(const char **Names, const Triple &TT) { Names[RTLIB::FPEXT_F16_F32] = "__extendhfsf2"; Names[RTLIB::FPROUND_F32_F16] = "__truncsfhf2"; } + + Names[RTLIB::DEOPTIMIZE] = "__llvm_deoptimize"; } /// InitLibcallCallingConvs - Set default libcall CallingConvs. diff --git a/llvm/test/CodeGen/X86/deopt-intrinsic.ll b/llvm/test/CodeGen/X86/deopt-intrinsic.ll new file mode 100644 index 0000000..044e1c0 --- /dev/null +++ b/llvm/test/CodeGen/X86/deopt-intrinsic.ll @@ -0,0 +1,86 @@ +; RUN: llc < %s | FileCheck %s +; RUN: llc -debug-only=stackmaps < %s 2>&1 | FileCheck --check-prefix=STACKMAPS %s +; REQUIRES: asserts + +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-LABEL: _caller_0: +; CHECK-NEXT: {{.+cfi.+}} +; CHECK-NEXT: ##{{.+}} +; CHECK-NEXT: pushq %rax +; CHECK-NEXT: {{Ltmp[0-9]+}}: +; CHECK-NEXT: {{.+cfi.+}} +; CHECK-NEXT: callq ___llvm_deoptimize +; CHECK-NEXT: {{Ltmp[0-9]+}}: +; CHECK-NEXT: popq %rcx +; CHECK-NEXT: retq +entry: + %v = call i32(...) @llvm.experimental.deoptimize.i32() [ "deopt"(i32 0) ] + ret i32 %v +} + +define i8 @caller_1() { +; CHECK-LABEL: _caller_1: +; CHECK-NEXT: {{.+cfi.+}} +; CHECK-NEXT: ##{{.+}} +; CHECK-NEXT: pushq %rax +; CHECK-NEXT: {{Ltmp[0-9]+}}: +; CHECK-NEXT: {{.+cfi.+}} +; CHECK-NEXT: movss {{[a-zA-Z0-9_]+}}(%rip), %xmm0 ## xmm0 = mem[0],zero,zero,zero +; CHECK-NEXT: movl $42, %edi +; CHECK-NEXT: callq ___llvm_deoptimize +; CHECK-NEXT: {{Ltmp[0-9]+}}: +; CHECK-NEXT: popq %rcx +; CHECK-NEXT: retq + +entry: + %v = call i8(...) @llvm.experimental.deoptimize.i8(i32 42, float 500.0) [ "deopt"(i32 1) ] + ret i8 %v +} + +define i8 @caller_2() { +; CHECK-LABEL: _caller_2: +; CHECK-NEXT: {{.+cfi.+}} +; CHECK-NEXT: ##{{.+}} +; CHECK-NEXT: pushq %rax +; CHECK-NEXT: {{Ltmp[0-9]+}}: +; CHECK-NEXT: {{.+cfi.+}} +; CHECK-NEXT: movl $1140457472, (%rsp) ## imm = 0x43FA0000 +; CHECK-NEXT: movl $42, %eax +; CHECK-NEXT: callq ___llvm_deoptimize +; CHECK-NEXT: {{Ltmp[0-9]+}}: +; CHECK-NEXT: popq %rcx +; CHECK-NEXT: retq + +entry: + %v = call webkit_jscc i8(...) @llvm.experimental.deoptimize.i8(i32 42, float 500.0) [ "deopt"(i32 3) ] + 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 +; STACKMAPS-NEXT: Stack Maps: callsite 2882400015 +; STACKMAPS-NEXT: Stack Maps: has 4 locations +; STACKMAPS-NEXT: Stack Maps: Loc 0: Constant 12 [encoding: .byte 4, .byte 8, .short 0, .int 12] +; 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 3 [encoding: .byte 4, .byte 8, .short 0, .int 3] +; STACKMAPS-NEXT: Stack Maps: has 0 live-out registers -- 2.7.4