[llvm] ec11216 - [IRCE][Tests] Add more tests with range checks in the form of 'iv + offset vs limit'

Aleksandr Popov via llvm-commits llvm-commits at lists.llvm.org
Thu Jul 6 06:32:09 PDT 2023


Author: Aleksandr Popov
Date: 2023-07-06T15:31:26+02:00
New Revision: ec112160713f3caae1c0e9de0d203f1e54a395d4

URL: https://github.com/llvm/llvm-project/commit/ec112160713f3caae1c0e9de0d203f1e54a395d4
DIFF: https://github.com/llvm/llvm-project/commit/ec112160713f3caae1c0e9de0d203f1e54a395d4.diff

LOG: [IRCE][Tests] Add more tests with range checks in the form of 'iv + offset vs limit'

Added tests on range checks with non-strick predicate:
    * N - IV > limit
    * IV - N < limit
    * IV + N < limit

Also added tests with known to be non-negative N

Differential Revision: https://reviews.llvm.org/D154593

Added: 
    

Modified: 
    llvm/test/Transforms/IRCE/iv-plus-offset-range-check.ll

Removed: 
    


################################################################################
diff  --git a/llvm/test/Transforms/IRCE/iv-plus-offset-range-check.ll b/llvm/test/Transforms/IRCE/iv-plus-offset-range-check.ll
index cd076d0c10d964..fbab857a2f0556 100644
--- a/llvm/test/Transforms/IRCE/iv-plus-offset-range-check.ll
+++ b/llvm/test/Transforms/IRCE/iv-plus-offset-range-check.ll
@@ -3,7 +3,7 @@
 
 ; IV = 0; IV <s limit; IV += 1;
 ;   Check(N - IV >= 2)
