diff options
Diffstat (limited to 'llvm')
-rw-r--r-- | llvm/docs/LangRef.rst | 3 | ||||
-rw-r--r-- | llvm/lib/IR/Verifier.cpp | 26 | ||||
-rw-r--r-- | llvm/lib/Transforms/Utils/InlineFunction.cpp | 8 | ||||
-rw-r--r-- | llvm/test/CodeGen/X86/deopt-intrinsic-cconv.ll | 34 | ||||
-rw-r--r-- | llvm/test/CodeGen/X86/deopt-intrinsic.ll | 25 | ||||
-rw-r--r-- | llvm/test/Transforms/Inline/deoptimize-intrinsic-cconv.ll | 19 | ||||
-rw-r--r-- | llvm/test/Transforms/Inline/deoptimize-intrinsic.ll | 16 | ||||
-rw-r--r-- | llvm/test/Transforms/RewriteStatepointsForGC/deopt-intrinsic-cconv.ll | 16 | ||||
-rw-r--r-- | llvm/test/Transforms/RewriteStatepointsForGC/deopt-intrinsic.ll | 11 | ||||
-rw-r--r-- | llvm/test/Verifier/deoptimize-intrinsic.ll | 3 |
10 files changed, 108 insertions, 53 deletions
diff --git a/llvm/docs/LangRef.rst b/llvm/docs/LangRef.rst index 39b119cfc8d..2fa6293744f 100644 --- a/llvm/docs/LangRef.rst +++ b/llvm/docs/LangRef.rst @@ -12339,6 +12339,9 @@ The inliner composes the ``"deopt"`` continuations of the caller into the ``"deopt"`` continuations present in the inlinee, and also updates calls to this intrinsic to return directly from the frame of the function it inlined into. +All declarations of ``@llvm.experimental.deoptimize`` must share the +same calling convention. + .. _deoptimize_lowering: Lowering: diff --git a/llvm/lib/IR/Verifier.cpp b/llvm/lib/IR/Verifier.cpp index 5621962497a..1b36eb9bd68 100644 --- a/llvm/lib/IR/Verifier.cpp +++ b/llvm/lib/IR/Verifier.cpp @@ -243,6 +243,9 @@ class Verifier : public InstVisitor<Verifier>, VerifierSupport { /// Cache of constants visited in search of ConstantExprs. SmallPtrSet<const Constant *, 32> ConstantExprVisited; + /// Cache of declarations of the llvm.experimental.deoptimize.<ty> intrinsic. + SmallVector<const Function *, 4> DeoptimizeDeclarations; + // Verify that this GlobalValue is only used in this module. // This map is used to avoid visiting uses twice. We can arrive at a user // twice, if they have multiple operands. In particular for very large @@ -322,8 +325,11 @@ public: visitGlobalValue(F); // Check to make sure function prototypes are okay. - if (F.isDeclaration()) + if (F.isDeclaration()) { visitFunction(F); + if (F.getIntrinsicID() == Intrinsic::experimental_deoptimize) + DeoptimizeDeclarations.push_back(&F); + } } // Now that we've visited every function, verify that we never asked to @@ -346,6 +352,8 @@ public: verifyCompileUnits(); + verifyDeoptimizeCallingConvs(); + return !Broken; } @@ -470,6 +478,10 @@ private: /// Module-level debug info verification... void verifyCompileUnits(); + + /// Module-level verification that all @llvm.experimental.deoptimize + /// declarations share the same calling convention. + void verifyDeoptimizeCallingConvs(); }; } // End anonymous namespace @@ -4396,6 +4408,18 @@ void Verifier::verifyCompileUnits() { CUVisited.clear(); } +void Verifier::verifyDeoptimizeCallingConvs() { + if (DeoptimizeDeclarations.empty()) + return; + + const Function *First = DeoptimizeDeclarations[0]; + for (auto *F : makeArrayRef(DeoptimizeDeclarations).slice(1)) + Assert(First->getCallingConv() == F->getCallingConv(), + "All llvm.experimental.deoptimize declarations must have the same " + "calling convention", + First, F); +} + //===----------------------------------------------------------------------===// // Implement the public interfaces to this file... //===----------------------------------------------------------------------===// diff --git a/llvm/lib/Transforms/Utils/InlineFunction.cpp b/llvm/lib/Transforms/Utils/InlineFunction.cpp index 5b0640c7237..c8d76f4d9e8 100644 --- a/llvm/lib/Transforms/Utils/InlineFunction.cpp +++ b/llvm/lib/Transforms/Utils/InlineFunction.cpp @@ -1874,7 +1874,13 @@ bool llvm::InlineFunction(CallSite CS, InlineFunctionInfo &IFI, continue; } - auto CallingConv = DeoptCall->getCallingConv(); + // The calling convention on the deoptimize call itself may be bogus, + // since the code we're inlining may have undefined behavior (and may + // never actually execute at runtime); but all + // @llvm.experimental.deoptimize declarations have to have the same + // calling convention in a well-formed module. + auto CallingConv = DeoptCall->getCalledFunction()->getCallingConv(); + NewDeoptIntrinsic->setCallingConv(CallingConv); auto *CurBB = RI->getParent(); RI->eraseFromParent(); diff --git a/llvm/test/CodeGen/X86/deopt-intrinsic-cconv.ll b/llvm/test/CodeGen/X86/deopt-intrinsic-cconv.ll new file mode 100644 index 00000000000..8e240f8901d --- /dev/null +++ b/llvm/test/CodeGen/X86/deopt-intrinsic-cconv.ll @@ -0,0 +1,34 @@ +; 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 webkit_jscc i64 @llvm.experimental.deoptimize.i64(...) + +define i64 @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: movl $1140457472, (%rsp) ## imm = 0x43FA0000 +; CHECK-NEXT: movl $42, %eax +; CHECK-NEXT: callq ___llvm_deoptimize +; CHECK-NEXT: {{Ltmp[0-9]+}}: + +entry: + %v = call webkit_jscc i64(...) @llvm.experimental.deoptimize.i64(i32 42, float 500.0) [ "deopt"(i32 3) ] + ret i64 %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 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 diff --git a/llvm/test/CodeGen/X86/deopt-intrinsic.ll b/llvm/test/CodeGen/X86/deopt-intrinsic.ll index 008075bfeae..ceed2d24882 100644 --- a/llvm/test/CodeGen/X86/deopt-intrinsic.ll +++ b/llvm/test/CodeGen/X86/deopt-intrinsic.ll @@ -7,7 +7,6 @@ target triple = "x86_64-apple-macosx10.11.0" declare i32 @llvm.experimental.deoptimize.i32(...) declare i8 @llvm.experimental.deoptimize.i8(...) -declare webkit_jscc i64 @llvm.experimental.deoptimize.i64(...) define i32 @caller_0() { ; CHECK-LABEL: _caller_0: @@ -40,23 +39,6 @@ entry: ret i8 %v } -define i64 @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]+}}: - -entry: - %v = call webkit_jscc i64(...) @llvm.experimental.deoptimize.i64(i32 42, float 500.0) [ "deopt"(i32 3) ] - ret i64 %v -} - ; STACKMAPS: Stack Maps: callsites: ; STACKMAPS-NEXT: Stack Maps: callsite 2882400015 ; STACKMAPS-NEXT: Stack Maps: has 4 locations @@ -72,10 +54,3 @@ entry: ; 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 diff --git a/llvm/test/Transforms/Inline/deoptimize-intrinsic-cconv.ll b/llvm/test/Transforms/Inline/deoptimize-intrinsic-cconv.ll new file mode 100644 index 00000000000..4e2c3fe4786 --- /dev/null +++ b/llvm/test/Transforms/Inline/deoptimize-intrinsic-cconv.ll @@ -0,0 +1,19 @@ +; RUN: opt -S -always-inline < %s | FileCheck %s + +declare cc42 i32 @llvm.experimental.deoptimize.i32(...) + +define i32 @callee_with_coldcc() alwaysinline { + %v0 = call cc42 i32(...) @llvm.experimental.deoptimize.i32(i32 1) [ "deopt"() ] + ret i32 %v0 +} + +define void @caller_with_coldcc() { +; CHECK-LABEL: @caller_with_coldcc( +; CHECK-NEXT: call cc42 void (...) @llvm.experimental.deoptimize.isVoid(i32 1) [ "deopt"() ] +; CHECK-NEXT: ret void + + %val = call i32 @callee_with_coldcc() + ret void +} + +; CHECK: declare cc42 void @llvm.experimental.deoptimize.isVoid(...) diff --git a/llvm/test/Transforms/Inline/deoptimize-intrinsic.ll b/llvm/test/Transforms/Inline/deoptimize-intrinsic.ll index 98fbc68488e..848a9db0542 100644 --- a/llvm/test/Transforms/Inline/deoptimize-intrinsic.ll +++ b/llvm/test/Transforms/Inline/deoptimize-intrinsic.ll @@ -1,7 +1,7 @@ ; RUN: opt -S -always-inline < %s | FileCheck %s declare i8 @llvm.experimental.deoptimize.i8(...) -declare cc42 i32 @llvm.experimental.deoptimize.i32(...) +declare i32 @llvm.experimental.deoptimize.i32(...) define i8 @callee(i1* %c) alwaysinline { %c0 = load volatile i1, i1* %c @@ -121,17 +121,3 @@ define void @caller_with_stacksaverestore(i32 %n) { call i8 @callee_with_dynamic_alloca(i32 %n) ret void } - -define i32 @callee_with_coldcc() alwaysinline { - %v0 = call cc42 i32(...) @llvm.experimental.deoptimize.i32(i32 1) [ "deopt"() ] - ret i32 %v0 -} - -define void @caller_with_coldcc() { -; CHECK-LABEL: @caller_with_coldcc( -; CHECK-NEXT: call cc42 void (...) @llvm.experimental.deoptimize.isVoid(i32 1) [ "deopt"() ] -; CHECK-NEXT: ret void - - %val = call i32 @callee_with_coldcc() - ret void -} diff --git a/llvm/test/Transforms/RewriteStatepointsForGC/deopt-intrinsic-cconv.ll b/llvm/test/Transforms/RewriteStatepointsForGC/deopt-intrinsic-cconv.ll new file mode 100644 index 00000000000..b74c1963ddf --- /dev/null +++ b/llvm/test/Transforms/RewriteStatepointsForGC/deopt-intrinsic-cconv.ll @@ -0,0 +1,16 @@ +; RUN: opt -rewrite-statepoints-for-gc -S < %s | FileCheck %s + +target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128" +target triple = "x86_64-apple-macosx10.11.0" + +declare cc42 double @llvm.experimental.deoptimize.f64(...) + +define double @caller_3() gc "statepoint-example" { +; CHECK-LABELL @caller_3( +; CHECK: call cc42 token (i64, i32, void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint +; CHECK: unreachable + +entry: + %val = call cc42 double(...) @llvm.experimental.deoptimize.f64() [ "deopt"() ] + ret double %val +} diff --git a/llvm/test/Transforms/RewriteStatepointsForGC/deopt-intrinsic.ll b/llvm/test/Transforms/RewriteStatepointsForGC/deopt-intrinsic.ll index 559dc9d6501..ef0e2bd61af 100644 --- a/llvm/test/Transforms/RewriteStatepointsForGC/deopt-intrinsic.ll +++ b/llvm/test/Transforms/RewriteStatepointsForGC/deopt-intrinsic.ll @@ -5,7 +5,6 @@ target triple = "x86_64-apple-macosx10.11.0" declare i32 @llvm.experimental.deoptimize.i32(...) declare void @llvm.experimental.deoptimize.isVoid(...) -declare cc42 double @llvm.experimental.deoptimize.f64(...) define i32 @caller_0(i32 addrspace(1)* %ptr) gc "statepoint-example" { ; CHECK-LABEL: @caller_0( @@ -34,13 +33,3 @@ entry: call void(...) @llvm.experimental.deoptimize.isVoid() [ "deopt"(i32 0, i32 addrspace(1)* %ptr) ] ret void } - -define double @caller_3() gc "statepoint-example" { -; CHECK-LABELL @caller_3( -; CHECK: call cc42 token (i64, i32, void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint -; CHECK: unreachable - -entry: - %val = call cc42 double(...) @llvm.experimental.deoptimize.f64() [ "deopt"() ] - ret double %val -} diff --git a/llvm/test/Verifier/deoptimize-intrinsic.ll b/llvm/test/Verifier/deoptimize-intrinsic.ll index 81e4d3a8981..62c61d42b35 100644 --- a/llvm/test/Verifier/deoptimize-intrinsic.ll +++ b/llvm/test/Verifier/deoptimize-intrinsic.ll @@ -2,6 +2,7 @@ declare i8 @llvm.experimental.deoptimize.i8(...) declare void @llvm.experimental.deoptimize.isVoid(...) +declare cc40 void @llvm.experimental.deoptimize.double(...) declare void @unknown() @@ -40,3 +41,5 @@ entry: ; CHECK: calls to experimental_deoptimize must be followed by a return of the value computed by experimental_deoptimize ret i8 0 } + +; CHECK: All llvm.experimental.deoptimize declarations must have the same calling convention |