[ARM] Better OR's for MVE compares
[llvm-core.git] / test / Transforms / LICM / hoist-mustexec.ll
blob521d35296572062525061205020274794cd65a8a
1 ; REQUIRES: asserts
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(
13 entry:
14 ; CHECK: %i1 = load i32, i32* %a, align 4
15 ; CHECK-NEXT: br label %for.body
16   br label %for.body
18 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
23 continue:
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
30 for.cond.cleanup:
31   ret i32 %add
33 fail:
34   call void @f()
35   ret i32 -1
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(
41 entry:
42 ; CHECK: %i1 = load i32, i32* %a, align 4
43 ; CHECK-NEXT: br label %for.body
44   br label %for.body
46 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
51 continue:
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
58 for.cond.cleanup:
59   ret i32 %add
61 fail:
62   call void @f()
63   ret i32 -1
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(
71 entry:
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
75 preheader:
76   %lenminusone = add nsw i32 %len, -1
77   br label %for.body
78 for.body:
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
83 continue:
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
92 for.cond.cleanup:
93   ret i32 %add
95 fail:
96   call void @f()
97   ret i32 -1
100 ; trivially true for zero
101 define i32 @test3(i32* noalias nocapture readonly %a) nounwind uwtable {
102 ; CHECK-LABEL: @test3(
103 entry:
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
107 preheader:
108 ; CHECK: %i1 = load i32, i32* %a, align 4
109 ; CHECK-NEXT: br label %for.body
110   br label %for.body
111 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
116 continue:
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
123 for.cond.cleanup:
124   ret i32 %add
126 fail:
127   call void @f()
128   ret i32 -1
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(
136 ; CHECK-NEXT:  entry:
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:%.*]]
140 ; CHECK:       preheader:
141 ; CHECK-NEXT:    br label [[FOR_BODY:%.*]]
142 ; CHECK:       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:%.*]]
147 ; CHECK:       continue:
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]]
158 ; CHECK:       fail:
159 ; CHECK-NEXT:    call void @f()
160 ; CHECK-NEXT:    ret i32 -1
162 entry:
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
166 preheader:
167   br label %for.body
168 for.body:
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
173 continue:
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
180 for.cond.cleanup:
181   ret i32 %add
183 fail:
184   call void @f()
185   ret i32 -1
188 ; variation on test1 with branch swapped
189 define i32 @test-brswap(i32* noalias nocapture readonly %a) nounwind uwtable {
190 ; CHECK-LABEL: @test-brswap(
191 entry:
192 ; CHECK: %i1 = load i32, i32* %a, align 4
193 ; CHECK-NEXT: br label %for.body
194   br label %for.body
196 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
201 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
208 for.cond.cleanup:
209   ret i32 %add
211 fail:
212   call void @f()
213   ret i32 -1
216 define i32 @test-nonphi(i32* noalias nocapture readonly %a) nounwind uwtable {
217 ; CHECK-LABEL: @test-nonphi(
218 entry:
219   br label %for.body
221 for.body:
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
229 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
236 for.cond.cleanup:
237   ret i32 %add
239 fail:
240   call void @f()
241   ret i32 -1
244 define i32 @test-wrongphi(i32* noalias nocapture readonly %a) nounwind uwtable {
245 ; CHECK-LABEL: @test-wrongphi(
246 entry:
247   br label %for.body
249 for.body:
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
255 dummy_block1:
256   br label %dummy_block2
258 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
262 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
271 for.cond.cleanup:
272   ret i32 %add
274 fail:
275   call void @f()
276   ret i32 -1
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(
282 entry:
283 ; CHECK: %i1 = load i32, i32* %a, align 4
284 ; CHECK-NEXT: br label %for.body
285   br label %for.body
287 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
292 continue1:
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
298 continue2:
299   %exitcond = icmp eq i32 %inc, 1000
300   br i1 %exitcond, label %for.cond.cleanup, label %for.body
302 for.cond.cleanup:
303   ret i32 %add
305 fail:
306   call void @f()
307   ret i32 -1
310 define void @test-hoisting-in-presence-of-guards(i1 %c, i32* %p) {
312 ; CHECK-LABEL: @test-hoisting-in-presence-of-guards
313 ; CHECK:       entry:
314 ; CHECK:         %a = load i32, i32* %p
315 ; CHECK:         %invariant_cond = icmp ne i32 %a, 100
316 ; CHECK:       loop:
318 entry:
319   br label %loop
321 loop:
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
330 exit:
331   ret void
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(
342 ; CHECK:       entry:
343 ; CHECK-NEXT:  %load = load i32, i32* %p
344 ; CHECK-NOT:   load i32
346 entry:
347   br label %loop
349 loop:
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
357 if.true:
358   %a = add i32 %iv, %iv
359   br label %backedge
361 if.false:
362   %b = mul i32 %iv, %iv
363   br label %backedge
365 backedge:
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
371 exit:
372   ret void
375 define void @test_hoist_from_header_02(i32* %p, i32 %n) {
377 ; CHECK-LABEL: @test_hoist_from_header_02(
378 ; CHECK:       entry:
379 ; CHECK-NEXT:  %load = load i32, i32* %p
380 ; CHECK-NOT:   load i32
382 entry:
383   br label %loop
385 loop:
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
392 if.true:
393   call void @may_throw()
394   %a = add i32 %iv, %iv
395   br label %backedge
397 if.false:
398   %b = mul i32 %iv, %iv
399   br label %backedge
401 backedge:
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
407 exit:
408   ret void
411 define void @test_hoist_from_header_03(i32* %p, i32 %n) {
413 ; CHECK-LABEL: @test_hoist_from_header_03(
414 ; CHECK:       entry:
415 ; CHECK-NEXT:  %load = load i32, i32* %p
416 ; CHECK-NOT:   load i32
418 entry:
419   br label %loop
421 loop:
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
428 if.true:
429   %a = add i32 %iv, %iv
430   br label %backedge
432 if.false:
433   %b = mul i32 %iv, %iv
434   br label %backedge
436 backedge:
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
443 exit:
444   ret void
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(
451 ; CHECK:       entry:
452 ; CHECK:       loop:
453 ; CHECK:       %load = load i32, i32* %p
455 entry:
456   br label %loop
458 loop:
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
466 if.true:
467   %a = add i32 %iv, %iv
468   br label %backedge
470 if.false:
471   %b = mul i32 %iv, %iv
472   br label %backedge
474 backedge:
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
480 exit:
481   ret void
484 ; Check that we can hoist a mustexecute load from backedge even if something
485 ; throws after it.
486 define void @test_hoist_from_backedge_01(i32* %p, i32 %n) {
488 ; CHECK-LABEL: @test_hoist_from_backedge_01(
489 ; CHECK:       entry:
490 ; CHECK-NEXT:  %load = load i32, i32* %p
491 ; CHECK-NOT:   load i32
493 entry:
494   br label %loop
496 loop:
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
502 if.true:
503   %a = add i32 %iv, %iv
504   br label %backedge
506 if.false:
507   %b = mul i32 %iv, %iv
508   br label %backedge
510 backedge:
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
518 exit:
519   ret void
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(
526 ; CHECK:       entry:
527 ; CHECK:       loop:
528 ; CHECK:       %load = load i32, i32* %p
530 entry:
531   br label %loop
533 loop:
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
539 if.true:
540   %a = add i32 %iv, %iv
541   br label %backedge
543 if.false:
544   %b = mul i32 %iv, %iv
545   br label %backedge
547 backedge:
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
555 exit:
556   ret void
559 define void @test_hoist_from_backedge_03(i32* %p, i32 %n) {
561 ; CHECK-LABEL: @test_hoist_from_backedge_03(
562 ; CHECK:       entry:
563 ; CHECK:       loop:
564 ; CHECK:       %load = load i32, i32* %p
566 entry:
567   br label %loop
569 loop:
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
575 if.true:
576   %a = add i32 %iv, %iv
577   br label %backedge
579 if.false:
580   %b = mul i32 %iv, %iv
581   call void @may_throw()
582   br label %backedge
584 backedge:
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
591 exit:
592   ret void
595 define void @test_hoist_from_backedge_04(i32* %p, i32 %n) {
597 ; CHECK-LABEL: @test_hoist_from_backedge_04(
598 ; CHECK:       entry:
599 ; CHECK:       loop:
600 ; CHECK:       %load = load i32, i32* %p
602 entry:
603   br label %loop
605 loop:
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
612 if.true:
613   %a = add i32 %iv, %iv
614   br label %backedge
616 if.false:
617   %b = mul i32 %iv, %iv
618   br label %backedge
620 backedge:
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
627 exit:
628   ret void