1 ; RUN: opt -S -basic-aa -licm %s -enable-new-pm=0 | FileCheck %s
2 ; RUN: opt -aa-pipeline=basic-aa -passes='require<aa>,require<targetir>,require<scalar-evolution>,require<opt-remark-emit>,loop-mssa(licm)' < %s -S | FileCheck %s
4 define void @test(i32* %loc) {
7 ; CHECK: store i32 0, i32* %loc
13 %iv = phi i32 [0, %entry], [%iv.next, %loop]
14 store i32 0, i32* %loc
15 %iv.next = add i32 %iv, 1
16 %cmp = icmp slt i32 %iv, 200
17 br i1 %cmp, label %loop, label %exit
23 define void @test_multiexit(i32* %loc, i1 %earlycnd) {
24 ; CHECK-LABEL: @test_multiexit
26 ; CHECK: store i32 0, i32* %loc
32 %iv = phi i32 [0, %entry], [%iv.next, %backedge]
33 store i32 0, i32* %loc
34 %iv.next = add i32 %iv, 1
35 br i1 %earlycnd, label %exit1, label %backedge
38 %cmp = icmp slt i32 %iv, 200
39 br i1 %cmp, label %loop, label %exit2
47 define i32* @false_negative_2use(i32* %loc) {
48 ; CHECK-LABEL: @false_negative_2use
50 ; CHECK: store i32 0, i32* %loc
56 %iv = phi i32 [0, %entry], [%iv.next, %loop]
57 store i32 0, i32* %loc
58 %iv.next = add i32 %iv, 1
59 %cmp = icmp slt i32 %iv, 200
60 br i1 %cmp, label %loop, label %exit
66 define void @neg_lv_value(i32* %loc) {
67 ; CHECK-LABEL: @neg_lv_value
69 ; CHECK: store i32 %iv.lcssa, i32* %loc
74 %iv = phi i32 [0, %entry], [%iv.next, %loop]
75 store i32 %iv, i32* %loc
76 %iv.next = add i32 %iv, 1
77 %cmp = icmp slt i32 %iv, 200
78 br i1 %cmp, label %loop, label %exit
84 define void @neg_lv_addr(i32* %loc) {
85 ; CHECK-LABEL: @neg_lv_addr
87 ; CHECK: store i32 0, i32* %p
93 %iv = phi i32 [0, %entry], [%iv.next, %loop]
94 %p = getelementptr i32, i32* %loc, i32 %iv
96 %iv.next = add i32 %iv, 1
97 %cmp = icmp slt i32 %iv, 200
98 br i1 %cmp, label %loop, label %exit
104 define void @neg_mod(i32* %loc) {
105 ; CHECK-LABEL: @neg_mod
107 ; CHECK: store i32 %iv.lcssa, i32* %loc
112 %iv = phi i32 [0, %entry], [%iv.next, %loop]
113 store i32 0, i32* %loc
114 store i32 %iv, i32* %loc
115 %iv.next = add i32 %iv, 1
116 %cmp = icmp slt i32 %iv, 200
117 br i1 %cmp, label %loop, label %exit
123 ; Hoisting the store is actually valid here, as it dominates the load.
124 define void @neg_ref(i32* %loc) {
125 ; CHECK-LABEL: @neg_ref
126 ; CHECK-LABEL: exit1:
127 ; CHECK: store i32 0, i32* %loc
128 ; CHECK-LABEL: exit2:
129 ; CHECK: store i32 0, i32* %loc
134 %iv = phi i32 [0, %entry], [%iv.next, %backedge]
135 store i32 0, i32* %loc
136 %v = load i32, i32* %loc
137 %earlycnd = icmp eq i32 %v, 198
138 br i1 %earlycnd, label %exit1, label %backedge
141 %iv.next = add i32 %iv, 1
142 %cmp = icmp slt i32 %iv, 200
143 br i1 %cmp, label %loop, label %exit2
151 ; Hoisting the store here leads to a miscompile.
152 define void @neg_ref2(i32* %loc) {
153 ; CHECK-LABEL: @neg_ref2
154 ; CHECK-LABEL: exit1:
155 ; CHECK: store i32 0, i32* %loc
156 ; CHECK-LABEL: exit2:
157 ; CHECK: store i32 0, i32* %loc
159 store i32 198, i32* %loc
163 %iv = phi i32 [0, %entry], [%iv.next, %backedge]
164 %v = load i32, i32* %loc
165 store i32 0, i32* %loc
166 %earlycnd = icmp eq i32 %v, 198
167 br i1 %earlycnd, label %exit1, label %backedge
170 %iv.next = add i32 %iv, 1
171 %cmp = icmp slt i32 %iv, 200
172 br i1 %cmp, label %loop, label %exit2
180 declare void @modref()
182 define void @neg_modref(i32* %loc) {
183 ; CHECK-LABEL: @neg_modref
185 ; CHECK: store i32 0, i32* %loc
191 %iv = phi i32 [0, %entry], [%iv.next, %loop]
192 store i32 0, i32* %loc
194 %iv.next = add i32 %iv, 1
195 %cmp = icmp slt i32 %iv, 200
196 br i1 %cmp, label %loop, label %exit
202 define void @neg_fence(i32* %loc) {
203 ; CHECK-LABEL: @neg_fence
205 ; CHECK: store i32 0, i32* %loc
211 %iv = phi i32 [0, %entry], [%iv.next, %loop]
212 store i32 0, i32* %loc
214 %iv.next = add i32 %iv, 1
215 %cmp = icmp slt i32 %iv, 200
216 br i1 %cmp, label %loop, label %exit
222 define void @neg_volatile(i32* %loc) {
223 ; CHECK-LABEL: @neg_volatile
225 ; CHECK: store volatile i32 0, i32* %loc
231 %iv = phi i32 [0, %entry], [%iv.next, %loop]
232 store volatile i32 0, i32* %loc
233 %iv.next = add i32 %iv, 1
234 %cmp = icmp slt i32 %iv, 200
235 br i1 %cmp, label %loop, label %exit
241 define void @neg_release(i32* %loc) {
242 ; CHECK-LABEL: @neg_release
244 ; CHECK: store atomic i32 0, i32* %loc release, align 4
250 %iv = phi i32 [0, %entry], [%iv.next, %loop]
251 store atomic i32 0, i32* %loc release, align 4
252 %iv.next = add i32 %iv, 1
253 %cmp = icmp slt i32 %iv, 200
254 br i1 %cmp, label %loop, label %exit
260 define void @neg_seq_cst(i32* %loc) {
261 ; CHECK-LABEL: @neg_seq_cst
263 ; CHECK: store atomic i32 0, i32* %loc seq_cst, align 4
269 %iv = phi i32 [0, %entry], [%iv.next, %loop]
270 store atomic i32 0, i32* %loc seq_cst, align 4
271 %iv.next = add i32 %iv, 1
272 %cmp = icmp slt i32 %iv, 200
273 br i1 %cmp, label %loop, label %exit
279 declare void @maythrow() inaccessiblememonly
281 define void @neg_early_exit(i32* %loc) {
282 ; CHECK-LABEL: @neg_early_exit
284 ; CHECK: store i32 0, i32* %loc
290 %iv = phi i32 [0, %entry], [%iv.next, %body]
291 %is_null = icmp eq i32* %loc, null
292 br i1 %is_null, label %exit, label %body
294 call void @maythrow()
295 store i32 0, i32* %loc
296 %iv.next = add i32 %iv, 1
297 %cmp = icmp slt i32 %iv, 200
298 br i1 %cmp, label %loop, label %exit
304 define void @neg_early_throw(i32* %loc) {
305 ; CHECK-LABEL: @neg_early_throw
307 ; CHECK: store i32 0, i32* %loc
313 %iv = phi i32 [0, %entry], [%iv.next, %loop]
314 call void @maythrow()
315 store i32 0, i32* %loc
316 %iv.next = add i32 %iv, 1
317 %cmp = icmp slt i32 %iv, 200
318 br i1 %cmp, label %loop, label %exit
324 define void @test_late_throw(i32* %loc) {
325 ; CHECK-LABEL: @test_late_throw
326 ; CHECK-LABEL: entry:
327 ; CHECK: store i32 0, i32* %loc
333 %iv = phi i32 [0, %entry], [%iv.next, %loop]
334 store i32 0, i32* %loc
335 call void @maythrow()
336 %iv.next = add i32 %iv, 1
337 %cmp = icmp slt i32 %iv, 200
338 br i1 %cmp, label %loop, label %exit
344 ; TODO: could validly hoist the store here since we know what value
345 ; the load must observe.
346 define i32 @test_dominated_read(i32* %loc) {
347 ; CHECK-LABEL: @test_dominated_read
348 ; CHECK-LABEL: entry:
349 ; CHECK: store i32 0, i32* %loc
355 %iv = phi i32 [0, %entry], [%iv.next, %loop]
356 store i32 0, i32* %loc
357 %reload = load i32, i32* %loc
358 %iv.next = add i32 %iv, 1
359 %cmp = icmp slt i32 %iv, 200
360 br i1 %cmp, label %loop, label %exit
366 ; TODO: could validly hoist the store since we already hoisted the load and
367 ; it's no longer in the loop.
368 define i32 @test_dominating_read(i32* %loc) {
369 ; CHECK-LABEL: @test_dominating_read
371 ; CHECK: store i32 0, i32* %loc
376 %iv = phi i32 [0, %entry], [%iv.next, %loop]
377 %reload = load i32, i32* %loc
378 store i32 0, i32* %loc
379 %iv.next = add i32 %iv, 1
380 %cmp = icmp slt i32 %iv, 200
381 br i1 %cmp, label %loop, label %exit
387 declare void @readonly() readonly
389 ; TODO: can legally hoist since value read by call is known
390 define void @test_dominated_readonly(i32* %loc) {
391 ; CHECK-LABEL: @test_dominated_readonly
393 ; CHECK: store i32 0, i32* %loc
399 %iv = phi i32 [0, %entry], [%iv.next, %loop]
400 store i32 0, i32* %loc
401 call void @readonly()
402 %iv.next = add i32 %iv, 1
403 %cmp = icmp slt i32 %iv, 200
404 br i1 %cmp, label %loop, label %exit
410 ; While technically possible to hoist the store to %loc, this runs across
411 ; a funemental limitation of alias sets since both stores and the call are
412 ; within the same alias set and we can't distinguish them cheaply.
413 define void @test_aliasset_fn(i32* %loc, i32* %loc2) {
414 ; CHECK-LABEL: @test_aliasset_fn
416 ; CHECK: store i32 0, i32* %loc
422 %iv = phi i32 [0, %entry], [%iv.next, %loop]
423 store i32 0, i32* %loc
424 call void @readonly()
425 store i32 %iv, i32* %loc2
426 %iv.next = add i32 %iv, 1
427 %cmp = icmp slt i32 %iv, 200
428 br i1 %cmp, label %loop, label %exit
435 ; If we can't tell if the value is read before the write, we can't hoist the
436 ; write over the potential read (since we don't know the value read)
437 define void @neg_may_read(i32* %loc, i1 %maybe) {
438 ; CHECK-LABEL: @neg_may_read
440 ; CHECK: store i32 0, i32* %loc
446 %iv = phi i32 [0, %entry], [%iv.next, %merge]
447 ;; maybe is a placeholder for an unanalyzable condition
448 br i1 %maybe, label %taken, label %merge
450 call void @readonly()
453 store i32 0, i32* %loc
454 %iv.next = add i32 %iv, 1
455 %cmp = icmp slt i32 %iv, 200
456 br i1 %cmp, label %loop, label %exit