summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--llvm/docs/LangRef.rst8
-rw-r--r--llvm/include/llvm/CodeGen/RuntimeLibcalls.h3
-rw-r--r--llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp4
-rw-r--r--llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.h2
-rw-r--r--llvm/lib/CodeGen/SelectionDAG/StatepointLowering.cpp34
-rw-r--r--llvm/lib/CodeGen/TargetLoweringBase.cpp2
-rw-r--r--llvm/test/CodeGen/X86/deopt-intrinsic.ll86
7 files changed, 137 insertions, 2 deletions
diff --git a/llvm/docs/LangRef.rst b/llvm/docs/LangRef.rst
index 4316848ca69..01c255d2459 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 8beb55d71da..bdf8d9ce086 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 6f653613385..5126bdea724 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 eebae0d35a5..4b222a9c435 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 f50d7d0453b..bf9f1fa26fb 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<const Use>(DeoptBundle.Inputs.begin(), DeoptBundle.Inputs.end());
+ SI.StatepointFlags = static_cast<uint64_t>(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 d714ad19260..747950f948e 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 00000000000..044e1c062c5
--- /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
OpenPOWER on IntegriCloud