1; RUN: opt -safepoint-ir-verifier-print-only -verify-safepoint-ir -S %s 2>&1 | FileCheck %s
2
3define i8 addrspace(1)* @test.not.ok.0(i8 addrspace(1)* %arg) gc "statepoint-example" {
4; CHECK-LABEL: Verifying gc pointers in function: test.not.ok.0
5 bci_0:
6  br i1 undef, label %left, label %right
7
8 left:
9  %safepoint_token = call token (i64, i32, void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(i64 0, i32 0, void ()* undef, i32 0, i32 0, i32 0, i32 5, i32 0, i32 -1, i32 0, i32 0, i32 0)
10  br label %merge
11
12 right:
13  br label %merge
14
15 merge:
16; CHECK: Illegal use of unrelocated value found!
17; CHECK-NEXT: Def:   %val = phi i8 addrspace(1)* [ %arg, %left ], [ %arg, %right ]
18; CHECK-NEXT: Use:   ret i8 addrspace(1)* %val
19  %val = phi i8 addrspace(1)* [ %arg, %left ], [ %arg, %right ]
20  ret i8 addrspace(1)* %val
21}
22
23define i8 addrspace(1)* @test.not.ok.1(i8 addrspace(1)* %arg) gc "statepoint-example" {
24; CHECK-LABEL: Verifying gc pointers in function: test.not.ok.1
25 bci_0:
26  br i1 undef, label %left, label %right
27
28 left:
29  %safepoint_token = call token (i64, i32, void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(i64 0, i32 0, void ()* undef, i32 0, i32 0, i32 0, i32 5, i32 0, i32 -1, i32 0, i32 0, i32 0)
30  br label %merge
31
32 right:
33  br label %merge
34
35 merge:
36; CHECK: Illegal use of unrelocated value found!
37; CHECK-NEXT: Def:   %val = phi i8 addrspace(1)* [ %arg, %left ], [ null, %right ]
38; CHECK-NEXT: Use:   ret i8 addrspace(1)* %val
39  %val = phi i8 addrspace(1)* [ %arg, %left ], [ null, %right ]
40  ret i8 addrspace(1)* %val
41}
42
43define i8 addrspace(1)* @test.ok.0(i8 addrspace(1)* %arg) gc "statepoint-example" {
44; CHECK: No illegal uses found by SafepointIRVerifier in: test.ok.0
45 bci_0:
46  br i1 undef, label %left, label %right
47
48 left:
49  %safepoint_token = call token (i64, i32, void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(i64 0, i32 0, void ()* undef, i32 0, i32 0, i32 0, i32 5, i32 0, i32 -1, i32 0, i32 0, i32 0)
50  br label %merge
51
52 right:
53  br label %merge
54
55 merge:
56  %val = phi i8 addrspace(1)* [ null, %left ], [ null, %right]
57  ret i8 addrspace(1)* %val
58}
59
60define i8 addrspace(1)* @test.ok.1(i8 addrspace(1)* %arg) gc "statepoint-example" {
61; CHECK: No illegal uses found by SafepointIRVerifier in: test.ok.1
62 bci_0:
63  br i1 undef, label %left, label %right
64
65 left:
66  call void @not_statepoint()
67  br label %merge
68
69 right:
70  br label %merge
71
72 merge:
73  %val = phi i8 addrspace(1)* [ %arg, %left ], [ %arg, %right]
74  ret i8 addrspace(1)* %val
75}
76
77; It should be allowed to compare poisoned ptr with null.
78define void @test.poisoned.cmp.ok(i8 addrspace(1)* %arg) gc "statepoint-example" {
79; CHECK-LABEL: Verifying gc pointers in function: test.poisoned.cmp.ok
80 bci_0:
81  br i1 undef, label %left, label %right
82
83 left:
84  %safepoint_token = call token (i64, i32, void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(i64 0, i32 0, void ()* undef, i32 0, i32 0, i32 0, i32 0, i8 addrspace(1)* %arg , i32 -1, i32 0, i32 0, i32 0)
85  %arg.relocated = call i8 addrspace(1)* @llvm.experimental.gc.relocate.p1i8(token %safepoint_token, i32 7, i32 7) ; arg, arg
86  br label %merge
87
88 right:
89  %safepoint_token2 = call token (i64, i32, void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(i64 0, i32 0, void ()* undef, i32 0, i32 0, i32 0, i32 0, i8 addrspace(1)* %arg , i32 -1, i32 0, i32 0, i32 0)
90  br label %merge
91
92 merge:
93; CHECK: No illegal uses found by SafepointIRVerifier in: test.poisoned.cmp.ok
94  %val.poisoned = phi i8 addrspace(1)* [ %arg.relocated, %left ], [ %arg, %right ]
95  %c = icmp eq i8 addrspace(1)* %val.poisoned, null
96  ret void
97}
98
99; It is illegal to compare poisoned ptr and relocated.
100define void @test.poisoned.cmp.fail.0(i8 addrspace(1)* %arg) gc "statepoint-example" {
101; CHECK-LABEL: Verifying gc pointers in function: test.poisoned.cmp.fail.0
102 bci_0:
103  br i1 undef, label %left, label %right
104
105 left:
106  %safepoint_token = call token (i64, i32, void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(i64 0, i32 0, void ()* undef, i32 0, i32 0, i32 0, i32 0, i8 addrspace(1)* %arg , i32 -1, i32 0, i32 0, i32 0)
107  %arg.relocated = call i8 addrspace(1)* @llvm.experimental.gc.relocate.p1i8(token %safepoint_token, i32 7, i32 7) ; arg, arg
108  br label %merge
109
110 right:
111  %safepoint_token2 = call token (i64, i32, void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(i64 0, i32 0, void ()* undef, i32 0, i32 0, i32 0, i32 0, i8 addrspace(1)* %arg , i32 -1, i32 0, i32 0, i32 0)
112  %arg.relocated2 = call i8 addrspace(1)* @llvm.experimental.gc.relocate.p1i8(token %safepoint_token2, i32 7, i32 7) ; arg, arg
113  br label %merge
114
115 merge:
116; CHECK: Illegal use of unrelocated value found!
117; CHECK-NEXT: Def:   %val.poisoned = phi i8 addrspace(1)* [ %arg.relocated, %left ], [ %arg, %right ]
118; CHECK-NEXT: Use:   %c = icmp eq i8 addrspace(1)* %val.poisoned, %val
119  %val.poisoned = phi i8 addrspace(1)* [ %arg.relocated, %left ], [ %arg, %right ]
120  %val = phi i8 addrspace(1)* [ %arg.relocated, %left ], [ %arg.relocated2, %right ]
121  %c = icmp eq i8 addrspace(1)* %val.poisoned, %val
122  ret void
123}
124
125; It is illegal to compare poisoned ptr and unrelocated.
126define void @test.poisoned.cmp.fail.1(i8 addrspace(1)* %arg) gc "statepoint-example" {
127; CHECK-LABEL: Verifying gc pointers in function: test.poisoned.cmp.fail.1
128 bci_0:
129  br i1 undef, label %left, label %right
130
131 left:
132  %safepoint_token = call token (i64, i32, void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(i64 0, i32 0, void ()* undef, i32 0, i32 0, i32 0, i32 0, i8 addrspace(1)* %arg , i32 -1, i32 0, i32 0, i32 0)
133  %arg.relocated = call i8 addrspace(1)* @llvm.experimental.gc.relocate.p1i8(token %safepoint_token, i32 7, i32 7) ; arg, arg
134  br label %merge
135
136 right:
137  %safepoint_token2 = call token (i64, i32, void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(i64 0, i32 0, void ()* undef, i32 0, i32 0, i32 0, i32 0, i8 addrspace(1)* %arg , i32 -1, i32 0, i32 0, i32 0)
138  %arg.relocated2 = call i8 addrspace(1)* @llvm.experimental.gc.relocate.p1i8(token %safepoint_token2, i32 7, i32 7) ; arg, arg
139  br label %merge
140
141 merge:
142; CHECK: Illegal use of unrelocated value found!
143; CHECK-NEXT: Def:   %val.poisoned = phi i8 addrspace(1)* [ %arg.relocated, %left ], [ %arg, %right ]
144; CHECK-NEXT: Use:   %c = icmp eq i8 addrspace(1)* %val.poisoned, %arg
145  %val.poisoned = phi i8 addrspace(1)* [ %arg.relocated, %left ], [ %arg, %right ]
146  %c = icmp eq i8 addrspace(1)* %val.poisoned, %arg
147  ret void
148}
149
150; It should be allowed to compare unrelocated phi with unrelocated value.
151define void @test.unrelocated-phi.cmp.ok(i8 addrspace(1)* %arg) gc "statepoint-example" {
152; CHECK-LABEL: Verifying gc pointers in function: test.unrelocated-phi.cmp.ok
153 bci_0:
154  br i1 undef, label %left, label %right
155
156 left:
157  %safepoint_token = call token (i64, i32, void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(i64 0, i32 0, void ()* undef, i32 0, i32 0, i32 0, i32 5, i32 0, i32 -1, i32 0, i32 0, i32 0)
158  br label %merge
159
160 right:
161  br label %merge
162
163 merge:
164; CHECK: No illegal uses found by SafepointIRVerifier in: test.unrelocated-phi.cmp.ok
165  %val.unrelocated = phi i8 addrspace(1)* [ %arg, %left ], [ null, %right ]
166  %c = icmp eq i8 addrspace(1)* %val.unrelocated, %arg
167  ret void
168}
169
170declare token @llvm.experimental.gc.statepoint.p0f_isVoidf(i64, i32, void ()*, i32, i32, ...)
171declare i8 addrspace(1)* @llvm.experimental.gc.relocate.p1i8(token, i32, i32)
172declare void @not_statepoint()
173