143 lines · plain
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py2; RUN: opt -passes=constraint-elimination -S %s | FileCheck %s3 4; Here we can remove range check because:5; length >= min_length (from entry)6; idx < min_length (from in_bounds check)7; therefore, idx < length is trivially true.8 9define i32 @test_01(ptr %p, ptr %array, i32 %min_length) {10; CHECK-LABEL: @test_01(11; CHECK-NEXT: entry:12; CHECK-NEXT: br label [[LOOP:%.*]]13; CHECK: loop:14; CHECK-NEXT: [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ]15; CHECK-NEXT: [[ELEM_PTR:%.*]] = getelementptr i32, ptr [[P:%.*]], i32 [[IV]]16; CHECK-NEXT: [[IDX:%.*]] = load i32, ptr [[ELEM_PTR]], align 417; CHECK-NEXT: [[IN_BOUNDS:%.*]] = icmp ult i32 [[IDX]], [[MIN_LENGTH:%.*]]18; CHECK-NEXT: br i1 [[IN_BOUNDS]], label [[RANGE_CHECK_BLOCK:%.*]], label [[OUT_OF_BOUNDS:%.*]]19; CHECK: range_check_block:20; CHECK-NEXT: br i1 true, label [[BACKEDGE]], label [[RANGE_CHECK_FAILED:%.*]]21; CHECK: backedge:22; CHECK-NEXT: [[ARR_PTR:%.*]] = getelementptr i32, ptr [[ARRAY:%.*]], i32 [[IDX]]23; CHECK-NEXT: store i32 [[IV]], ptr [[ARR_PTR]], align 424; CHECK-NEXT: [[IV_NEXT]] = add i32 [[IV]], 125; CHECK-NEXT: [[LOOP_COND:%.*]] = call i1 @cond()26; CHECK-NEXT: br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT:%.*]]27; CHECK: exit:28; CHECK-NEXT: [[IV_LCSSA:%.*]] = phi i32 [ [[IV]], [[BACKEDGE]] ]29; CHECK-NEXT: ret i32 [[IV_LCSSA]]30; CHECK: out_of_bounds:31; CHECK-NEXT: ret i32 -132; CHECK: range_check_failed:33; CHECK-NEXT: [[IV_LCSSA_RC:%.*]] = phi i32 [ [[IV]], [[RANGE_CHECK_BLOCK]] ]34; CHECK-NEXT: call void @failed_range_check(i32 [[IV_LCSSA_RC]])35; CHECK-NEXT: unreachable36;37entry:38 br label %loop39 40loop: ; preds = %backedge, %entry41 %iv = phi i32 [ 0, %entry ], [ %iv.next, %backedge ]42 %elem_ptr = getelementptr i32, ptr %p, i32 %iv43 %idx = load i32, ptr %elem_ptr, align 444 %in_bounds = icmp ult i32 %idx, %min_length45 br i1 %in_bounds, label %range_check_block, label %out_of_bounds46 47range_check_block: ; preds = %loop48 %range_check = icmp ult i32 %idx, %min_length49 br i1 %range_check, label %backedge, label %range_check_failed50 51backedge: ; preds = %range_check_block52 %arr_ptr = getelementptr i32, ptr %array, i32 %idx53 store i32 %iv, ptr %arr_ptr, align 454 %iv.next = add i32 %iv, 155 %loop_cond = call i1 @cond()56 br i1 %loop_cond, label %loop, label %exit57 58exit: ; preds = %backedge59 %iv.lcssa = phi i32 [ %iv, %backedge ]60 ret i32 %iv.lcssa61 62out_of_bounds: ; preds = %loop63 ret i32 -164 65range_check_failed: ; preds = %range_check_block66 %iv.lcssa.rc = phi i32 [ %iv, %range_check_block ]67 call void @failed_range_check(i32 %iv.lcssa.rc)68 unreachable69}70 71define i32 @test_02(ptr %p, ptr %array, i32 %length, i32 %min_length) {72; CHECK-LABEL: @test_02(73; CHECK-NEXT: entry:74; CHECK-NEXT: [[LENGTH_CHECK:%.*]] = icmp uge i32 [[LENGTH:%.*]], [[MIN_LENGTH:%.*]]75; CHECK-NEXT: br i1 [[LENGTH_CHECK]], label [[LOOP:%.*]], label [[FAILED:%.*]]76; CHECK: loop:77; CHECK-NEXT: [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ]78; CHECK-NEXT: [[ELEM_PTR:%.*]] = getelementptr i32, ptr [[P:%.*]], i32 [[IV]]79; CHECK-NEXT: [[IDX:%.*]] = load i32, ptr [[ELEM_PTR]], align 480; CHECK-NEXT: [[IN_BOUNDS:%.*]] = icmp ult i32 [[IDX]], [[MIN_LENGTH]]81; CHECK-NEXT: br i1 [[IN_BOUNDS]], label [[RANGE_CHECK_BLOCK:%.*]], label [[OUT_OF_BOUNDS:%.*]]82; CHECK: range_check_block:83; CHECK-NEXT: br i1 true, label [[BACKEDGE]], label [[RANGE_CHECK_FAILED:%.*]]84; CHECK: backedge:85; CHECK-NEXT: [[ARR_PTR:%.*]] = getelementptr i32, ptr [[ARRAY:%.*]], i32 [[IDX]]86; CHECK-NEXT: store i32 [[IV]], ptr [[ARR_PTR]], align 487; CHECK-NEXT: [[IV_NEXT]] = add i32 [[IV]], 188; CHECK-NEXT: [[LOOP_COND:%.*]] = call i1 @cond()89; CHECK-NEXT: br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT:%.*]]90; CHECK: exit:91; CHECK-NEXT: [[IV_LCSSA:%.*]] = phi i32 [ [[IV]], [[BACKEDGE]] ]92; CHECK-NEXT: ret i32 [[IV_LCSSA]]93; CHECK: failed:94; CHECK-NEXT: unreachable95; CHECK: out_of_bounds:96; CHECK-NEXT: ret i32 -197; CHECK: range_check_failed:98; CHECK-NEXT: [[IV_LCSSA_RC:%.*]] = phi i32 [ [[IV]], [[RANGE_CHECK_BLOCK]] ]99; CHECK-NEXT: call void @failed_range_check(i32 [[IV_LCSSA_RC]])100; CHECK-NEXT: unreachable101;102entry:103 %length_check = icmp uge i32 %length, %min_length104 br i1 %length_check, label %loop, label %failed105 106loop: ; preds = %backedge, %entry107 %iv = phi i32 [ 0, %entry ], [ %iv.next, %backedge ]108 %elem_ptr = getelementptr i32, ptr %p, i32 %iv109 %idx = load i32, ptr %elem_ptr, align 4110 %in_bounds = icmp ult i32 %idx, %min_length111 br i1 %in_bounds, label %range_check_block, label %out_of_bounds112 113range_check_block: ; preds = %loop114 %range_check = icmp ult i32 %idx, %length115 br i1 %range_check, label %backedge, label %range_check_failed116 117backedge: ; preds = %range_check_block118 %arr_ptr = getelementptr i32, ptr %array, i32 %idx119 store i32 %iv, ptr %arr_ptr, align 4120 %iv.next = add i32 %iv, 1121 %loop_cond = call i1 @cond()122 br i1 %loop_cond, label %loop, label %exit123 124exit: ; preds = %backedge125 %iv.lcssa = phi i32 [ %iv, %backedge ]126 ret i32 %iv.lcssa127 128failed: ; preds = %entry129 unreachable130 131out_of_bounds: ; preds = %loop132 ret i32 -1133 134range_check_failed: ; preds = %range_check_block135 %iv.lcssa.rc = phi i32 [ %iv, %range_check_block ]136 call void @failed_range_check(i32 %iv.lcssa.rc)137 unreachable138}139 140declare i1 @cond()141 142declare void @failed_range_check(i32)143