2 ; RUN: opt -S -basicaa -licm -ipt-expensive-asserts=true < %s | FileCheck %s
3 ; RUN: opt -aa-pipeline=basic-aa -passes='require<opt-remark-emit>,loop(licm)' -ipt-expensive-asserts=true -S %s | FileCheck %s
4 target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
5 target triple = "x86_64-unknown-linux-gnu"
7 declare void @f() nounwind
8 declare void @llvm.experimental.guard(i1,...)
10 ; constant fold on first ieration
11 define i32 @test1(i32* noalias nocapture readonly %a) nounwind uwtable {
12 ; CHECK-LABEL: @test1(
14 ; CHECK: %i1 = load i32, i32* %a, align 4
15 ; CHECK-NEXT: br label %for.body
19 %iv = phi i32 [ 0, %entry ], [ %inc, %continue ]
20 %acc = phi i32 [ 0, %entry ], [ %add, %continue ]
21 %r.chk = icmp ult i32 %iv, 2000
22 br i1 %r.chk, label %continue, label %fail
24 %i1 = load i32, i32* %a, align 4
25 %add = add nsw i32 %i1, %acc
26 %inc = add nuw nsw i32 %iv, 1
27 %exitcond = icmp eq i32 %inc, 1000
28 br i1 %exitcond, label %for.cond.cleanup, label %for.body
38 ; Same as test1, but with a floating point IR and fcmp
39 define i32 @test_fcmp(i32* noalias nocapture readonly %a) nounwind uwtable {
40 ; CHECK-LABEL: @test_fcmp(
42 ; CHECK: %i1 = load i32, i32* %a, align 4
43 ; CHECK-NEXT: br label %for.body
47 %iv = phi float [ 0.0, %entry ], [ %inc, %continue ]
48 %acc = phi i32 [ 0, %entry ], [ %add, %continue ]
49 %r.chk = fcmp olt float %iv, 2000.0
50 br i1 %r.chk, label %continue, label %fail
52 %i1 = load i32, i32* %a, align 4
53 %add = add nsw i32 %i1, %acc
54 %inc = fadd float %iv, 1.0
55 %exitcond = fcmp ogt float %inc, 1000.0
56 br i1 %exitcond, label %for.cond.cleanup, label %for.body
66 ; Count down from a.length w/entry guard
67 ; TODO: currently unable to prove the following:
68 ; ule i32 (add nsw i32 %len, -1), %len where len is [0, 512]
69 define i32 @test2(i32* noalias nocapture readonly %a) nounwind uwtable {
70 ; CHECK-LABEL: @test2(
72 %len = load i32, i32* %a, align 4, !range !{i32 0, i32 512}
73 %is.non.pos = icmp eq i32 %len, 0
74 br i1 %is.non.pos, label %fail, label %preheader
76 %lenminusone = add nsw i32 %len, -1
79 %iv = phi i32 [ %lenminusone, %preheader ], [ %dec, %continue ]
80 %acc = phi i32 [ 0, %preheader ], [ %add, %continue ]
81 %r.chk = icmp ule i32 %iv, %len
82 br i1 %r.chk, label %continue, label %fail
84 ; CHECK-LABEL: continue
85 ; CHECK: %i1 = load i32, i32* %a, align 4
86 %i1 = load i32, i32* %a, align 4
87 %add = add nsw i32 %i1, %acc
88 %dec = add nsw i32 %iv, -1
89 %exitcond = icmp eq i32 %dec, 0
90 br i1 %exitcond, label %for.cond.cleanup, label %for.body
100 ; trivially true for zero
101 define i32 @test3(i32* noalias nocapture readonly %a) nounwind uwtable {
102 ; CHECK-LABEL: @test3(
104 %len = load i32, i32* %a, align 4, !range !{i32 0, i32 512}
105 %is.zero = icmp eq i32 %len, 0
106 br i1 %is.zero, label %fail, label %preheader
108 ; CHECK: %i1 = load i32, i32* %a, align 4
109 ; CHECK-NEXT: br label %for.body
112 %iv = phi i32 [ 0, %preheader ], [ %inc, %continue ]
113 %acc = phi i32 [ 0, %preheader ], [ %add, %continue ]
114 %r.chk = icmp ule i32 %iv, %len
115 br i1 %r.chk, label %continue, label %fail
117 %i1 = load i32, i32* %a, align 4
118 %add = add nsw i32 %i1, %acc
119 %inc = add nuw nsw i32 %iv, 1
120 %exitcond = icmp eq i32 %inc, 1000
121 br i1 %exitcond, label %for.cond.cleanup, label %for.body
131 ; requires fact length is non-zero
132 ; TODO: IsKnownNonNullFromDominatingConditions is currently only be done for
133 ; pointers; should handle integers too
134 define i32 @test4(i32* noalias nocapture readonly %a) nounwind uwtable {
135 ; CHECK-LABEL: @test4(
137 ; CHECK-NEXT: [[LEN:%.*]] = load i32, i32* [[A:%.*]], align 4, !range !0
138 ; CHECK-NEXT: [[IS_ZERO:%.*]] = icmp eq i32 [[LEN]], 0
139 ; CHECK-NEXT: br i1 [[IS_ZERO]], label [[FAIL:%.*]], label [[PREHEADER:%.*]]
141 ; CHECK-NEXT: br label [[FOR_BODY:%.*]]
143 ; CHECK-NEXT: [[IV:%.*]] = phi i32 [ 0, [[PREHEADER]] ], [ [[INC:%.*]], [[CONTINUE:%.*]] ]
144 ; CHECK-NEXT: [[ACC:%.*]] = phi i32 [ 0, [[PREHEADER]] ], [ [[ADD:%.*]], [[CONTINUE]] ]
145 ; CHECK-NEXT: [[R_CHK:%.*]] = icmp ult i32 [[IV]], [[LEN]]
146 ; CHECK-NEXT: br i1 [[R_CHK]], label [[CONTINUE]], label [[FAIL_LOOPEXIT:%.*]]
148 ; CHECK-NEXT: [[I1:%.*]] = load i32, i32* [[A]], align 4
149 ; CHECK-NEXT: [[ADD]] = add nsw i32 [[I1]], [[ACC]]
150 ; CHECK-NEXT: [[INC]] = add nuw nsw i32 [[IV]], 1
151 ; CHECK-NEXT: [[EXITCOND:%.*]] = icmp eq i32 [[INC]], 1000
152 ; CHECK-NEXT: br i1 [[EXITCOND]], label [[FOR_COND_CLEANUP:%.*]], label [[FOR_BODY]]
153 ; CHECK: for.cond.cleanup:
154 ; CHECK-NEXT: [[ADD_LCSSA:%.*]] = phi i32 [ [[ADD]], [[CONTINUE]] ]
155 ; CHECK-NEXT: ret i32 [[ADD_LCSSA]]
156 ; CHECK: fail.loopexit:
157 ; CHECK-NEXT: br label [[FAIL]]
159 ; CHECK-NEXT: call void @f()
160 ; CHECK-NEXT: ret i32 -1
163 %len = load i32, i32* %a, align 4, !range !{i32 0, i32 512}
164 %is.zero = icmp eq i32 %len, 0
165 br i1 %is.zero, label %fail, label %preheader
169 %iv = phi i32 [ 0, %preheader ], [ %inc, %continue ]
170 %acc = phi i32 [ 0, %preheader ], [ %add, %continue ]
171 %r.chk = icmp ult i32 %iv, %len
172 br i1 %r.chk, label %continue, label %fail
174 %i1 = load i32, i32* %a, align 4
175 %add = add nsw i32 %i1, %acc
176 %inc = add nuw nsw i32 %iv, 1
177 %exitcond = icmp eq i32 %inc, 1000
178 br i1 %exitcond, label %for.cond.cleanup, label %for.body
188 ; variation on test1 with branch swapped
189 define i32 @test-brswap(i32* noalias nocapture readonly %a) nounwind uwtable {
190 ; CHECK-LABEL: @test-brswap(
192 ; CHECK: %i1 = load i32, i32* %a, align 4
193 ; CHECK-NEXT: br label %for.body
197 %iv = phi i32 [ 0, %entry ], [ %inc, %continue ]
198 %acc = phi i32 [ 0, %entry ], [ %add, %continue ]
199 %r.chk = icmp ugt i32 %iv, 2000
200 br i1 %r.chk, label %fail, label %continue
202 %i1 = load i32, i32* %a, align 4
203 %add = add nsw i32 %i1, %acc
204 %inc = add nuw nsw i32 %iv, 1
205 %exitcond = icmp eq i32 %inc, 1000
206 br i1 %exitcond, label %for.cond.cleanup, label %for.body
216 define i32 @test-nonphi(i32* noalias nocapture readonly %a) nounwind uwtable {
217 ; CHECK-LABEL: @test-nonphi(
222 ; CHECK-LABEL: continue
223 ; CHECK: %i1 = load i32, i32* %a, align 4
224 %iv = phi i32 [ 0, %entry ], [ %inc, %continue ]
225 %acc = phi i32 [ 0, %entry ], [ %add, %continue ]
226 %xor = xor i32 %iv, 72
227 %r.chk = icmp ugt i32 %xor, 2000
228 br i1 %r.chk, label %fail, label %continue
230 %i1 = load i32, i32* %a, align 4
231 %add = add nsw i32 %i1, %acc
232 %inc = add nuw nsw i32 %iv, 1
233 %exitcond = icmp eq i32 %inc, 1000
234 br i1 %exitcond, label %for.cond.cleanup, label %for.body
244 define i32 @test-wrongphi(i32* noalias nocapture readonly %a) nounwind uwtable {
245 ; CHECK-LABEL: @test-wrongphi(
250 %iv = phi i32 [ 0, %entry ], [ %inc, %continue ]
251 %acc = phi i32 [ 0, %entry ], [ %add, %continue ]
252 %cond = icmp ult i32 %iv, 500
253 br i1 %cond, label %dummy_block1, label %dummy_block2
256 br label %dummy_block2
259 %wrongphi = phi i32 [11, %for.body], [12, %dummy_block1]
260 %r.chk = icmp ugt i32 %wrongphi, 2000
261 br i1 %r.chk, label %fail, label %continue
263 ; CHECK-LABEL: continue
264 ; CHECK: %i1 = load i32, i32* %a, align 4
265 %i1 = load i32, i32* %a, align 4
266 %add = add nsw i32 %i1, %acc
267 %inc = add nuw nsw i32 %iv, 1
268 %exitcond = icmp eq i32 %inc, 1000
269 br i1 %exitcond, label %for.cond.cleanup, label %for.body
279 ; This works because loop-simplify is run implicitly, but test for it anyways
280 define i32 @test-multiple-latch(i32* noalias nocapture readonly %a) nounwind uwtable {
281 ; CHECK-LABEL: @test-multiple-latch(
283 ; CHECK: %i1 = load i32, i32* %a, align 4
284 ; CHECK-NEXT: br label %for.body
288 %iv = phi i32 [ 0, %entry ], [ %inc, %continue1 ], [ %inc, %continue2 ]
289 %acc = phi i32 [ 0, %entry ], [ %add, %continue1 ], [ %add, %continue2 ]
290 %r.chk = icmp ult i32 %iv, 2000
291 br i1 %r.chk, label %continue1, label %fail
293 %i1 = load i32, i32* %a, align 4
294 %add = add nsw i32 %i1, %acc
295 %inc = add nuw nsw i32 %iv, 1
296 %cmp = icmp eq i32 %add, 0
297 br i1 %cmp, label %continue2, label %for.body
299 %exitcond = icmp eq i32 %inc, 1000
300 br i1 %exitcond, label %for.cond.cleanup, label %for.body
310 define void @test-hoisting-in-presence-of-guards(i1 %c, i32* %p) {
312 ; CHECK-LABEL: @test-hoisting-in-presence-of-guards
314 ; CHECK: %a = load i32, i32* %p
315 ; CHECK: %invariant_cond = icmp ne i32 %a, 100
322 %iv = phi i32 [ 0, %entry ], [ %iv.next, %loop ]
323 %iv.next = add i32 %iv, 1
324 %a = load i32, i32* %p
325 %invariant_cond = icmp ne i32 %a, 100
326 call void (i1, ...) @llvm.experimental.guard(i1 %invariant_cond) [ "deopt"() ]
327 %loop_cond = icmp slt i32 %iv.next, 1000
328 br i1 %loop_cond, label %loop, label %exit
335 declare void @may_throw() inaccessiblememonly
337 ; Test that we can sink a mustexecute load from loop header even in presence of
338 ; throwing instructions after it.
339 define void @test_hoist_from_header_01(i32* %p, i32 %n) {
341 ; CHECK-LABEL: @test_hoist_from_header_01(
343 ; CHECK-NEXT: %load = load i32, i32* %p
344 ; CHECK-NOT: load i32
350 %iv = phi i32 [ 0, %entry ], [ %iv.next, %backedge ]
351 %dummy = phi i32 [ 0, %entry ], [ %merge, %backedge ]
352 %load = load i32, i32* %p
353 call void @may_throw()
354 %cond = icmp slt i32 %iv, %n
355 br i1 %cond, label %if.true, label %if.false
358 %a = add i32 %iv, %iv
362 %b = mul i32 %iv, %iv
366 %merge = phi i32 [ %a, %if.true ], [ %b, %if.false ]
367 %iv.next = add i32 %iv, %merge
368 %loop.cond = icmp ult i32 %iv.next, %load
369 br i1 %loop.cond, label %loop, label %exit
375 define void @test_hoist_from_header_02(i32* %p, i32 %n) {
377 ; CHECK-LABEL: @test_hoist_from_header_02(
379 ; CHECK-NEXT: %load = load i32, i32* %p
380 ; CHECK-NOT: load i32
386 %iv = phi i32 [ 0, %entry ], [ %iv.next, %backedge ]
387 %dummy = phi i32 [ 0, %entry ], [ %merge, %backedge ]
388 %load = load i32, i32* %p
389 %cond = icmp slt i32 %iv, %n
390 br i1 %cond, label %if.true, label %if.false
393 call void @may_throw()
394 %a = add i32 %iv, %iv
398 %b = mul i32 %iv, %iv
402 %merge = phi i32 [ %a, %if.true ], [ %b, %if.false ]
403 %iv.next = add i32 %iv, %merge
404 %loop.cond = icmp ult i32 %iv.next, %load
405 br i1 %loop.cond, label %loop, label %exit
411 define void @test_hoist_from_header_03(i32* %p, i32 %n) {
413 ; CHECK-LABEL: @test_hoist_from_header_03(
415 ; CHECK-NEXT: %load = load i32, i32* %p
416 ; CHECK-NOT: load i32
422 %iv = phi i32 [ 0, %entry ], [ %iv.next, %backedge ]
423 %dummy = phi i32 [ 0, %entry ], [ %merge, %backedge ]
424 %load = load i32, i32* %p
425 %cond = icmp slt i32 %iv, %n
426 br i1 %cond, label %if.true, label %if.false
429 %a = add i32 %iv, %iv
433 %b = mul i32 %iv, %iv
437 %merge = phi i32 [ %a, %if.true ], [ %b, %if.false ]
438 call void @may_throw()
439 %iv.next = add i32 %iv, %merge
440 %loop.cond = icmp ult i32 %iv.next, %load
441 br i1 %loop.cond, label %loop, label %exit
447 ; Check that a throwing instruction prohibits hoisting across it.
448 define void @test_hoist_from_header_04(i32* %p, i32 %n) {
450 ; CHECK-LABEL: @test_hoist_from_header_04(
453 ; CHECK: %load = load i32, i32* %p
459 %iv = phi i32 [ 0, %entry ], [ %iv.next, %backedge ]
460 %dummy = phi i32 [ 0, %entry ], [ %merge, %backedge ]
461 call void @may_throw()
462 %load = load i32, i32* %p
463 %cond = icmp slt i32 %iv, %n
464 br i1 %cond, label %if.true, label %if.false
467 %a = add i32 %iv, %iv
471 %b = mul i32 %iv, %iv
475 %merge = phi i32 [ %a, %if.true ], [ %b, %if.false ]
476 %iv.next = add i32 %iv, %merge
477 %loop.cond = icmp ult i32 %iv.next, %load
478 br i1 %loop.cond, label %loop, label %exit
484 ; Check that we can hoist a mustexecute load from backedge even if something
486 define void @test_hoist_from_backedge_01(i32* %p, i32 %n) {
488 ; CHECK-LABEL: @test_hoist_from_backedge_01(
490 ; CHECK-NEXT: %load = load i32, i32* %p
491 ; CHECK-NOT: load i32
497 %iv = phi i32 [ 0, %entry ], [ %iv.next, %backedge ]
498 %dummy = phi i32 [ 0, %entry ], [ %merge, %backedge ]
499 %cond = icmp slt i32 %iv, %n
500 br i1 %cond, label %if.true, label %if.false
503 %a = add i32 %iv, %iv
507 %b = mul i32 %iv, %iv
511 %merge = phi i32 [ %a, %if.true ], [ %b, %if.false ]
512 %iv.next = add i32 %iv, %merge
513 %load = load i32, i32* %p
514 call void @may_throw()
515 %loop.cond = icmp ult i32 %iv.next, %load
516 br i1 %loop.cond, label %loop, label %exit
522 ; Check that we don't hoist the load if something before it can throw.
523 define void @test_hoist_from_backedge_02(i32* %p, i32 %n) {
525 ; CHECK-LABEL: @test_hoist_from_backedge_02(
528 ; CHECK: %load = load i32, i32* %p
534 %iv = phi i32 [ 0, %entry ], [ %iv.next, %backedge ]
535 %dummy = phi i32 [ 0, %entry ], [ %merge, %backedge ]
536 %cond = icmp slt i32 %iv, %n
537 br i1 %cond, label %if.true, label %if.false
540 %a = add i32 %iv, %iv
544 %b = mul i32 %iv, %iv
548 %merge = phi i32 [ %a, %if.true ], [ %b, %if.false ]
549 %iv.next = add i32 %iv, %merge
550 call void @may_throw()
551 %load = load i32, i32* %p
552 %loop.cond = icmp ult i32 %iv.next, %load
553 br i1 %loop.cond, label %loop, label %exit
559 define void @test_hoist_from_backedge_03(i32* %p, i32 %n) {
561 ; CHECK-LABEL: @test_hoist_from_backedge_03(
564 ; CHECK: %load = load i32, i32* %p
570 %iv = phi i32 [ 0, %entry ], [ %iv.next, %backedge ]
571 %dummy = phi i32 [ 0, %entry ], [ %merge, %backedge ]
572 %cond = icmp slt i32 %iv, %n
573 br i1 %cond, label %if.true, label %if.false
576 %a = add i32 %iv, %iv
580 %b = mul i32 %iv, %iv
581 call void @may_throw()
585 %merge = phi i32 [ %a, %if.true ], [ %b, %if.false ]
586 %iv.next = add i32 %iv, %merge
587 %load = load i32, i32* %p
588 %loop.cond = icmp ult i32 %iv.next, %load
589 br i1 %loop.cond, label %loop, label %exit
595 define void @test_hoist_from_backedge_04(i32* %p, i32 %n) {
597 ; CHECK-LABEL: @test_hoist_from_backedge_04(
600 ; CHECK: %load = load i32, i32* %p
606 %iv = phi i32 [ 0, %entry ], [ %iv.next, %backedge ]
607 %dummy = phi i32 [ 0, %entry ], [ %merge, %backedge ]
608 call void @may_throw()
609 %cond = icmp slt i32 %iv, %n
610 br i1 %cond, label %if.true, label %if.false
613 %a = add i32 %iv, %iv
617 %b = mul i32 %iv, %iv
621 %merge = phi i32 [ %a, %if.true ], [ %b, %if.false ]
622 %iv.next = add i32 %iv, %merge
623 %load = load i32, i32* %p
624 %loop.cond = icmp ult i32 %iv.next, %load
625 br i1 %loop.cond, label %loop, label %exit