Taints the non-acquire RMW's store address with the load part
[oota-llvm.git] / test / Transforms / RewriteStatepointsForGC / relocation.ll
1 ; RUN: opt %s -rewrite-statepoints-for-gc -spp-rematerialization-threshold=0 -S 2>&1 | FileCheck %s
2
3
4 declare void @foo()
5 declare void @use(...)
6
7 define i64 addrspace(1)* @test1(i64 addrspace(1)* %obj, i64 addrspace(1)* %obj2, i1 %condition) gc "statepoint-example" {
8 entry:
9 ; CHECK-LABEL: @test1
10 ; CHECK-DAG: %obj.relocated
11 ; CHECK-DAG: %obj2.relocated
12   %safepoint_token = call token (i64, i32, void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(i64 0, i32 0, void ()* @foo, i32 0, i32 0, i32 0, i32 0)
13   br label %joint
14
15 joint:
16 ; CHECK-LABEL: joint:
17 ; CHECK: %phi1 = phi i64 addrspace(1)* [ %obj.relocated.casted, %entry ], [ %obj3, %joint2 ]
18   %phi1 = phi i64 addrspace(1)* [ %obj, %entry ], [ %obj3, %joint2 ]
19   br i1 %condition, label %use, label %joint2
20
21 use:
22   br label %joint2
23
24 joint2:
25 ; CHECK-LABEL: joint2:
26 ; CHECK: %phi2 = phi i64 addrspace(1)* [ %obj.relocated.casted, %use ], [ %obj2.relocated.casted, %joint ]
27 ; CHECK: %obj3 = getelementptr i64, i64 addrspace(1)* %obj2.relocated.casted, i32 1
28   %phi2 = phi i64 addrspace(1)* [ %obj, %use ], [ %obj2, %joint ]
29   %obj3 = getelementptr i64, i64 addrspace(1)* %obj2, i32 1
30   br label %joint
31 }
32
33 declare i64 addrspace(1)* @generate_obj()
34
35 declare void @consume_obj(i64 addrspace(1)*)
36
37 declare i1 @rt()
38
39 define void @test2() gc "statepoint-example" {
40 ; CHECK-LABEL: @test2
41 entry:
42   %obj_init = call i64 addrspace(1)* @generate_obj()
43   %obj = getelementptr i64, i64 addrspace(1)* %obj_init, i32 42
44   br label %loop
45
46 loop:
47 ; CHECK: loop:
48 ; CHECK-DAG: [ %obj_init.relocated.casted, %loop.backedge ]
49 ; CHECK-DAG: [ %obj_init, %entry ]
50 ; CHECK-DAG: [ %obj.relocated.casted, %loop.backedge ]
51 ; CHECK-DAG: [ %obj, %entry ]
52   %index = phi i32 [ 0, %entry ], [ %index.inc, %loop.backedge ]
53 ; CHECK-NOT: %location = getelementptr i64, i64 addrspace(1)* %obj, i32 %index
54   %location = getelementptr i64, i64 addrspace(1)* %obj, i32 %index
55   call void @consume_obj(i64 addrspace(1)* %location)
56   %index.inc = add i32 %index, 1
57   %condition = call i1 @rt()
58   br i1 %condition, label %loop_x, label %loop_y
59
60 loop_x:
61   br label %loop.backedge
62
63 loop.backedge:
64   %safepoint_token = call token (i64, i32, void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(i64 0, i32 0, void ()* @do_safepoint, i32 0, i32 0, i32 0, i32 0)
65   br label %loop
66
67 loop_y:
68   br label %loop.backedge
69 }
70
71 declare void @some_call(i8 addrspace(1)*)
72
73 define void @relocate_merge(i1 %cnd, i8 addrspace(1)* %arg) gc "statepoint-example" {
74 ; CHECK-LABEL: @relocate_merge
75 bci_0:
76   br i1 %cnd, label %if_branch, label %else_branch
77
78 if_branch:
79 ; CHECK-LABEL: if_branch:
80 ; CHECK: gc.statepoint
81 ; CHECK: gc.relocate
82   %safepoint_token = call token (i64, i32, void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(i64 0, i32 0, void ()* @foo, i32 0, i32 0, i32 0, i32 0)
83   br label %join
84
85 else_branch:
86 ; CHECK-LABEL: else_branch:
87 ; CHECK: gc.statepoint
88 ; CHECK: gc.relocate
89   %safepoint_token1 = call token (i64, i32, void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(i64 0, i32 0, void ()* @foo, i32 0, i32 0, i32 0, i32 0)
90   br label %join
91
92 join:
93 ; We need to end up with a single relocation phi updated from both paths 
94 ; CHECK-LABEL: join:
95 ; CHECK: phi i8 addrspace(1)*
96 ; CHECK-DAG: [ %arg.relocated, %if_branch ]
97 ; CHECK-DAG: [ %arg.relocated4, %else_branch ]
98 ; CHECK-NOT: phi
99   call void (i8 addrspace(1)*) @some_call(i8 addrspace(1)* %arg)
100   ret void
101 }
102
103 ; Make sure a use in a statepoint gets properly relocated at a previous one.  
104 ; This is basically just making sure that statepoints aren't accidentally 
105 ; treated specially.
106 define void @test3(i64 addrspace(1)* %obj) gc "statepoint-example" {
107 entry:
108 ; CHECK-LABEL: @test3
109 ; CHECK: gc.statepoint
110 ; CHECK-NEXT: gc.relocate
111 ; CHECK-NEXT: bitcast
112 ; CHECK-NEXT: gc.statepoint
113   %safepoint_token = call token (i64, i32, void (i64)*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidi64f(i64 0, i32 0, void (i64)* undef, i32 1, i32 0, i64 undef, i32 0, i32 5, i32 0, i32 -1, i32 0, i32 0, i32 0)
114   %safepoint_token1 = call token (i64, i32, i32 (i64 addrspace(1)*)*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_i32p1i64f(i64 0, i32 0, i32 (i64 addrspace(1)*)* undef, i32 1, i32 0, i64 addrspace(1)* %obj, i32 0, i32 5, i32 0, i32 -1, i32 0, i32 0, i32 0)
115   ret void
116 }
117
118 ; Check specifically for the case where the result of a statepoint needs to 
119 ; be relocated itself
120 define void @test4() gc "statepoint-example" {
121 ; CHECK-LABEL: @test4
122 ; CHECK: gc.statepoint
123 ; CHECK: gc.result
124 ; CHECK: gc.statepoint
125 ; CHECK: gc.relocate
126 ; CHECK: @use(i8 addrspace(1)* %res.relocated)
127   %safepoint_token2 = tail call token (i64, i32, i8 addrspace(1)* ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_p1i8f(i64 0, i32 0, i8 addrspace(1)* ()* undef, i32 0, i32 0, i32 0, i32 0)
128   %res = call i8 addrspace(1)* @llvm.experimental.gc.result.p1i8(token %safepoint_token2)
129   call token (i64, i32, i8 addrspace(1)* ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_p1i8f(i64 0, i32 0, i8 addrspace(1)* ()* undef, i32 0, i32 0, i32 0, i32 0)
130   call void (...) @use(i8 addrspace(1)* %res)
131   unreachable
132 }
133
134
135 ; Test updating a phi where not all inputs are live to begin with
136 define void @test5(i8 addrspace(1)* %arg) gc "statepoint-example" {
137 ; CHECK-LABEL: test5
138 entry:
139   call token (i64, i32, i8 addrspace(1)* ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_p1i8f(i64 0, i32 0, i8 addrspace(1)* ()* undef, i32 0, i32 0, i32 0, i32 0)
140   switch i32 undef, label %kill [
141     i32 10, label %merge
142     i32 13, label %merge
143   ]
144
145 kill:
146   br label %merge
147
148 merge:
149 ; CHECK: merge:
150 ; CHECK: %test = phi i8 addrspace(1)
151 ; CHECK-DAG: [ null, %kill ]
152 ; CHECK-DAG: [ %arg.relocated, %entry ]
153 ; CHECK-DAG: [ %arg.relocated, %entry ]
154   %test = phi i8 addrspace(1)* [ null, %kill ], [ %arg, %entry ], [ %arg, %entry ]
155   call void (...) @use(i8 addrspace(1)* %test)
156   unreachable
157 }
158
159
160 ; Check to make sure we handle values live over an entry statepoint
161 define void @test6(i8 addrspace(1)* %arg1, i8 addrspace(1)* %arg2, 
162                   i8 addrspace(1)* %arg3) gc "statepoint-example" {
163 ; CHECK-LABEL: @test6
164 entry:
165   br i1 undef, label %gc.safepoint_poll.exit2, label %do_safepoint
166
167 do_safepoint:
168 ; CHECK-LABEL: do_safepoint:
169 ; CHECK: gc.statepoint
170 ; CHECK: arg1.relocated = 
171 ; CHECK: arg2.relocated = 
172 ; CHECK: arg3.relocated = 
173   call token (i64, i32, void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(i64 0, i32 0, void ()* @foo, i32 0, i32 0, i32 0, i32 3, i8 addrspace(1)* %arg1, i8 addrspace(1)* %arg2, i8 addrspace(1)* %arg3)
174   br label %gc.safepoint_poll.exit2
175
176 gc.safepoint_poll.exit2:
177 ; CHECK-LABEL: gc.safepoint_poll.exit2:
178 ; CHECK: phi i8 addrspace(1)*
179 ; CHECK-DAG: [ %arg3, %entry ]
180 ; CHECK-DAG: [ %arg3.relocated, %do_safepoint ]
181 ; CHECK: phi i8 addrspace(1)*
182 ; CHECK-DAG: [ %arg2, %entry ]
183 ; CHECK-DAG: [ %arg2.relocated, %do_safepoint ]
184 ; CHECK: phi i8 addrspace(1)*
185 ; CHECK-DAG: [ %arg1, %entry ]
186 ; CHECK-DAG:  [ %arg1.relocated, %do_safepoint ]
187   call void (...) @use(i8 addrspace(1)* %arg1, i8 addrspace(1)* %arg2, i8 addrspace(1)* %arg3)
188   ret void
189 }
190
191 ; Check relocation in a loop nest where a relocation happens in the outer
192 ; but not the inner loop
193 define void @test_outer_loop(i8 addrspace(1)* %arg1, i8 addrspace(1)* %arg2, 
194                   i1 %cmp) gc "statepoint-example" {
195 ; CHECK-LABEL: @test_outer_loop
196 bci_0:
197   br label %outer-loop
198
199 outer-loop:
200 ; CHECK-LABEL: outer-loop:
201 ; CHECK: phi i8 addrspace(1)* [ %arg2, %bci_0 ], [ %arg2.relocated, %outer-inc ]
202 ; CHECK: phi i8 addrspace(1)* [ %arg1, %bci_0 ], [ %arg1.relocated, %outer-inc ]
203   br label %inner-loop
204
205 inner-loop:
206   br i1 %cmp, label %inner-loop, label %outer-inc
207
208 outer-inc:
209 ; CHECK-LABEL: outer-inc:
210 ; CHECK: %arg1.relocated
211 ; CHECK: %arg2.relocated
212   %safepoint_token = call token (i64, i32, void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(i64 0, i32 0, void ()* @foo, i32 0, i32 0, i32 0, i32 2, i8 addrspace(1)* %arg1, i8 addrspace(1)* %arg2)
213   br label %outer-loop
214 }
215
216 ; Check that both inner and outer loops get phis when relocation is in
217 ;  inner loop
218 define void @test_inner_loop(i8 addrspace(1)* %arg1, i8 addrspace(1)* %arg2, 
219                   i1 %cmp) gc "statepoint-example" {
220 ; CHECK-LABEL: @test_inner_loop
221 bci_0:
222   br label %outer-loop
223
224 outer-loop:
225 ; CHECK-LABEL: outer-loop:
226 ; CHECK: phi i8 addrspace(1)* [ %arg2, %bci_0 ], [ %arg2.relocated, %outer-inc ]
227 ; CHECK: phi i8 addrspace(1)* [ %arg1, %bci_0 ], [ %arg1.relocated, %outer-inc ]
228   br label %inner-loop
229
230 inner-loop:
231 ; CHECK-LABEL: inner-loop
232 ; CHECK: phi i8 addrspace(1)* 
233 ; CHECK-DAG: %outer-loop ]
234 ; CHECK-DAG: [ %arg2.relocated, %inner-loop ]
235 ; CHECK: phi i8 addrspace(1)* 
236 ; CHECK-DAG: %outer-loop ]
237 ; CHECK-DAG: [ %arg1.relocated, %inner-loop ]
238 ; CHECK: gc.statepoint
239 ; CHECK: %arg1.relocated
240 ; CHECK: %arg2.relocated
241   %safepoint_token = call token (i64, i32, void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(i64 0, i32 0, void ()* @foo, i32 0, i32 0, i32 0, i32 2, i8 addrspace(1)* %arg1, i8 addrspace(1)* %arg2)
242   br i1 %cmp, label %inner-loop, label %outer-inc
243
244 outer-inc:
245 ; CHECK-LABEL: outer-inc:
246   br label %outer-loop
247 }
248
249
250 ; This test shows why updating just those uses of the original value being
251 ; relocated dominated by the inserted relocation is not always sufficient.
252 define i64 addrspace(1)* @test7(i64 addrspace(1)* %obj, i64 addrspace(1)* %obj2, i1 %condition) gc "statepoint-example" {
253 ; CHECK-LABEL: @test7
254 entry:
255   br i1 %condition, label %branch2, label %join
256
257 branch2:
258   br i1 %condition, label %callbb, label %join2
259
260 callbb:
261   %safepoint_token = call token (i64, i32, void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(i64 0, i32 0, void ()* @foo, i32 0, i32 0, i32 0, i32 5, i32 0, i32 -1, i32 0, i32 0, i32 0)
262   br label %join
263
264 join:
265 ; CHECK-LABEL: join:
266 ; CHECK: phi i64 addrspace(1)* [ %obj.relocated.casted, %callbb ], [ %obj, %entry ]
267 ; CHECK: phi i64 addrspace(1)* 
268 ; CHECK-DAG: [ %obj, %entry ]
269 ; CHECK-DAG: [ %obj2.relocated.casted, %callbb ]
270   ; This is a phi outside the dominator region of the new defs inserted by
271   ; the safepoint, BUT we can't stop the search here or we miss the second
272   ; phi below.
273   %phi1 = phi i64 addrspace(1)* [ %obj, %entry ], [ %obj2, %callbb ]
274   br label %join2
275
276 join2:
277 ; CHECK-LABEL: join2:
278 ; CHECK: phi2 = phi i64 addrspace(1)* 
279 ; CHECK-DAG: %join ] 
280 ; CHECK-DAG:  [ %obj2, %branch2 ]
281   %phi2 = phi i64 addrspace(1)* [ %obj, %join ], [ %obj2, %branch2 ]
282   ret i64 addrspace(1)* %phi2
283 }
284
285
286 declare void @do_safepoint()
287
288 declare token @llvm.experimental.gc.statepoint.p0f_isVoidf(i64, i32, void ()*, i32, i32, ...)
289 declare token @llvm.experimental.gc.statepoint.p0f_p1i8f(i64, i32, i8 addrspace(1)* ()*, i32, i32, ...)
290 declare token @llvm.experimental.gc.statepoint.p0f_isVoidi64f(i64, i32, void (i64)*, i32, i32, ...)
291 declare token @llvm.experimental.gc.statepoint.p0f_i32p1i64f(i64, i32, i32 (i64 addrspace(1)*)*, i32, i32, ...)
292 declare i8 addrspace(1)* @llvm.experimental.gc.result.p1i8(token) #3
293
294
295