1 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 4
2 ; RUN: opt < %s -passes=correlated-propagation -S | FileCheck %s
4 define void @test0(i32 %a) {
5 ; CHECK-LABEL: define void @test0(
6 ; CHECK-SAME: i32 [[A:%.*]]) {
8 ; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 [[A]], 100
9 ; CHECK-NEXT: br i1 [[CMP]], label [[BB:%.*]], label [[EXIT:%.*]]
11 ; CHECK-NEXT: [[ADD:%.*]] = add nsw i32 [[A]], 1
12 ; CHECK-NEXT: br label [[EXIT]]
14 ; CHECK-NEXT: ret void
17 %cmp = icmp slt i32 %a, 100
18 br i1 %cmp, label %bb, label %exit
28 define void @test1(i32 %a) {
29 ; CHECK-LABEL: define void @test1(
30 ; CHECK-SAME: i32 [[A:%.*]]) {
32 ; CHECK-NEXT: [[CMP:%.*]] = icmp ult i32 [[A]], 100
33 ; CHECK-NEXT: br i1 [[CMP]], label [[BB:%.*]], label [[EXIT:%.*]]
35 ; CHECK-NEXT: [[ADD:%.*]] = add nuw nsw i32 [[A]], 1
36 ; CHECK-NEXT: br label [[EXIT]]
38 ; CHECK-NEXT: ret void
41 %cmp = icmp ult i32 %a, 100
42 br i1 %cmp, label %bb, label %exit
52 define void @test2(i32 %a) {
53 ; CHECK-LABEL: define void @test2(
54 ; CHECK-SAME: i32 [[A:%.*]]) {
56 ; CHECK-NEXT: [[CMP:%.*]] = icmp ult i32 [[A]], -1
57 ; CHECK-NEXT: br i1 [[CMP]], label [[BB:%.*]], label [[EXIT:%.*]]
59 ; CHECK-NEXT: [[ADD:%.*]] = add nuw i32 [[A]], 1
60 ; CHECK-NEXT: br label [[EXIT]]
62 ; CHECK-NEXT: ret void
65 %cmp = icmp ult i32 %a, -1
66 br i1 %cmp, label %bb, label %exit
76 define void @test3(i32 %a) {
77 ; CHECK-LABEL: define void @test3(
78 ; CHECK-SAME: i32 [[A:%.*]]) {
80 ; CHECK-NEXT: [[CMP:%.*]] = icmp ule i32 [[A]], -1
81 ; CHECK-NEXT: br i1 [[CMP]], label [[BB:%.*]], label [[EXIT:%.*]]
83 ; CHECK-NEXT: [[ADD:%.*]] = add i32 [[A]], 1
84 ; CHECK-NEXT: br label [[EXIT]]
86 ; CHECK-NEXT: ret void
89 %cmp = icmp ule i32 %a, -1
90 br i1 %cmp, label %bb, label %exit
100 define void @test4(i32 %a) {
101 ; CHECK-LABEL: define void @test4(
102 ; CHECK-SAME: i32 [[A:%.*]]) {
104 ; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 [[A]], 2147483647
105 ; CHECK-NEXT: br i1 [[CMP]], label [[BB:%.*]], label [[EXIT:%.*]]
107 ; CHECK-NEXT: [[ADD:%.*]] = add nsw i32 [[A]], 1
108 ; CHECK-NEXT: br label [[EXIT]]
110 ; CHECK-NEXT: ret void
113 %cmp = icmp slt i32 %a, 2147483647
114 br i1 %cmp, label %bb, label %exit
124 define void @test5(i32 %a) {
125 ; CHECK-LABEL: define void @test5(
126 ; CHECK-SAME: i32 [[A:%.*]]) {
128 ; CHECK-NEXT: [[CMP:%.*]] = icmp sle i32 [[A]], 2147483647
129 ; CHECK-NEXT: br i1 [[CMP]], label [[BB:%.*]], label [[EXIT:%.*]]
131 ; CHECK-NEXT: [[ADD:%.*]] = add i32 [[A]], 1
132 ; CHECK-NEXT: br label [[EXIT]]
134 ; CHECK-NEXT: ret void
137 %cmp = icmp sle i32 %a, 2147483647
138 br i1 %cmp, label %bb, label %exit
148 ; Check for a corner case where an integer value is represented with a constant
149 ; LVILatticeValue instead of constantrange. Check that we don't fail with an
150 ; assertion in this case.
151 @b = global i32 0, align 4
152 define void @test6(i32 %a) {
153 ; CHECK-LABEL: define void @test6(
154 ; CHECK-SAME: i32 [[A:%.*]]) {
156 ; CHECK-NEXT: [[ADD:%.*]] = add i32 [[A]], ptrtoint (ptr @b to i32)
157 ; CHECK-NEXT: ret void
160 %add = add i32 %a, ptrtoint (ptr @b to i32)
164 ; Check that we can gather information for conditions is the form of
165 ; and ( i s< 100, Unknown )
166 define void @test7(i32 %a, i1 %flag) {
167 ; CHECK-LABEL: define void @test7(
168 ; CHECK-SAME: i32 [[A:%.*]], i1 [[FLAG:%.*]]) {
170 ; CHECK-NEXT: [[CMP_1:%.*]] = icmp slt i32 [[A]], 100
171 ; CHECK-NEXT: [[CMP:%.*]] = and i1 [[CMP_1]], [[FLAG]]
172 ; CHECK-NEXT: br i1 [[CMP]], label [[BB:%.*]], label [[EXIT:%.*]]
174 ; CHECK-NEXT: [[ADD:%.*]] = add nsw i32 [[A]], 1
175 ; CHECK-NEXT: br label [[EXIT]]
177 ; CHECK-NEXT: ret void
180 %cmp.1 = icmp slt i32 %a, 100
181 %cmp = and i1 %cmp.1, %flag
182 br i1 %cmp, label %bb, label %exit
192 ; Check that we can gather information for conditions is the form of
193 ; and ( i s< 100, i s> 0 )
194 define void @test8(i32 %a) {
195 ; CHECK-LABEL: define void @test8(
196 ; CHECK-SAME: i32 [[A:%.*]]) {
198 ; CHECK-NEXT: [[CMP_1:%.*]] = icmp slt i32 [[A]], 100
199 ; CHECK-NEXT: [[CMP_2:%.*]] = icmp sgt i32 [[A]], 0
200 ; CHECK-NEXT: [[CMP:%.*]] = and i1 [[CMP_1]], [[CMP_2]]
201 ; CHECK-NEXT: br i1 [[CMP]], label [[BB:%.*]], label [[EXIT:%.*]]
203 ; CHECK-NEXT: [[ADD:%.*]] = add nuw nsw i32 [[A]], 1
204 ; CHECK-NEXT: br label [[EXIT]]
206 ; CHECK-NEXT: ret void
209 %cmp.1 = icmp slt i32 %a, 100
210 %cmp.2 = icmp sgt i32 %a, 0
211 %cmp = and i1 %cmp.1, %cmp.2
212 br i1 %cmp, label %bb, label %exit
222 ; Check that for conditions is the form of cond1 && cond2 we don't mistakenly
223 ; assume that !cond1 && !cond2 holds down to false path.
224 define void @test8_neg(i32 %a) {
225 ; CHECK-LABEL: define void @test8_neg(
226 ; CHECK-SAME: i32 [[A:%.*]]) {
228 ; CHECK-NEXT: [[CMP_1:%.*]] = icmp sge i32 [[A]], 100
229 ; CHECK-NEXT: [[CMP_2:%.*]] = icmp sle i32 [[A]], 0
230 ; CHECK-NEXT: [[CMP:%.*]] = and i1 [[CMP_1]], [[CMP_2]]
231 ; CHECK-NEXT: br i1 [[CMP]], label [[EXIT:%.*]], label [[BB:%.*]]
233 ; CHECK-NEXT: [[ADD:%.*]] = add i32 [[A]], 1
234 ; CHECK-NEXT: br label [[EXIT]]
236 ; CHECK-NEXT: ret void
239 %cmp.1 = icmp sge i32 %a, 100
240 %cmp.2 = icmp sle i32 %a, 0
241 %cmp = and i1 %cmp.1, %cmp.2
242 br i1 %cmp, label %exit, label %bb
252 ; Check that we can gather information for conditions is the form of
253 ; and ( i s< 100, and (i s> 0, Unknown )
254 define void @test9(i32 %a, i1 %flag) {
255 ; CHECK-LABEL: define void @test9(
256 ; CHECK-SAME: i32 [[A:%.*]], i1 [[FLAG:%.*]]) {
258 ; CHECK-NEXT: [[CMP_1:%.*]] = icmp slt i32 [[A]], 100
259 ; CHECK-NEXT: [[CMP_2:%.*]] = icmp sgt i32 [[A]], 0
260 ; CHECK-NEXT: [[CMP_3:%.*]] = and i1 [[CMP_2]], [[FLAG]]
261 ; CHECK-NEXT: [[CMP:%.*]] = and i1 [[CMP_1]], [[CMP_3]]
262 ; CHECK-NEXT: br i1 [[CMP]], label [[BB:%.*]], label [[EXIT:%.*]]
264 ; CHECK-NEXT: [[ADD:%.*]] = add nuw nsw i32 [[A]], 1
265 ; CHECK-NEXT: br label [[EXIT]]
267 ; CHECK-NEXT: ret void
270 %cmp.1 = icmp slt i32 %a, 100
271 %cmp.2 = icmp sgt i32 %a, 0
272 %cmp.3 = and i1 %cmp.2, %flag
273 %cmp = and i1 %cmp.1, %cmp.3
274 br i1 %cmp, label %bb, label %exit
284 ; Check that we can gather information for conditions is the form of
285 ; and ( i s< Unknown, ... )
286 define void @test10(i32 %a, i32 %b, i1 %flag) {
287 ; CHECK-LABEL: define void @test10(
288 ; CHECK-SAME: i32 [[A:%.*]], i32 [[B:%.*]], i1 [[FLAG:%.*]]) {
290 ; CHECK-NEXT: [[CMP_1:%.*]] = icmp slt i32 [[A]], [[B]]
291 ; CHECK-NEXT: [[CMP:%.*]] = and i1 [[CMP_1]], [[FLAG]]
292 ; CHECK-NEXT: br i1 [[CMP]], label [[BB:%.*]], label [[EXIT:%.*]]
294 ; CHECK-NEXT: [[ADD:%.*]] = add nsw i32 [[A]], 1
295 ; CHECK-NEXT: br label [[EXIT]]
297 ; CHECK-NEXT: ret void
300 %cmp.1 = icmp slt i32 %a, %b
301 %cmp = and i1 %cmp.1, %flag
302 br i1 %cmp, label %bb, label %exit
312 @limit = external global i32
313 define i32 @test11(ptr %p, i32 %i) {
314 ; CHECK-LABEL: define range(i32 0, 2147483645) i32 @test11(
315 ; CHECK-SAME: ptr [[P:%.*]], i32 [[I:%.*]]) {
316 ; CHECK-NEXT: [[LIMIT:%.*]] = load i32, ptr [[P]], align 4, !range [[RNG0:![0-9]+]]
317 ; CHECK-NEXT: [[WITHIN_1:%.*]] = icmp ugt i32 [[LIMIT]], [[I]]
318 ; CHECK-NEXT: [[I_PLUS_7:%.*]] = add i32 [[I]], 7
319 ; CHECK-NEXT: [[WITHIN_2:%.*]] = icmp ugt i32 [[LIMIT]], [[I_PLUS_7]]
320 ; CHECK-NEXT: [[WITHIN:%.*]] = and i1 [[WITHIN_1]], [[WITHIN_2]]
321 ; CHECK-NEXT: br i1 [[WITHIN]], label [[THEN:%.*]], label [[ELSE:%.*]]
323 ; CHECK-NEXT: [[I_PLUS_6:%.*]] = add nuw nsw i32 [[I]], 6
324 ; CHECK-NEXT: ret i32 [[I_PLUS_6]]
326 ; CHECK-NEXT: ret i32 0
328 %limit = load i32, ptr %p, !range !{i32 0, i32 2147483647}
329 %within.1 = icmp ugt i32 %limit, %i
330 %i.plus.7 = add i32 %i, 7
331 %within.2 = icmp ugt i32 %limit, %i.plus.7
332 %within = and i1 %within.1, %within.2
333 br i1 %within, label %then, label %else
336 %i.plus.6 = add i32 %i, 6
343 ; Check that we can gather information for conditions is the form of
344 ; or ( i s>= 100, Unknown )
345 define void @test12(i32 %a, i1 %flag) {
346 ; CHECK-LABEL: define void @test12(
347 ; CHECK-SAME: i32 [[A:%.*]], i1 [[FLAG:%.*]]) {
349 ; CHECK-NEXT: [[CMP_1:%.*]] = icmp sge i32 [[A]], 100
350 ; CHECK-NEXT: [[CMP:%.*]] = or i1 [[CMP_1]], [[FLAG]]
351 ; CHECK-NEXT: br i1 [[CMP]], label [[EXIT:%.*]], label [[BB:%.*]]
353 ; CHECK-NEXT: [[ADD:%.*]] = add nsw i32 [[A]], 1
354 ; CHECK-NEXT: br label [[EXIT]]
356 ; CHECK-NEXT: ret void
359 %cmp.1 = icmp sge i32 %a, 100
360 %cmp = or i1 %cmp.1, %flag
361 br i1 %cmp, label %exit, label %bb
371 ; Check that we can gather information for conditions is the form of
372 ; or ( i s>= 100, i s<= 0 )
373 define void @test13(i32 %a) {
374 ; CHECK-LABEL: define void @test13(
375 ; CHECK-SAME: i32 [[A:%.*]]) {
377 ; CHECK-NEXT: [[CMP_1:%.*]] = icmp sge i32 [[A]], 100
378 ; CHECK-NEXT: [[CMP_2:%.*]] = icmp sle i32 [[A]], 0
379 ; CHECK-NEXT: [[CMP:%.*]] = or i1 [[CMP_1]], [[CMP_2]]
380 ; CHECK-NEXT: br i1 [[CMP]], label [[EXIT:%.*]], label [[BB:%.*]]
382 ; CHECK-NEXT: [[ADD:%.*]] = add nuw nsw i32 [[A]], 1
383 ; CHECK-NEXT: br label [[EXIT]]
385 ; CHECK-NEXT: ret void
388 %cmp.1 = icmp sge i32 %a, 100
389 %cmp.2 = icmp sle i32 %a, 0
390 %cmp = or i1 %cmp.1, %cmp.2
391 br i1 %cmp, label %exit, label %bb
401 ; Check that for conditions is the form of cond1 || cond2 we don't mistakenly
402 ; assume that cond1 || cond2 holds down to true path.
403 define void @test13_neg(i32 %a) {
404 ; CHECK-LABEL: define void @test13_neg(
405 ; CHECK-SAME: i32 [[A:%.*]]) {
407 ; CHECK-NEXT: [[CMP_1:%.*]] = icmp slt i32 [[A]], 100
408 ; CHECK-NEXT: [[CMP_2:%.*]] = icmp sgt i32 [[A]], 0
409 ; CHECK-NEXT: [[CMP:%.*]] = or i1 [[CMP_1]], [[CMP_2]]
410 ; CHECK-NEXT: br i1 [[CMP]], label [[BB:%.*]], label [[EXIT:%.*]]
412 ; CHECK-NEXT: [[ADD:%.*]] = add i32 [[A]], 1
413 ; CHECK-NEXT: br label [[EXIT]]
415 ; CHECK-NEXT: ret void
418 %cmp.1 = icmp slt i32 %a, 100
419 %cmp.2 = icmp sgt i32 %a, 0
420 %cmp = or i1 %cmp.1, %cmp.2
421 br i1 %cmp, label %bb, label %exit
431 ; Check that we can gather information for conditions is the form of
432 ; or ( i s>=100, or (i s<= 0, Unknown )
433 define void @test14(i32 %a, i1 %flag) {
434 ; CHECK-LABEL: define void @test14(
435 ; CHECK-SAME: i32 [[A:%.*]], i1 [[FLAG:%.*]]) {
437 ; CHECK-NEXT: [[CMP_1:%.*]] = icmp sge i32 [[A]], 100
438 ; CHECK-NEXT: [[CMP_2:%.*]] = icmp sle i32 [[A]], 0
439 ; CHECK-NEXT: [[CMP_3:%.*]] = or i1 [[CMP_2]], [[FLAG]]
440 ; CHECK-NEXT: [[CMP:%.*]] = or i1 [[CMP_1]], [[CMP_3]]
441 ; CHECK-NEXT: br i1 [[CMP]], label [[EXIT:%.*]], label [[BB:%.*]]
443 ; CHECK-NEXT: [[ADD:%.*]] = add nuw nsw i32 [[A]], 1
444 ; CHECK-NEXT: br label [[EXIT]]
446 ; CHECK-NEXT: ret void
449 %cmp.1 = icmp sge i32 %a, 100
450 %cmp.2 = icmp sle i32 %a, 0
451 %cmp.3 = or i1 %cmp.2, %flag
452 %cmp = or i1 %cmp.1, %cmp.3
453 br i1 %cmp, label %exit, label %bb
463 ; Check that we can gather information for conditions is the form of
464 ; or ( i s>= Unknown, ... )
465 define void @test15(i32 %a, i32 %b, i1 %flag) {
466 ; CHECK-LABEL: define void @test15(
467 ; CHECK-SAME: i32 [[A:%.*]], i32 [[B:%.*]], i1 [[FLAG:%.*]]) {
469 ; CHECK-NEXT: [[CMP_1:%.*]] = icmp sge i32 [[A]], [[B]]
470 ; CHECK-NEXT: [[CMP:%.*]] = or i1 [[CMP_1]], [[FLAG]]
471 ; CHECK-NEXT: br i1 [[CMP]], label [[EXIT:%.*]], label [[BB:%.*]]
473 ; CHECK-NEXT: [[ADD:%.*]] = add nsw i32 [[A]], 1
474 ; CHECK-NEXT: br label [[EXIT]]
476 ; CHECK-NEXT: ret void
479 %cmp.1 = icmp sge i32 %a, %b
480 %cmp = or i1 %cmp.1, %flag
481 br i1 %cmp, label %exit, label %bb
491 ; single basic block loop
492 ; because the loop exit condition is SLT, we can supplement the iv add
493 ; (iv.next def) with an nsw.
494 define i32 @test16(ptr %n, ptr %a) {
495 ; CHECK-LABEL: define i32 @test16(
496 ; CHECK-SAME: ptr [[N:%.*]], ptr [[A:%.*]]) {
497 ; CHECK-NEXT: preheader:
498 ; CHECK-NEXT: br label [[LOOP:%.*]]
500 ; CHECK-NEXT: [[IV:%.*]] = phi i32 [ 0, [[PREHEADER:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP]] ]
501 ; CHECK-NEXT: [[ACC:%.*]] = phi i32 [ 0, [[PREHEADER]] ], [ [[ACC_CURR:%.*]], [[LOOP]] ]
502 ; CHECK-NEXT: [[X:%.*]] = load atomic i32, ptr [[A]] unordered, align 8
503 ; CHECK-NEXT: fence acquire
504 ; CHECK-NEXT: [[ACC_CURR]] = add i32 [[ACC]], [[X]]
505 ; CHECK-NEXT: [[IV_NEXT]] = add nsw i32 [[IV]], 1
506 ; CHECK-NEXT: [[NVAL:%.*]] = load atomic i32, ptr [[N]] unordered, align 8
507 ; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 [[IV_NEXT]], [[NVAL]]
508 ; CHECK-NEXT: br i1 [[CMP]], label [[LOOP]], label [[EXIT:%.*]]
510 ; CHECK-NEXT: ret i32 [[ACC_CURR]]
516 %iv = phi i32 [ 0, %preheader ], [ %iv.next, %loop ]
517 %acc = phi i32 [ 0, %preheader ], [ %acc.curr, %loop ]
518 %x = load atomic i32, ptr %a unordered, align 8
520 %acc.curr = add i32 %acc, %x
521 %iv.next = add i32 %iv, 1
522 %nval = load atomic i32, ptr %n unordered, align 8
523 %cmp = icmp slt i32 %iv.next, %nval
524 br i1 %cmp, label %loop, label %exit
530 define i32 @test_undef_range(i32 %x) {
531 ; CHECK-LABEL: define i32 @test_undef_range(
532 ; CHECK-SAME: i32 [[X:%.*]]) {
534 ; CHECK-NEXT: switch i32 [[X]], label [[JOIN:%.*]] [
535 ; CHECK-NEXT: i32 1, label [[CASE1:%.*]]
536 ; CHECK-NEXT: i32 2, label [[CASE2:%.*]]
539 ; CHECK-NEXT: br label [[JOIN]]
541 ; CHECK-NEXT: br label [[JOIN]]
543 ; CHECK-NEXT: [[PHI:%.*]] = phi i32 [ 1, [[CASE1]] ], [ 2, [[CASE2]] ], [ undef, [[ENTRY:%.*]] ]
544 ; CHECK-NEXT: [[ADD:%.*]] = add i32 [[PHI]], 1
545 ; CHECK-NEXT: ret i32 [[ADD]]
548 switch i32 %x, label %join [
560 %phi = phi i32 [ 1, %case1 ], [ 2, %case2 ], [ undef, %entry ]
561 %add = add i32 %phi, 1
566 ; CHECK: [[RNG0]] = !{i32 0, i32 2147483647}