da092ee3d244de3fe8e18a7f2c015d39e6ba693a
[oota-llvm.git] / test / Transforms / RewriteStatepointsForGC / relocation.ll
1 ; RUN: opt %s -rewrite-statepoints-for-gc -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 i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @foo, 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, %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, %use ], [ %obj2.relocated, %joint ]
27 ; CHECK: %obj3 = getelementptr i64, i64 addrspace(1)* %obj2.relocated, 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, %loop.backedge ]
49 ; CHECK-DAG: [ %obj_init, %entry ]
50 ; CHECK-DAG: [ %obj.relocated, %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 i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @do_safepoint, 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 i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @foo, 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 i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @foo, 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: gc.statepoint
112   %safepoint_token = call i32 (void (i64)*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidi64f(void (i64)* undef, i32 1, i32 0, i64 undef, i32 5, i32 0, i32 -1, i32 0, i32 0, i32 0)
113   %safepoint_token1 = call i32 (i32 (i64 addrspace(1)*)*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_i32p1i64f(i32 (i64 addrspace(1)*)* undef, i32 1, i32 0, i64 addrspace(1)* %obj, i32 5, i32 0, i32 -1, i32 0, i32 0, i32 0)
114   ret void
115 }
116
117 ; Check specifically for the case where the result of a statepoint needs to 
118 ; be relocated itself
119 define void @test4() gc "statepoint-example" {
120 ; CHECK-LABEL: @test4
121 ; CHECK: gc.statepoint
122 ; CHECK: gc.result
123 ; CHECK: gc.statepoint
124 ; CHECK: gc.relocate
125 ; CHECK: @use(i8 addrspace(1)* %res.relocated)
126   %safepoint_token2 = tail call i32 (i8 addrspace(1)* ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_p1i8f(i8 addrspace(1)* ()* undef, i32 0, i32 0, i32 0)
127   %res = call i8 addrspace(1)* @llvm.experimental.gc.result.ptr.p1i8(i32 %safepoint_token2)
128   call i32 (i8 addrspace(1)* ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_p1i8f(i8 addrspace(1)* ()* undef, i32 0, i32 0, i32 0)
129   call void (...) @use(i8 addrspace(1)* %res)
130   unreachable
131 }
132
133
134 ; Test updating a phi where not all inputs are live to begin with
135 define void @test5(i8 addrspace(1)* %arg) gc "statepoint-example" {
136 ; CHECK-LABEL: test5
137 entry:
138   call i32 (i8 addrspace(1)* ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_p1i8f(i8 addrspace(1)* ()* undef, i32 0, i32 0, i32 0)
139   switch i32 undef, label %kill [
140     i32 10, label %merge
141     i32 13, label %merge
142   ]
143
144 kill:
145   br label %merge
146
147 merge:
148 ; CHECK: merge:
149 ; CHECK: %test = phi i8 addrspace(1)
150 ; CHECK-DAG: [ null, %kill ]
151 ; CHECK-DAG: [ %arg.relocated, %entry ]
152 ; CHECK-DAG: [ %arg.relocated, %entry ]
153   %test = phi i8 addrspace(1)* [ null, %kill ], [ %arg, %entry ], [ %arg, %entry ]
154   call void (...) @use(i8 addrspace(1)* %test)
155   unreachable
156 }
157
158
159 ; Check to make sure we handle values live over an entry statepoint
160 define void @test6(i8 addrspace(1)* %arg1, i8 addrspace(1)* %arg2, 
161                   i8 addrspace(1)* %arg3) gc "statepoint-example" {
162 ; CHECK-LABEL: @test6
163 entry:
164   br i1 undef, label %gc.safepoint_poll.exit2, label %do_safepoint
165
166 do_safepoint:
167 ; CHECK-LABEL: do_safepoint:
168 ; CHECK: gc.statepoint
169 ; CHECK: arg1.relocated = 
170 ; CHECK: arg2.relocated = 
171 ; CHECK: arg3.relocated = 
172   call i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @foo, i32 0, i32 0, i32 3, i8 addrspace(1)* %arg1, i8 addrspace(1)* %arg2, i8 addrspace(1)* %arg3)
173   br label %gc.safepoint_poll.exit2
174
175 gc.safepoint_poll.exit2:
176 ; CHECK-LABEL: gc.safepoint_poll.exit2:
177 ; CHECK: phi i8 addrspace(1)*
178 ; CHECK-DAG: [ %arg3, %entry ]
179 ; CHECK-DAG: [ %arg3.relocated, %do_safepoint ]
180 ; CHECK: phi i8 addrspace(1)*
181 ; CHECK-DAG: [ %arg2, %entry ]
182 ; CHECK-DAG: [ %arg2.relocated, %do_safepoint ]
183 ; CHECK: phi i8 addrspace(1)*
184 ; CHECK-DAG: [ %arg1, %entry ]
185 ; CHECK-DAG:  [ %arg1.relocated, %do_safepoint ]
186   call void (...) @use(i8 addrspace(1)* %arg1, i8 addrspace(1)* %arg2, i8 addrspace(1)* %arg3)
187   ret void
188 }
189
190 ; Check relocation in a loop nest where a relocation happens in the outer
191 ; but not the inner loop
192 define void @test_outer_loop(i8 addrspace(1)* %arg1, i8 addrspace(1)* %arg2, 
193                   i1 %cmp) gc "statepoint-example" {
194 ; CHECK-LABEL: @test_outer_loop
195 bci_0:
196   br label %outer-loop
197
198 outer-loop:
199 ; CHECK-LABEL: outer-loop:
200 ; CHECK: phi i8 addrspace(1)* [ %arg2, %bci_0 ], [ %arg2.relocated, %outer-inc ]
201 ; CHECK: phi i8 addrspace(1)* [ %arg1, %bci_0 ], [ %arg1.relocated, %outer-inc ]
202   br label %inner-loop
203
204 inner-loop:
205   br i1 %cmp, label %inner-loop, label %outer-inc
206
207 outer-inc:
208 ; CHECK-LABEL: outer-inc:
209 ; CHECK: %arg1.relocated
210 ; CHECK: %arg2.relocated
211   %safepoint_token = call i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @foo, i32 0, i32 0, i32 2, i8 addrspace(1)* %arg1, i8 addrspace(1)* %arg2)
212   br label %outer-loop
213 }
214
215 ; Check that both inner and outer loops get phis when relocation is in
216 ;  inner loop
217 define void @test_inner_loop(i8 addrspace(1)* %arg1, i8 addrspace(1)* %arg2, 
218                   i1 %cmp) gc "statepoint-example" {
219 ; CHECK-LABEL: @test_inner_loop
220 bci_0:
221   br label %outer-loop
222
223 outer-loop:
224 ; CHECK-LABEL: outer-loop:
225 ; CHECK: phi i8 addrspace(1)* [ %arg2, %bci_0 ], [ %arg2.relocated, %outer-inc ]
226 ; CHECK: phi i8 addrspace(1)* [ %arg1, %bci_0 ], [ %arg1.relocated, %outer-inc ]
227   br label %inner-loop
228
229 inner-loop:
230 ; CHECK-LABEL: inner-loop
231 ; CHECK: phi i8 addrspace(1)* 
232 ; CHECK-DAG: %outer-loop ]
233 ; CHECK-DAG: [ %arg2.relocated, %inner-loop ]
234 ; CHECKL phi i8 addrspace(1)* 
235 ; CHECK-DAG: %outer-loop ]
236 ; CHECK-DAG: [ %arg1.relocated, %inner-loop ]
237 ; CHECK: gc.statepoint
238 ; CHECK: %arg1.relocated
239 ; CHECK: %arg2.relocated
240   %safepoint_token = call i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @foo, i32 0, i32 0, i32 2, i8 addrspace(1)* %arg1, i8 addrspace(1)* %arg2)
241   br i1 %cmp, label %inner-loop, label %outer-inc
242
243 outer-inc:
244 ; CHECK-LABEL: outer-inc:
245   br label %outer-loop
246 }
247
248
249 ; This test shows why updating just those uses of the original value being
250 ; relocated dominated by the inserted relocation is not always sufficient.
251 define i64 addrspace(1)* @test7(i64 addrspace(1)* %obj, i64 addrspace(1)* %obj2, i1 %condition) gc "statepoint-example" {
252 ; CHECK-LABEL: @test7
253 entry:
254   br i1 %condition, label %branch2, label %join
255
256 branch2:
257   br i1 %condition, label %callbb, label %join2
258
259 callbb:
260   %safepoint_token = call i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @foo, i32 0, i32 0, i32 5, i32 0, i32 -1, i32 0, i32 0, i32 0)
261   br label %join
262
263 join:
264 ; CHECK-LABEL: join:
265 ; CHECK: phi i64 addrspace(1)* [ %obj.relocated, %callbb ], [ %obj, %entry ]
266 ; CHECK: phi i64 addrspace(1)* 
267 ; CHECK-DAG: [ %obj, %entry ]
268 ; CHECK-DAG: [ %obj2.relocated, %callbb ]
269   ; This is a phi outside the dominator region of the new defs inserted by
270   ; the safepoint, BUT we can't stop the search here or we miss the second
271   ; phi below.
272   %phi1 = phi i64 addrspace(1)* [ %obj, %entry ], [ %obj2, %callbb ]
273   br label %join2
274
275 join2:
276 ; CHECK-LABEL: join2:
277 ; CHECK: phi2 = phi i64 addrspace(1)* 
278 ; CHECK-DAG: %join ] 
279 ; CHECK-DAG:  [ %obj2, %branch2 ]
280   %phi2 = phi i64 addrspace(1)* [ %obj, %join ], [ %obj2, %branch2 ]
281   ret i64 addrspace(1)* %phi2
282 }
283
284
285 declare void @do_safepoint()
286
287 declare i32 @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()*, i32, i32, ...)
288 declare i32 @llvm.experimental.gc.statepoint.p0f_p1i8f(i8 addrspace(1)* ()*, i32, i32, ...)
289 declare i32 @llvm.experimental.gc.statepoint.p0f_isVoidi64f(void (i64)*, i32, i32, ...)
290 declare i32 @llvm.experimental.gc.statepoint.p0f_i32p1i64f(i32 (i64 addrspace(1)*)*, i32, i32, ...)
291 declare i8 addrspace(1)* @llvm.experimental.gc.result.ptr.p1i8(i32) #3
292
293
294
295