1 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2 ; RUN: opt < %s -passes=correlated-propagation -S | FileCheck %s
4 define void @test0(i32 %a) {
7 ; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i32 [[A:%.*]], 100
8 ; CHECK-NEXT: br i1 [[CMP]], label [[BB:%.*]], label [[EXIT:%.*]]
10 ; CHECK-NEXT: [[SUB:%.*]] = sub nuw nsw i32 [[A]], 1
11 ; CHECK-NEXT: br label [[EXIT]]
13 ; CHECK-NEXT: ret void
16 %cmp = icmp sgt i32 %a, 100
17 br i1 %cmp, label %bb, label %exit
27 define void @test1(i32 %a) {
28 ; CHECK-LABEL: @test1(
30 ; CHECK-NEXT: [[CMP:%.*]] = icmp ugt i32 [[A:%.*]], 100
31 ; CHECK-NEXT: br i1 [[CMP]], label [[BB:%.*]], label [[EXIT:%.*]]
33 ; CHECK-NEXT: [[SUB:%.*]] = sub nuw i32 [[A]], 1
34 ; CHECK-NEXT: br label [[EXIT]]
36 ; CHECK-NEXT: ret void
39 %cmp = icmp ugt i32 %a, 100
40 br i1 %cmp, label %bb, label %exit
50 define void @test2(i32 %a) {
51 ; CHECK-LABEL: @test2(
53 ; CHECK-NEXT: [[CMP:%.*]] = icmp ugt i32 [[A:%.*]], -1
54 ; CHECK-NEXT: br i1 [[CMP]], label [[BB:%.*]], label [[EXIT:%.*]]
56 ; CHECK-NEXT: [[SUB:%.*]] = sub nuw nsw i32 [[A]], 1
57 ; CHECK-NEXT: br label [[EXIT]]
59 ; CHECK-NEXT: ret void
62 %cmp = icmp ugt i32 %a, -1
63 br i1 %cmp, label %bb, label %exit
73 define void @test3(i32 %a) {
74 ; CHECK-LABEL: @test3(
76 ; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i32 [[A:%.*]], -1
77 ; CHECK-NEXT: br i1 [[CMP]], label [[BB:%.*]], label [[EXIT:%.*]]
79 ; CHECK-NEXT: [[SUB:%.*]] = sub nsw i32 [[A]], 1
80 ; CHECK-NEXT: br label [[EXIT]]
82 ; CHECK-NEXT: ret void
85 %cmp = icmp sgt i32 %a, -1
86 br i1 %cmp, label %bb, label %exit
96 define void @test4(i32 %a) {
97 ; CHECK-LABEL: @test4(
99 ; CHECK-NEXT: [[CMP:%.*]] = icmp ugt i32 [[A:%.*]], 2147483647
100 ; CHECK-NEXT: br i1 [[CMP]], label [[BB:%.*]], label [[EXIT:%.*]]
102 ; CHECK-NEXT: [[SUB:%.*]] = sub nuw i32 [[A]], 1
103 ; CHECK-NEXT: br label [[EXIT]]
105 ; CHECK-NEXT: ret void
108 %cmp = icmp ugt i32 %a, 2147483647
109 br i1 %cmp, label %bb, label %exit
119 define void @test5(i32 %a) {
120 ; CHECK-LABEL: @test5(
122 ; CHECK-NEXT: [[CMP:%.*]] = icmp sle i32 [[A:%.*]], 2147483647
123 ; CHECK-NEXT: br i1 [[CMP]], label [[BB:%.*]], label [[EXIT:%.*]]
125 ; CHECK-NEXT: [[SUB:%.*]] = sub i32 [[A]], 1
126 ; CHECK-NEXT: br label [[EXIT]]
128 ; CHECK-NEXT: ret void
131 %cmp = icmp sle i32 %a, 2147483647
132 br i1 %cmp, label %bb, label %exit
142 ; Check for a corner case where an integer value is represented with a constant
143 ; LVILatticeValue instead of constantrange. Check that we don't fail with an
144 ; assertion in this case.
145 @b = global i32 0, align 4
146 define void @test6(i32 %a) {
147 ; CHECK-LABEL: @test6(
149 ; CHECK-NEXT: [[SUB:%.*]] = sub i32 [[A:%.*]], ptrtoint (ptr @b to i32)
150 ; CHECK-NEXT: ret void
153 %sub = sub i32 %a, ptrtoint (ptr @b to i32)
157 ; Check that we can gather information for conditions in the form of
158 ; and ( i s< 100, Unknown )
159 define void @test7(i32 %a, i1 %flag) {
160 ; CHECK-LABEL: @test7(
162 ; CHECK-NEXT: [[CMP_1:%.*]] = icmp ugt i32 [[A:%.*]], 100
163 ; CHECK-NEXT: [[CMP:%.*]] = and i1 [[CMP_1]], [[FLAG:%.*]]
164 ; CHECK-NEXT: br i1 [[CMP]], label [[BB:%.*]], label [[EXIT:%.*]]
166 ; CHECK-NEXT: [[SUB:%.*]] = sub nuw i32 [[A]], 1
167 ; CHECK-NEXT: br label [[EXIT]]
169 ; CHECK-NEXT: ret void
172 %cmp.1 = icmp ugt i32 %a, 100
173 %cmp = and i1 %cmp.1, %flag
174 br i1 %cmp, label %bb, label %exit
184 ; Check that we can gather information for conditions in the form of
185 ; and ( i s< 100, i s> 0 )
186 define void @test8(i32 %a) {
187 ; CHECK-LABEL: @test8(
189 ; CHECK-NEXT: [[CMP_1:%.*]] = icmp slt i32 [[A:%.*]], 100
190 ; CHECK-NEXT: [[CMP_2:%.*]] = icmp sgt i32 [[A]], 0
191 ; CHECK-NEXT: [[CMP:%.*]] = and i1 [[CMP_1]], [[CMP_2]]
192 ; CHECK-NEXT: br i1 [[CMP]], label [[BB:%.*]], label [[EXIT:%.*]]
194 ; CHECK-NEXT: [[SUB:%.*]] = sub nuw nsw i32 [[A]], 1
195 ; CHECK-NEXT: br label [[EXIT]]
197 ; CHECK-NEXT: ret void
200 %cmp.1 = icmp slt i32 %a, 100
201 %cmp.2 = icmp sgt i32 %a, 0
202 %cmp = and i1 %cmp.1, %cmp.2
203 br i1 %cmp, label %bb, label %exit
213 ; Check that for conditions in the form of cond1 && cond2 we don't mistakenly
214 ; assume that !cond1 && !cond2 holds down to false path.
215 define void @test8_neg(i32 %a) {
216 ; CHECK-LABEL: @test8_neg(
218 ; CHECK-NEXT: [[CMP_1:%.*]] = icmp sge i32 [[A:%.*]], 100
219 ; CHECK-NEXT: [[CMP_2:%.*]] = icmp sle i32 [[A]], 0
220 ; CHECK-NEXT: [[CMP:%.*]] = and i1 [[CMP_1]], [[CMP_2]]
221 ; CHECK-NEXT: br i1 [[CMP]], label [[EXIT:%.*]], label [[BB:%.*]]
223 ; CHECK-NEXT: [[SUB:%.*]] = sub i32 [[A]], 1
224 ; CHECK-NEXT: br label [[EXIT]]
226 ; CHECK-NEXT: ret void
229 %cmp.1 = icmp sge i32 %a, 100
230 %cmp.2 = icmp sle i32 %a, 0
231 %cmp = and i1 %cmp.1, %cmp.2
232 br i1 %cmp, label %exit, label %bb
242 ; Check that we can gather information for conditions in the form of
243 ; and ( i s< 100, and (i s> 0, Unknown )
244 define void @test9(i32 %a, i1 %flag) {
245 ; CHECK-LABEL: @test9(
247 ; CHECK-NEXT: [[CMP_1:%.*]] = icmp slt i32 [[A:%.*]], 100
248 ; CHECK-NEXT: [[CMP_2:%.*]] = icmp sgt i32 [[A]], 0
249 ; CHECK-NEXT: [[CMP_3:%.*]] = and i1 [[CMP_2]], [[FLAG:%.*]]
250 ; CHECK-NEXT: [[CMP:%.*]] = and i1 [[CMP_1]], [[CMP_3]]
251 ; CHECK-NEXT: br i1 [[CMP]], label [[BB:%.*]], label [[EXIT:%.*]]
253 ; CHECK-NEXT: [[SUB:%.*]] = sub nuw nsw i32 [[A]], 1
254 ; CHECK-NEXT: br label [[EXIT]]
256 ; CHECK-NEXT: ret void
259 %cmp.1 = icmp slt i32 %a, 100
260 %cmp.2 = icmp sgt i32 %a, 0
261 %cmp.3 = and i1 %cmp.2, %flag
262 %cmp = and i1 %cmp.1, %cmp.3
263 br i1 %cmp, label %bb, label %exit
273 ; Check that we can gather information for conditions in the form of
274 ; and ( i s> Unknown, ... )
275 define void @test10(i32 %a, i32 %b, i1 %flag) {
276 ; CHECK-LABEL: @test10(
278 ; CHECK-NEXT: [[CMP_1:%.*]] = icmp sgt i32 [[A:%.*]], [[B:%.*]]
279 ; CHECK-NEXT: [[CMP:%.*]] = and i1 [[CMP_1]], [[FLAG:%.*]]
280 ; CHECK-NEXT: br i1 [[CMP]], label [[BB:%.*]], label [[EXIT:%.*]]
282 ; CHECK-NEXT: [[SUB:%.*]] = sub nsw i32 [[A]], 1
283 ; CHECK-NEXT: br label [[EXIT]]
285 ; CHECK-NEXT: ret void
288 %cmp.1 = icmp sgt i32 %a, %b
289 %cmp = and i1 %cmp.1, %flag
290 br i1 %cmp, label %bb, label %exit
300 @limit = external global i32
301 define i32 @test11(ptr %p, i32 %i) {
302 ; CHECK-LABEL: @test11(
303 ; CHECK-NEXT: [[LIMIT:%.*]] = load i32, ptr [[P:%.*]], !range !0
304 ; CHECK-NEXT: [[WITHIN_1:%.*]] = icmp slt i32 [[LIMIT]], [[I:%.*]]
305 ; CHECK-NEXT: [[I_MINUS_7:%.*]] = add i32 [[I]], -7
306 ; CHECK-NEXT: [[WITHIN_2:%.*]] = icmp slt i32 [[LIMIT]], [[I_MINUS_7]]
307 ; CHECK-NEXT: [[WITHIN:%.*]] = and i1 [[WITHIN_1]], [[WITHIN_2]]
308 ; CHECK-NEXT: br i1 [[WITHIN]], label [[THEN:%.*]], label [[ELSE:%.*]]
310 ; CHECK-NEXT: [[I_MINUS_6:%.*]] = sub nuw nsw i32 [[I]], 6
311 ; CHECK-NEXT: ret i32 [[I_MINUS_6]]
313 ; CHECK-NEXT: ret i32 0
315 %limit = load i32, ptr %p, !range !{i32 0, i32 2147483647}
316 %within.1 = icmp slt i32 %limit, %i
317 %i.minus.7 = add i32 %i, -7
318 %within.2 = icmp slt i32 %limit, %i.minus.7
319 %within = and i1 %within.1, %within.2
320 br i1 %within, label %then, label %else
323 %i.minus.6 = sub i32 %i, 6
330 ; Check that we can gather information for conditions is the form of
331 ; or ( i s<= -100, Unknown )
332 define void @test12(i32 %a, i1 %flag) {
333 ; CHECK-LABEL: @test12(
335 ; CHECK-NEXT: [[CMP_1:%.*]] = icmp sle i32 [[A:%.*]], -100
336 ; CHECK-NEXT: [[CMP:%.*]] = or i1 [[CMP_1]], [[FLAG:%.*]]
337 ; CHECK-NEXT: br i1 [[CMP]], label [[EXIT:%.*]], label [[BB:%.*]]
339 ; CHECK-NEXT: [[SUB:%.*]] = sub nsw i32 [[A]], 1
340 ; CHECK-NEXT: br label [[EXIT]]
342 ; CHECK-NEXT: ret void
345 %cmp.1 = icmp sle i32 %a, -100
346 %cmp = or i1 %cmp.1, %flag
347 br i1 %cmp, label %exit, label %bb
357 ; Check that we can gather information for conditions is the form of
358 ; or ( i s>= 100, i s<= 0 )
359 define void @test13(i32 %a) {
360 ; CHECK-LABEL: @test13(
362 ; CHECK-NEXT: [[CMP_1:%.*]] = icmp sge i32 [[A:%.*]], 100
363 ; CHECK-NEXT: [[CMP_2:%.*]] = icmp sle i32 [[A]], 0
364 ; CHECK-NEXT: [[CMP:%.*]] = or i1 [[CMP_1]], [[CMP_2]]
365 ; CHECK-NEXT: br i1 [[CMP]], label [[EXIT:%.*]], label [[BB:%.*]]
367 ; CHECK-NEXT: [[SUB:%.*]] = sub nuw nsw i32 [[A]], 1
368 ; CHECK-NEXT: br label [[EXIT]]
370 ; CHECK-NEXT: ret void
373 %cmp.1 = icmp sge i32 %a, 100
374 %cmp.2 = icmp sle i32 %a, 0
375 %cmp = or i1 %cmp.1, %cmp.2
376 br i1 %cmp, label %exit, label %bb
386 ; Check that for conditions is the form of cond1 || cond2 we don't mistakenly
387 ; assume that cond1 || cond2 holds down to true path.
388 define void @test13_neg(i32 %a) {
389 ; CHECK-LABEL: @test13_neg(
391 ; CHECK-NEXT: [[CMP_1:%.*]] = icmp slt i32 [[A:%.*]], 100
392 ; CHECK-NEXT: [[CMP_2:%.*]] = icmp sgt i32 [[A]], 0
393 ; CHECK-NEXT: [[CMP:%.*]] = or i1 [[CMP_1]], [[CMP_2]]
394 ; CHECK-NEXT: br i1 [[CMP]], label [[BB:%.*]], label [[EXIT:%.*]]
396 ; CHECK-NEXT: [[SUB:%.*]] = sub i32 [[A]], 1
397 ; CHECK-NEXT: br label [[EXIT]]
399 ; CHECK-NEXT: ret void
402 %cmp.1 = icmp slt i32 %a, 100
403 %cmp.2 = icmp sgt i32 %a, 0
404 %cmp = or i1 %cmp.1, %cmp.2
405 br i1 %cmp, label %bb, label %exit
415 ; Check that we can gather information for conditions is the form of
416 ; or ( i s>=100, or (i s<= 0, Unknown )
417 define void @test14(i32 %a, i1 %flag) {
418 ; CHECK-LABEL: @test14(
420 ; CHECK-NEXT: [[CMP_1:%.*]] = icmp sge i32 [[A:%.*]], 100
421 ; CHECK-NEXT: [[CMP_2:%.*]] = icmp sle i32 [[A]], 0
422 ; CHECK-NEXT: [[CMP_3:%.*]] = or i1 [[CMP_2]], [[FLAG:%.*]]
423 ; CHECK-NEXT: [[CMP:%.*]] = or i1 [[CMP_1]], [[CMP_3]]
424 ; CHECK-NEXT: br i1 [[CMP]], label [[EXIT:%.*]], label [[BB:%.*]]
426 ; CHECK-NEXT: [[SUB:%.*]] = sub nuw nsw i32 [[A]], 1
427 ; CHECK-NEXT: br label [[EXIT]]
429 ; CHECK-NEXT: ret void
432 %cmp.1 = icmp sge i32 %a, 100
433 %cmp.2 = icmp sle i32 %a, 0
434 %cmp.3 = or i1 %cmp.2, %flag
435 %cmp = or i1 %cmp.1, %cmp.3
436 br i1 %cmp, label %exit, label %bb
446 ; Check that we can gather information for conditions is the form of
447 ; or ( i s<= Unknown, ... )
448 define void @test15(i32 %a, i32 %b, i1 %flag) {
449 ; CHECK-LABEL: @test15(
451 ; CHECK-NEXT: [[CMP_1:%.*]] = icmp sle i32 [[A:%.*]], [[B:%.*]]
452 ; CHECK-NEXT: [[CMP:%.*]] = or i1 [[CMP_1]], [[FLAG:%.*]]
453 ; CHECK-NEXT: br i1 [[CMP]], label [[EXIT:%.*]], label [[BB:%.*]]
455 ; CHECK-NEXT: [[SUB:%.*]] = sub nsw i32 [[A]], 1
456 ; CHECK-NEXT: br label [[EXIT]]
458 ; CHECK-NEXT: ret void
461 %cmp.1 = icmp sle i32 %a, %b
462 %cmp = or i1 %cmp.1, %flag
463 br i1 %cmp, label %exit, label %bb
473 ; single basic block loop
474 ; because the loop exit condition is SLT, we can supplement the iv sub
475 ; (iv.next def) with an nsw.
476 define i32 @test16(ptr %n, ptr %a) {
477 ; CHECK-LABEL: @test16(
478 ; CHECK-NEXT: preheader:
479 ; CHECK-NEXT: br label [[LOOP:%.*]]
481 ; CHECK-NEXT: [[IV:%.*]] = phi i32 [ 0, [[PREHEADER:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP]] ]
482 ; CHECK-NEXT: [[ACC:%.*]] = phi i32 [ 0, [[PREHEADER]] ], [ [[ACC_CURR:%.*]], [[LOOP]] ]
483 ; CHECK-NEXT: [[X:%.*]] = load atomic i32, ptr [[A:%.*]] unordered, align 8
484 ; CHECK-NEXT: fence acquire
485 ; CHECK-NEXT: [[ACC_CURR]] = sub i32 [[ACC]], [[X]]
486 ; CHECK-NEXT: [[IV_NEXT]] = sub nsw i32 [[IV]], -1
487 ; CHECK-NEXT: [[NVAL:%.*]] = load atomic i32, ptr [[N:%.*]] unordered, align 8
488 ; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 [[IV_NEXT]], [[NVAL]]
489 ; CHECK-NEXT: br i1 [[CMP]], label [[LOOP]], label [[EXIT:%.*]]
491 ; CHECK-NEXT: ret i32 [[ACC_CURR]]
497 %iv = phi i32 [ 0, %preheader ], [ %iv.next, %loop ]
498 %acc = phi i32 [ 0, %preheader ], [ %acc.curr, %loop ]
499 %x = load atomic i32, ptr %a unordered, align 8
501 %acc.curr = sub i32 %acc, %x
502 %iv.next = sub i32 %iv, -1
503 %nval = load atomic i32, ptr %n unordered, align 8
504 %cmp = icmp slt i32 %iv.next, %nval
505 br i1 %cmp, label %loop, label %exit
511 define void @test17(i32 %a) {
512 ; CHECK-LABEL: @test17(
514 ; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i32 [[A:%.*]], 100
515 ; CHECK-NEXT: br i1 [[CMP]], label [[BB:%.*]], label [[EXIT:%.*]]
517 ; CHECK-NEXT: [[SUB:%.*]] = sub nsw i32 1, [[A]]
518 ; CHECK-NEXT: br label [[EXIT]]
520 ; CHECK-NEXT: ret void
523 %cmp = icmp sgt i32 %a, 100
524 br i1 %cmp, label %bb, label %exit
534 define void @test18(i32 %a) {
535 ; CHECK-LABEL: @test18(
537 ; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i32 [[A:%.*]], 10000
538 ; CHECK-NEXT: br i1 [[CMP]], label [[BB:%.*]], label [[EXIT:%.*]]
540 ; CHECK-NEXT: [[SUB:%.*]] = sub nuw i32 -2, [[A]]
541 ; CHECK-NEXT: br label [[EXIT]]
543 ; CHECK-NEXT: ret void
546 %cmp = icmp sgt i32 %a, 10000
547 br i1 %cmp, label %bb, label %exit
550 %sub = sub i32 -2, %a
557 define void @test19(i32 %a) {
558 ; CHECK-LABEL: @test19(
560 ; CHECK-NEXT: [[CMP:%.*]] = icmp ult i32 [[A:%.*]], 100
561 ; CHECK-NEXT: br i1 [[CMP]], label [[BB:%.*]], label [[EXIT:%.*]]
563 ; CHECK-NEXT: [[SUB:%.*]] = sub nuw nsw i32 -1, [[A]]
564 ; CHECK-NEXT: br label [[EXIT]]
566 ; CHECK-NEXT: ret void
569 %cmp = icmp ult i32 %a, 100
570 br i1 %cmp, label %bb, label %exit
573 %sub = sub i32 -1, %a
580 define void @test20(i32 %a) {
581 ; CHECK-LABEL: @test20(
583 ; CHECK-NEXT: [[CMP:%.*]] = icmp ugt i32 [[A:%.*]], 2147483647
584 ; CHECK-NEXT: br i1 [[CMP]], label [[BB:%.*]], label [[EXIT:%.*]]
586 ; CHECK-NEXT: [[SUB:%.*]] = sub i32 0, [[A]]
587 ; CHECK-NEXT: br label [[EXIT]]
589 ; CHECK-NEXT: ret void
592 %cmp = icmp ugt i32 %a, 2147483647
593 br i1 %cmp, label %bb, label %exit