llvm.org GIT mirror llvm / d2e75bd
All llvm.deoptimize declarations must use the same calling convention This new verifier rule lets us unambigously pick a calling convention when creating a new declaration for `@llvm.experimental.deoptimize.<ty>`. It is also congruent with our lowering strategy -- since all calls to `@llvm.experimental.deoptimize` are lowered to calls to `__llvm_deoptimize`, it is reasonable to enforce a unique calling convention. Some of the tests that were breaking this verifier rule have had to be split up into different .ll files. The inliner was violating this rule as well, and has been fixed to avoid producing invalid IR. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@269261 91177308-0d34-0410-b5e6-96231b3b80d8 Sanjoy Das 3 years ago
10 changed file(s) with 108 addition(s) and 53 deletion(s). Raw diff Collapse all Expand all
1233812338 ``"deopt"`` continuations present in the inlinee, and also updates calls to this
1233912339 intrinsic to return directly from the frame of the function it inlined into.
1234012340
12341 All declarations of ``@llvm.experimental.deoptimize`` must share the
12342 same calling convention.
12343
1234112344 .. _deoptimize_lowering:
1234212345
1234312346 Lowering:
242242 /// Cache of constants visited in search of ConstantExprs.
243243 SmallPtrSet ConstantExprVisited;
244244
245 /// Cache of declarations of the llvm.experimental.deoptimize. intrinsic.
246 SmallVector DeoptimizeDeclarations;
247
245248 // Verify that this GlobalValue is only used in this module.
246249 // This map is used to avoid visiting uses twice. We can arrive at a user
247250 // twice, if they have multiple operands. In particular for very large
321324 visitGlobalValue(F);
322325
323326 // Check to make sure function prototypes are okay.
324 if (F.isDeclaration())
327 if (F.isDeclaration()) {
325328 visitFunction(F);
329 if (F.getIntrinsicID() == Intrinsic::experimental_deoptimize)
330 DeoptimizeDeclarations.push_back(&F);
331 }
326332 }
327333
328334 // Now that we've visited every function, verify that we never asked to
344350 visitModuleIdents(M);
345351
346352 verifyCompileUnits();
353
354 verifyDeoptimizeCallingConvs();
347355
348356 return !Broken;
349357 }
469477
470478 /// Module-level debug info verification...
471479 void verifyCompileUnits();
480
481 /// Module-level verification that all @llvm.experimental.deoptimize
482 /// declarations share the same calling convention.
483 void verifyDeoptimizeCallingConvs();
472484 };
473485 } // End anonymous namespace
474486
43954407 CUVisited.clear();
43964408 }
43974409
4410 void Verifier::verifyDeoptimizeCallingConvs() {
4411 if (DeoptimizeDeclarations.empty())
4412 return;
4413
4414 const Function *First = DeoptimizeDeclarations[0];
4415 for (auto *F : makeArrayRef(DeoptimizeDeclarations).slice(1))
4416 Assert(First->getCallingConv() == F->getCallingConv(),
4417 "All llvm.experimental.deoptimize declarations must have the same "
4418 "calling convention",
4419 First, F);
4420 }
4421
43984422 //===----------------------------------------------------------------------===//
43994423 // Implement the public interfaces to this file...
44004424 //===----------------------------------------------------------------------===//
18731873 continue;
18741874 }
18751875
1876 auto CallingConv = DeoptCall->getCallingConv();
1876 // The calling convention on the deoptimize call itself may be bogus,
1877 // since the code we're inlining may have undefined behavior (and may
1878 // never actually execute at runtime); but all
1879 // @llvm.experimental.deoptimize declarations have to have the same
1880 // calling convention in a well-formed module.
1881 auto CallingConv = DeoptCall->getCalledFunction()->getCallingConv();
1882 NewDeoptIntrinsic->setCallingConv(CallingConv);
18771883 auto *CurBB = RI->getParent();
18781884 RI->eraseFromParent();
18791885
0 ; RUN: llc < %s | FileCheck %s
1 ; RUN: llc -debug-only=stackmaps < %s 2>&1 | FileCheck --check-prefix=STACKMAPS %s
2 ; REQUIRES: asserts
3
4 target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128"
5 target triple = "x86_64-apple-macosx10.11.0"
6
7 declare webkit_jscc i64 @llvm.experimental.deoptimize.i64(...)
8
9 define i64 @caller_1() {
10 ; CHECK-LABEL: _caller_1:
11 ; CHECK-NEXT: {{.+cfi.+}}
12 ; CHECK-NEXT: ##{{.+}}
13 ; CHECK-NEXT: pushq %rax
14 ; CHECK-NEXT: {{Ltmp[0-9]+}}:
15 ; CHECK-NEXT: {{.+cfi.+}}
16 ; CHECK-NEXT: movl $1140457472, (%rsp) ## imm = 0x43FA0000
17 ; CHECK-NEXT: movl $42, %eax
18 ; CHECK-NEXT: callq ___llvm_deoptimize
19 ; CHECK-NEXT: {{Ltmp[0-9]+}}:
20
21 entry:
22 %v = call webkit_jscc i64(...) @llvm.experimental.deoptimize.i64(i32 42, float 500.0) [ "deopt"(i32 3) ]
23 ret i64 %v
24 }
25
26 ; STACKMAPS: Stack Maps: callsites:
27 ; STACKMAPS-NEXT: Stack Maps: callsite 2882400015
28 ; STACKMAPS-NEXT: Stack Maps: has 4 locations
29 ; STACKMAPS-NEXT: Stack Maps: Loc 0: Constant 12 [encoding: .byte 4, .byte 8, .short 0, .int 12]
30 ; STACKMAPS-NEXT: Stack Maps: Loc 1: Constant 0 [encoding: .byte 4, .byte 8, .short 0, .int 0]
31 ; STACKMAPS-NEXT: Stack Maps: Loc 2: Constant 1 [encoding: .byte 4, .byte 8, .short 0, .int 1]
32 ; STACKMAPS-NEXT: Stack Maps: Loc 3: Constant 3 [encoding: .byte 4, .byte 8, .short 0, .int 3]
33 ; STACKMAPS-NEXT: Stack Maps: has 0 live-out registers
66
77 declare i32 @llvm.experimental.deoptimize.i32(...)
88 declare i8 @llvm.experimental.deoptimize.i8(...)
9 declare webkit_jscc i64 @llvm.experimental.deoptimize.i64(...)
109
1110 define i32 @caller_0() {
1211 ; CHECK-LABEL: _caller_0:
3938 ret i8 %v
4039 }
4140
42 define i64 @caller_2() {
43 ; CHECK-LABEL: _caller_2:
44 ; CHECK-NEXT: {{.+cfi.+}}
45 ; CHECK-NEXT: ##{{.+}}
46 ; CHECK-NEXT: pushq %rax
47 ; CHECK-NEXT: {{Ltmp[0-9]+}}:
48 ; CHECK-NEXT: {{.+cfi.+}}
49 ; CHECK-NEXT: movl $1140457472, (%rsp) ## imm = 0x43FA0000
50 ; CHECK-NEXT: movl $42, %eax
51 ; CHECK-NEXT: callq ___llvm_deoptimize
52 ; CHECK-NEXT: {{Ltmp[0-9]+}}:
53
54 entry:
55 %v = call webkit_jscc i64(...) @llvm.experimental.deoptimize.i64(i32 42, float 500.0) [ "deopt"(i32 3) ]
56 ret i64 %v
57 }
58
5941 ; STACKMAPS: Stack Maps: callsites:
6042 ; STACKMAPS-NEXT: Stack Maps: callsite 2882400015
6143 ; STACKMAPS-NEXT: Stack Maps: has 4 locations
7153 ; STACKMAPS-NEXT: Stack Maps: Loc 2: Constant 1 [encoding: .byte 4, .byte 8, .short 0, .int 1]
7254 ; STACKMAPS-NEXT: Stack Maps: Loc 3: Constant 1 [encoding: .byte 4, .byte 8, .short 0, .int 1]
7355 ; STACKMAPS-NEXT: Stack Maps: has 0 live-out registers
74 ; STACKMAPS-NEXT: Stack Maps: callsite 2882400015
75 ; STACKMAPS-NEXT: Stack Maps: has 4 locations
76 ; STACKMAPS-NEXT: Stack Maps: Loc 0: Constant 12 [encoding: .byte 4, .byte 8, .short 0, .int 12]
77 ; STACKMAPS-NEXT: Stack Maps: Loc 1: Constant 0 [encoding: .byte 4, .byte 8, .short 0, .int 0]
78 ; STACKMAPS-NEXT: Stack Maps: Loc 2: Constant 1 [encoding: .byte 4, .byte 8, .short 0, .int 1]
79 ; STACKMAPS-NEXT: Stack Maps: Loc 3: Constant 3 [encoding: .byte 4, .byte 8, .short 0, .int 3]
80 ; STACKMAPS-NEXT: Stack Maps: has 0 live-out registers
0 ; RUN: opt -S -always-inline < %s | FileCheck %s
1
2 declare cc42 i32 @llvm.experimental.deoptimize.i32(...)
3
4 define i32 @callee_with_coldcc() alwaysinline {
5 %v0 = call cc42 i32(...) @llvm.experimental.deoptimize.i32(i32 1) [ "deopt"() ]
6 ret i32 %v0
7 }
8
9 define void @caller_with_coldcc() {
10 ; CHECK-LABEL: @caller_with_coldcc(
11 ; CHECK-NEXT: call cc42 void (...) @llvm.experimental.deoptimize.isVoid(i32 1) [ "deopt"() ]
12 ; CHECK-NEXT: ret void
13
14 %val = call i32 @callee_with_coldcc()
15 ret void
16 }
17
18 ; CHECK: declare cc42 void @llvm.experimental.deoptimize.isVoid(...)
0 ; RUN: opt -S -always-inline < %s | FileCheck %s
11
22 declare i8 @llvm.experimental.deoptimize.i8(...)
3 declare cc42 i32 @llvm.experimental.deoptimize.i32(...)
3 declare i32 @llvm.experimental.deoptimize.i32(...)
44
55 define i8 @callee(i1* %c) alwaysinline {
66 %c0 = load volatile i1, i1* %c
120120 call i8 @callee_with_dynamic_alloca(i32 %n)
121121 ret void
122122 }
123
124 define i32 @callee_with_coldcc() alwaysinline {
125 %v0 = call cc42 i32(...) @llvm.experimental.deoptimize.i32(i32 1) [ "deopt"() ]
126 ret i32 %v0
127 }
128
129 define void @caller_with_coldcc() {
130 ; CHECK-LABEL: @caller_with_coldcc(
131 ; CHECK-NEXT: call cc42 void (...) @llvm.experimental.deoptimize.isVoid(i32 1) [ "deopt"() ]
132 ; CHECK-NEXT: ret void
133
134 %val = call i32 @callee_with_coldcc()
135 ret void
136 }
0 ; RUN: opt -rewrite-statepoints-for-gc -S < %s | FileCheck %s
1
2 target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128"
3 target triple = "x86_64-apple-macosx10.11.0"
4
5 declare cc42 double @llvm.experimental.deoptimize.f64(...)
6
7 define double @caller_3() gc "statepoint-example" {
8 ; CHECK-LABELL @caller_3(
9 ; CHECK: call cc42 token (i64, i32, void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint
10 ; CHECK: unreachable
11
12 entry:
13 %val = call cc42 double(...) @llvm.experimental.deoptimize.f64() [ "deopt"() ]
14 ret double %val
15 }
44
55 declare i32 @llvm.experimental.deoptimize.i32(...)
66 declare void @llvm.experimental.deoptimize.isVoid(...)
7 declare cc42 double @llvm.experimental.deoptimize.f64(...)
87
98 define i32 @caller_0(i32 addrspace(1)* %ptr) gc "statepoint-example" {
109 ; CHECK-LABEL: @caller_0(
3332 call void(...) @llvm.experimental.deoptimize.isVoid() [ "deopt"(i32 0, i32 addrspace(1)* %ptr) ]
3433 ret void
3534 }
36
37 define double @caller_3() gc "statepoint-example" {
38 ; CHECK-LABELL @caller_3(
39 ; CHECK: call cc42 token (i64, i32, void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint
40 ; CHECK: unreachable
41
42 entry:
43 %val = call cc42 double(...) @llvm.experimental.deoptimize.f64() [ "deopt"() ]
44 ret double %val
45 }
11
22 declare i8 @llvm.experimental.deoptimize.i8(...)
33 declare void @llvm.experimental.deoptimize.isVoid(...)
4 declare cc40 void @llvm.experimental.deoptimize.double(...)
45
56 declare void @unknown()
67
3940 ; CHECK: calls to experimental_deoptimize must be followed by a return of the value computed by experimental_deoptimize
4041 ret i8 0
4142 }
43
44 ; CHECK: All llvm.experimental.deoptimize declarations must have the same calling convention