xref: /llvm-project/llvm/test/SafepointIRVerifier/use-derived-unrelocated.ll (revision d1c1a1187eeb78a6ba0dabfdde2c453f57787413)
1; RUN: opt -safepoint-ir-verifier-print-only -verify-safepoint-ir -S %s 2>&1 | FileCheck %s
2
3; Checking if verifier accepts chain of GEPs/bitcasts.
4define void @test.deriving.ok(i32, ptr addrspace(1) %base1, ptr addrspace(1) %base2) gc "statepoint-example" {
5; CHECK-LABEL: Verifying gc pointers in function: test.deriving.ok
6; CHECK-NEXT: No illegal uses found by SafepointIRVerifier in: test.deriving.ok
7  %ptr = getelementptr i8, ptr addrspace(1) %base1, i64 4
8  %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) %base1)]
9  %ptr2 = getelementptr i8, ptr addrspace(1) %base2, i64 8
10  ret void
11}
12
13; Checking if verifier accepts cmp of two derived pointers when one defined
14; before safepoint and one after and both have unrelocated base.
15define void @test.cmp.ok(i32, ptr addrspace(1) %base1, ptr addrspace(1) %base2) gc "statepoint-example" {
16; CHECK-LABEL: Verifying gc pointers in function: test.cmp.ok
17; CHECK-NEXT: No illegal uses found by SafepointIRVerifier in: test.cmp.ok
18  %ptr = getelementptr i8, ptr addrspace(1) %base1, i64 4
19  %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) %base1)]
20  %ptr2 = getelementptr i8, ptr addrspace(1) %base2, i64 8
21  %c2 = icmp sgt ptr addrspace(1) %ptr2, %ptr
22  ret void
23}
24
25; Checking if verifier accepts cmp of two derived pointers when one defined
26; before safepoint and one after and both have unrelocated base. One of pointers
27; defined as a long chain of geps/bitcasts.
28define void @test.cmp-long_chain.ok(i32, ptr addrspace(1) %base1, ptr addrspace(1) %base2) gc "statepoint-example" {
29; CHECK-LABEL: Verifying gc pointers in function: test.cmp-long_chain.ok
30; CHECK-NEXT: No illegal uses found by SafepointIRVerifier in: test.cmp-long_chain.ok
31  %ptr = getelementptr i8, ptr addrspace(1) %base1, i64 4
32  %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) %base1)]
33  %ptr2 = getelementptr i8, ptr addrspace(1) %base2, i64 8
34  %ptr2.i32.2 = getelementptr i32, ptr addrspace(1) %ptr2, i64 4
35  %ptr2.i32.3 = getelementptr i32, ptr addrspace(1) %ptr2.i32.2, i64 8
36  %ptr2.i32.4 = getelementptr i32, ptr addrspace(1) %ptr2.i32.3, i64 8
37  %ptr2.i32.5 = getelementptr i32, ptr addrspace(1) %ptr2.i32.4, i64 8
38  %ptr2.i32.6 = getelementptr i32, ptr addrspace(1) %ptr2.i32.5, i64 8
39  %ptr2.i32.6.i8.i32.2 = getelementptr i32, ptr addrspace(1) %ptr2.i32.6, i64 8
40  %c2 = icmp sgt ptr addrspace(1) %ptr2.i32.6.i8.i32.2, %ptr
41  ret void
42}
43
44; GEP and bitcast of unrelocated pointer is acceptable, but load by resulting
45; pointer should be reported.
46define void @test.load.fail(i32, ptr addrspace(1) %base) gc "statepoint-example" {
47; CHECK-LABEL: Verifying gc pointers in function: test.load.fail
48  %ptr = getelementptr i8, ptr addrspace(1) %base, i64 4
49  %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) %base)]
50; CHECK-NEXT: Illegal use of unrelocated value found!
51; CHECK-NEXT: Def:   %ptr = getelementptr i8, ptr addrspace(1) %base, i64 4
52; CHECK-NEXT: Use:   %ptr.val = load i32, ptr addrspace(1) %ptr
53  %ptr.val = load i32, ptr addrspace(1) %ptr
54  ret void
55}
56
57; Comparison between pointer derived from unrelocated one (though defined after
58; safepoint) and relocated pointer should be reported.
59define void @test.cmp.fail(i64 %arg, ptr addrspace(1) %base1, ptr addrspace(1) %base2) gc "statepoint-example" {
60; CHECK-LABEL: Verifying gc pointers in function: test.cmp.fail
61  %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) %base2)]
62  %base2.relocated = call ptr addrspace(1) @llvm.experimental.gc.relocate.p1(token %safepoint_token, i32 0, i32 0) ; base2, base2
63  %addr1 = getelementptr i8, ptr addrspace(1) %base1, i64 %arg
64; CHECK-NEXT: Illegal use of unrelocated value found!
65; CHECK-NEXT: Def:   %addr1 = getelementptr i8, ptr addrspace(1) %base1, i64 %arg
66; CHECK-NEXT: Use:   %cmp = icmp eq ptr addrspace(1) %addr1, %base2.relocated
67  %cmp = icmp eq ptr addrspace(1) %addr1, %base2.relocated
68  ret void
69}
70
71; Same as test.cmp.fail but splitted into two BBs.
72define void @test.cmp2.fail(i64 %arg, ptr addrspace(1) %base1, ptr addrspace(1) %base2) gc "statepoint-example" {
73.b0:
74; CHECK-LABEL: Verifying gc pointers in function: test.cmp2.fail
75  %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) %base2)]
76  %base2.relocated = call ptr addrspace(1) @llvm.experimental.gc.relocate.p1(token %safepoint_token, i32 0, i32 0) ; base2, base2
77  %addr1 = getelementptr i8, ptr addrspace(1) %base1, i64 %arg
78  br label %.b1
79
80.b1:
81; CHECK-NEXT: Illegal use of unrelocated value found!
82; CHECK-NEXT: Def:   %addr1 = getelementptr i8, ptr addrspace(1) %base1, i64 %arg
83; CHECK-NEXT: Use:   %cmp = icmp eq ptr addrspace(1) %addr1, %base2.relocated
84  %cmp = icmp eq ptr addrspace(1) %addr1, %base2.relocated
85  ret void
86}
87
88; Checking that cmp of two unrelocated pointers is OK and load is not.
89define void @test.cmp-load.fail(i64 %arg, ptr addrspace(1) %base1, ptr addrspace(1) %base2) gc "statepoint-example" {
90; CHECK-LABEL: Verifying gc pointers in function: test.cmp-load.fail
91  %addr1 = getelementptr i8, ptr addrspace(1) %base1, i64 %arg
92  %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) %base2)]
93  %addr2 = getelementptr i8, ptr addrspace(1) %base2, i64 8
94  %cmp = icmp eq ptr addrspace(1) %addr1, %addr2
95; CHECK-NEXT: Illegal use of unrelocated value found!
96; CHECK-NEXT: Def:   %addr2 = getelementptr i8, ptr addrspace(1) %base2, i64 8
97; CHECK-NEXT: Use:   %val = load i8, ptr addrspace(1) %addr2
98  %val = load i8, ptr addrspace(1) %addr2
99  ret void
100}
101
102; Same as test.cmp-load.fail but splitted into thee BBs.
103define void @test.cmp-load2.fail(i64 %arg, ptr addrspace(1) %base1, ptr addrspace(1) %base2) gc "statepoint-example" {
104.b0:
105; CHECK-LABEL: Verifying gc pointers in function: test.cmp-load2.fail
106  %addr1 = getelementptr i8, ptr addrspace(1) %base1, i64 %arg
107  %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) %base2)]
108  br label %.b1
109
110.b1:
111  %addr2 = getelementptr i8, ptr addrspace(1) %base2, i64 8
112  br label %.b2
113
114.b2:
115  %cmp = icmp eq ptr addrspace(1) %addr1, %addr2
116; CHECK-NEXT: Illegal use of unrelocated value found!
117; CHECK-NEXT: Def:   %addr2 = getelementptr i8, ptr addrspace(1) %base2, i64 8
118; CHECK-NEXT: Use:   %val = load i8, ptr addrspace(1) %addr2
119  %val = load i8, ptr addrspace(1) %addr2
120  ret void
121}
122
123; Same as test.cmp.ok but with multiple safepoints within one BB. And the last
124; one is in the very end of BB so that Contribution of this BB is empty.
125define void @test.cmp.multi-sp.ok(i64 %arg, ptr addrspace(1) %base1, ptr addrspace(1) %base2) gc "statepoint-example" {
126; CHECK-LABEL: Verifying gc pointers in function: test.cmp.multi-sp.ok
127; CHECK-NEXT: No illegal uses found by SafepointIRVerifier in: test.cmp.multi-sp.ok
128  %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) %base2)]
129  %base2.relocated = call ptr addrspace(1) @llvm.experimental.gc.relocate.p1(token %safepoint_token, i32 0, i32 0) ; base2, base2
130  %addr1 = getelementptr i8, ptr addrspace(1) %base1, i64 %arg
131  %safepoint_token2 = 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) %base2.relocated)]
132  %base2.relocated2 = call ptr addrspace(1) @llvm.experimental.gc.relocate.p1(token %safepoint_token2, i32 0, i32 0) ; base2.relocated, base2.relocated
133  %addr2 = getelementptr i8, ptr addrspace(1) %base2, i64 %arg
134  %cmp = icmp eq ptr addrspace(1) %addr1, %addr2
135  %safepoint_token3 = 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) %base2.relocated2)]
136  ret void
137}
138
139; Function Attrs: nounwind
140declare token @llvm.experimental.gc.statepoint.p0(i64, i32, ptr, i32, i32, ...)
141declare ptr addrspace(1) @llvm.experimental.gc.relocate.p1(token, i32, i32)
142
143