1*a34b5212SMax Kazantsev; NOTE: Assertions have been autogenerated by utils/update_test_checks.py 2*a34b5212SMax Kazantsev; RUN: opt -passes=constraint-elimination -S %s | FileCheck %s 3*a34b5212SMax Kazantsev 4*a34b5212SMax Kazantsev; Here we can remove range check because: 5*a34b5212SMax Kazantsev; length >= min_length (from entry) 6*a34b5212SMax Kazantsev; idx < min_length (from in_bounds check) 7*a34b5212SMax Kazantsev; therefore, idx < length is trivially true. 8*a34b5212SMax Kazantsev 9*a34b5212SMax Kazantsevdefine i32 @test_01(ptr %p, ptr %array, i32 %min_length) { 10*a34b5212SMax Kazantsev; CHECK-LABEL: @test_01( 11*a34b5212SMax Kazantsev; CHECK-NEXT: entry: 12*a34b5212SMax Kazantsev; CHECK-NEXT: br label [[LOOP:%.*]] 13*a34b5212SMax Kazantsev; CHECK: loop: 14*a34b5212SMax Kazantsev; CHECK-NEXT: [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ] 15*a34b5212SMax Kazantsev; CHECK-NEXT: [[ELEM_PTR:%.*]] = getelementptr i32, ptr [[P:%.*]], i32 [[IV]] 16*a34b5212SMax Kazantsev; CHECK-NEXT: [[IDX:%.*]] = load i32, ptr [[ELEM_PTR]], align 4 17*a34b5212SMax Kazantsev; CHECK-NEXT: [[IN_BOUNDS:%.*]] = icmp ult i32 [[IDX]], [[MIN_LENGTH:%.*]] 18*a34b5212SMax Kazantsev; CHECK-NEXT: br i1 [[IN_BOUNDS]], label [[RANGE_CHECK_BLOCK:%.*]], label [[OUT_OF_BOUNDS:%.*]] 19*a34b5212SMax Kazantsev; CHECK: range_check_block: 20*a34b5212SMax Kazantsev; CHECK-NEXT: br i1 true, label [[BACKEDGE]], label [[RANGE_CHECK_FAILED:%.*]] 21*a34b5212SMax Kazantsev; CHECK: backedge: 22*a34b5212SMax Kazantsev; CHECK-NEXT: [[ARR_PTR:%.*]] = getelementptr i32, ptr [[ARRAY:%.*]], i32 [[IDX]] 23*a34b5212SMax Kazantsev; CHECK-NEXT: store i32 [[IV]], ptr [[ARR_PTR]], align 4 24*a34b5212SMax Kazantsev; CHECK-NEXT: [[IV_NEXT]] = add i32 [[IV]], 1 25*a34b5212SMax Kazantsev; CHECK-NEXT: [[LOOP_COND:%.*]] = call i1 @cond() 26*a34b5212SMax Kazantsev; CHECK-NEXT: br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT:%.*]] 27*a34b5212SMax Kazantsev; CHECK: exit: 28*a34b5212SMax Kazantsev; CHECK-NEXT: [[IV_LCSSA:%.*]] = phi i32 [ [[IV]], [[BACKEDGE]] ] 29*a34b5212SMax Kazantsev; CHECK-NEXT: ret i32 [[IV_LCSSA]] 30*a34b5212SMax Kazantsev; CHECK: out_of_bounds: 31*a34b5212SMax Kazantsev; CHECK-NEXT: ret i32 -1 32*a34b5212SMax Kazantsev; CHECK: range_check_failed: 33*a34b5212SMax Kazantsev; CHECK-NEXT: [[IV_LCSSA_RC:%.*]] = phi i32 [ [[IV]], [[RANGE_CHECK_BLOCK]] ] 34*a34b5212SMax Kazantsev; CHECK-NEXT: call void @failed_range_check(i32 [[IV_LCSSA_RC]]) 35*a34b5212SMax Kazantsev; CHECK-NEXT: unreachable 36*a34b5212SMax Kazantsev; 37*a34b5212SMax Kazantseventry: 38*a34b5212SMax Kazantsev br label %loop 39*a34b5212SMax Kazantsev 40*a34b5212SMax Kazantsevloop: ; preds = %backedge, %entry 41*a34b5212SMax Kazantsev %iv = phi i32 [ 0, %entry ], [ %iv.next, %backedge ] 42*a34b5212SMax Kazantsev %elem_ptr = getelementptr i32, ptr %p, i32 %iv 43*a34b5212SMax Kazantsev %idx = load i32, ptr %elem_ptr, align 4 44*a34b5212SMax Kazantsev %in_bounds = icmp ult i32 %idx, %min_length 45*a34b5212SMax Kazantsev br i1 %in_bounds, label %range_check_block, label %out_of_bounds 46*a34b5212SMax Kazantsev 47*a34b5212SMax Kazantsevrange_check_block: ; preds = %loop 48*a34b5212SMax Kazantsev %range_check = icmp ult i32 %idx, %min_length 49*a34b5212SMax Kazantsev br i1 %range_check, label %backedge, label %range_check_failed 50*a34b5212SMax Kazantsev 51*a34b5212SMax Kazantsevbackedge: ; preds = %range_check_block 52*a34b5212SMax Kazantsev %arr_ptr = getelementptr i32, ptr %array, i32 %idx 53*a34b5212SMax Kazantsev store i32 %iv, ptr %arr_ptr, align 4 54*a34b5212SMax Kazantsev %iv.next = add i32 %iv, 1 55*a34b5212SMax Kazantsev %loop_cond = call i1 @cond() 56*a34b5212SMax Kazantsev br i1 %loop_cond, label %loop, label %exit 57*a34b5212SMax Kazantsev 58*a34b5212SMax Kazantsevexit: ; preds = %backedge 59*a34b5212SMax Kazantsev %iv.lcssa = phi i32 [ %iv, %backedge ] 60*a34b5212SMax Kazantsev ret i32 %iv.lcssa 61*a34b5212SMax Kazantsev 62*a34b5212SMax Kazantsevout_of_bounds: ; preds = %loop 63*a34b5212SMax Kazantsev ret i32 -1 64*a34b5212SMax Kazantsev 65*a34b5212SMax Kazantsevrange_check_failed: ; preds = %range_check_block 66*a34b5212SMax Kazantsev %iv.lcssa.rc = phi i32 [ %iv, %range_check_block ] 67*a34b5212SMax Kazantsev call void @failed_range_check(i32 %iv.lcssa.rc) 68*a34b5212SMax Kazantsev unreachable 69*a34b5212SMax Kazantsev} 70*a34b5212SMax Kazantsev 71*a34b5212SMax Kazantsevdefine i32 @test_02(ptr %p, ptr %array, i32 %length, i32 %min_length) { 72*a34b5212SMax Kazantsev; CHECK-LABEL: @test_02( 73*a34b5212SMax Kazantsev; CHECK-NEXT: entry: 74*a34b5212SMax Kazantsev; CHECK-NEXT: [[LENGTH_CHECK:%.*]] = icmp uge i32 [[LENGTH:%.*]], [[MIN_LENGTH:%.*]] 75*a34b5212SMax Kazantsev; CHECK-NEXT: br i1 [[LENGTH_CHECK]], label [[LOOP:%.*]], label [[FAILED:%.*]] 76*a34b5212SMax Kazantsev; CHECK: loop: 77*a34b5212SMax Kazantsev; CHECK-NEXT: [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ] 78*a34b5212SMax Kazantsev; CHECK-NEXT: [[ELEM_PTR:%.*]] = getelementptr i32, ptr [[P:%.*]], i32 [[IV]] 79*a34b5212SMax Kazantsev; CHECK-NEXT: [[IDX:%.*]] = load i32, ptr [[ELEM_PTR]], align 4 80*a34b5212SMax Kazantsev; CHECK-NEXT: [[IN_BOUNDS:%.*]] = icmp ult i32 [[IDX]], [[MIN_LENGTH]] 81*a34b5212SMax Kazantsev; CHECK-NEXT: br i1 [[IN_BOUNDS]], label [[RANGE_CHECK_BLOCK:%.*]], label [[OUT_OF_BOUNDS:%.*]] 82*a34b5212SMax Kazantsev; CHECK: range_check_block: 83*a34b5212SMax Kazantsev; CHECK-NEXT: br i1 true, label [[BACKEDGE]], label [[RANGE_CHECK_FAILED:%.*]] 84*a34b5212SMax Kazantsev; CHECK: backedge: 85*a34b5212SMax Kazantsev; CHECK-NEXT: [[ARR_PTR:%.*]] = getelementptr i32, ptr [[ARRAY:%.*]], i32 [[IDX]] 86*a34b5212SMax Kazantsev; CHECK-NEXT: store i32 [[IV]], ptr [[ARR_PTR]], align 4 87*a34b5212SMax Kazantsev; CHECK-NEXT: [[IV_NEXT]] = add i32 [[IV]], 1 88*a34b5212SMax Kazantsev; CHECK-NEXT: [[LOOP_COND:%.*]] = call i1 @cond() 89*a34b5212SMax Kazantsev; CHECK-NEXT: br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT:%.*]] 90*a34b5212SMax Kazantsev; CHECK: exit: 91*a34b5212SMax Kazantsev; CHECK-NEXT: [[IV_LCSSA:%.*]] = phi i32 [ [[IV]], [[BACKEDGE]] ] 92*a34b5212SMax Kazantsev; CHECK-NEXT: ret i32 [[IV_LCSSA]] 93*a34b5212SMax Kazantsev; CHECK: failed: 94*a34b5212SMax Kazantsev; CHECK-NEXT: unreachable 95*a34b5212SMax Kazantsev; CHECK: out_of_bounds: 96*a34b5212SMax Kazantsev; CHECK-NEXT: ret i32 -1 97*a34b5212SMax Kazantsev; CHECK: range_check_failed: 98*a34b5212SMax Kazantsev; CHECK-NEXT: [[IV_LCSSA_RC:%.*]] = phi i32 [ [[IV]], [[RANGE_CHECK_BLOCK]] ] 99*a34b5212SMax Kazantsev; CHECK-NEXT: call void @failed_range_check(i32 [[IV_LCSSA_RC]]) 100*a34b5212SMax Kazantsev; CHECK-NEXT: unreachable 101*a34b5212SMax Kazantsev; 102*a34b5212SMax Kazantseventry: 103*a34b5212SMax Kazantsev %length_check = icmp uge i32 %length, %min_length 104*a34b5212SMax Kazantsev br i1 %length_check, label %loop, label %failed 105*a34b5212SMax Kazantsev 106*a34b5212SMax Kazantsevloop: ; preds = %backedge, %entry 107*a34b5212SMax Kazantsev %iv = phi i32 [ 0, %entry ], [ %iv.next, %backedge ] 108*a34b5212SMax Kazantsev %elem_ptr = getelementptr i32, ptr %p, i32 %iv 109*a34b5212SMax Kazantsev %idx = load i32, ptr %elem_ptr, align 4 110*a34b5212SMax Kazantsev %in_bounds = icmp ult i32 %idx, %min_length 111*a34b5212SMax Kazantsev br i1 %in_bounds, label %range_check_block, label %out_of_bounds 112*a34b5212SMax Kazantsev 113*a34b5212SMax Kazantsevrange_check_block: ; preds = %loop 114*a34b5212SMax Kazantsev %range_check = icmp ult i32 %idx, %length 115*a34b5212SMax Kazantsev br i1 %range_check, label %backedge, label %range_check_failed 116*a34b5212SMax Kazantsev 117*a34b5212SMax Kazantsevbackedge: ; preds = %range_check_block 118*a34b5212SMax Kazantsev %arr_ptr = getelementptr i32, ptr %array, i32 %idx 119*a34b5212SMax Kazantsev store i32 %iv, ptr %arr_ptr, align 4 120*a34b5212SMax Kazantsev %iv.next = add i32 %iv, 1 121*a34b5212SMax Kazantsev %loop_cond = call i1 @cond() 122*a34b5212SMax Kazantsev br i1 %loop_cond, label %loop, label %exit 123*a34b5212SMax Kazantsev 124*a34b5212SMax Kazantsevexit: ; preds = %backedge 125*a34b5212SMax Kazantsev %iv.lcssa = phi i32 [ %iv, %backedge ] 126*a34b5212SMax Kazantsev ret i32 %iv.lcssa 127*a34b5212SMax Kazantsev 128*a34b5212SMax Kazantsevfailed: ; preds = %entry 129*a34b5212SMax Kazantsev unreachable 130*a34b5212SMax Kazantsev 131*a34b5212SMax Kazantsevout_of_bounds: ; preds = %loop 132*a34b5212SMax Kazantsev ret i32 -1 133*a34b5212SMax Kazantsev 134*a34b5212SMax Kazantsevrange_check_failed: ; preds = %range_check_block 135*a34b5212SMax Kazantsev %iv.lcssa.rc = phi i32 [ %iv, %range_check_block ] 136*a34b5212SMax Kazantsev call void @failed_range_check(i32 %iv.lcssa.rc) 137*a34b5212SMax Kazantsev unreachable 138*a34b5212SMax Kazantsev} 139*a34b5212SMax Kazantsev 140*a34b5212SMax Kazantsevdeclare i1 @cond() 141*a34b5212SMax Kazantsev 142*a34b5212SMax Kazantsevdeclare void @failed_range_check(i32) 143