Skip to content

Commit

Permalink
[IRCE] Add NSW flag to main loop's indvar base
Browse files Browse the repository at this point in the history
We have guarantees that induction variable will not overflow in the main
loop after the loop constrained. Therefore we can add no wrap flags on
its base in order not to miss info that loop is countable.

Add NSW flag now, since adding NUW flag requires a bit more complicated
analysis.

Reviewed By: skatkov

Differential Revision: https://reviews.llvm.org/D154954
  • Loading branch information
aleks-tmb committed Jul 16, 2023
1 parent 33acdc1 commit bca5501
Show file tree
Hide file tree
Showing 9 changed files with 90 additions and 69 deletions.
21 changes: 21 additions & 0 deletions llvm/lib/Transforms/Scalar/InductiveRangeCheckElimination.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1717,6 +1717,27 @@ bool LoopConstrainer::run() {
CanonicalizeLoop(PostL, false);
CanonicalizeLoop(&OriginalLoop, true);

/// At this point:
/// - We've broken a "main loop" out of the loop in a way that the "main loop"
/// runs with the induction variable in a subset of [Begin, End).
/// - There is no overflow when computing "main loop" exit limit.
/// - Max latch taken count of the loop is limited.
/// It guarantees that induction variable will not overflow iterating in the
/// "main loop".
if (auto BO = dyn_cast<BinaryOperator>(MainLoopStructure.IndVarBase))
if (IsSignedPredicate)
BO->setHasNoSignedWrap(true);
/// TODO: support unsigned predicate.
/// To add NUW flag we need to prove that both operands of BO are
/// non-negative. E.g:
/// ...
/// %iv.next = add nsw i32 %iv, -1
/// %cmp = icmp ult i32 %iv.next, %n
/// br i1 %cmp, label %loopexit, label %loop
///
/// -1 is MAX_UINT in terms of unsigned int. Adding anything but zero will
/// overflow, therefore NUW flag is not legal here.

return true;
}

