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 ; CHECK: store i32 0, i32* %loc
357 %iv = phi i32 [0, %entry], [%iv.next, %loop]
358 store i32 0, i32* %loc
359 %reload = load i32, i32* %loc
360 %iv.next = add i32 %iv, 1
361 %cmp = icmp slt i32 %iv, 200
362 br i1 %cmp, label %loop, label %exit
368 ; TODO: could validly hoist the store since we already hoisted the load and
369 ; it's no longer in the loop.
370 define i32 @test_dominating_read(i32* %loc) {
371 ; CHECK-LABEL: @test_dominating_read
373 ; CHECK: store i32 0, i32* %loc
378 %iv = phi i32 [0, %entry], [%iv.next, %loop]
379 %reload = load i32, i32* %loc
380 store i32 0, i32* %loc
381 %iv.next = add i32 %iv, 1
382 %cmp = icmp slt i32 %iv, 200
383 br i1 %cmp, label %loop, label %exit
389 declare void @readonly() readonly
391 ; TODO: can legally hoist since value read by call is known
392 define void @test_dominated_readonly(i32* %loc) {
393 ; CHECK-LABEL: @test_dominated_readonly
395 ; CHECK: store i32 0, i32* %loc
401 %iv = phi i32 [0, %entry], [%iv.next, %loop]
402 store i32 0, i32* %loc
403 call void @readonly()
404 %iv.next = add i32 %iv, 1
405 %cmp = icmp slt i32 %iv, 200
406 br i1 %cmp, label %loop, label %exit
412 ; While technically possible to hoist the store to %loc, this runs across
413 ; a funemental limitation of alias sets since both stores and the call are
414 ; within the same alias set and we can't distinguish them cheaply.
415 define void @test_aliasset_fn(i32* %loc, i32* %loc2) {
416 ; CHECK-LABEL: @test_aliasset_fn
418 ; CHECK: store i32 0, i32* %loc
424 %iv = phi i32 [0, %entry], [%iv.next, %loop]
425 store i32 0, i32* %loc
426 call void @readonly()
427 store i32 %iv, i32* %loc2
428 %iv.next = add i32 %iv, 1
429 %cmp = icmp slt i32 %iv, 200
430 br i1 %cmp, label %loop, label %exit
437 ; If we can't tell if the value is read before the write, we can't hoist the
438 ; write over the potential read (since we don't know the value read)
439 define void @neg_may_read(i32* %loc, i1 %maybe) {
440 ; CHECK-LABEL: @neg_may_read
442 ; CHECK: store i32 0, i32* %loc
448 %iv = phi i32 [0, %entry], [%iv.next, %merge]
449 ;; maybe is a placeholder for an unanalyzable condition
450 br i1 %maybe, label %taken, label %merge
452 call void @readonly()
455 store i32 0, i32* %loc
456 %iv.next = add i32 %iv, 1
457 %cmp = icmp slt i32 %iv, 200
458 br i1 %cmp, label %loop, label %exit