Skip to content

Commit

Permalink
Add lowering support for llvm.experimental.deoptimize
Browse files Browse the repository at this point in the history
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
  • Loading branch information
sanjoy committed Mar 24, 2016
1 parent c9d4caa commit df9ae70
Show file tree
Hide file tree
Showing 7 changed files with 137 additions and 2 deletions.
8 changes: 6 additions & 2 deletions llvm/docs/LangRef.rst
Expand Up @@ -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
--------------------
Expand Down
3 changes: 3 additions & 0 deletions llvm/include/llvm/CodeGen/RuntimeLibcalls.h
Expand Up @@ -401,6 +401,9 @@ namespace RTLIB {
// Stack Protector Fail.
STACKPROTECTOR_CHECK_FAIL,

// Deoptimization.
DEOPTIMIZE,

UNKNOWN_LIBCALL
};

Expand Down
4 changes: 4 additions & 0 deletions llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
Expand Up @@ -5460,6 +5460,10 @@ SelectionDAGBuilder::visitIntrinsicCall(const CallInst &I, unsigned Intrinsic) {
setValue(&I, N);
return nullptr;
}

case Intrinsic::experimental_deoptimize:
LowerDeoptimizeCall(&I);
return nullptr;
}
}

Expand Down
2 changes: 2 additions & 0 deletions llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.h
Expand Up @@ -781,6 +781,8 @@ class SelectionDAGBuilder {
void LowerCallSiteWithDeoptBundle(ImmutableCallSite CS, SDValue Callee,
const BasicBlock *EHPadBB);

void LowerDeoptimizeCall(const CallInst *CI);

private:
// Terminator instructions.
void visitRet(const ReturnInst &I);
Expand Down
34 changes: 34 additions & 0 deletions llvm/lib/CodeGen/SelectionDAG/StatepointLowering.cpp
Expand Up @@ -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);
}
}
2 changes: 2 additions & 0 deletions llvm/lib/CodeGen/TargetLoweringBase.cpp
Expand Up @@ -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.
Expand Down
86 changes: 86 additions & 0 deletions 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

0 comments on commit df9ae70

Please sign in to comment.