Expand Down
8 changes: 4 additions & 4 deletions llvm/test/Transforms/IRCE/conjunctive-checks.ll
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ define void @f_0(ptr %arr, ptr %a_len_ptr, i32 %n, ptr %cond_buf) {
; CHECK-NEXT: br label [[LOOP:%.*]]
; CHECK: loop:
; CHECK-NEXT: [[IDX:%.*]] = phi i32 [ [[IDX_NEXT:%.*]], [[IN_BOUNDS:%.*]] ], [ 0, [[LOOP_PREHEADER1]] ]
; CHECK-NEXT: [[IDX_NEXT]] = add i32 [[IDX]], 1
; CHECK-NEXT: [[IDX_NEXT]] = add nsw i32 [[IDX]], 1
; CHECK-NEXT: [[IDX_FOR_ABC:%.*]] = add i32 [[IDX]], 4
; CHECK-NEXT: [[ABC_ACTUAL:%.*]] = icmp slt i32 [[IDX_FOR_ABC]], [[LEN]]
; CHECK-NEXT: [[COND:%.*]] = load volatile i1, ptr [[COND_BUF:%.*]], align 1
Expand Down Expand Up @@ -64,7 +64,7 @@ define void @f_0(ptr %arr, ptr %a_len_ptr, i32 %n, ptr %cond_buf) {
; CHECK-NEXT: [[ADDR_POSTLOOP:%.*]] = getelementptr i32, ptr [[ARR]], i32 [[IDX_FOR_ABC_POSTLOOP]]
; CHECK-NEXT: store i32 0, ptr [[ADDR_POSTLOOP]], align 4
; CHECK-NEXT: [[NEXT_POSTLOOP:%.*]] = icmp slt i32 [[IDX_NEXT_POSTLOOP]], [[N]]
; CHECK-NEXT: br i1 [[NEXT_POSTLOOP]], label [[LOOP_POSTLOOP]], label [[EXIT_LOOPEXIT_LOOPEXIT:%.*]], !llvm.loop [[LOOP2:![0-9]+]], !irce.loop.clone !7
; CHECK-NEXT: br i1 [[NEXT_POSTLOOP]], label [[LOOP_POSTLOOP]], label [[EXIT_LOOPEXIT_LOOPEXIT:%.*]], !llvm.loop [[LOOP2:![0-9]+]], !irce.loop.clone [[META7:![0-9]+]]
;
entry:
%len = load i32, ptr %a_len_ptr, !range !0
Expand Down Expand Up @@ -110,7 +110,7 @@ define void @f_1(
; CHECK-NEXT: br label [[LOOP:%.*]]
; CHECK: loop:
; CHECK-NEXT: [[IDX:%.*]] = phi i32 [ [[IDX_NEXT:%.*]], [[IN_BOUNDS:%.*]] ], [ 0, [[LOOP_PREHEADER2]] ]
; CHECK-NEXT: [[IDX_NEXT]] = add i32 [[IDX]], 1
; CHECK-NEXT: [[IDX_NEXT]] = add nsw i32 [[IDX]], 1
; CHECK-NEXT: [[ABC_A:%.*]] = icmp slt i32 [[IDX]], [[LEN_A]]
; CHECK-NEXT: [[ABC_B:%.*]] = icmp slt i32 [[IDX]], [[LEN_B]]
; CHECK-NEXT: [[ABC:%.*]] = and i1 true, true
Expand Down Expand Up @@ -158,7 +158,7 @@ define void @f_1(
; CHECK-NEXT: [[ADDR_B_POSTLOOP:%.*]] = getelementptr i32, ptr [[ARR_B]], i32 [[IDX_POSTLOOP]]
; CHECK-NEXT: store i32 -1, ptr [[ADDR_B_POSTLOOP]], align 4
; CHECK-NEXT: [[NEXT_POSTLOOP:%.*]] = icmp slt i32 [[IDX_NEXT_POSTLOOP]], [[N]]
; CHECK-NEXT: br i1 [[NEXT_POSTLOOP]], label [[LOOP_POSTLOOP]], label [[EXIT_LOOPEXIT_LOOPEXIT:%.*]], !llvm.loop [[LOOP8:![0-9]+]], !irce.loop.clone !7
; CHECK-NEXT: br i1 [[NEXT_POSTLOOP]], label [[LOOP_POSTLOOP]], label [[EXIT_LOOPEXIT_LOOPEXIT:%.*]], !llvm.loop [[LOOP8:![0-9]+]], !irce.loop.clone [[META7]]
;
ptr %arr_a, ptr %a_len_ptr, ptr %arr_b, ptr %b_len_ptr, i32 %n) {

Expand Down
6 changes: 3 additions & 3 deletions llvm/test/Transforms/IRCE/correct-loop-info.ll
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ define void @baz() personality ptr @ham {
; CHECK-NEXT: invoke void @pluto()
; CHECK-NEXT: to label [[BB5:%.*]] unwind label [[OUTER_EXITING_LOOPEXIT_SPLIT_LP_LOOPEXIT_SPLIT_LP:%.*]]
; CHECK: bb5:
; CHECK-NEXT: [[TMP6]] = add i32 [[TMP4]], 1
; CHECK-NEXT: [[TMP6]] = add nsw i32 [[TMP4]], 1
; CHECK-NEXT: [[TMP7:%.*]] = icmp slt i32 [[TMP6]], 1
; CHECK-NEXT: br i1 true, label [[BB8]], label [[EXIT3_LOOPEXIT5:%.*]]
; CHECK: bb8:
Expand Down Expand Up @@ -99,7 +99,7 @@ define void @baz() personality ptr @ham {
; CHECK: bb8.preloop:
; CHECK-NEXT: [[TMP9_PRELOOP:%.*]] = icmp slt i32 [[TMP6_PRELOOP]], 84
; CHECK-NEXT: [[TMP4:%.*]] = icmp slt i32 [[TMP6_PRELOOP]], [[EXIT_PRELOOP_AT]]
; CHECK-NEXT: br i1 [[TMP4]], label [[INNERHEADER_PRELOOP]], label [[PRELOOP_EXIT_SELECTOR:%.*]], [[LOOP0:!llvm.loop !.*]], !irce.loop.clone !5
; CHECK-NEXT: br i1 [[TMP4]], label [[INNERHEADER_PRELOOP]], label [[PRELOOP_EXIT_SELECTOR:%.*]], !llvm.loop [[LOOP0:![0-9]+]], !irce.loop.clone [[META5:![0-9]+]]
; CHECK: preloop.exit.selector:
; CHECK-NEXT: [[TMP6_PRELOOP_LCSSA:%.*]] = phi i32 [ [[TMP6_PRELOOP]], [[BB8_PRELOOP]] ]
; CHECK-NEXT: [[TMP5:%.*]] = icmp slt i32 [[TMP6_PRELOOP_LCSSA]], 84
Expand All @@ -120,7 +120,7 @@ define void @baz() personality ptr @ham {
; CHECK-NEXT: br i1 [[TMP7_POSTLOOP]], label [[BB8_POSTLOOP]], label [[EXIT3_LOOPEXIT4:%.*]]
; CHECK: bb8.postloop:
; CHECK-NEXT: [[TMP9_POSTLOOP:%.*]] = icmp slt i32 [[TMP6_POSTLOOP]], 84
; CHECK-NEXT: br i1 [[TMP9_POSTLOOP]], label [[INNERHEADER_POSTLOOP]], label [[BB13_LOOPEXIT:%.*]], [[LOOP6:!llvm.loop !.*]], !irce.loop.clone !5
; CHECK-NEXT: br i1 [[TMP9_POSTLOOP]], label [[INNERHEADER_POSTLOOP]], label [[BB13_LOOPEXIT:%.*]], !llvm.loop [[LOOP6:![0-9]+]], !irce.loop.clone [[META5]]
;
bb:
br label %outerheader
Expand Down
18 changes: 9 additions & 9 deletions llvm/test/Transforms/IRCE/iv-plus-offset-range-check.ll
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ define i8 @test1(i8 %limit, i8 %n) {
; CHECK-NEXT: [[CHECK:%.*]] = icmp sge i8 [[SUB]], 2
; CHECK-NEXT: br i1 true, label [[INBOUNDS]], label [[OUT_OF_BOUNDS_LOOPEXIT8:%.*]]
; CHECK: inbounds:
; CHECK-NEXT: [[IDX_NEXT]] = add nuw i8 [[IDX]], 1
; CHECK-NEXT: [[IDX_NEXT]] = add nuw nsw i8 [[IDX]], 1
; CHECK-NEXT: [[CMP:%.*]] = icmp slt i8 [[IDX_NEXT]], [[LIMIT]]
; CHECK-NEXT: [[TMP11:%.*]] = icmp slt i8 [[IDX_NEXT]], [[EXIT_MAINLOOP_AT]]
; CHECK-NEXT: br i1 [[TMP11]], label [[LOOP]], label [[MAIN_EXIT_SELECTOR:%.*]]
Expand Down Expand Up @@ -150,7 +150,7 @@ define i8 @test1a(i8 %limit, ptr %p) {
; CHECK-NEXT: [[CHECK:%.*]] = icmp sge i8 [[SUB]], 2
; CHECK-NEXT: br i1 true, label [[INBOUNDS]], label [[OUT_OF_BOUNDS_LOOPEXIT5:%.*]]
; CHECK: inbounds:
; CHECK-NEXT: [[IDX_NEXT]] = add nuw i8 [[IDX]], 1
; CHECK-NEXT: [[IDX_NEXT]] = add nuw nsw i8 [[IDX]], 1
; CHECK-NEXT: [[CMP:%.*]] = icmp slt i8 [[IDX_NEXT]], [[LIMIT]]
; CHECK-NEXT: [[TMP4:%.*]] = icmp slt i8 [[IDX_NEXT]], [[EXIT_MAINLOOP_AT]]
; CHECK-NEXT: br i1 [[TMP4]], label [[LOOP]], label [[MAIN_EXIT_SELECTOR:%.*]]
Expand Down Expand Up @@ -404,7 +404,7 @@ define i8 @test3a(i8 %limit, ptr %p) {
; CHECK-NEXT: [[CHECK:%.*]] = icmp sle i8 [[ADD]], [[N]]
; CHECK-NEXT: br i1 true, label [[INBOUNDS]], label [[OUT_OF_BOUNDS_LOOPEXIT4:%.*]]
; CHECK: inbounds:
; CHECK-NEXT: [[IDX_NEXT]] = add nuw i8 [[IDX]], 1
; CHECK-NEXT: [[IDX_NEXT]] = add nuw nsw i8 [[IDX]], 1
; CHECK-NEXT: [[CMP:%.*]] = icmp slt i8 [[IDX_NEXT]], [[LIMIT]]
; CHECK-NEXT: [[TMP2:%.*]] = icmp slt i8 [[IDX_NEXT]], [[EXIT_MAINLOOP_AT]]
; CHECK-NEXT: br i1 [[TMP2]], label [[LOOP]], label [[MAIN_EXIT_SELECTOR:%.*]]
Expand Down Expand Up @@ -508,7 +508,7 @@ define i8 @test4(i8 %limit, i8 %n) {
; CHECK-NEXT: [[CHECK:%.*]] = icmp sgt i8 [[SUB]], 2
; CHECK-NEXT: br i1 true, label [[INBOUNDS]], label [[OUT_OF_BOUNDS_LOOPEXIT9:%.*]]
; CHECK: inbounds:
; CHECK-NEXT: [[IDX_NEXT]] = add nuw i8 [[IDX]], 1
; CHECK-NEXT: [[IDX_NEXT]] = add nuw nsw i8 [[IDX]], 1
; CHECK-NEXT: [[CMP:%.*]] = icmp slt i8 [[IDX_NEXT]], [[LIMIT]]
; CHECK-NEXT: [[TMP11:%.*]] = icmp slt i8 [[IDX_NEXT]], [[EXIT_MAINLOOP_AT]]
; CHECK-NEXT: br i1 [[TMP11]], label [[LOOP]], label [[MAIN_EXIT_SELECTOR:%.*]]
Expand Down Expand Up @@ -607,7 +607,7 @@ define i8 @test4a(i8 %limit, ptr %p) {
; CHECK-NEXT: [[CHECK:%.*]] = icmp sgt i8 [[SUB]], 2
; CHECK-NEXT: br i1 true, label [[INBOUNDS]], label [[OUT_OF_BOUNDS_LOOPEXIT7:%.*]]
; CHECK: inbounds:
; CHECK-NEXT: [[IDX_NEXT]] = add nuw i8 [[IDX]], 1
; CHECK-NEXT: [[IDX_NEXT]] = add nuw nsw i8 [[IDX]], 1
; CHECK-NEXT: [[CMP:%.*]] = icmp slt i8 [[IDX_NEXT]], [[LIMIT]]
; CHECK-NEXT: [[TMP7:%.*]] = icmp slt i8 [[IDX_NEXT]], [[EXIT_MAINLOOP_AT]]
; CHECK-NEXT: br i1 [[TMP7]], label [[LOOP]], label [[MAIN_EXIT_SELECTOR:%.*]]
Expand Down Expand Up @@ -812,7 +812,7 @@ define i8 @test6(i8 %limit, i8 %n) {
; CHECK-NEXT: [[CHECK:%.*]] = icmp slt i8 [[ADD]], [[N]]
; CHECK-NEXT: br i1 true, label [[INBOUNDS]], label [[OUT_OF_BOUNDS_LOOPEXIT7:%.*]]
; CHECK: inbounds:
; CHECK-NEXT: [[IDX_NEXT]] = add nuw i8 [[IDX]], 1
; CHECK-NEXT: [[IDX_NEXT]] = add nuw nsw i8 [[IDX]], 1
; CHECK-NEXT: [[CMP:%.*]] = icmp slt i8 [[IDX_NEXT]], [[LIMIT]]
; CHECK-NEXT: [[TMP5:%.*]] = icmp slt i8 [[IDX_NEXT]], [[EXIT_MAINLOOP_AT]]
; CHECK-NEXT: br i1 [[TMP5]], label [[LOOP]], label [[MAIN_EXIT_SELECTOR:%.*]]
Expand Down Expand Up @@ -903,7 +903,7 @@ define i8 @test6a(i8 %limit, ptr %p) {
; CHECK-NEXT: [[CHECK:%.*]] = icmp slt i8 [[ADD]], [[N]]
; CHECK-NEXT: br i1 true, label [[INBOUNDS]], label [[OUT_OF_BOUNDS_LOOPEXIT4:%.*]]
; CHECK: inbounds:
; CHECK-NEXT: [[IDX_NEXT]] = add nuw i8 [[IDX]], 1
; CHECK-NEXT: [[IDX_NEXT]] = add nuw nsw i8 [[IDX]], 1
; CHECK-NEXT: [[CMP:%.*]] = icmp slt i8 [[IDX_NEXT]], [[LIMIT]]
; CHECK-NEXT: [[TMP2:%.*]] = icmp slt i8 [[IDX_NEXT]], [[EXIT_MAINLOOP_AT]]
; CHECK-NEXT: br i1 [[TMP2]], label [[LOOP]], label [[MAIN_EXIT_SELECTOR:%.*]]
Expand Down Expand Up @@ -997,7 +997,7 @@ define i8 @test_overflow_check_compile_time(i8 %limit, ptr %p) {
; CHECK-NEXT: [[CHECK:%.*]] = icmp sgt i8 [[SUB]], -2
; CHECK-NEXT: br i1 true, label [[INBOUNDS]], label [[OUT_OF_BOUNDS_LOOPEXIT4:%.*]]
; CHECK: inbounds:
; CHECK-NEXT: [[IDX_NEXT]] = add nuw i8 [[IDX]], 1
; CHECK-NEXT: [[IDX_NEXT]] = add nuw nsw i8 [[IDX]], 1
; CHECK-NEXT: [[CMP:%.*]] = icmp slt i8 [[IDX_NEXT]], [[LIMIT]]
; CHECK-NEXT: [[TMP2:%.*]] = icmp slt i8 [[IDX_NEXT]], [[EXIT_MAINLOOP_AT]]
; CHECK-NEXT: br i1 [[TMP2]], label [[LOOP]], label [[MAIN_EXIT_SELECTOR:%.*]]
Expand Down Expand Up @@ -1106,7 +1106,7 @@ define i8 @test_overflow_check_runtime(i8 %limit, ptr %p) {
; CHECK-NEXT: [[CHECK:%.*]] = icmp sge i8 [[SUB]], -2
; CHECK-NEXT: br i1 true, label [[INBOUNDS]], label [[OUT_OF_BOUNDS_LOOPEXIT8:%.*]]
; CHECK: inbounds:
; CHECK-NEXT: [[IDX_NEXT]] = add nuw i8 [[IDX]], 1
; CHECK-NEXT: [[IDX_NEXT]] = add nuw nsw i8 [[IDX]], 1
; CHECK-NEXT: [[CMP:%.*]] = icmp slt i8 [[IDX_NEXT]], [[LIMIT]]
; CHECK-NEXT: [[TMP12:%.*]] = icmp slt i8 [[IDX_NEXT]], [[EXIT_MAINLOOP_AT]]
; CHECK-NEXT: br i1 [[TMP12]], label [[LOOP]], label [[MAIN_EXIT_SELECTOR:%.*]]
Expand Down
4 changes: 2 additions & 2 deletions llvm/test/Transforms/IRCE/multiple-access-no-preloop.ll
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ define void @multiple_access_no_preloop(
; CHECK-NEXT: br label [[LOOP:%.*]]
; CHECK: loop:
; CHECK-NEXT: [[IDX:%.*]] = phi i32 [ [[IDX_NEXT:%.*]], [[IN_BOUNDS_B:%.*]] ], [ 0, [[LOOP_PREHEADER2]] ]
; CHECK-NEXT: [[IDX_NEXT]] = add i32 [[IDX]], 1
; CHECK-NEXT: [[IDX_NEXT]] = add nsw i32 [[IDX]], 1
; CHECK-NEXT: [[ABC_A:%.*]] = icmp slt i32 [[IDX]], [[LEN_A]]
; CHECK-NEXT: br i1 true, label [[IN_BOUNDS_A:%.*]], label [[OUT_OF_BOUNDS_LOOPEXIT3:%.*]], !prof [[PROF1:![0-9]+]]
; CHECK: in.bounds.a:
Expand Down Expand Up @@ -69,7 +69,7 @@ define void @multiple_access_no_preloop(
; CHECK-NEXT: [[ADDR_B_POSTLOOP:%.*]] = getelementptr i32, ptr [[ARR_B]], i32 [[IDX_POSTLOOP]]
; CHECK-NEXT: store i32 -1, ptr [[ADDR_B_POSTLOOP]], align 4
; CHECK-NEXT: [[NEXT_POSTLOOP:%.*]] = icmp slt i32 [[IDX_NEXT_POSTLOOP]], [[N]]
; CHECK-NEXT: br i1 [[NEXT_POSTLOOP]], label [[LOOP_POSTLOOP]], label [[EXIT_LOOPEXIT_LOOPEXIT:%.*]], !llvm.loop [[LOOP2:![0-9]+]], !irce.loop.clone !7
; CHECK-NEXT: br i1 [[NEXT_POSTLOOP]], label [[LOOP_POSTLOOP]], label [[EXIT_LOOPEXIT_LOOPEXIT:%.*]], !llvm.loop [[LOOP2:![0-9]+]], !irce.loop.clone [[META7:![0-9]+]]
;
ptr %arr_a, ptr %a_len_ptr, ptr %arr_b, ptr %b_len_ptr, i32 %n) {

Expand Down
4 changes: 2 additions & 2 deletions llvm/test/Transforms/IRCE/pre_post_loops.ll
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ define void @test_01(ptr %arr, ptr %a_len_ptr) {
; CHECK-NEXT: br label [[LOOP:%.*]]
; CHECK: loop:
; CHECK-NEXT: [[IDX:%.*]] = phi i32 [ [[IDX_NEXT:%.*]], [[IN_BOUNDS:%.*]] ], [ 0, [[LOOP_PREHEADER]] ]
; CHECK-NEXT: [[IDX_NEXT]] = add i32 [[IDX]], 1
; CHECK-NEXT: [[IDX_NEXT]] = add nsw i32 [[IDX]], 1
; CHECK-NEXT: [[ABC:%.*]] = icmp slt i32 [[IDX]], [[EXIT_MAINLOOP_AT]]
; CHECK-NEXT: br i1 true, label [[IN_BOUNDS]], label [[OUT_OF_BOUNDS_LOOPEXIT1:%.*]]
; CHECK: in.bounds:
Expand Down Expand Up @@ -94,7 +94,7 @@ define void @test_02(ptr %arr, ptr %a_len_ptr) {
; CHECK-NEXT: br label [[LOOP:%.*]]
; CHECK: loop:
; CHECK-NEXT: [[IDX:%.*]] = phi i32 [ [[IDX_PRELOOP_COPY:%.*]], [[MAINLOOP:%.*]] ], [ [[IDX_NEXT:%.*]], [[IN_BOUNDS:%.*]] ]
; CHECK-NEXT: [[IDX_NEXT]] = add i32 [[IDX]], -1
; CHECK-NEXT: [[IDX_NEXT]] = add nsw i32 [[IDX]], -1
; CHECK-NEXT: [[ABC:%.*]] = icmp slt i32 [[IDX]], [[LEN]]
; CHECK-NEXT: br i1 true, label [[IN_BOUNDS]], label [[OUT_OF_BOUNDS_LOOPEXIT1:%.*]]
; CHECK: in.bounds:
Expand Down
Loading

0 comments on commit bca5501

Please sign in to comment.