-; TODO: IRCE is allowed
+; TODO: IRCE is allowed.
 define i8 @test1(i8 %limit, i8 %n) {
 ; CHECK-LABEL: define i8 @test1
 ; CHECK-SAME: (i8 [[LIMIT:%.*]], i8 [[N:%.*]]) {
@@ -54,9 +54,65 @@ out_of_bounds:
   ret i8 %idx;
 }
 
+; IV = 0; IV <s limit; IV += 1;
+;   Check(N - IV >= 2)
+; N is known to be non-negative.
+; TODO: IRCE is allowed.
+define i8 @test1a(i8 %limit, ptr %p) {
+; CHECK-LABEL: define i8 @test1a
+; CHECK-SAME: (i8 [[LIMIT:%.*]], ptr [[P:%.*]]) {
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[N:%.*]] = load i8, ptr [[P]], align 1, !range [[RNG0:![0-9]+]]
+; CHECK-NEXT:    [[PRECHECK:%.*]] = icmp sgt i8 [[LIMIT]], 0
+; CHECK-NEXT:    br i1 [[PRECHECK]], label [[LOOP_PREHEADER:%.*]], label [[EXIT:%.*]]
+; CHECK:       loop.preheader:
+; CHECK-NEXT:    br label [[LOOP:%.*]]
+; CHECK:       loop:
+; CHECK-NEXT:    [[IDX:%.*]] = phi i8 [ [[IDX_NEXT:%.*]], [[INBOUNDS:%.*]] ], [ 0, [[LOOP_PREHEADER]] ]
+; CHECK-NEXT:    [[SUB:%.*]] = sub i8 [[N]], [[IDX]]
+; CHECK-NEXT:    [[CHECK:%.*]] = icmp sge i8 [[SUB]], 2
+; CHECK-NEXT:    br i1 [[CHECK]], label [[INBOUNDS]], label [[OUT_OF_BOUNDS:%.*]]
+; CHECK:       inbounds:
+; CHECK-NEXT:    [[IDX_NEXT]] = add nuw i8 [[IDX]], 1
+; CHECK-NEXT:    [[CMP:%.*]] = icmp slt i8 [[IDX_NEXT]], [[LIMIT]]
+; CHECK-NEXT:    br i1 [[CMP]], label [[LOOP]], label [[EXIT_LOOPEXIT:%.*]]
+; CHECK:       exit.loopexit:
+; CHECK-NEXT:    [[IDX_LCSSA1:%.*]] = phi i8 [ [[IDX]], [[INBOUNDS]] ]
+; CHECK-NEXT:    br label [[EXIT]]
+; CHECK:       exit:
+; CHECK-NEXT:    [[RES:%.*]] = phi i8 [ 0, [[ENTRY:%.*]] ], [ [[IDX_LCSSA1]], [[EXIT_LOOPEXIT]] ]
+; CHECK-NEXT:    ret i8 [[RES]]
+; CHECK:       out_of_bounds:
+; CHECK-NEXT:    [[IDX_LCSSA:%.*]] = phi i8 [ [[IDX]], [[LOOP]] ]
+; CHECK-NEXT:    ret i8 [[IDX_LCSSA]]
+;
+entry:
+  %n = load i8, ptr %p, !range !0
+  %precheck = icmp sgt i8 %limit, 0
+  br i1 %precheck, label %loop, label %exit
+
+loop:
+  %idx = phi i8 [ %idx.next, %inbounds ], [ 0, %entry ]
+  %sub = sub i8 %n, %idx
+  %check = icmp sge i8 %sub, 2
+  br i1 %check, label %inbounds, label %out_of_bounds
+
+inbounds:
+  %idx.next = add nuw i8 %idx, 1
+  %cmp = icmp slt i8 %idx.next, %limit
+  br i1 %cmp, label %loop, label %exit
+
+exit:
+  %res = phi i8 [ 0, %entry ], [ %idx, %inbounds ]
+  ret i8 %res
+
+out_of_bounds:
+  ret i8 %idx;
+}
+
 ; IV = 0; IV <s limit; IV += 1;
 ;   Check(IV - N <= -2)
-; TODO: IRCE is allowed
+; TODO: IRCE is allowed.
 define i8 @test2(i8 %limit, i8 %n) {
 ; CHECK-LABEL: define i8 @test2
 ; CHECK-SAME: (i8 [[LIMIT:%.*]], i8 [[N:%.*]]) {
@@ -107,9 +163,65 @@ out_of_bounds:
   ret i8 %idx;
 }
 
+; IV = 0; IV <s limit; IV += 1;
+;   Check(IV - N <= -2)
+; N is known to be non-negative.
+; TODO: IRCE is allowed.
+define i8 @test2a(i8 %limit, ptr %p) {
+; CHECK-LABEL: define i8 @test2a
+; CHECK-SAME: (i8 [[LIMIT:%.*]], ptr [[P:%.*]]) {
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[N:%.*]] = load i8, ptr [[P]], align 1, !range [[RNG0]]
+; CHECK-NEXT:    [[PRECHECK:%.*]] = icmp sgt i8 [[LIMIT]], 0
+; CHECK-NEXT:    br i1 [[PRECHECK]], label [[LOOP_PREHEADER:%.*]], label [[EXIT:%.*]]
+; CHECK:       loop.preheader:
+; CHECK-NEXT:    br label [[LOOP:%.*]]
+; CHECK:       loop:
+; CHECK-NEXT:    [[IDX:%.*]] = phi i8 [ [[IDX_NEXT:%.*]], [[INBOUNDS:%.*]] ], [ 0, [[LOOP_PREHEADER]] ]
+; CHECK-NEXT:    [[SUB:%.*]] = sub i8 [[IDX]], [[N]]
+; CHECK-NEXT:    [[CHECK:%.*]] = icmp sle i8 [[SUB]], -2
+; CHECK-NEXT:    br i1 [[CHECK]], label [[INBOUNDS]], label [[OUT_OF_BOUNDS:%.*]]
+; CHECK:       inbounds:
+; CHECK-NEXT:    [[IDX_NEXT]] = add nuw i8 [[IDX]], 1
+; CHECK-NEXT:    [[CMP:%.*]] = icmp slt i8 [[IDX_NEXT]], [[LIMIT]]
+; CHECK-NEXT:    br i1 [[CMP]], label [[LOOP]], label [[EXIT_LOOPEXIT:%.*]]
+; CHECK:       exit.loopexit:
+; CHECK-NEXT:    [[IDX_LCSSA1:%.*]] = phi i8 [ [[IDX]], [[INBOUNDS]] ]
+; CHECK-NEXT:    br label [[EXIT]]
+; CHECK:       exit:
+; CHECK-NEXT:    [[RES:%.*]] = phi i8 [ 0, [[ENTRY:%.*]] ], [ [[IDX_LCSSA1]], [[EXIT_LOOPEXIT]] ]
+; CHECK-NEXT:    ret i8 [[RES]]
+; CHECK:       out_of_bounds:
+; CHECK-NEXT:    [[IDX_LCSSA:%.*]] = phi i8 [ [[IDX]], [[LOOP]] ]
+; CHECK-NEXT:    ret i8 [[IDX_LCSSA]]
+;
+entry:
+  %n = load i8, ptr %p, !range !0
+  %precheck = icmp sgt i8 %limit, 0
+  br i1 %precheck, label %loop, label %exit
+
+loop:
+  %idx = phi i8 [ %idx.next, %inbounds ], [ 0, %entry ]
+  %sub = sub i8 %idx, %n
+  %check = icmp sle i8 %sub, -2
+  br i1 %check, label %inbounds, label %out_of_bounds
+
+inbounds:
+  %idx.next = add nuw i8 %idx, 1
+  %cmp = icmp slt i8 %idx.next, %limit
+  br i1 %cmp, label %loop, label %exit
+
+exit:
+  %res = phi i8 [ 0, %entry ], [ %idx, %inbounds ]
+  ret i8 %res
+
+out_of_bounds:
+  ret i8 %idx;
+}
+
 ; IV = 0; IV <s limit; IV += 1;
 ;   Check(IV + 2 <= N)
-; TODO: IRCE is allowed
+; TODO: IRCE is allowed.
 define i8 @test3(i8 %limit, i8 %n) {
 ; CHECK-LABEL: define i8 @test3
 ; CHECK-SAME: (i8 [[LIMIT:%.*]], i8 [[N:%.*]]) {
@@ -159,3 +271,502 @@ exit:
 out_of_bounds:
   ret i8 %idx;
 }
+
+; IV = 0; IV <s limit; IV += 1;
+;   Check(IV + 2 <= N)
+; N is known to be non-negative.
+; IRCE is allowed.
+define i8 @test3a(i8 %limit, ptr %p) {
+; CHECK-LABEL: define i8 @test3a
+; CHECK-SAME: (i8 [[LIMIT:%.*]], ptr [[P:%.*]]) {
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[N:%.*]] = load i8, ptr [[P]], align 1, !range [[RNG0]]
+; CHECK-NEXT:    [[PRECHECK:%.*]] = icmp sgt i8 [[LIMIT]], 0
+; CHECK-NEXT:    br i1 [[PRECHECK]], label [[LOOP_PREHEADER:%.*]], label [[EXIT:%.*]]
+; CHECK:       loop.preheader:
+; CHECK-NEXT:    [[TMP0:%.*]] = add nsw i8 [[N]], -1
+; CHECK-NEXT:    [[SMIN:%.*]] = call i8 @llvm.smin.i8(i8 [[LIMIT]], i8 [[TMP0]])
+; CHECK-NEXT:    [[EXIT_MAINLOOP_AT:%.*]] = call i8 @llvm.smax.i8(i8 [[SMIN]], i8 0)
+; CHECK-NEXT:    [[TMP1:%.*]] = icmp slt i8 0, [[EXIT_MAINLOOP_AT]]
+; CHECK-NEXT:    br i1 [[TMP1]], label [[LOOP_PREHEADER3:%.*]], label [[MAIN_PSEUDO_EXIT:%.*]]
+; CHECK:       loop.preheader3:
+; CHECK-NEXT:    br label [[LOOP:%.*]]
+; CHECK:       loop:
+; CHECK-NEXT:    [[IDX:%.*]] = phi i8 [ [[IDX_NEXT:%.*]], [[INBOUNDS:%.*]] ], [ 0, [[LOOP_PREHEADER3]] ]
+; CHECK-NEXT:    [[ADD:%.*]] = add i8 [[IDX]], 2
+; 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:    [[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:%.*]]
+; CHECK:       main.exit.selector:
+; CHECK-NEXT:    [[IDX_NEXT_LCSSA:%.*]] = phi i8 [ [[IDX_NEXT]], [[INBOUNDS]] ]
+; CHECK-NEXT:    [[IDX_LCSSA2:%.*]] = phi i8 [ [[IDX]], [[INBOUNDS]] ]
+; CHECK-NEXT:    [[TMP3:%.*]] = icmp slt i8 [[IDX_NEXT_LCSSA]], [[LIMIT]]
+; CHECK-NEXT:    br i1 [[TMP3]], label [[MAIN_PSEUDO_EXIT]], label [[EXIT_LOOPEXIT:%.*]]
+; CHECK:       main.pseudo.exit:
+; CHECK-NEXT:    [[IDX_COPY:%.*]] = phi i8 [ 0, [[LOOP_PREHEADER]] ], [ [[IDX_NEXT_LCSSA]], [[MAIN_EXIT_SELECTOR]] ]
+; CHECK-NEXT:    [[INDVAR_END:%.*]] = phi i8 [ 0, [[LOOP_PREHEADER]] ], [ [[IDX_NEXT_LCSSA]], [[MAIN_EXIT_SELECTOR]] ]
+; CHECK-NEXT:    br label [[POSTLOOP:%.*]]
+; CHECK:       exit.loopexit.loopexit:
+; CHECK-NEXT:    [[IDX_LCSSA1_PH:%.*]] = phi i8 [ [[IDX_POSTLOOP:%.*]], [[INBOUNDS_POSTLOOP:%.*]] ]
+; CHECK-NEXT:    br label [[EXIT_LOOPEXIT]]
+; CHECK:       exit.loopexit:
+; CHECK-NEXT:    [[IDX_LCSSA1:%.*]] = phi i8 [ [[IDX_LCSSA2]], [[MAIN_EXIT_SELECTOR]] ], [ [[IDX_LCSSA1_PH]], [[EXIT_LOOPEXIT_LOOPEXIT:%.*]] ]
+; CHECK-NEXT:    br label [[EXIT]]
+; CHECK:       exit:
+; CHECK-NEXT:    [[RES:%.*]] = phi i8 [ 0, [[ENTRY:%.*]] ], [ [[IDX_LCSSA1]], [[EXIT_LOOPEXIT]] ]
+; CHECK-NEXT:    ret i8 [[RES]]
+; CHECK:       out_of_bounds.loopexit:
+; CHECK-NEXT:    [[IDX_LCSSA_PH:%.*]] = phi i8 [ [[IDX_POSTLOOP]], [[LOOP_POSTLOOP:%.*]] ]
+; CHECK-NEXT:    br label [[OUT_OF_BOUNDS:%.*]]
+; CHECK:       out_of_bounds.loopexit4:
+; CHECK-NEXT:    [[IDX_LCSSA_PH5:%.*]] = phi i8 [ [[IDX]], [[LOOP]] ]
+; CHECK-NEXT:    br label [[OUT_OF_BOUNDS]]
+; CHECK:       out_of_bounds:
+; CHECK-NEXT:    [[IDX_LCSSA:%.*]] = phi i8 [ [[IDX_LCSSA_PH]], [[OUT_OF_BOUNDS_LOOPEXIT:%.*]] ], [ [[IDX_LCSSA_PH5]], [[OUT_OF_BOUNDS_LOOPEXIT4]] ]
+; CHECK-NEXT:    ret i8 [[IDX_LCSSA]]
+; CHECK:       postloop:
+; CHECK-NEXT:    br label [[LOOP_POSTLOOP]]
+; CHECK:       loop.postloop:
+; CHECK-NEXT:    [[IDX_POSTLOOP]] = phi i8 [ [[IDX_NEXT_POSTLOOP:%.*]], [[INBOUNDS_POSTLOOP]] ], [ [[IDX_COPY]], [[POSTLOOP]] ]
+; CHECK-NEXT:    [[ADD_POSTLOOP:%.*]] = add i8 [[IDX_POSTLOOP]], 2
+; CHECK-NEXT:    [[CHECK_POSTLOOP:%.*]] = icmp sle i8 [[ADD_POSTLOOP]], [[N]]
+; CHECK-NEXT:    br i1 [[CHECK_POSTLOOP]], label [[INBOUNDS_POSTLOOP]], label [[OUT_OF_BOUNDS_LOOPEXIT]]
+; CHECK:       inbounds.postloop:
+; CHECK-NEXT:    [[IDX_NEXT_POSTLOOP]] = add nuw i8 [[IDX_POSTLOOP]], 1
+; CHECK-NEXT:    [[CMP_POSTLOOP:%.*]] = icmp slt i8 [[IDX_NEXT_POSTLOOP]], [[LIMIT]]
+; CHECK-NEXT:    br i1 [[CMP_POSTLOOP]], label [[LOOP_POSTLOOP]], label [[EXIT_LOOPEXIT_LOOPEXIT]], !llvm.loop [[LOOP1:![0-9]+]], !irce.loop.clone !6
+;
+entry:
+  %n = load i8, ptr %p, !range !0
+  %precheck = icmp sgt i8 %limit, 0
+  br i1 %precheck, label %loop, label %exit
+
+loop:
+  %idx = phi i8 [ %idx.next, %inbounds ], [ 0, %entry ]
+  %add = add i8 %idx, 2
+  %check = icmp sle i8 %add, %n
+  br i1 %check, label %inbounds, label %out_of_bounds
+
+inbounds:
+  %idx.next = add nuw i8 %idx, 1
+  %cmp = icmp slt i8 %idx.next, %limit
+  br i1 %cmp, label %loop, label %exit
+
+exit:
+  %res = phi i8 [ 0, %entry ], [ %idx, %inbounds ]
+  ret i8 %res
+
+out_of_bounds:
+  ret i8 %idx;
+}
+
+; IV = 0; IV <s limit; IV += 1;
+;   Check(N - IV > 2)
+; TODO: IRCE is allowed.
+define i8 @test4(i8 %limit, i8 %n) {
+; CHECK-LABEL: define i8 @test4
+; CHECK-SAME: (i8 [[LIMIT:%.*]], i8 [[N:%.*]]) {
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[PRECHECK:%.*]] = icmp sgt i8 [[LIMIT]], 0
+; CHECK-NEXT:    br i1 [[PRECHECK]], label [[LOOP_PREHEADER:%.*]], label [[EXIT:%.*]]
+; CHECK:       loop.preheader:
+; CHECK-NEXT:    br label [[LOOP:%.*]]
+; CHECK:       loop:
+; CHECK-NEXT:    [[IDX:%.*]] = phi i8 [ [[IDX_NEXT:%.*]], [[INBOUNDS:%.*]] ], [ 0, [[LOOP_PREHEADER]] ]
+; CHECK-NEXT:    [[SUB:%.*]] = sub i8 [[N]], [[IDX]]
+; CHECK-NEXT:    [[CHECK:%.*]] = icmp sgt i8 [[SUB]], 2
+; CHECK-NEXT:    br i1 [[CHECK]], label [[INBOUNDS]], label [[OUT_OF_BOUNDS:%.*]]
+; CHECK:       inbounds:
+; CHECK-NEXT:    [[IDX_NEXT]] = add nuw i8 [[IDX]], 1
+; CHECK-NEXT:    [[CMP:%.*]] = icmp slt i8 [[IDX_NEXT]], [[LIMIT]]
+; CHECK-NEXT:    br i1 [[CMP]], label [[LOOP]], label [[EXIT_LOOPEXIT:%.*]]
+; CHECK:       exit.loopexit:
+; CHECK-NEXT:    [[IDX_LCSSA1:%.*]] = phi i8 [ [[IDX]], [[INBOUNDS]] ]
+; CHECK-NEXT:    br label [[EXIT]]
+; CHECK:       exit:
+; CHECK-NEXT:    [[RES:%.*]] = phi i8 [ 0, [[ENTRY:%.*]] ], [ [[IDX_LCSSA1]], [[EXIT_LOOPEXIT]] ]
+; CHECK-NEXT:    ret i8 [[RES]]
+; CHECK:       out_of_bounds:
+; CHECK-NEXT:    [[IDX_LCSSA:%.*]] = phi i8 [ [[IDX]], [[LOOP]] ]
+; CHECK-NEXT:    ret i8 [[IDX_LCSSA]]
+;
+entry:
+  %precheck = icmp sgt i8 %limit, 0
+  br i1 %precheck, label %loop, label %exit
+
+loop:
+  %idx = phi i8 [ %idx.next, %inbounds ], [ 0, %entry ]
+  %sub = sub i8 %n, %idx
+  %check = icmp sgt i8 %sub, 2
+  br i1 %check, label %inbounds, label %out_of_bounds
+
+inbounds:
+  %idx.next = add nuw i8 %idx, 1
+  %cmp = icmp slt i8 %idx.next, %limit
+  br i1 %cmp, label %loop, label %exit
+
+exit:
+  %res = phi i8 [ 0, %entry ], [ %idx, %inbounds ]
+  ret i8 %res
+
+out_of_bounds:
+  ret i8 %idx;
+}
+
+; IV = 0; IV <s limit; IV += 1;
+;   Check(N - IV > 2)
+; N is known to be non-negative.
+; TODO: IRCE is allowed.
+define i8 @test4a(i8 %limit, ptr %p) {
+; CHECK-LABEL: define i8 @test4a
+; CHECK-SAME: (i8 [[LIMIT:%.*]], ptr [[P:%.*]]) {
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[N:%.*]] = load i8, ptr [[P]], align 1, !range [[RNG0]]
+; CHECK-NEXT:    [[PRECHECK:%.*]] = icmp sgt i8 [[LIMIT]], 0
+; CHECK-NEXT:    br i1 [[PRECHECK]], label [[LOOP_PREHEADER:%.*]], label [[EXIT:%.*]]
+; CHECK:       loop.preheader:
+; CHECK-NEXT:    br label [[LOOP:%.*]]
+; CHECK:       loop:
+; CHECK-NEXT:    [[IDX:%.*]] = phi i8 [ [[IDX_NEXT:%.*]], [[INBOUNDS:%.*]] ], [ 0, [[LOOP_PREHEADER]] ]
+; CHECK-NEXT:    [[SUB:%.*]] = sub i8 [[N]], [[IDX]]
+; CHECK-NEXT:    [[CHECK:%.*]] = icmp sgt i8 [[SUB]], 2
+; CHECK-NEXT:    br i1 [[CHECK]], label [[INBOUNDS]], label [[OUT_OF_BOUNDS:%.*]]
+; CHECK:       inbounds:
+; CHECK-NEXT:    [[IDX_NEXT]] = add nuw i8 [[IDX]], 1
+; CHECK-NEXT:    [[CMP:%.*]] = icmp slt i8 [[IDX_NEXT]], [[LIMIT]]
+; CHECK-NEXT:    br i1 [[CMP]], label [[LOOP]], label [[EXIT_LOOPEXIT:%.*]]
+; CHECK:       exit.loopexit:
+; CHECK-NEXT:    [[IDX_LCSSA1:%.*]] = phi i8 [ [[IDX]], [[INBOUNDS]] ]
+; CHECK-NEXT:    br label [[EXIT]]
+; CHECK:       exit:
+; CHECK-NEXT:    [[RES:%.*]] = phi i8 [ 0, [[ENTRY:%.*]] ], [ [[IDX_LCSSA1]], [[EXIT_LOOPEXIT]] ]
+; CHECK-NEXT:    ret i8 [[RES]]
+; CHECK:       out_of_bounds:
+; CHECK-NEXT:    [[IDX_LCSSA:%.*]] = phi i8 [ [[IDX]], [[LOOP]] ]
+; CHECK-NEXT:    ret i8 [[IDX_LCSSA]]
+;
+entry:
+  %n = load i8, ptr %p, !range !0
+  %precheck = icmp sgt i8 %limit, 0
+  br i1 %precheck, label %loop, label %exit
+
+loop:
+  %idx = phi i8 [ %idx.next, %inbounds ], [ 0, %entry ]
+  %sub = sub i8 %n, %idx
+  %check = icmp sgt i8 %sub, 2
+  br i1 %check, label %inbounds, label %out_of_bounds
+
+inbounds:
+  %idx.next = add nuw i8 %idx, 1
+  %cmp = icmp slt i8 %idx.next, %limit
+  br i1 %cmp, label %loop, label %exit
+
+exit:
+  %res = phi i8 [ 0, %entry ], [ %idx, %inbounds ]
+  ret i8 %res
+
+out_of_bounds:
+  ret i8 %idx;
+}
+
+; IV = 0; IV <s limit; IV += 1;
+;   Check(IV - N < -2)
+; TODO: IRCE is allowed.
+define i8 @test5(i8 %limit, i8 %n) {
+; CHECK-LABEL: define i8 @test5
+; CHECK-SAME: (i8 [[LIMIT:%.*]], i8 [[N:%.*]]) {
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[PRECHECK:%.*]] = icmp sgt i8 [[LIMIT]], 0
+; CHECK-NEXT:    br i1 [[PRECHECK]], label [[LOOP_PREHEADER:%.*]], label [[EXIT:%.*]]
+; CHECK:       loop.preheader:
+; CHECK-NEXT:    br label [[LOOP:%.*]]
+; CHECK:       loop:
+; CHECK-NEXT:    [[IDX:%.*]] = phi i8 [ [[IDX_NEXT:%.*]], [[INBOUNDS:%.*]] ], [ 0, [[LOOP_PREHEADER]] ]
+; CHECK-NEXT:    [[SUB:%.*]] = sub i8 [[IDX]], [[N]]
+; CHECK-NEXT:    [[CHECK:%.*]] = icmp slt i8 [[SUB]], -2
+; CHECK-NEXT:    br i1 [[CHECK]], label [[INBOUNDS]], label [[OUT_OF_BOUNDS:%.*]]
+; CHECK:       inbounds:
+; CHECK-NEXT:    [[IDX_NEXT]] = add nuw i8 [[IDX]], 1
+; CHECK-NEXT:    [[CMP:%.*]] = icmp slt i8 [[IDX_NEXT]], [[LIMIT]]
+; CHECK-NEXT:    br i1 [[CMP]], label [[LOOP]], label [[EXIT_LOOPEXIT:%.*]]
+; CHECK:       exit.loopexit:
+; CHECK-NEXT:    [[IDX_LCSSA1:%.*]] = phi i8 [ [[IDX]], [[INBOUNDS]] ]
+; CHECK-NEXT:    br label [[EXIT]]
+; CHECK:       exit:
+; CHECK-NEXT:    [[RES:%.*]] = phi i8 [ 0, [[ENTRY:%.*]] ], [ [[IDX_LCSSA1]], [[EXIT_LOOPEXIT]] ]
+; CHECK-NEXT:    ret i8 [[RES]]
+; CHECK:       out_of_bounds:
+; CHECK-NEXT:    [[IDX_LCSSA:%.*]] = phi i8 [ [[IDX]], [[LOOP]] ]
+; CHECK-NEXT:    ret i8 [[IDX_LCSSA]]
+;
+entry:
+  %precheck = icmp sgt i8 %limit, 0
+  br i1 %precheck, label %loop, label %exit
+
+loop:
+  %idx = phi i8 [ %idx.next, %inbounds ], [ 0, %entry ]
+  %sub = sub i8 %idx, %n
+  %check = icmp slt i8 %sub, -2
+  br i1 %check, label %inbounds, label %out_of_bounds
+
+inbounds:
+  %idx.next = add nuw i8 %idx, 1
+  %cmp = icmp slt i8 %idx.next, %limit
+  br i1 %cmp, label %loop, label %exit
+
+exit:
+  %res = phi i8 [ 0, %entry ], [ %idx, %inbounds ]
+  ret i8 %res
+
+out_of_bounds:
+  ret i8 %idx;
+}
+
+; IV = 0; IV <s limit; IV += 1;
+;   Check(IV - N < -2)
+; N is known to be non-negative.
+; TODO: IRCE is allowed.
+define i8 @test5a(i8 %limit, ptr %p) {
+; CHECK-LABEL: define i8 @test5a
+; CHECK-SAME: (i8 [[LIMIT:%.*]], ptr [[P:%.*]]) {
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[N:%.*]] = load i8, ptr [[P]], align 1, !range [[RNG0]]
+; CHECK-NEXT:    [[PRECHECK:%.*]] = icmp sgt i8 [[LIMIT]], 0
+; CHECK-NEXT:    br i1 [[PRECHECK]], label [[LOOP_PREHEADER:%.*]], label [[EXIT:%.*]]
+; CHECK:       loop.preheader:
+; CHECK-NEXT:    br label [[LOOP:%.*]]
+; CHECK:       loop:
+; CHECK-NEXT:    [[IDX:%.*]] = phi i8 [ [[IDX_NEXT:%.*]], [[INBOUNDS:%.*]] ], [ 0, [[LOOP_PREHEADER]] ]
+; CHECK-NEXT:    [[SUB:%.*]] = sub i8 [[IDX]], [[N]]
+; CHECK-NEXT:    [[CHECK:%.*]] = icmp slt i8 [[SUB]], -2
+; CHECK-NEXT:    br i1 [[CHECK]], label [[INBOUNDS]], label [[OUT_OF_BOUNDS:%.*]]
+; CHECK:       inbounds:
+; CHECK-NEXT:    [[IDX_NEXT]] = add nuw i8 [[IDX]], 1
+; CHECK-NEXT:    [[CMP:%.*]] = icmp slt i8 [[IDX_NEXT]], [[LIMIT]]
+; CHECK-NEXT:    br i1 [[CMP]], label [[LOOP]], label [[EXIT_LOOPEXIT:%.*]]
+; CHECK:       exit.loopexit:
+; CHECK-NEXT:    [[IDX_LCSSA1:%.*]] = phi i8 [ [[IDX]], [[INBOUNDS]] ]
+; CHECK-NEXT:    br label [[EXIT]]
+; CHECK:       exit:
+; CHECK-NEXT:    [[RES:%.*]] = phi i8 [ 0, [[ENTRY:%.*]] ], [ [[IDX_LCSSA1]], [[EXIT_LOOPEXIT]] ]
+; CHECK-NEXT:    ret i8 [[RES]]
+; CHECK:       out_of_bounds:
+; CHECK-NEXT:    [[IDX_LCSSA:%.*]] = phi i8 [ [[IDX]], [[LOOP]] ]
+; CHECK-NEXT:    ret i8 [[IDX_LCSSA]]
+;
+entry:
+  %n = load i8, ptr %p, !range !0
+  %precheck = icmp sgt i8 %limit, 0
+  br i1 %precheck, label %loop, label %exit
+
+loop:
+  %idx = phi i8 [ %idx.next, %inbounds ], [ 0, %entry ]
+  %sub = sub i8 %idx, %n
+  %check = icmp slt i8 %sub, -2
+  br i1 %check, label %inbounds, label %out_of_bounds
+
+inbounds:
+  %idx.next = add nuw i8 %idx, 1
+  %cmp = icmp slt i8 %idx.next, %limit
+  br i1 %cmp, label %loop, label %exit
+
+exit:
+  %res = phi i8 [ 0, %entry ], [ %idx, %inbounds ]
+  ret i8 %res
+
+out_of_bounds:
+  ret i8 %idx;
+}
+
+; IV = 0; IV <s limit; IV += 1;
+;   Check(IV + 2 < N)
+; IRCE is allowed.
+define i8 @test6(i8 %limit, i8 %n) {
+; CHECK-LABEL: define i8 @test6
+; CHECK-SAME: (i8 [[LIMIT:%.*]], i8 [[N:%.*]]) {
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[PRECHECK:%.*]] = icmp sgt i8 [[LIMIT]], 0
+; CHECK-NEXT:    br i1 [[PRECHECK]], label [[LOOP_PREHEADER:%.*]], label [[EXIT:%.*]]
+; CHECK:       loop.preheader:
+; CHECK-NEXT:    [[TMP0:%.*]] = add i8 [[N]], -127
+; CHECK-NEXT:    [[SMAX:%.*]] = call i8 @llvm.smax.i8(i8 [[TMP0]], i8 2)
+; CHECK-NEXT:    [[TMP1:%.*]] = sub i8 [[N]], [[SMAX]]
+; CHECK-NEXT:    [[SMIN:%.*]] = call i8 @llvm.smin.i8(i8 [[N]], i8 0)
+; CHECK-NEXT:    [[SMAX2:%.*]] = call i8 @llvm.smax.i8(i8 [[SMIN]], i8 -1)
+; CHECK-NEXT:    [[TMP2:%.*]] = add nsw i8 [[SMAX2]], 1
+; CHECK-NEXT:    [[TMP3:%.*]] = mul i8 [[TMP1]], [[TMP2]]
+; CHECK-NEXT:    [[SMIN3:%.*]] = call i8 @llvm.smin.i8(i8 [[LIMIT]], i8 [[TMP3]])
+; CHECK-NEXT:    [[EXIT_MAINLOOP_AT:%.*]] = call i8 @llvm.smax.i8(i8 [[SMIN3]], i8 0)
+; CHECK-NEXT:    [[TMP4:%.*]] = icmp slt i8 0, [[EXIT_MAINLOOP_AT]]
+; CHECK-NEXT:    br i1 [[TMP4]], label [[LOOP_PREHEADER6:%.*]], label [[MAIN_PSEUDO_EXIT:%.*]]
+; CHECK:       loop.preheader6:
+; CHECK-NEXT:    br label [[LOOP:%.*]]
+; CHECK:       loop:
+; CHECK-NEXT:    [[IDX:%.*]] = phi i8 [ [[IDX_NEXT:%.*]], [[INBOUNDS:%.*]] ], [ 0, [[LOOP_PREHEADER6]] ]
+; CHECK-NEXT:    [[ADD:%.*]] = add i8 [[IDX]], 2
+; 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:    [[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:%.*]]
+; CHECK:       main.exit.selector:
+; CHECK-NEXT:    [[IDX_NEXT_LCSSA:%.*]] = phi i8 [ [[IDX_NEXT]], [[INBOUNDS]] ]
+; CHECK-NEXT:    [[IDX_LCSSA5:%.*]] = phi i8 [ [[IDX]], [[INBOUNDS]] ]
+; CHECK-NEXT:    [[TMP6:%.*]] = icmp slt i8 [[IDX_NEXT_LCSSA]], [[LIMIT]]
+; CHECK-NEXT:    br i1 [[TMP6]], label [[MAIN_PSEUDO_EXIT]], label [[EXIT_LOOPEXIT:%.*]]
+; CHECK:       main.pseudo.exit:
+; CHECK-NEXT:    [[IDX_COPY:%.*]] = phi i8 [ 0, [[LOOP_PREHEADER]] ], [ [[IDX_NEXT_LCSSA]], [[MAIN_EXIT_SELECTOR]] ]
+; CHECK-NEXT:    [[INDVAR_END:%.*]] = phi i8 [ 0, [[LOOP_PREHEADER]] ], [ [[IDX_NEXT_LCSSA]], [[MAIN_EXIT_SELECTOR]] ]
+; CHECK-NEXT:    br label [[POSTLOOP:%.*]]
+; CHECK:       exit.loopexit.loopexit:
+; CHECK-NEXT:    [[IDX_LCSSA1_PH:%.*]] = phi i8 [ [[IDX_POSTLOOP:%.*]], [[INBOUNDS_POSTLOOP:%.*]] ]
+; CHECK-NEXT:    br label [[EXIT_LOOPEXIT]]
+; CHECK:       exit.loopexit:
+; CHECK-NEXT:    [[IDX_LCSSA1:%.*]] = phi i8 [ [[IDX_LCSSA5]], [[MAIN_EXIT_SELECTOR]] ], [ [[IDX_LCSSA1_PH]], [[EXIT_LOOPEXIT_LOOPEXIT:%.*]] ]
+; CHECK-NEXT:    br label [[EXIT]]
+; CHECK:       exit:
+; CHECK-NEXT:    [[RES:%.*]] = phi i8 [ 0, [[ENTRY:%.*]] ], [ [[IDX_LCSSA1]], [[EXIT_LOOPEXIT]] ]
+; CHECK-NEXT:    ret i8 [[RES]]
+; CHECK:       out_of_bounds.loopexit:
+; CHECK-NEXT:    [[IDX_LCSSA_PH:%.*]] = phi i8 [ [[IDX_POSTLOOP]], [[LOOP_POSTLOOP:%.*]] ]
+; CHECK-NEXT:    br label [[OUT_OF_BOUNDS:%.*]]
+; CHECK:       out_of_bounds.loopexit7:
+; CHECK-NEXT:    [[IDX_LCSSA_PH8:%.*]] = phi i8 [ [[IDX]], [[LOOP]] ]
+; CHECK-NEXT:    br label [[OUT_OF_BOUNDS]]
+; CHECK:       out_of_bounds:
+; CHECK-NEXT:    [[IDX_LCSSA:%.*]] = phi i8 [ [[IDX_LCSSA_PH]], [[OUT_OF_BOUNDS_LOOPEXIT:%.*]] ], [ [[IDX_LCSSA_PH8]], [[OUT_OF_BOUNDS_LOOPEXIT7]] ]
+; CHECK-NEXT:    ret i8 [[IDX_LCSSA]]
+; CHECK:       postloop:
+; CHECK-NEXT:    br label [[LOOP_POSTLOOP]]
+; CHECK:       loop.postloop:
+; CHECK-NEXT:    [[IDX_POSTLOOP]] = phi i8 [ [[IDX_NEXT_POSTLOOP:%.*]], [[INBOUNDS_POSTLOOP]] ], [ [[IDX_COPY]], [[POSTLOOP]] ]
+; CHECK-NEXT:    [[ADD_POSTLOOP:%.*]] = add i8 [[IDX_POSTLOOP]], 2
+; CHECK-NEXT:    [[CHECK_POSTLOOP:%.*]] = icmp slt i8 [[ADD_POSTLOOP]], [[N]]
+; CHECK-NEXT:    br i1 [[CHECK_POSTLOOP]], label [[INBOUNDS_POSTLOOP]], label [[OUT_OF_BOUNDS_LOOPEXIT]]
+; CHECK:       inbounds.postloop:
+; CHECK-NEXT:    [[IDX_NEXT_POSTLOOP]] = add nuw i8 [[IDX_POSTLOOP]], 1
+; CHECK-NEXT:    [[CMP_POSTLOOP:%.*]] = icmp slt i8 [[IDX_NEXT_POSTLOOP]], [[LIMIT]]
+; CHECK-NEXT:    br i1 [[CMP_POSTLOOP]], label [[LOOP_POSTLOOP]], label [[EXIT_LOOPEXIT_LOOPEXIT]], !llvm.loop [[LOOP7:![0-9]+]], !irce.loop.clone !6
+;
+entry:
+  %precheck = icmp sgt i8 %limit, 0
+  br i1 %precheck, label %loop, label %exit
+
+loop:
+  %idx = phi i8 [ %idx.next, %inbounds ], [ 0, %entry ]
+  %add = add i8 %idx, 2
+  %check = icmp slt i8 %add, %n
+  br i1 %check, label %inbounds, label %out_of_bounds
+
+inbounds:
+  %idx.next = add nuw i8 %idx, 1
+  %cmp = icmp slt i8 %idx.next, %limit
+  br i1 %cmp, label %loop, label %exit
+
+exit:
+  %res = phi i8 [ 0, %entry ], [ %idx, %inbounds ]
+  ret i8 %res
+
+out_of_bounds:
+  ret i8 %idx;
+}
+
+; IV = 0; IV <s limit; IV += 1;
+;   Check(IV + 2 < N)
+; N is known to be non-negative.
+; IRCE is allowed.
+define i8 @test6a(i8 %limit, ptr %p) {
+; CHECK-LABEL: define i8 @test6a
+; CHECK-SAME: (i8 [[LIMIT:%.*]], ptr [[P:%.*]]) {
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[N:%.*]] = load i8, ptr [[P]], align 1, !range [[RNG0]]
+; CHECK-NEXT:    [[PRECHECK:%.*]] = icmp sgt i8 [[LIMIT]], 0
+; CHECK-NEXT:    br i1 [[PRECHECK]], label [[LOOP_PREHEADER:%.*]], label [[EXIT:%.*]]
+; CHECK:       loop.preheader:
+; CHECK-NEXT:    [[TMP0:%.*]] = add nsw i8 [[N]], -2
+; CHECK-NEXT:    [[SMIN:%.*]] = call i8 @llvm.smin.i8(i8 [[LIMIT]], i8 [[TMP0]])
+; CHECK-NEXT:    [[EXIT_MAINLOOP_AT:%.*]] = call i8 @llvm.smax.i8(i8 [[SMIN]], i8 0)
+; CHECK-NEXT:    [[TMP1:%.*]] = icmp slt i8 0, [[EXIT_MAINLOOP_AT]]
+; CHECK-NEXT:    br i1 [[TMP1]], label [[LOOP_PREHEADER3:%.*]], label [[MAIN_PSEUDO_EXIT:%.*]]
+; CHECK:       loop.preheader3:
+; CHECK-NEXT:    br label [[LOOP:%.*]]
+; CHECK:       loop:
+; CHECK-NEXT:    [[IDX:%.*]] = phi i8 [ [[IDX_NEXT:%.*]], [[INBOUNDS:%.*]] ], [ 0, [[LOOP_PREHEADER3]] ]
+; CHECK-NEXT:    [[ADD:%.*]] = add i8 [[IDX]], 2
+; 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:    [[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:%.*]]
+; CHECK:       main.exit.selector:
+; CHECK-NEXT:    [[IDX_NEXT_LCSSA:%.*]] = phi i8 [ [[IDX_NEXT]], [[INBOUNDS]] ]
+; CHECK-NEXT:    [[IDX_LCSSA2:%.*]] = phi i8 [ [[IDX]], [[INBOUNDS]] ]
+; CHECK-NEXT:    [[TMP3:%.*]] = icmp slt i8 [[IDX_NEXT_LCSSA]], [[LIMIT]]
+; CHECK-NEXT:    br i1 [[TMP3]], label [[MAIN_PSEUDO_EXIT]], label [[EXIT_LOOPEXIT:%.*]]
+; CHECK:       main.pseudo.exit:
+; CHECK-NEXT:    [[IDX_COPY:%.*]] = phi i8 [ 0, [[LOOP_PREHEADER]] ], [ [[IDX_NEXT_LCSSA]], [[MAIN_EXIT_SELECTOR]] ]
+; CHECK-NEXT:    [[INDVAR_END:%.*]] = phi i8 [ 0, [[LOOP_PREHEADER]] ], [ [[IDX_NEXT_LCSSA]], [[MAIN_EXIT_SELECTOR]] ]
+; CHECK-NEXT:    br label [[POSTLOOP:%.*]]
+; CHECK:       exit.loopexit.loopexit:
+; CHECK-NEXT:    [[IDX_LCSSA1_PH:%.*]] = phi i8 [ [[IDX_POSTLOOP:%.*]], [[INBOUNDS_POSTLOOP:%.*]] ]
+; CHECK-NEXT:    br label [[EXIT_LOOPEXIT]]
+; CHECK:       exit.loopexit:
+; CHECK-NEXT:    [[IDX_LCSSA1:%.*]] = phi i8 [ [[IDX_LCSSA2]], [[MAIN_EXIT_SELECTOR]] ], [ [[IDX_LCSSA1_PH]], [[EXIT_LOOPEXIT_LOOPEXIT:%.*]] ]
+; CHECK-NEXT:    br label [[EXIT]]
+; CHECK:       exit:
+; CHECK-NEXT:    [[RES:%.*]] = phi i8 [ 0, [[ENTRY:%.*]] ], [ [[IDX_LCSSA1]], [[EXIT_LOOPEXIT]] ]
+; CHECK-NEXT:    ret i8 [[RES]]
+; CHECK:       out_of_bounds.loopexit:
+; CHECK-NEXT:    [[IDX_LCSSA_PH:%.*]] = phi i8 [ [[IDX_POSTLOOP]], [[LOOP_POSTLOOP:%.*]] ]
+; CHECK-NEXT:    br label [[OUT_OF_BOUNDS:%.*]]
+; CHECK:       out_of_bounds.loopexit4:
+; CHECK-NEXT:    [[IDX_LCSSA_PH5:%.*]] = phi i8 [ [[IDX]], [[LOOP]] ]
+; CHECK-NEXT:    br label [[OUT_OF_BOUNDS]]
+; CHECK:       out_of_bounds:
+; CHECK-NEXT:    [[IDX_LCSSA:%.*]] = phi i8 [ [[IDX_LCSSA_PH]], [[OUT_OF_BOUNDS_LOOPEXIT:%.*]] ], [ [[IDX_LCSSA_PH5]], [[OUT_OF_BOUNDS_LOOPEXIT4]] ]
+; CHECK-NEXT:    ret i8 [[IDX_LCSSA]]
+; CHECK:       postloop:
+; CHECK-NEXT:    br label [[LOOP_POSTLOOP]]
+; CHECK:       loop.postloop:
+; CHECK-NEXT:    [[IDX_POSTLOOP]] = phi i8 [ [[IDX_NEXT_POSTLOOP:%.*]], [[INBOUNDS_POSTLOOP]] ], [ [[IDX_COPY]], [[POSTLOOP]] ]
+; CHECK-NEXT:    [[ADD_POSTLOOP:%.*]] = add i8 [[IDX_POSTLOOP]], 2
+; CHECK-NEXT:    [[CHECK_POSTLOOP:%.*]] = icmp slt i8 [[ADD_POSTLOOP]], [[N]]
+; CHECK-NEXT:    br i1 [[CHECK_POSTLOOP]], label [[INBOUNDS_POSTLOOP]], label [[OUT_OF_BOUNDS_LOOPEXIT]]
+; CHECK:       inbounds.postloop:
+; CHECK-NEXT:    [[IDX_NEXT_POSTLOOP]] = add nuw i8 [[IDX_POSTLOOP]], 1
+; CHECK-NEXT:    [[CMP_POSTLOOP:%.*]] = icmp slt i8 [[IDX_NEXT_POSTLOOP]], [[LIMIT]]
+; CHECK-NEXT:    br i1 [[CMP_POSTLOOP]], label [[LOOP_POSTLOOP]], label [[EXIT_LOOPEXIT_LOOPEXIT]], !llvm.loop [[LOOP8:![0-9]+]], !irce.loop.clone !6
+;
+entry:
+  %n = load i8, ptr %p, !range !0
+  %precheck = icmp sgt i8 %limit, 0
+  br i1 %precheck, label %loop, label %exit
+
+loop:
+  %idx = phi i8 [ %idx.next, %inbounds ], [ 0, %entry ]
+  %add = add i8 %idx, 2
+  %check = icmp slt i8 %add, %n
+  br i1 %check, label %inbounds, label %out_of_bounds
+
+inbounds:
+  %idx.next = add nuw i8 %idx, 1
+  %cmp = icmp slt i8 %idx.next, %limit
+  br i1 %cmp, label %loop, label %exit
+
+exit:
+  %res = phi i8 [ 0, %entry ], [ %idx, %inbounds ]
+  ret i8 %res
+
+out_of_bounds:
+  ret i8 %idx;
+}
+
+!0 = !{i8 0, i8 127}


        


More information about the llvm-commits mailing list