Remove compares after replacing all uses. Cleaning dead compares can enable additional simplifications when adjusting the position of the pass slightly. In particular, it seems like the additional dead instructions may prevent SimplifyCFG performing some folds. Reviewed By: nikic Differential Revision: https://reviews.llvm.org/D158760
143 lines
5.9 KiB
LLVM
143 lines
5.9 KiB
LLVM
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
|
|
; RUN: opt -passes=constraint-elimination -S %s | FileCheck %s
|
|
|
|
; Here we can remove range check because:
|
|
; length >= min_length (from entry)
|
|
; idx < min_length (from in_bounds check)
|
|
; therefore, idx < length is trivially true.
|
|
|
|
define i32 @test_01(ptr %p, ptr %array, i32 %min_length) {
|
|
; CHECK-LABEL: @test_01(
|
|
; CHECK-NEXT: entry:
|
|
; CHECK-NEXT: br label [[LOOP:%.*]]
|
|
; CHECK: loop:
|
|
; CHECK-NEXT: [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ]
|
|
; CHECK-NEXT: [[ELEM_PTR:%.*]] = getelementptr i32, ptr [[P:%.*]], i32 [[IV]]
|
|
; CHECK-NEXT: [[IDX:%.*]] = load i32, ptr [[ELEM_PTR]], align 4
|
|
; CHECK-NEXT: [[IN_BOUNDS:%.*]] = icmp ult i32 [[IDX]], [[MIN_LENGTH:%.*]]
|
|
; CHECK-NEXT: br i1 [[IN_BOUNDS]], label [[RANGE_CHECK_BLOCK:%.*]], label [[OUT_OF_BOUNDS:%.*]]
|
|
; CHECK: range_check_block:
|
|
; CHECK-NEXT: br i1 true, label [[BACKEDGE]], label [[RANGE_CHECK_FAILED:%.*]]
|
|
; CHECK: backedge:
|
|
; CHECK-NEXT: [[ARR_PTR:%.*]] = getelementptr i32, ptr [[ARRAY:%.*]], i32 [[IDX]]
|
|
; CHECK-NEXT: store i32 [[IV]], ptr [[ARR_PTR]], align 4
|
|
; CHECK-NEXT: [[IV_NEXT]] = add i32 [[IV]], 1
|
|
; CHECK-NEXT: [[LOOP_COND:%.*]] = call i1 @cond()
|
|
; CHECK-NEXT: br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT:%.*]]
|
|
; CHECK: exit:
|
|
; CHECK-NEXT: [[IV_LCSSA:%.*]] = phi i32 [ [[IV]], [[BACKEDGE]] ]
|
|
; CHECK-NEXT: ret i32 [[IV_LCSSA]]
|
|
; CHECK: out_of_bounds:
|
|
; CHECK-NEXT: ret i32 -1
|
|
; CHECK: range_check_failed:
|
|
; CHECK-NEXT: [[IV_LCSSA_RC:%.*]] = phi i32 [ [[IV]], [[RANGE_CHECK_BLOCK]] ]
|
|
; CHECK-NEXT: call void @failed_range_check(i32 [[IV_LCSSA_RC]])
|
|
; CHECK-NEXT: unreachable
|
|
;
|
|
entry:
|
|
br label %loop
|
|
|
|
loop: ; preds = %backedge, %entry
|
|
%iv = phi i32 [ 0, %entry ], [ %iv.next, %backedge ]
|
|
%elem_ptr = getelementptr i32, ptr %p, i32 %iv
|
|
%idx = load i32, ptr %elem_ptr, align 4
|
|
%in_bounds = icmp ult i32 %idx, %min_length
|
|
br i1 %in_bounds, label %range_check_block, label %out_of_bounds
|
|
|
|
range_check_block: ; preds = %loop
|
|
%range_check = icmp ult i32 %idx, %min_length
|
|
br i1 %range_check, label %backedge, label %range_check_failed
|
|
|
|
backedge: ; preds = %range_check_block
|
|
%arr_ptr = getelementptr i32, ptr %array, i32 %idx
|
|
store i32 %iv, ptr %arr_ptr, align 4
|
|
%iv.next = add i32 %iv, 1
|
|
%loop_cond = call i1 @cond()
|
|
br i1 %loop_cond, label %loop, label %exit
|
|
|
|
exit: ; preds = %backedge
|
|
%iv.lcssa = phi i32 [ %iv, %backedge ]
|
|
ret i32 %iv.lcssa
|
|
|
|
out_of_bounds: ; preds = %loop
|
|
ret i32 -1
|
|
|
|
range_check_failed: ; preds = %range_check_block
|
|
%iv.lcssa.rc = phi i32 [ %iv, %range_check_block ]
|
|
call void @failed_range_check(i32 %iv.lcssa.rc)
|
|
unreachable
|
|
}
|
|
|
|
define i32 @test_02(ptr %p, ptr %array, i32 %length, i32 %min_length) {
|
|
; CHECK-LABEL: @test_02(
|
|
; CHECK-NEXT: entry:
|
|
; CHECK-NEXT: [[LENGTH_CHECK:%.*]] = icmp uge i32 [[LENGTH:%.*]], [[MIN_LENGTH:%.*]]
|
|
; CHECK-NEXT: br i1 [[LENGTH_CHECK]], label [[LOOP:%.*]], label [[FAILED:%.*]]
|
|
; CHECK: loop:
|
|
; CHECK-NEXT: [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ]
|
|
; CHECK-NEXT: [[ELEM_PTR:%.*]] = getelementptr i32, ptr [[P:%.*]], i32 [[IV]]
|
|
; CHECK-NEXT: [[IDX:%.*]] = load i32, ptr [[ELEM_PTR]], align 4
|
|
; CHECK-NEXT: [[IN_BOUNDS:%.*]] = icmp ult i32 [[IDX]], [[MIN_LENGTH]]
|
|
; CHECK-NEXT: br i1 [[IN_BOUNDS]], label [[RANGE_CHECK_BLOCK:%.*]], label [[OUT_OF_BOUNDS:%.*]]
|
|
; CHECK: range_check_block:
|
|
; CHECK-NEXT: br i1 true, label [[BACKEDGE]], label [[RANGE_CHECK_FAILED:%.*]]
|
|
; CHECK: backedge:
|
|
; CHECK-NEXT: [[ARR_PTR:%.*]] = getelementptr i32, ptr [[ARRAY:%.*]], i32 [[IDX]]
|
|
; CHECK-NEXT: store i32 [[IV]], ptr [[ARR_PTR]], align 4
|
|
; CHECK-NEXT: [[IV_NEXT]] = add i32 [[IV]], 1
|
|
; CHECK-NEXT: [[LOOP_COND:%.*]] = call i1 @cond()
|
|
; CHECK-NEXT: br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT:%.*]]
|
|
; CHECK: exit:
|
|
; CHECK-NEXT: [[IV_LCSSA:%.*]] = phi i32 [ [[IV]], [[BACKEDGE]] ]
|
|
; CHECK-NEXT: ret i32 [[IV_LCSSA]]
|
|
; CHECK: failed:
|
|
; CHECK-NEXT: unreachable
|
|
; CHECK: out_of_bounds:
|
|
; CHECK-NEXT: ret i32 -1
|
|
; CHECK: range_check_failed:
|
|
; CHECK-NEXT: [[IV_LCSSA_RC:%.*]] = phi i32 [ [[IV]], [[RANGE_CHECK_BLOCK]] ]
|
|
; CHECK-NEXT: call void @failed_range_check(i32 [[IV_LCSSA_RC]])
|
|
; CHECK-NEXT: unreachable
|
|
;
|
|
entry:
|
|
%length_check = icmp uge i32 %length, %min_length
|
|
br i1 %length_check, label %loop, label %failed
|
|
|
|
loop: ; preds = %backedge, %entry
|
|
%iv = phi i32 [ 0, %entry ], [ %iv.next, %backedge ]
|
|
%elem_ptr = getelementptr i32, ptr %p, i32 %iv
|
|
%idx = load i32, ptr %elem_ptr, align 4
|
|
%in_bounds = icmp ult i32 %idx, %min_length
|
|
br i1 %in_bounds, label %range_check_block, label %out_of_bounds
|
|
|
|
range_check_block: ; preds = %loop
|
|
%range_check = icmp ult i32 %idx, %length
|
|
br i1 %range_check, label %backedge, label %range_check_failed
|
|
|
|
backedge: ; preds = %range_check_block
|
|
%arr_ptr = getelementptr i32, ptr %array, i32 %idx
|
|
store i32 %iv, ptr %arr_ptr, align 4
|
|
%iv.next = add i32 %iv, 1
|
|
%loop_cond = call i1 @cond()
|
|
br i1 %loop_cond, label %loop, label %exit
|
|
|
|
exit: ; preds = %backedge
|
|
%iv.lcssa = phi i32 [ %iv, %backedge ]
|
|
ret i32 %iv.lcssa
|
|
|
|
failed: ; preds = %entry
|
|
unreachable
|
|
|
|
out_of_bounds: ; preds = %loop
|
|
ret i32 -1
|
|
|
|
range_check_failed: ; preds = %range_check_block
|
|
%iv.lcssa.rc = phi i32 [ %iv, %range_check_block ]
|
|
call void @failed_range_check(i32 %iv.lcssa.rc)
|
|
unreachable
|
|
}
|
|
|
|
declare i1 @cond()
|
|
|
|
declare void @failed_range_check(i32)
|