1 ; RUN: opt -S -basicaa -licm %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
5 define void @test(i32* %loc) {
8 ; CHECK: store i32 0, i32* %loc
14 %iv = phi i32 [0, %entry], [%iv.next, %loop]
15 store i32 0, i32* %loc
16 %iv.next = add i32 %iv, 1
17 %cmp = icmp slt i32 %iv, 200
18 br i1 %cmp, label %loop, label %exit
24 define void @test_multiexit(i32* %loc, i1 %earlycnd) {
25 ; CHECK-LABEL: @test_multiexit
27 ; CHECK: store i32 0, i32* %loc
33 %iv = phi i32 [0, %entry], [%iv.next, %backedge]
34 store i32 0, i32* %loc
35 %iv.next = add i32 %iv, 1
36 br i1 %earlycnd, label %exit1, label %backedge
39 %cmp = icmp slt i32 %iv, 200
40 br i1 %cmp, label %loop, label %exit2
48 define i32* @false_negative_2use(i32* %loc) {
49 ; CHECK-LABEL: @false_negative_2use
51 ; AST: store i32 0, i32* %loc
53 ; MSSA: store i32 0, i32* %loc
59 %iv = phi i32 [0, %entry], [%iv.next, %loop]
60 store i32 0, i32* %loc
61 %iv.next = add i32 %iv, 1
62 %cmp = icmp slt i32 %iv, 200
63 br i1 %cmp, label %loop, label %exit
69 define void @neg_lv_value(i32* %loc) {
70 ; CHECK-LABEL: @neg_lv_value
72 ; CHECK: store i32 %iv.lcssa, i32* %loc
77 %iv = phi i32 [0, %entry], [%iv.next, %loop]
78 store i32 %iv, i32* %loc
79 %iv.next = add i32 %iv, 1
80 %cmp = icmp slt i32 %iv, 200
81 br i1 %cmp, label %loop, label %exit
87 define void @neg_lv_addr(i32* %loc) {
88 ; CHECK-LABEL: @neg_lv_addr
90 ; CHECK: store i32 0, i32* %p
96 %iv = phi i32 [0, %entry], [%iv.next, %loop]
97 %p = getelementptr i32, i32* %loc, i32 %iv
99 %iv.next = add i32 %iv, 1
100 %cmp = icmp slt i32 %iv, 200
101 br i1 %cmp, label %loop, label %exit
107 define void @neg_mod(i32* %loc) {
108 ; CHECK-LABEL: @neg_mod
110 ; CHECK: store i32 %iv.lcssa, i32* %loc
115 %iv = phi i32 [0, %entry], [%iv.next, %loop]
116 store i32 0, i32* %loc
117 store i32 %iv, i32* %loc
118 %iv.next = add i32 %iv, 1
119 %cmp = icmp slt i32 %iv, 200
120 br i1 %cmp, label %loop, label %exit
126 ; Hoisting the store is actually valid here, as it dominates the load.
127 define void @neg_ref(i32* %loc) {
128 ; CHECK-LABEL: @neg_ref
129 ; CHECK-LABEL: exit1:
130 ; CHECK: store i32 0, i32* %loc
131 ; CHECK-LABEL: exit2:
132 ; CHECK: store i32 0, i32* %loc
137 %iv = phi i32 [0, %entry], [%iv.next, %backedge]
138 store i32 0, i32* %loc
139 %v = load i32, i32* %loc
140 %earlycnd = icmp eq i32 %v, 198
141 br i1 %earlycnd, label %exit1, label %backedge
144 %iv.next = add i32 %iv, 1
145 %cmp = icmp slt i32 %iv, 200
146 br i1 %cmp, label %loop, label %exit2
154 ; Hoisting the store here leads to a miscompile.
155 define void @neg_ref2(i32* %loc) {
156 ; CHECK-LABEL: @neg_ref2
157 ; CHECK-LABEL: exit1:
158 ; CHECK: store i32 0, i32* %loc
159 ; CHECK-LABEL: exit2:
160 ; CHECK: store i32 0, i32* %loc
162 store i32 198, i32* %loc
166 %iv = phi i32 [0, %entry], [%iv.next, %backedge]
167 %v = load i32, i32* %loc
168 store i32 0, i32* %loc
169 %earlycnd = icmp eq i32 %v, 198
170 br i1 %earlycnd, label %exit1, label %backedge
173 %iv.next = add i32 %iv, 1
174 %cmp = icmp slt i32 %iv, 200
175 br i1 %cmp, label %loop, label %exit2
183 declare void @modref()
185 define void @neg_modref(i32* %loc) {
186 ; CHECK-LABEL: @neg_modref
188 ; CHECK: store i32 0, i32* %loc
194 %iv = phi i32 [0, %entry], [%iv.next, %loop]
195 store i32 0, i32* %loc
197 %iv.next = add i32 %iv, 1
198 %cmp = icmp slt i32 %iv, 200
199 br i1 %cmp, label %loop, label %exit
205 define void @neg_fence(i32* %loc) {
206 ; CHECK-LABEL: @neg_fence
208 ; CHECK: store i32 0, i32* %loc
214 %iv = phi i32 [0, %entry], [%iv.next, %loop]
215 store i32 0, i32* %loc
217 %iv.next = add i32 %iv, 1
218 %cmp = icmp slt i32 %iv, 200
219 br i1 %cmp, label %loop, label %exit
225 define void @neg_volatile(i32* %loc) {
226 ; CHECK-LABEL: @neg_volatile
228 ; CHECK: store volatile i32 0, i32* %loc
234 %iv = phi i32 [0, %entry], [%iv.next, %loop]
235 store volatile i32 0, i32* %loc
236 %iv.next = add i32 %iv, 1
237 %cmp = icmp slt i32 %iv, 200
238 br i1 %cmp, label %loop, label %exit
244 define void @neg_release(i32* %loc) {
245 ; CHECK-LABEL: @neg_release
247 ; CHECK: store atomic i32 0, i32* %loc release, align 4
253 %iv = phi i32 [0, %entry], [%iv.next, %loop]
254 store atomic i32 0, i32* %loc release, align 4
255 %iv.next = add i32 %iv, 1
256 %cmp = icmp slt i32 %iv, 200
257 br i1 %cmp, label %loop, label %exit
263 define void @neg_seq_cst(i32* %loc) {
264 ; CHECK-LABEL: @neg_seq_cst
266 ; CHECK: store atomic i32 0, i32* %loc seq_cst, align 4
272 %iv = phi i32 [0, %entry], [%iv.next, %loop]
273 store atomic i32 0, i32* %loc seq_cst, align 4
274 %iv.next = add i32 %iv, 1
275 %cmp = icmp slt i32 %iv, 200
276 br i1 %cmp, label %loop, label %exit
282 declare void @maythrow() inaccessiblememonly
284 define void @neg_early_exit(i32* %loc) {
285 ; CHECK-LABEL: @neg_early_exit
287 ; CHECK: store i32 0, i32* %loc
293 %iv = phi i32 [0, %entry], [%iv.next, %body]
294 %is_null = icmp eq i32* %loc, null
295 br i1 %is_null, label %exit, label %body
297 call void @maythrow()
298 store i32 0, i32* %loc
299 %iv.next = add i32 %iv, 1
300 %cmp = icmp slt i32 %iv, 200
301 br i1 %cmp, label %loop, label %exit
307 define void @neg_early_throw(i32* %loc) {
308 ; CHECK-LABEL: @neg_early_throw
310 ; CHECK: store i32 0, i32* %loc
316 %iv = phi i32 [0, %entry], [%iv.next, %loop]
317 call void @maythrow()
318 store i32 0, i32* %loc
319 %iv.next = add i32 %iv, 1
320 %cmp = icmp slt i32 %iv, 200
321 br i1 %cmp, label %loop, label %exit
327 define void @test_late_throw(i32* %loc) {
328 ; CHECK-LABEL: @test_late_throw
329 ; CHECK-LABEL: entry:
330 ; CHECK: store i32 0, i32* %loc
336 %iv = phi i32 [0, %entry], [%iv.next, %loop]
337 store i32 0, i32* %loc
338 call void @maythrow()
339 %iv.next = add i32 %iv, 1
340 %cmp = icmp slt i32 %iv, 200
341 br i1 %cmp, label %loop, label %exit
347 ; TODO: could validly hoist the store here since we know what value
348 ; the load must observe.
349 define i32 @test_dominated_read(i32* %loc) {
350 ; CHECK-LABEL: @test_dominated_read
352 ; MSSA: store i32 0, i32* %loc
355 ; AST: store i32 0, i32* %loc
360 %iv = phi i32 [0, %entry], [%iv.next, %loop]
361 store i32 0, i32* %loc
362 %reload = load i32, i32* %loc
363 %iv.next = add i32 %iv, 1
364 %cmp = icmp slt i32 %iv, 200
365 br i1 %cmp, label %loop, label %exit
371 ; TODO: could validly hoist the store since we already hoisted the load and
372 ; it's no longer in the loop.
373 define i32 @test_dominating_read(i32* %loc) {
374 ; CHECK-LABEL: @test_dominating_read
376 ; CHECK: store i32 0, i32* %loc
381 %iv = phi i32 [0, %entry], [%iv.next, %loop]
382 %reload = load i32, i32* %loc
383 store i32 0, i32* %loc
384 %iv.next = add i32 %iv, 1
385 %cmp = icmp slt i32 %iv, 200
386 br i1 %cmp, label %loop, label %exit
392 declare void @readonly() readonly
394 ; TODO: can legally hoist since value read by call is known
395 define void @test_dominated_readonly(i32* %loc) {
396 ; CHECK-LABEL: @test_dominated_readonly
398 ; CHECK: store i32 0, i32* %loc
404 %iv = phi i32 [0, %entry], [%iv.next, %loop]
405 store i32 0, i32* %loc
406 call void @readonly()
407 %iv.next = add i32 %iv, 1
408 %cmp = icmp slt i32 %iv, 200
409 br i1 %cmp, label %loop, label %exit
415 ; While technically possible to hoist the store to %loc, this runs across
416 ; a funemental limitation of alias sets since both stores and the call are
417 ; within the same alias set and we can't distinguish them cheaply.
418 define void @test_aliasset_fn(i32* %loc, i32* %loc2) {
419 ; CHECK-LABEL: @test_aliasset_fn
421 ; CHECK: store i32 0, i32* %loc
427 %iv = phi i32 [0, %entry], [%iv.next, %loop]
428 store i32 0, i32* %loc
429 call void @readonly()
430 store i32 %iv, i32* %loc2
431 %iv.next = add i32 %iv, 1
432 %cmp = icmp slt i32 %iv, 200
433 br i1 %cmp, label %loop, label %exit
440 ; If we can't tell if the value is read before the write, we can't hoist the
441 ; write over the potential read (since we don't know the value read)
442 define void @neg_may_read(i32* %loc, i1 %maybe) {
443 ; CHECK-LABEL: @neg_may_read
445 ; CHECK: store i32 0, i32* %loc
451 %iv = phi i32 [0, %entry], [%iv.next, %merge]
452 ;; maybe is a placeholder for an unanalyzable condition
453 br i1 %maybe, label %taken, label %merge
455 call void @readonly()
458 store i32 0, i32* %loc
459 %iv.next = add i32 %iv, 1
460 %cmp = icmp slt i32 %iv, 200
461 br i1 %cmp, label %loop, label %exit