| ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 4 |
| ; RUN: opt < %s -passes=correlated-propagation -S | FileCheck %s |
| |
| define void @test0(i32 %a) { |
| ; CHECK-LABEL: define void @test0( |
| ; CHECK-SAME: i32 [[A:%.*]]) { |
| ; CHECK-NEXT: entry: |
| ; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 [[A]], 100 |
| ; CHECK-NEXT: br i1 [[CMP]], label [[BB:%.*]], label [[EXIT:%.*]] |
| ; CHECK: bb: |
| ; CHECK-NEXT: [[ADD:%.*]] = add nsw i32 [[A]], 1 |
| ; CHECK-NEXT: br label [[EXIT]] |
| ; CHECK: exit: |
| ; CHECK-NEXT: ret void |
| ; |
| entry: |
| %cmp = icmp slt i32 %a, 100 |
| br i1 %cmp, label %bb, label %exit |
| |
| bb: |
| %add = add i32 %a, 1 |
| br label %exit |
| |
| exit: |
| ret void |
| } |
| |
| define void @test1(i32 %a) { |
| ; CHECK-LABEL: define void @test1( |
| ; CHECK-SAME: i32 [[A:%.*]]) { |
| ; CHECK-NEXT: entry: |
| ; CHECK-NEXT: [[CMP:%.*]] = icmp ult i32 [[A]], 100 |
| ; CHECK-NEXT: br i1 [[CMP]], label [[BB:%.*]], label [[EXIT:%.*]] |
| ; CHECK: bb: |
| ; CHECK-NEXT: [[ADD:%.*]] = add nuw nsw i32 [[A]], 1 |
| ; CHECK-NEXT: br label [[EXIT]] |
| ; CHECK: exit: |
| ; CHECK-NEXT: ret void |
| ; |
| entry: |
| %cmp = icmp ult i32 %a, 100 |
| br i1 %cmp, label %bb, label %exit |
| |
| bb: |
| %add = add i32 %a, 1 |
| br label %exit |
| |
| exit: |
| ret void |
| } |
| |
| define void @test2(i32 %a) { |
| ; CHECK-LABEL: define void @test2( |
| ; CHECK-SAME: i32 [[A:%.*]]) { |
| ; CHECK-NEXT: entry: |
| ; CHECK-NEXT: [[CMP:%.*]] = icmp ult i32 [[A]], -1 |
| ; CHECK-NEXT: br i1 [[CMP]], label [[BB:%.*]], label [[EXIT:%.*]] |
| ; CHECK: bb: |
| ; CHECK-NEXT: [[ADD:%.*]] = add nuw i32 [[A]], 1 |
| ; CHECK-NEXT: br label [[EXIT]] |
| ; CHECK: exit: |
| ; CHECK-NEXT: ret void |
| ; |
| entry: |
| %cmp = icmp ult i32 %a, -1 |
| br i1 %cmp, label %bb, label %exit |
| |
| bb: |
| %add = add i32 %a, 1 |
| br label %exit |
| |
| exit: |
| ret void |
| } |
| |
| define void @test3(i32 %a) { |
| ; CHECK-LABEL: define void @test3( |
| ; CHECK-SAME: i32 [[A:%.*]]) { |
| ; CHECK-NEXT: entry: |
| ; CHECK-NEXT: [[CMP:%.*]] = icmp ule i32 [[A]], -1 |
| ; CHECK-NEXT: br i1 [[CMP]], label [[BB:%.*]], label [[EXIT:%.*]] |
| ; CHECK: bb: |
| ; CHECK-NEXT: [[ADD:%.*]] = add i32 [[A]], 1 |
| ; CHECK-NEXT: br label [[EXIT]] |
| ; CHECK: exit: |
| ; CHECK-NEXT: ret void |
| ; |
| entry: |
| %cmp = icmp ule i32 %a, -1 |
| br i1 %cmp, label %bb, label %exit |
| |
| bb: |
| %add = add i32 %a, 1 |
| br label %exit |
| |
| exit: |
| ret void |
| } |
| |
| define void @test4(i32 %a) { |
| ; CHECK-LABEL: define void @test4( |
| ; CHECK-SAME: i32 [[A:%.*]]) { |
| ; CHECK-NEXT: entry: |
| ; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 [[A]], 2147483647 |
| ; CHECK-NEXT: br i1 [[CMP]], label [[BB:%.*]], label [[EXIT:%.*]] |
| ; CHECK: bb: |
| ; CHECK-NEXT: [[ADD:%.*]] = add nsw i32 [[A]], 1 |
| ; CHECK-NEXT: br label [[EXIT]] |
| ; CHECK: exit: |
| ; CHECK-NEXT: ret void |
| ; |
| entry: |
| %cmp = icmp slt i32 %a, 2147483647 |
| br i1 %cmp, label %bb, label %exit |
| |
| bb: |
| %add = add i32 %a, 1 |
| br label %exit |
| |
| exit: |
| ret void |
| } |
| |
| define void @test5(i32 %a) { |
| ; CHECK-LABEL: define void @test5( |
| ; CHECK-SAME: i32 [[A:%.*]]) { |
| ; CHECK-NEXT: entry: |
| ; CHECK-NEXT: [[CMP:%.*]] = icmp sle i32 [[A]], 2147483647 |
| ; CHECK-NEXT: br i1 [[CMP]], label [[BB:%.*]], label [[EXIT:%.*]] |
| ; CHECK: bb: |
| ; CHECK-NEXT: [[ADD:%.*]] = add i32 [[A]], 1 |
| ; CHECK-NEXT: br label [[EXIT]] |
| ; CHECK: exit: |
| ; CHECK-NEXT: ret void |
| ; |
| entry: |
| %cmp = icmp sle i32 %a, 2147483647 |
| br i1 %cmp, label %bb, label %exit |
| |
| bb: |
| %add = add i32 %a, 1 |
| br label %exit |
| |
| exit: |
| ret void |
| } |
| |
| ; Check for a corner case where an integer value is represented with a constant |
| ; LVILatticeValue instead of constantrange. Check that we don't fail with an |
| ; assertion in this case. |
| @b = global i32 0, align 4 |
| define void @test6(i32 %a) { |
| ; CHECK-LABEL: define void @test6( |
| ; CHECK-SAME: i32 [[A:%.*]]) { |
| ; CHECK-NEXT: bb: |
| ; CHECK-NEXT: [[ADD:%.*]] = add i32 [[A]], ptrtoint (ptr @b to i32) |
| ; CHECK-NEXT: ret void |
| ; |
| bb: |
| %add = add i32 %a, ptrtoint (ptr @b to i32) |
| ret void |
| } |
| |
| ; Check that we can gather information for conditions is the form of |
| ; and ( i s< 100, Unknown ) |
| define void @test7(i32 %a, i1 %flag) { |
| ; CHECK-LABEL: define void @test7( |
| ; CHECK-SAME: i32 [[A:%.*]], i1 [[FLAG:%.*]]) { |
| ; CHECK-NEXT: entry: |
| ; CHECK-NEXT: [[CMP_1:%.*]] = icmp slt i32 [[A]], 100 |
| ; CHECK-NEXT: [[CMP:%.*]] = and i1 [[CMP_1]], [[FLAG]] |
| ; CHECK-NEXT: br i1 [[CMP]], label [[BB:%.*]], label [[EXIT:%.*]] |
| ; CHECK: bb: |
| ; CHECK-NEXT: [[ADD:%.*]] = add nsw i32 [[A]], 1 |
| ; CHECK-NEXT: br label [[EXIT]] |
| ; CHECK: exit: |
| ; CHECK-NEXT: ret void |
| ; |
| entry: |
| %cmp.1 = icmp slt i32 %a, 100 |
| %cmp = and i1 %cmp.1, %flag |
| br i1 %cmp, label %bb, label %exit |
| |
| bb: |
| %add = add i32 %a, 1 |
| br label %exit |
| |
| exit: |
| ret void |
| } |
| |
| ; Check that we can gather information for conditions is the form of |
| ; and ( i s< 100, i s> 0 ) |
| define void @test8(i32 %a) { |
| ; CHECK-LABEL: define void @test8( |
| ; CHECK-SAME: i32 [[A:%.*]]) { |
| ; CHECK-NEXT: entry: |
| ; CHECK-NEXT: [[CMP_1:%.*]] = icmp slt i32 [[A]], 100 |
| ; CHECK-NEXT: [[CMP_2:%.*]] = icmp sgt i32 [[A]], 0 |
| ; CHECK-NEXT: [[CMP:%.*]] = and i1 [[CMP_1]], [[CMP_2]] |
| ; CHECK-NEXT: br i1 [[CMP]], label [[BB:%.*]], label [[EXIT:%.*]] |
| ; CHECK: bb: |
| ; CHECK-NEXT: [[ADD:%.*]] = add nuw nsw i32 [[A]], 1 |
| ; CHECK-NEXT: br label [[EXIT]] |
| ; CHECK: exit: |
| ; CHECK-NEXT: ret void |
| ; |
| entry: |
| %cmp.1 = icmp slt i32 %a, 100 |
| %cmp.2 = icmp sgt i32 %a, 0 |
| %cmp = and i1 %cmp.1, %cmp.2 |
| br i1 %cmp, label %bb, label %exit |
| |
| bb: |
| %add = add i32 %a, 1 |
| br label %exit |
| |
| exit: |
| ret void |
| } |
| |
| ; Check that for conditions is the form of cond1 && cond2 we don't mistakenly |
| ; assume that !cond1 && !cond2 holds down to false path. |
| define void @test8_neg(i32 %a) { |
| ; CHECK-LABEL: define void @test8_neg( |
| ; CHECK-SAME: i32 [[A:%.*]]) { |
| ; CHECK-NEXT: entry: |
| ; CHECK-NEXT: [[CMP_1:%.*]] = icmp sge i32 [[A]], 100 |
| ; CHECK-NEXT: [[CMP_2:%.*]] = icmp sle i32 [[A]], 0 |
| ; CHECK-NEXT: [[CMP:%.*]] = and i1 [[CMP_1]], [[CMP_2]] |
| ; CHECK-NEXT: br i1 [[CMP]], label [[EXIT:%.*]], label [[BB:%.*]] |
| ; CHECK: bb: |
| ; CHECK-NEXT: [[ADD:%.*]] = add i32 [[A]], 1 |
| ; CHECK-NEXT: br label [[EXIT]] |
| ; CHECK: exit: |
| ; CHECK-NEXT: ret void |
| ; |
| entry: |
| %cmp.1 = icmp sge i32 %a, 100 |
| %cmp.2 = icmp sle i32 %a, 0 |
| %cmp = and i1 %cmp.1, %cmp.2 |
| br i1 %cmp, label %exit, label %bb |
| |
| bb: |
| %add = add i32 %a, 1 |
| br label %exit |
| |
| exit: |
| ret void |
| } |
| |
| ; Check that we can gather information for conditions is the form of |
| ; and ( i s< 100, and (i s> 0, Unknown ) |
| define void @test9(i32 %a, i1 %flag) { |
| ; CHECK-LABEL: define void @test9( |
| ; CHECK-SAME: i32 [[A:%.*]], i1 [[FLAG:%.*]]) { |
| ; CHECK-NEXT: entry: |
| ; CHECK-NEXT: [[CMP_1:%.*]] = icmp slt i32 [[A]], 100 |
| ; CHECK-NEXT: [[CMP_2:%.*]] = icmp sgt i32 [[A]], 0 |
| ; CHECK-NEXT: [[CMP_3:%.*]] = and i1 [[CMP_2]], [[FLAG]] |
| ; CHECK-NEXT: [[CMP:%.*]] = and i1 [[CMP_1]], [[CMP_3]] |
| ; CHECK-NEXT: br i1 [[CMP]], label [[BB:%.*]], label [[EXIT:%.*]] |
| ; CHECK: bb: |
| ; CHECK-NEXT: [[ADD:%.*]] = add nuw nsw i32 [[A]], 1 |
| ; CHECK-NEXT: br label [[EXIT]] |
| ; CHECK: exit: |
| ; CHECK-NEXT: ret void |
| ; |
| entry: |
| %cmp.1 = icmp slt i32 %a, 100 |
| %cmp.2 = icmp sgt i32 %a, 0 |
| %cmp.3 = and i1 %cmp.2, %flag |
| %cmp = and i1 %cmp.1, %cmp.3 |
| br i1 %cmp, label %bb, label %exit |
| |
| bb: |
| %add = add i32 %a, 1 |
| br label %exit |
| |
| exit: |
| ret void |
| } |
| |
| ; Check that we can gather information for conditions is the form of |
| ; and ( i s< Unknown, ... ) |
| define void @test10(i32 %a, i32 %b, i1 %flag) { |
| ; CHECK-LABEL: define void @test10( |
| ; CHECK-SAME: i32 [[A:%.*]], i32 [[B:%.*]], i1 [[FLAG:%.*]]) { |
| ; CHECK-NEXT: entry: |
| ; CHECK-NEXT: [[CMP_1:%.*]] = icmp slt i32 [[A]], [[B]] |
| ; CHECK-NEXT: [[CMP:%.*]] = and i1 [[CMP_1]], [[FLAG]] |
| ; CHECK-NEXT: br i1 [[CMP]], label [[BB:%.*]], label [[EXIT:%.*]] |
| ; CHECK: bb: |
| ; CHECK-NEXT: [[ADD:%.*]] = add nsw i32 [[A]], 1 |
| ; CHECK-NEXT: br label [[EXIT]] |
| ; CHECK: exit: |
| ; CHECK-NEXT: ret void |
| ; |
| entry: |
| %cmp.1 = icmp slt i32 %a, %b |
| %cmp = and i1 %cmp.1, %flag |
| br i1 %cmp, label %bb, label %exit |
| |
| bb: |
| %add = add i32 %a, 1 |
| br label %exit |
| |
| exit: |
| ret void |
| } |
| |
| @limit = external global i32 |
| define i32 @test11(ptr %p, i32 %i) { |
| ; CHECK-LABEL: define range(i32 0, 2147483645) i32 @test11( |
| ; CHECK-SAME: ptr [[P:%.*]], i32 [[I:%.*]]) { |
| ; CHECK-NEXT: [[LIMIT:%.*]] = load i32, ptr [[P]], align 4, !range [[RNG0:![0-9]+]] |
| ; CHECK-NEXT: [[WITHIN_1:%.*]] = icmp ugt i32 [[LIMIT]], [[I]] |
| ; CHECK-NEXT: [[I_PLUS_7:%.*]] = add i32 [[I]], 7 |
| ; CHECK-NEXT: [[WITHIN_2:%.*]] = icmp ugt i32 [[LIMIT]], [[I_PLUS_7]] |
| ; CHECK-NEXT: [[WITHIN:%.*]] = and i1 [[WITHIN_1]], [[WITHIN_2]] |
| ; CHECK-NEXT: br i1 [[WITHIN]], label [[THEN:%.*]], label [[ELSE:%.*]] |
| ; CHECK: then: |
| ; CHECK-NEXT: [[I_PLUS_6:%.*]] = add nuw nsw i32 [[I]], 6 |
| ; CHECK-NEXT: ret i32 [[I_PLUS_6]] |
| ; CHECK: else: |
| ; CHECK-NEXT: ret i32 0 |
| ; |
| %limit = load i32, ptr %p, !range !{i32 0, i32 2147483647} |
| %within.1 = icmp ugt i32 %limit, %i |
| %i.plus.7 = add i32 %i, 7 |
| %within.2 = icmp ugt i32 %limit, %i.plus.7 |
| %within = and i1 %within.1, %within.2 |
| br i1 %within, label %then, label %else |
| |
| then: |
| %i.plus.6 = add i32 %i, 6 |
| ret i32 %i.plus.6 |
| |
| else: |
| ret i32 0 |
| } |
| |
| ; Check that we can gather information for conditions is the form of |
| ; or ( i s>= 100, Unknown ) |
| define void @test12(i32 %a, i1 %flag) { |
| ; CHECK-LABEL: define void @test12( |
| ; CHECK-SAME: i32 [[A:%.*]], i1 [[FLAG:%.*]]) { |
| ; CHECK-NEXT: entry: |
| ; CHECK-NEXT: [[CMP_1:%.*]] = icmp sge i32 [[A]], 100 |
| ; CHECK-NEXT: [[CMP:%.*]] = or i1 [[CMP_1]], [[FLAG]] |
| ; CHECK-NEXT: br i1 [[CMP]], label [[EXIT:%.*]], label [[BB:%.*]] |
| ; CHECK: bb: |
| ; CHECK-NEXT: [[ADD:%.*]] = add nsw i32 [[A]], 1 |
| ; CHECK-NEXT: br label [[EXIT]] |
| ; CHECK: exit: |
| ; CHECK-NEXT: ret void |
| ; |
| entry: |
| %cmp.1 = icmp sge i32 %a, 100 |
| %cmp = or i1 %cmp.1, %flag |
| br i1 %cmp, label %exit, label %bb |
| |
| bb: |
| %add = add i32 %a, 1 |
| br label %exit |
| |
| exit: |
| ret void |
| } |
| |
| ; Check that we can gather information for conditions is the form of |
| ; or ( i s>= 100, i s<= 0 ) |
| define void @test13(i32 %a) { |
| ; CHECK-LABEL: define void @test13( |
| ; CHECK-SAME: i32 [[A:%.*]]) { |
| ; CHECK-NEXT: entry: |
| ; CHECK-NEXT: [[CMP_1:%.*]] = icmp sge i32 [[A]], 100 |
| ; CHECK-NEXT: [[CMP_2:%.*]] = icmp sle i32 [[A]], 0 |
| ; CHECK-NEXT: [[CMP:%.*]] = or i1 [[CMP_1]], [[CMP_2]] |
| ; CHECK-NEXT: br i1 [[CMP]], label [[EXIT:%.*]], label [[BB:%.*]] |
| ; CHECK: bb: |
| ; CHECK-NEXT: [[ADD:%.*]] = add nuw nsw i32 [[A]], 1 |
| ; CHECK-NEXT: br label [[EXIT]] |
| ; CHECK: exit: |
| ; CHECK-NEXT: ret void |
| ; |
| entry: |
| %cmp.1 = icmp sge i32 %a, 100 |
| %cmp.2 = icmp sle i32 %a, 0 |
| %cmp = or i1 %cmp.1, %cmp.2 |
| br i1 %cmp, label %exit, label %bb |
| |
| bb: |
| %add = add i32 %a, 1 |
| br label %exit |
| |
| exit: |
| ret void |
| } |
| |
| ; Check that for conditions is the form of cond1 || cond2 we don't mistakenly |
| ; assume that cond1 || cond2 holds down to true path. |
| define void @test13_neg(i32 %a) { |
| ; CHECK-LABEL: define void @test13_neg( |
| ; CHECK-SAME: i32 [[A:%.*]]) { |
| ; CHECK-NEXT: entry: |
| ; CHECK-NEXT: [[CMP_1:%.*]] = icmp slt i32 [[A]], 100 |
| ; CHECK-NEXT: [[CMP_2:%.*]] = icmp sgt i32 [[A]], 0 |
| ; CHECK-NEXT: [[CMP:%.*]] = or i1 [[CMP_1]], [[CMP_2]] |
| ; CHECK-NEXT: br i1 [[CMP]], label [[BB:%.*]], label [[EXIT:%.*]] |
| ; CHECK: bb: |
| ; CHECK-NEXT: [[ADD:%.*]] = add i32 [[A]], 1 |
| ; CHECK-NEXT: br label [[EXIT]] |
| ; CHECK: exit: |
| ; CHECK-NEXT: ret void |
| ; |
| entry: |
| %cmp.1 = icmp slt i32 %a, 100 |
| %cmp.2 = icmp sgt i32 %a, 0 |
| %cmp = or i1 %cmp.1, %cmp.2 |
| br i1 %cmp, label %bb, label %exit |
| |
| bb: |
| %add = add i32 %a, 1 |
| br label %exit |
| |
| exit: |
| ret void |
| } |
| |
| ; Check that we can gather information for conditions is the form of |
| ; or ( i s>=100, or (i s<= 0, Unknown ) |
| define void @test14(i32 %a, i1 %flag) { |
| ; CHECK-LABEL: define void @test14( |
| ; CHECK-SAME: i32 [[A:%.*]], i1 [[FLAG:%.*]]) { |
| ; CHECK-NEXT: entry: |
| ; CHECK-NEXT: [[CMP_1:%.*]] = icmp sge i32 [[A]], 100 |
| ; CHECK-NEXT: [[CMP_2:%.*]] = icmp sle i32 [[A]], 0 |
| ; CHECK-NEXT: [[CMP_3:%.*]] = or i1 [[CMP_2]], [[FLAG]] |
| ; CHECK-NEXT: [[CMP:%.*]] = or i1 [[CMP_1]], [[CMP_3]] |
| ; CHECK-NEXT: br i1 [[CMP]], label [[EXIT:%.*]], label [[BB:%.*]] |
| ; CHECK: bb: |
| ; CHECK-NEXT: [[ADD:%.*]] = add nuw nsw i32 [[A]], 1 |
| ; CHECK-NEXT: br label [[EXIT]] |
| ; CHECK: exit: |
| ; CHECK-NEXT: ret void |
| ; |
| entry: |
| %cmp.1 = icmp sge i32 %a, 100 |
| %cmp.2 = icmp sle i32 %a, 0 |
| %cmp.3 = or i1 %cmp.2, %flag |
| %cmp = or i1 %cmp.1, %cmp.3 |
| br i1 %cmp, label %exit, label %bb |
| |
| bb: |
| %add = add i32 %a, 1 |
| br label %exit |
| |
| exit: |
| ret void |
| } |
| |
| ; Check that we can gather information for conditions is the form of |
| ; or ( i s>= Unknown, ... ) |
| define void @test15(i32 %a, i32 %b, i1 %flag) { |
| ; CHECK-LABEL: define void @test15( |
| ; CHECK-SAME: i32 [[A:%.*]], i32 [[B:%.*]], i1 [[FLAG:%.*]]) { |
| ; CHECK-NEXT: entry: |
| ; CHECK-NEXT: [[CMP_1:%.*]] = icmp sge i32 [[A]], [[B]] |
| ; CHECK-NEXT: [[CMP:%.*]] = or i1 [[CMP_1]], [[FLAG]] |
| ; CHECK-NEXT: br i1 [[CMP]], label [[EXIT:%.*]], label [[BB:%.*]] |
| ; CHECK: bb: |
| ; CHECK-NEXT: [[ADD:%.*]] = add nsw i32 [[A]], 1 |
| ; CHECK-NEXT: br label [[EXIT]] |
| ; CHECK: exit: |
| ; CHECK-NEXT: ret void |
| ; |
| entry: |
| %cmp.1 = icmp sge i32 %a, %b |
| %cmp = or i1 %cmp.1, %flag |
| br i1 %cmp, label %exit, label %bb |
| |
| bb: |
| %add = add i32 %a, 1 |
| br label %exit |
| |
| exit: |
| ret void |
| } |
| |
| ; single basic block loop |
| ; because the loop exit condition is SLT, we can supplement the iv add |
| ; (iv.next def) with an nsw. |
| define i32 @test16(ptr %n, ptr %a) { |
| ; CHECK-LABEL: define i32 @test16( |
| ; CHECK-SAME: ptr [[N:%.*]], ptr [[A:%.*]]) { |
| ; CHECK-NEXT: preheader: |
| ; CHECK-NEXT: br label [[LOOP:%.*]] |
| ; CHECK: loop: |
| ; CHECK-NEXT: [[IV:%.*]] = phi i32 [ 0, [[PREHEADER:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP]] ] |
| ; CHECK-NEXT: [[ACC:%.*]] = phi i32 [ 0, [[PREHEADER]] ], [ [[ACC_CURR:%.*]], [[LOOP]] ] |
| ; CHECK-NEXT: [[X:%.*]] = load atomic i32, ptr [[A]] unordered, align 8 |
| ; CHECK-NEXT: fence acquire |
| ; CHECK-NEXT: [[ACC_CURR]] = add i32 [[ACC]], [[X]] |
| ; CHECK-NEXT: [[IV_NEXT]] = add nsw i32 [[IV]], 1 |
| ; CHECK-NEXT: [[NVAL:%.*]] = load atomic i32, ptr [[N]] unordered, align 8 |
| ; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 [[IV_NEXT]], [[NVAL]] |
| ; CHECK-NEXT: br i1 [[CMP]], label [[LOOP]], label [[EXIT:%.*]] |
| ; CHECK: exit: |
| ; CHECK-NEXT: ret i32 [[ACC_CURR]] |
| ; |
| preheader: |
| br label %loop |
| |
| loop: |
| %iv = phi i32 [ 0, %preheader ], [ %iv.next, %loop ] |
| %acc = phi i32 [ 0, %preheader ], [ %acc.curr, %loop ] |
| %x = load atomic i32, ptr %a unordered, align 8 |
| fence acquire |
| %acc.curr = add i32 %acc, %x |
| %iv.next = add i32 %iv, 1 |
| %nval = load atomic i32, ptr %n unordered, align 8 |
| %cmp = icmp slt i32 %iv.next, %nval |
| br i1 %cmp, label %loop, label %exit |
| |
| exit: |
| ret i32 %acc.curr |
| } |
| |
| define i32 @test_undef_range(i32 %x) { |
| ; CHECK-LABEL: define i32 @test_undef_range( |
| ; CHECK-SAME: i32 [[X:%.*]]) { |
| ; CHECK-NEXT: entry: |
| ; CHECK-NEXT: switch i32 [[X]], label [[JOIN:%.*]] [ |
| ; CHECK-NEXT: i32 1, label [[CASE1:%.*]] |
| ; CHECK-NEXT: i32 2, label [[CASE2:%.*]] |
| ; CHECK-NEXT: ] |
| ; CHECK: case1: |
| ; CHECK-NEXT: br label [[JOIN]] |
| ; CHECK: case2: |
| ; CHECK-NEXT: br label [[JOIN]] |
| ; CHECK: join: |
| ; CHECK-NEXT: [[PHI:%.*]] = phi i32 [ 1, [[CASE1]] ], [ 2, [[CASE2]] ], [ undef, [[ENTRY:%.*]] ] |
| ; CHECK-NEXT: [[ADD:%.*]] = add i32 [[PHI]], 1 |
| ; CHECK-NEXT: ret i32 [[ADD]] |
| ; |
| entry: |
| switch i32 %x, label %join [ |
| i32 1, label %case1 |
| i32 2, label %case2 |
| ] |
| |
| case1: |
| br label %join |
| |
| case2: |
| br label %join |
| |
| join: |
| %phi = phi i32 [ 1, %case1 ], [ 2, %case2 ], [ undef, %entry ] |
| %add = add i32 %phi, 1 |
| ret i32 %add |
| } |
| |
| ;. |
| ; CHECK: [[RNG0]] = !{i32 0, i32 2147483647} |
| ;. |