xref: /llvm-project/llvm/test/Verifier/statepoint.ll (revision c820f2a43eaba02db97c4ff60c58a58e6bdd391d)
1; RUN: opt -S %s -passes=verify | FileCheck %s
2
3declare void @use(...)
4declare ptr addrspace(1) @llvm.experimental.gc.relocate.p1(token, i32, i32)
5declare token @llvm.experimental.gc.statepoint.p0(i64, i32, ptr, i32, i32, ...)
6declare i32 @"personality_function"()
7
8;; Basic usage
9define ptr addrspace(1) @test1(ptr addrspace(1) %arg) gc "statepoint-example" {
10entry:
11  %safepoint_token = call token (i64, i32, ptr, i32, i32, ...) @llvm.experimental.gc.statepoint.p0(i64 0, i32 0, ptr elementtype(void ()) undef, i32 0, i32 0, i32 0, i32 0) ["gc-live" (ptr addrspace(1) %arg, ptr addrspace(1) %arg, ptr addrspace(1) %arg, ptr addrspace(1) %arg), "deopt" (i32 0, i32 0, i32 0, i32 10, i32 0)]
12  %reloc = call ptr addrspace(1) @llvm.experimental.gc.relocate.p1(token %safepoint_token, i32 0, i32 1)
13  ;; It is perfectly legal to relocate the same value multiple times...
14  %reloc2 = call ptr addrspace(1) @llvm.experimental.gc.relocate.p1(token %safepoint_token, i32 0, i32 1)
15  %reloc3 = call ptr addrspace(1) @llvm.experimental.gc.relocate.p1(token %safepoint_token, i32 1, i32 0)
16  ret ptr addrspace(1) %reloc
17; CHECK-LABEL: test1
18; CHECK: statepoint
19; CHECK: gc.relocate
20; CHECK: gc.relocate
21; CHECK: gc.relocate
22; CHECK: ret ptr addrspace(1) %reloc
23}
24
25; This test catches two cases where the verifier was too strict:
26; 1) A base doesn't need to be relocated if it's never used again
27; 2) A value can be replaced by one which is known equal.  This
28; means a potentially derived pointer can be known base and that
29; we can't check that derived pointer are never bases.
30define void @test2(ptr addrspace(1) %arg, ptr addrspace(1) %arg2) gc "statepoint-example" {
31entry:
32  %c = icmp eq ptr addrspace(1) %arg,  %arg2
33  br i1 %c, label %equal, label %notequal
34
35notequal:
36  ret void
37
38equal:
39  %safepoint_token = call token (i64, i32, ptr, i32, i32, ...) @llvm.experimental.gc.statepoint.p0(i64 0, i32 0, ptr elementtype(void ()) undef, i32 0, i32 0, i32 0, i32 0) ["gc-live" (ptr addrspace(1) %arg, ptr addrspace(1) %arg, ptr addrspace(1) %arg, ptr addrspace(1) %arg), "deopt" (i32 0, i32 0, i32 0, i32 10, i32 0)]
40  %reloc = call ptr addrspace(1) @llvm.experimental.gc.relocate.p1(token %safepoint_token, i32 0, i32 0)
41  call void undef(ptr addrspace(1) %reloc)
42  ret void
43; CHECK-LABEL: test2
44; CHECK-LABEL: equal
45; CHECK: statepoint
46; CHECK-NEXT: %reloc = call
47; CHECK-NEXT: call
48; CHECK-NEXT: ret voi
49}
50
51; Basic test for invoke statepoints
52define ptr addrspace(1) @test3(ptr addrspace(1) %obj, ptr addrspace(1) %obj1) gc "statepoint-example" personality ptr @"personality_function" {
53; CHECK-LABEL: test3
54entry:
55  ; CHECK-LABEL: entry
56  ; CHECK: statepoint
57  %0 = invoke token (i64, i32, ptr, i32, i32, ...) @llvm.experimental.gc.statepoint.p0(i64 0, i32 0, ptr elementtype(void ()) undef, i32 0, i32 0, i32 0, i32 0) ["gc-live" (ptr addrspace(1) %obj, ptr addrspace(1) %obj1), "deopt" (i32 0, i32 -1, i32 0, i32 0, i32 0)]
58          to label %normal_dest unwind label %exceptional_return
59
60normal_dest:
61  ; CHECK-LABEL: normal_dest:
62  ; CHECK: gc.relocate
63  ; CHECK: gc.relocate
64  ; CHECK: ret
65  %obj.relocated = call coldcc ptr addrspace(1) @llvm.experimental.gc.relocate.p1(token %0, i32 0, i32 0)
66  %obj1.relocated = call coldcc ptr addrspace(1) @llvm.experimental.gc.relocate.p1(token %0, i32 1, i32 1)
67  ret ptr addrspace(1) %obj.relocated
68
69exceptional_return:
70  ; CHECK-LABEL: exceptional_return
71  ; CHECK: gc.relocate
72  ; CHECK: gc.relocate
73  %landing_pad = landingpad token
74          cleanup
75  %obj.relocated1 = call coldcc ptr addrspace(1) @llvm.experimental.gc.relocate.p1(token %landing_pad, i32 0, i32 0)
76  %obj1.relocated1 = call coldcc ptr addrspace(1) @llvm.experimental.gc.relocate.p1(token %landing_pad, i32 1, i32 1)
77  ret ptr addrspace(1) %obj1.relocated1
78}
79
80; Test for statepoint with sret attribute.
81; This should be allowed as long as the wrapped function is not vararg.
82%struct = type { i64, i64, i64 }
83
84declare void @fn_sret(ptr sret(%struct))
85
86define void @test_sret() gc "statepoint-example" {
87  %x = alloca %struct
88  %statepoint_token = call token (i64, i32, ptr, i32, i32, ...) @llvm.experimental.gc.statepoint.p0(i64 0, i32 0, ptr elementtype(void (ptr)) @fn_sret, i32 1, i32 0, ptr sret(%struct) %x, i32 0, i32 0)
89  ret void
90  ; CHECK-LABEL: test_sret
91  ; CHECK: alloca
92  ; CHECK: statepoint
93  ; CHECK-SAME: sret
94  ; CHECK: ret
95}
96