1 ; RUN: opt -S -basicaa -licm -enable-mssa-loop-dependency=false %s | FileCheck -check-prefixes=CHECK,AST %s
2 ; RUN: opt -S -basicaa -licm -enable-mssa-loop-dependency=true %s | FileCheck -check-prefixes=CHECK,MSSA %s
3 ; RUN: opt -aa-pipeline=basic-aa -passes='require<aa>,require<targetir>,require<scalar-evolution>,require<opt-remark-emit>,loop(licm)' < %s -S | FileCheck -check-prefixes=CHECK,AST %s
4 ; RUN: opt -aa-pipeline=basic-aa -passes='require<aa>,require<targetir>,require<scalar-evolution>,require<opt-remark-emit>,loop-mssa(licm)' < %s -S | FileCheck -check-prefixes=CHECK,MSSA %s
6 define void @test(i32* %loc) {
9 ; CHECK: store i32 0, i32* %loc
15 %iv = phi i32 [0, %entry], [%iv.next, %loop]
16 store i32 0, i32* %loc
17 %iv.next = add i32 %iv, 1
18 %cmp = icmp slt i32 %iv, 200
19 br i1 %cmp, label %loop, label %exit
25 define void @test_multiexit(i32* %loc, i1 %earlycnd) {
26 ; CHECK-LABEL: @test_multiexit
28 ; CHECK: store i32 0, i32* %loc
34 %iv = phi i32 [0, %entry], [%iv.next, %backedge]
35 store i32 0, i32* %loc
36 %iv.next = add i32 %iv, 1
37 br i1 %earlycnd, label %exit1, label %backedge
40 %cmp = icmp slt i32 %iv, 200
41 br i1 %cmp, label %loop, label %exit2
49 define i32* @false_negative_2use(i32* %loc) {
50 ; CHECK-LABEL: @false_negative_2use
52 ; AST: store i32 0, i32* %loc
54 ; MSSA: store i32 0, i32* %loc
60 %iv = phi i32 [0, %entry], [%iv.next, %loop]
61 store i32 0, i32* %loc
62 %iv.next = add i32 %iv, 1
63 %cmp = icmp slt i32 %iv, 200
64 br i1 %cmp, label %loop, label %exit
70 define void @neg_lv_value(i32* %loc) {
71 ; CHECK-LABEL: @neg_lv_value
73 ; CHECK: store i32 %iv.lcssa, i32* %loc
78 %iv = phi i32 [0, %entry], [%iv.next, %loop]
79 store i32 %iv, i32* %loc
80 %iv.next = add i32 %iv, 1
81 %cmp = icmp slt i32 %iv, 200
82 br i1 %cmp, label %loop, label %exit
88 define void @neg_lv_addr(i32* %loc) {
89 ; CHECK-LABEL: @neg_lv_addr
91 ; CHECK: store i32 0, i32* %p
97 %iv = phi i32 [0, %entry], [%iv.next, %loop]
98 %p = getelementptr i32, i32* %loc, i32 %iv
100 %iv.next = add i32 %iv, 1
101 %cmp = icmp slt i32 %iv, 200
102 br i1 %cmp, label %loop, label %exit
108 define void @neg_mod(i32* %loc) {
109 ; CHECK-LABEL: @neg_mod
111 ; CHECK: store i32 %iv.lcssa, i32* %loc
116 %iv = phi i32 [0, %entry], [%iv.next, %loop]
117 store i32 0, i32* %loc
118 store i32 %iv, i32* %loc
119 %iv.next = add i32 %iv, 1
120 %cmp = icmp slt i32 %iv, 200
121 br i1 %cmp, label %loop, label %exit
127 ; Hoisting the store is actually valid here, as it dominates the load.
128 define void @neg_ref(i32* %loc) {
129 ; CHECK-LABEL: @neg_ref
130 ; CHECK-LABEL: exit1:
131 ; CHECK: store i32 0, i32* %loc
132 ; CHECK-LABEL: exit2:
133 ; CHECK: store i32 0, i32* %loc
138 %iv = phi i32 [0, %entry], [%iv.next, %backedge]
139 store i32 0, i32* %loc
140 %v = load i32, i32* %loc
141 %earlycnd = icmp eq i32 %v, 198
142 br i1 %earlycnd, label %exit1, label %backedge
145 %iv.next = add i32 %iv, 1
146 %cmp = icmp slt i32 %iv, 200
147 br i1 %cmp, label %loop, label %exit2
155 ; Hoisting the store here leads to a miscompile.
156 define void @neg_ref2(i32* %loc) {
157 ; CHECK-LABEL: @neg_ref2
158 ; CHECK-LABEL: exit1:
159 ; CHECK: store i32 0, i32* %loc
160 ; CHECK-LABEL: exit2:
161 ; CHECK: store i32 0, i32* %loc
163 store i32 198, i32* %loc
167 %iv = phi i32 [0, %entry], [%iv.next, %backedge]
168 %v = load i32, i32* %loc
169 store i32 0, i32* %loc
170 %earlycnd = icmp eq i32 %v, 198
171 br i1 %earlycnd, label %exit1, label %backedge
174 %iv.next = add i32 %iv, 1
175 %cmp = icmp slt i32 %iv, 200
176 br i1 %cmp, label %loop, label %exit2
184 declare void @modref()
186 define void @neg_modref(i32* %loc) {
187 ; CHECK-LABEL: @neg_modref
189 ; CHECK: store i32 0, i32* %loc
195 %iv = phi i32 [0, %entry], [%iv.next, %loop]
196 store i32 0, i32* %loc
198 %iv.next = add i32 %iv, 1
199 %cmp = icmp slt i32 %iv, 200
200 br i1 %cmp, label %loop, label %exit
206 define void @neg_fence(i32* %loc) {
207 ; CHECK-LABEL: @neg_fence
209 ; CHECK: store i32 0, i32* %loc
215 %iv = phi i32 [0, %entry], [%iv.next, %loop]
216 store i32 0, i32* %loc
218 %iv.next = add i32 %iv, 1
219 %cmp = icmp slt i32 %iv, 200
220 br i1 %cmp, label %loop, label %exit
226 define void @neg_volatile(i32* %loc) {
227 ; CHECK-LABEL: @neg_volatile
229 ; CHECK: store volatile i32 0, i32* %loc
235 %iv = phi i32 [0, %entry], [%iv.next, %loop]
236 store volatile i32 0, i32* %loc
237 %iv.next = add i32 %iv, 1
238 %cmp = icmp slt i32 %iv, 200
239 br i1 %cmp, label %loop, label %exit
245 define void @neg_release(i32* %loc) {
246 ; CHECK-LABEL: @neg_release
248 ; CHECK: store atomic i32 0, i32* %loc release, align 4
254 %iv = phi i32 [0, %entry], [%iv.next, %loop]
255 store atomic i32 0, i32* %loc release, align 4
256 %iv.next = add i32 %iv, 1
257 %cmp = icmp slt i32 %iv, 200
258 br i1 %cmp, label %loop, label %exit
264 define void @neg_seq_cst(i32* %loc) {
265 ; CHECK-LABEL: @neg_seq_cst
267 ; CHECK: store atomic i32 0, i32* %loc seq_cst, align 4
273 %iv = phi i32 [0, %entry], [%iv.next, %loop]
274 store atomic i32 0, i32* %loc seq_cst, align 4
275 %iv.next = add i32 %iv, 1
276 %cmp = icmp slt i32 %iv, 200
277 br i1 %cmp, label %loop, label %exit
283 declare void @maythrow() inaccessiblememonly
285 define void @neg_early_exit(i32* %loc) {
286 ; CHECK-LABEL: @neg_early_exit
288 ; CHECK: store i32 0, i32* %loc
294 %iv = phi i32 [0, %entry], [%iv.next, %body]
295 %is_null = icmp eq i32* %loc, null
296 br i1 %is_null, label %exit, label %body
298 call void @maythrow()
299 store i32 0, i32* %loc
300 %iv.next = add i32 %iv, 1
301 %cmp = icmp slt i32 %iv, 200
302 br i1 %cmp, label %loop, label %exit
308 define void @neg_early_throw(i32* %loc) {
309 ; CHECK-LABEL: @neg_early_throw
311 ; CHECK: store i32 0, i32* %loc
317 %iv = phi i32 [0, %entry], [%iv.next, %loop]
318 call void @maythrow()
319 store i32 0, i32* %loc
320 %iv.next = add i32 %iv, 1
321 %cmp = icmp slt i32 %iv, 200
322 br i1 %cmp, label %loop, label %exit
328 define void @test_late_throw(i32* %loc) {
329 ; CHECK-LABEL: @test_late_throw
330 ; CHECK-LABEL: entry:
331 ; CHECK: store i32 0, i32* %loc
337 %iv = phi i32 [0, %entry], [%iv.next, %loop]
338 store i32 0, i32* %loc
339 call void @maythrow()
340 %iv.next = add i32 %iv, 1
341 %cmp = icmp slt i32 %iv, 200
342 br i1 %cmp, label %loop, label %exit
348 ; TODO: could validly hoist the store here since we know what value
349 ; the load must observe.
350 define i32 @test_dominated_read(i32* %loc) {
351 ; CHECK-LABEL: @test_dominated_read
353 ; MSSA: store i32 0, i32* %loc
356 ; AST: store i32 0, i32* %loc
361 %iv = phi i32 [0, %entry], [%iv.next, %loop]
362 store i32 0, i32* %loc
363 %reload = load i32, i32* %loc
364 %iv.next = add i32 %iv, 1
365 %cmp = icmp slt i32 %iv, 200
366 br i1 %cmp, label %loop, label %exit
372 ; TODO: could validly hoist the store since we already hoisted the load and
373 ; it's no longer in the loop.
374 define i32 @test_dominating_read(i32* %loc) {
375 ; CHECK-LABEL: @test_dominating_read
377 ; CHECK: store i32 0, i32* %loc
382 %iv = phi i32 [0, %entry], [%iv.next, %loop]
383 %reload = load i32, i32* %loc
384 store i32 0, i32* %loc
385 %iv.next = add i32 %iv, 1
386 %cmp = icmp slt i32 %iv, 200
387 br i1 %cmp, label %loop, label %exit
393 declare void @readonly() readonly
395 ; TODO: can legally hoist since value read by call is known
396 define void @test_dominated_readonly(i32* %loc) {
397 ; CHECK-LABEL: @test_dominated_readonly
399 ; CHECK: store i32 0, i32* %loc
405 %iv = phi i32 [0, %entry], [%iv.next, %loop]
406 store i32 0, i32* %loc
407 call void @readonly()
408 %iv.next = add i32 %iv, 1
409 %cmp = icmp slt i32 %iv, 200
410 br i1 %cmp, label %loop, label %exit
416 ; While technically possible to hoist the store to %loc, this runs across
417 ; a funemental limitation of alias sets since both stores and the call are
418 ; within the same alias set and we can't distinguish them cheaply.
419 define void @test_aliasset_fn(i32* %loc, i32* %loc2) {
420 ; CHECK-LABEL: @test_aliasset_fn
422 ; CHECK: store i32 0, i32* %loc
428 %iv = phi i32 [0, %entry], [%iv.next, %loop]
429 store i32 0, i32* %loc
430 call void @readonly()
431 store i32 %iv, i32* %loc2
432 %iv.next = add i32 %iv, 1
433 %cmp = icmp slt i32 %iv, 200
434 br i1 %cmp, label %loop, label %exit
441 ; If we can't tell if the value is read before the write, we can't hoist the
442 ; write over the potential read (since we don't know the value read)
443 define void @neg_may_read(i32* %loc, i1 %maybe) {
444 ; CHECK-LABEL: @neg_may_read
446 ; CHECK: store i32 0, i32* %loc
452 %iv = phi i32 [0, %entry], [%iv.next, %merge]
453 ;; maybe is a placeholder for an unanalyzable condition
454 br i1 %maybe, label %taken, label %merge
456 call void @readonly()
459 store i32 0, i32* %loc
460 %iv.next = add i32 %iv, 1
461 %cmp = icmp slt i32 %iv, 200
462 br i1 %cmp, label %loop, label %exit