+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 2
; RUN: opt -verify-loop-info -irce-print-changed-loops -passes=irce -S < %s 2>&1 | FileCheck %s
; RUN: opt -verify-loop-info -irce-print-changed-loops -passes='require<branch-prob>,irce' -S < %s 2>&1 | FileCheck %s
; IV = 0; IV <s 100; IV += 7; 0 <= Len <= 50. IRCE is allowed.
define void @test_01(ptr %arr, ptr %a_len_ptr) {
-
-; CHECK: @test_01(
-; CHECK: entry:
-; CHECK-NEXT: %exit.mainloop.at = load i32, ptr %a_len_ptr
-; CHECK-NEXT: [[COND1:%[^ ]+]] = icmp slt i32 0, %exit.mainloop.at
-; CHECK-NEXT: br i1 [[COND1]], label %loop.preheader, label %main.pseudo.exit
-; CHECK: loop.preheader:
-; 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, 7
-; 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:
-; CHECK-NEXT: %addr = getelementptr i32, ptr %arr, i32 %idx
-; CHECK-NEXT: store i32 0, ptr %addr
-; CHECK-NEXT: %next = icmp slt i32 %idx.next, 100
-; CHECK-NEXT: [[COND2:%[^ ]+]] = icmp slt i32 %idx.next, %exit.mainloop.at
-; CHECK-NEXT: br i1 [[COND2]], label %loop, label %main.exit.selector
-; CHECK: main.exit.selector:
-; CHECK-NEXT: %idx.next.lcssa = phi i32 [ %idx.next, %in.bounds ]
-; CHECK-NEXT: [[COND3:%[^ ]+]] = icmp slt i32 %idx.next.lcssa, 100
-; CHECK-NEXT: br i1 [[COND3]], label %main.pseudo.exit, label %exit
-; CHECK: main.pseudo.exit:
-; CHECK-NEXT: %idx.copy = phi i32 [ 0, %entry ], [ %idx.next.lcssa, %main.exit.selector ]
-; CHECK-NEXT: %indvar.end = phi i32 [ 0, %entry ], [ %idx.next.lcssa, %main.exit.selector ]
-; CHECK-NEXT: br label %postloop
-; CHECK: postloop:
-; CHECK-NEXT: br label %loop.postloop
-; CHECK: loop.postloop:
-; CHECK-NEXT: %idx.postloop = phi i32 [ %idx.copy, %postloop ], [ %idx.next.postloop, %in.bounds.postloop ]
-; CHECK-NEXT: %idx.next.postloop = add i32 %idx.postloop, 7
-; CHECK-NEXT: %abc.postloop = icmp slt i32 %idx.postloop, %exit.mainloop.at
-; CHECK-NEXT: br i1 %abc.postloop, label %in.bounds.postloop, label %out.of.bounds.loopexit
-; CHECK: in.bounds.postloop:
-; CHECK-NEXT: %addr.postloop = getelementptr i32, ptr %arr, i32 %idx.postloop
-; CHECK-NEXT: store i32 0, ptr %addr.postloop
-; CHECK-NEXT: %next.postloop = icmp slt i32 %idx.next.postloop, 100
-; CHECK-NEXT: br i1 %next.postloop, label %loop.postloop, label %exit.loopexit
+; CHECK-LABEL: define void @test_01
+; CHECK-SAME: (ptr [[ARR:%.*]], ptr [[A_LEN_PTR:%.*]]) {
+; CHECK-NEXT: entry:
+; CHECK-NEXT: [[EXIT_MAINLOOP_AT:%.*]] = load i32, ptr [[A_LEN_PTR]], align 4, !range [[RNG0:![0-9]+]]
+; CHECK-NEXT: [[TMP0:%.*]] = icmp slt i32 0, [[EXIT_MAINLOOP_AT]]
+; CHECK-NEXT: br i1 [[TMP0]], label [[LOOP_PREHEADER:%.*]], label [[MAIN_PSEUDO_EXIT:%.*]]
+; CHECK: loop.preheader:
+; 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]], 7
+; 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:
+; CHECK-NEXT: [[ADDR:%.*]] = getelementptr i32, ptr [[ARR]], i32 [[IDX]]
+; CHECK-NEXT: store i32 0, ptr [[ADDR]], align 4
+; CHECK-NEXT: [[NEXT:%.*]] = icmp slt i32 [[IDX_NEXT]], 100
+; CHECK-NEXT: [[TMP1:%.*]] = icmp slt i32 [[IDX_NEXT]], [[EXIT_MAINLOOP_AT]]
+; CHECK-NEXT: br i1 [[TMP1]], label [[LOOP]], label [[MAIN_EXIT_SELECTOR:%.*]]
+; CHECK: main.exit.selector:
+; CHECK-NEXT: [[IDX_NEXT_LCSSA:%.*]] = phi i32 [ [[IDX_NEXT]], [[IN_BOUNDS]] ]
+; CHECK-NEXT: [[TMP2:%.*]] = icmp slt i32 [[IDX_NEXT_LCSSA]], 100
+; CHECK-NEXT: br i1 [[TMP2]], label [[MAIN_PSEUDO_EXIT]], label [[EXIT:%.*]]
+; CHECK: main.pseudo.exit:
+; CHECK-NEXT: [[IDX_COPY:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IDX_NEXT_LCSSA]], [[MAIN_EXIT_SELECTOR]] ]
+; CHECK-NEXT: [[INDVAR_END:%.*]] = phi i32 [ 0, [[ENTRY]] ], [ [[IDX_NEXT_LCSSA]], [[MAIN_EXIT_SELECTOR]] ]
+; CHECK-NEXT: br label [[POSTLOOP:%.*]]
+; CHECK: out.of.bounds.loopexit:
+; CHECK-NEXT: br label [[OUT_OF_BOUNDS:%.*]]
+; CHECK: out.of.bounds.loopexit1:
+; CHECK-NEXT: br label [[OUT_OF_BOUNDS]]
+; CHECK: out.of.bounds:
+; CHECK-NEXT: ret void
+; CHECK: exit.loopexit:
+; CHECK-NEXT: br label [[EXIT]]
+; CHECK: exit:
+; CHECK-NEXT: ret void
+; CHECK: postloop:
+; CHECK-NEXT: br label [[LOOP_POSTLOOP:%.*]]
+; CHECK: loop.postloop:
+; CHECK-NEXT: [[IDX_POSTLOOP:%.*]] = phi i32 [ [[IDX_COPY]], [[POSTLOOP]] ], [ [[IDX_NEXT_POSTLOOP:%.*]], [[IN_BOUNDS_POSTLOOP:%.*]] ]
+; CHECK-NEXT: [[IDX_NEXT_POSTLOOP]] = add i32 [[IDX_POSTLOOP]], 7
+; CHECK-NEXT: [[ABC_POSTLOOP:%.*]] = icmp slt i32 [[IDX_POSTLOOP]], [[EXIT_MAINLOOP_AT]]
+; CHECK-NEXT: br i1 [[ABC_POSTLOOP]], label [[IN_BOUNDS_POSTLOOP]], label [[OUT_OF_BOUNDS_LOOPEXIT:%.*]]
+; CHECK: in.bounds.postloop:
+; CHECK-NEXT: [[ADDR_POSTLOOP:%.*]] = getelementptr i32, ptr [[ARR]], i32 [[IDX_POSTLOOP]]
+; CHECK-NEXT: store i32 0, ptr [[ADDR_POSTLOOP]], align 4
+; CHECK-NEXT: [[NEXT_POSTLOOP:%.*]] = icmp slt i32 [[IDX_NEXT_POSTLOOP]], 100
+; CHECK-NEXT: br i1 [[NEXT_POSTLOOP]], label [[LOOP_POSTLOOP]], label [[EXIT_LOOPEXIT:%.*]], !llvm.loop [[LOOP1:![0-9]+]], !irce.loop.clone !6
+;
entry:
%len = load i32, ptr %a_len_ptr, !range !0
; IV = 0; IV <s MAX_INT - 7; IV += 7; 0 <= Len <= 50. IRCE is allowed.
define void @test_02(ptr %arr, ptr %a_len_ptr) {
-
-; CHECK: @test_02(
-; CHECK: entry:
-; CHECK-NEXT: %exit.mainloop.at = load i32, ptr %a_len_ptr
-; CHECK-NEXT: [[COND1:%[^ ]+]] = icmp slt i32 0, %exit.mainloop.at
-; CHECK-NEXT: br i1 [[COND1]], label %loop.preheader, label %main.pseudo.exit
-; CHECK: loop.preheader:
-; 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, 7
-; 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:
-; CHECK-NEXT: %addr = getelementptr i32, ptr %arr, i32 %idx
-; CHECK-NEXT: store i32 0, ptr %addr
-; CHECK-NEXT: %next = icmp slt i32 %idx.next, 2147483640
-; CHECK-NEXT: [[COND2:%[^ ]+]] = icmp slt i32 %idx.next, %exit.mainloop.at
-; CHECK-NEXT: br i1 [[COND2]], label %loop, label %main.exit.selector
-; CHECK: main.exit.selector:
-; CHECK-NEXT: %idx.next.lcssa = phi i32 [ %idx.next, %in.bounds ]
-; CHECK-NEXT: [[COND3:%[^ ]+]] = icmp slt i32 %idx.next.lcssa, 2147483640
-; CHECK-NEXT: br i1 [[COND3]], label %main.pseudo.exit, label %exit
-; CHECK: main.pseudo.exit:
-; CHECK-NEXT: %idx.copy = phi i32 [ 0, %entry ], [ %idx.next.lcssa, %main.exit.selector ]
-; CHECK-NEXT: %indvar.end = phi i32 [ 0, %entry ], [ %idx.next.lcssa, %main.exit.selector ]
-; CHECK-NEXT: br label %postloop
-; CHECK: postloop:
-; CHECK-NEXT: br label %loop.postloop
-; CHECK: loop.postloop:
-; CHECK-NEXT: %idx.postloop = phi i32 [ %idx.copy, %postloop ], [ %idx.next.postloop, %in.bounds.postloop ]
-; CHECK-NEXT: %idx.next.postloop = add i32 %idx.postloop, 7
-; CHECK-NEXT: %abc.postloop = icmp slt i32 %idx.postloop, %exit.mainloop.at
-; CHECK-NEXT: br i1 %abc.postloop, label %in.bounds.postloop, label %out.of.bounds.loopexit
-; CHECK: in.bounds.postloop:
-; CHECK-NEXT: %addr.postloop = getelementptr i32, ptr %arr, i32 %idx.postloop
-; CHECK-NEXT: store i32 0, ptr %addr.postloop
-; CHECK-NEXT: %next.postloop = icmp slt i32 %idx.next.postloop, 2147483640
-; CHECK-NEXT: br i1 %next.postloop, label %loop.postloop, label %exit.loopexit
+; CHECK-LABEL: define void @test_02
+; CHECK-SAME: (ptr [[ARR:%.*]], ptr [[A_LEN_PTR:%.*]]) {
+; CHECK-NEXT: entry:
+; CHECK-NEXT: [[EXIT_MAINLOOP_AT:%.*]] = load i32, ptr [[A_LEN_PTR]], align 4, !range [[RNG0]]
+; CHECK-NEXT: [[TMP0:%.*]] = icmp slt i32 0, [[EXIT_MAINLOOP_AT]]
+; CHECK-NEXT: br i1 [[TMP0]], label [[LOOP_PREHEADER:%.*]], label [[MAIN_PSEUDO_EXIT:%.*]]
+; CHECK: loop.preheader:
+; 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]], 7
+; 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:
+; CHECK-NEXT: [[ADDR:%.*]] = getelementptr i32, ptr [[ARR]], i32 [[IDX]]
+; CHECK-NEXT: store i32 0, ptr [[ADDR]], align 4
+; CHECK-NEXT: [[NEXT:%.*]] = icmp slt i32 [[IDX_NEXT]], 2147483640
+; CHECK-NEXT: [[TMP1:%.*]] = icmp slt i32 [[IDX_NEXT]], [[EXIT_MAINLOOP_AT]]
+; CHECK-NEXT: br i1 [[TMP1]], label [[LOOP]], label [[MAIN_EXIT_SELECTOR:%.*]]
+; CHECK: main.exit.selector:
+; CHECK-NEXT: [[IDX_NEXT_LCSSA:%.*]] = phi i32 [ [[IDX_NEXT]], [[IN_BOUNDS]] ]
+; CHECK-NEXT: [[TMP2:%.*]] = icmp slt i32 [[IDX_NEXT_LCSSA]], 2147483640
+; CHECK-NEXT: br i1 [[TMP2]], label [[MAIN_PSEUDO_EXIT]], label [[EXIT:%.*]]
+; CHECK: main.pseudo.exit:
+; CHECK-NEXT: [[IDX_COPY:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IDX_NEXT_LCSSA]], [[MAIN_EXIT_SELECTOR]] ]
+; CHECK-NEXT: [[INDVAR_END:%.*]] = phi i32 [ 0, [[ENTRY]] ], [ [[IDX_NEXT_LCSSA]], [[MAIN_EXIT_SELECTOR]] ]
+; CHECK-NEXT: br label [[POSTLOOP:%.*]]
+; CHECK: out.of.bounds.loopexit:
+; CHECK-NEXT: br label [[OUT_OF_BOUNDS:%.*]]
+; CHECK: out.of.bounds.loopexit1:
+; CHECK-NEXT: br label [[OUT_OF_BOUNDS]]
+; CHECK: out.of.bounds:
+; CHECK-NEXT: ret void
+; CHECK: exit.loopexit:
+; CHECK-NEXT: br label [[EXIT]]
+; CHECK: exit:
+; CHECK-NEXT: ret void
+; CHECK: postloop:
+; CHECK-NEXT: br label [[LOOP_POSTLOOP:%.*]]
+; CHECK: loop.postloop:
+; CHECK-NEXT: [[IDX_POSTLOOP:%.*]] = phi i32 [ [[IDX_COPY]], [[POSTLOOP]] ], [ [[IDX_NEXT_POSTLOOP:%.*]], [[IN_BOUNDS_POSTLOOP:%.*]] ]
+; CHECK-NEXT: [[IDX_NEXT_POSTLOOP]] = add i32 [[IDX_POSTLOOP]], 7
+; CHECK-NEXT: [[ABC_POSTLOOP:%.*]] = icmp slt i32 [[IDX_POSTLOOP]], [[EXIT_MAINLOOP_AT]]
+; CHECK-NEXT: br i1 [[ABC_POSTLOOP]], label [[IN_BOUNDS_POSTLOOP]], label [[OUT_OF_BOUNDS_LOOPEXIT:%.*]]
+; CHECK: in.bounds.postloop:
+; CHECK-NEXT: [[ADDR_POSTLOOP:%.*]] = getelementptr i32, ptr [[ARR]], i32 [[IDX_POSTLOOP]]
+; CHECK-NEXT: store i32 0, ptr [[ADDR_POSTLOOP]], align 4
+; CHECK-NEXT: [[NEXT_POSTLOOP:%.*]] = icmp slt i32 [[IDX_NEXT_POSTLOOP]], 2147483640
+; CHECK-NEXT: br i1 [[NEXT_POSTLOOP]], label [[LOOP_POSTLOOP]], label [[EXIT_LOOPEXIT:%.*]], !llvm.loop [[LOOP7:![0-9]+]], !irce.loop.clone !6
+;
entry:
%len = load i32, ptr %a_len_ptr, !range !0
; IV = 0; IV <s MAX_INT; IV += 7; 0 <= Len <= MAX_INT - 7. This is the greatest
; value of Len for which IRCE is allowed.
define void @test_03(ptr %arr, ptr %a_len_ptr) {
-
-; CHECK: @test_03(
-; CHECK: entry:
-; CHECK-NEXT: %exit.mainloop.at = load i32, ptr %a_len_ptr
-; CHECK-NEXT: [[COND1:%[^ ]+]] = icmp slt i32 0, %exit.mainloop.at
-; CHECK-NEXT: br i1 [[COND1]], label %loop.preheader, label %main.pseudo.exit
-; CHECK: loop.preheader:
-; 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, 7
-; 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:
-; CHECK-NEXT: %addr = getelementptr i32, ptr %arr, i32 %idx
-; CHECK-NEXT: store i32 0, ptr %addr
-; CHECK-NEXT: %next = icmp slt i32 %idx.next, 2147483647
-; CHECK-NEXT: [[COND2:%[^ ]+]] = icmp slt i32 %idx.next, %exit.mainloop.at
-; CHECK-NEXT: br i1 [[COND2]], label %loop, label %main.exit.selector
-; CHECK: main.exit.selector:
-; CHECK-NEXT: %idx.next.lcssa = phi i32 [ %idx.next, %in.bounds ]
-; CHECK-NEXT: [[COND3:%[^ ]+]] = icmp slt i32 %idx.next.lcssa, 2147483647
-; CHECK-NEXT: br i1 [[COND3]], label %main.pseudo.exit, label %exit
-; CHECK: main.pseudo.exit:
-; CHECK-NEXT: %idx.copy = phi i32 [ 0, %entry ], [ %idx.next.lcssa, %main.exit.selector ]
-; CHECK-NEXT: %indvar.end = phi i32 [ 0, %entry ], [ %idx.next.lcssa, %main.exit.selector ]
-; CHECK-NEXT: br label %postloop
-; CHECK: postloop:
-; CHECK-NEXT: br label %loop.postloop
-; CHECK: loop.postloop:
-; CHECK-NEXT: %idx.postloop = phi i32 [ %idx.copy, %postloop ], [ %idx.next.postloop, %in.bounds.postloop ]
-; CHECK-NEXT: %idx.next.postloop = add i32 %idx.postloop, 7
-; CHECK-NEXT: %abc.postloop = icmp slt i32 %idx.postloop, %exit.mainloop.at
-; CHECK-NEXT: br i1 %abc.postloop, label %in.bounds.postloop, label %out.of.bounds.loopexit
-; CHECK: in.bounds.postloop:
-; CHECK-NEXT: %addr.postloop = getelementptr i32, ptr %arr, i32 %idx.postloop
-; CHECK-NEXT: store i32 0, ptr %addr.postloop
-; CHECK-NEXT: %next.postloop = icmp slt i32 %idx.next.postloop, 2147483647
-; CHECK-NEXT: br i1 %next.postloop, label %loop.postloop, label %exit.loopexit
+; CHECK-LABEL: define void @test_03
+; CHECK-SAME: (ptr [[ARR:%.*]], ptr [[A_LEN_PTR:%.*]]) {
+; CHECK-NEXT: entry:
+; CHECK-NEXT: [[EXIT_MAINLOOP_AT:%.*]] = load i32, ptr [[A_LEN_PTR]], align 4, !range [[RNG8:![0-9]+]]
+; CHECK-NEXT: [[TMP0:%.*]] = icmp slt i32 0, [[EXIT_MAINLOOP_AT]]
+; CHECK-NEXT: br i1 [[TMP0]], label [[LOOP_PREHEADER:%.*]], label [[MAIN_PSEUDO_EXIT:%.*]]
+; CHECK: loop.preheader:
+; 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]], 7
+; 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:
+; CHECK-NEXT: [[ADDR:%.*]] = getelementptr i32, ptr [[ARR]], i32 [[IDX]]
+; CHECK-NEXT: store i32 0, ptr [[ADDR]], align 4
+; CHECK-NEXT: [[NEXT:%.*]] = icmp slt i32 [[IDX_NEXT]], 2147483647
+; CHECK-NEXT: [[TMP1:%.*]] = icmp slt i32 [[IDX_NEXT]], [[EXIT_MAINLOOP_AT]]
+; CHECK-NEXT: br i1 [[TMP1]], label [[LOOP]], label [[MAIN_EXIT_SELECTOR:%.*]]
+; CHECK: main.exit.selector:
+; CHECK-NEXT: [[IDX_NEXT_LCSSA:%.*]] = phi i32 [ [[IDX_NEXT]], [[IN_BOUNDS]] ]
+; CHECK-NEXT: [[TMP2:%.*]] = icmp slt i32 [[IDX_NEXT_LCSSA]], 2147483647
+; CHECK-NEXT: br i1 [[TMP2]], label [[MAIN_PSEUDO_EXIT]], label [[EXIT:%.*]]
+; CHECK: main.pseudo.exit:
+; CHECK-NEXT: [[IDX_COPY:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IDX_NEXT_LCSSA]], [[MAIN_EXIT_SELECTOR]] ]
+; CHECK-NEXT: [[INDVAR_END:%.*]] = phi i32 [ 0, [[ENTRY]] ], [ [[IDX_NEXT_LCSSA]], [[MAIN_EXIT_SELECTOR]] ]
+; CHECK-NEXT: br label [[POSTLOOP:%.*]]
+; CHECK: out.of.bounds.loopexit:
+; CHECK-NEXT: br label [[OUT_OF_BOUNDS:%.*]]
+; CHECK: out.of.bounds.loopexit1:
+; CHECK-NEXT: br label [[OUT_OF_BOUNDS]]
+; CHECK: out.of.bounds:
+; CHECK-NEXT: ret void
+; CHECK: exit.loopexit:
+; CHECK-NEXT: br label [[EXIT]]
+; CHECK: exit:
+; CHECK-NEXT: ret void
+; CHECK: postloop:
+; CHECK-NEXT: br label [[LOOP_POSTLOOP:%.*]]
+; CHECK: loop.postloop:
+; CHECK-NEXT: [[IDX_POSTLOOP:%.*]] = phi i32 [ [[IDX_COPY]], [[POSTLOOP]] ], [ [[IDX_NEXT_POSTLOOP:%.*]], [[IN_BOUNDS_POSTLOOP:%.*]] ]
+; CHECK-NEXT: [[IDX_NEXT_POSTLOOP]] = add i32 [[IDX_POSTLOOP]], 7
+; CHECK-NEXT: [[ABC_POSTLOOP:%.*]] = icmp slt i32 [[IDX_POSTLOOP]], [[EXIT_MAINLOOP_AT]]
+; CHECK-NEXT: br i1 [[ABC_POSTLOOP]], label [[IN_BOUNDS_POSTLOOP]], label [[OUT_OF_BOUNDS_LOOPEXIT:%.*]]
+; CHECK: in.bounds.postloop:
+; CHECK-NEXT: [[ADDR_POSTLOOP:%.*]] = getelementptr i32, ptr [[ARR]], i32 [[IDX_POSTLOOP]]
+; CHECK-NEXT: store i32 0, ptr [[ADDR_POSTLOOP]], align 4
+; CHECK-NEXT: [[NEXT_POSTLOOP:%.*]] = icmp slt i32 [[IDX_NEXT_POSTLOOP]], 2147483647
+; CHECK-NEXT: br i1 [[NEXT_POSTLOOP]], label [[LOOP_POSTLOOP]], label [[EXIT_LOOPEXIT:%.*]], !llvm.loop [[LOOP9:![0-9]+]], !irce.loop.clone !6
+;
entry:
%len = load i32, ptr %a_len_ptr, !range !1
; because the branch would fail once idx.next == MAX_INT - 1 keeping the
; access in bounds.
define void @test_04(ptr %arr, ptr %a_len_ptr) {
- ; CHECK: @test_04(
- ; CHECK: loop:
- ; CHECK: [[IV:%[^ ]+]] = phi i32
- ; CHECK: [[IDX_NEXT:%[^ ]+]] = add i32 [[IV]], 7
+; CHECK-LABEL: define void @test_04
+; CHECK-SAME: (ptr [[ARR:%.*]], ptr [[A_LEN_PTR:%.*]]) {
+; CHECK-NEXT: entry:
+; CHECK-NEXT: [[EXIT_MAINLOOP_AT:%.*]] = load i32, ptr [[A_LEN_PTR]], align 4, !range [[RNG10:![0-9]+]]
+; CHECK-NEXT: [[TMP0:%.*]] = icmp slt i32 0, [[EXIT_MAINLOOP_AT]]
+; CHECK-NEXT: br i1 [[TMP0]], label [[LOOP_PREHEADER:%.*]], label [[MAIN_PSEUDO_EXIT:%.*]]
+; CHECK: loop.preheader:
+; 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]], 7
+; 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:
+; CHECK-NEXT: [[ADDR:%.*]] = getelementptr i32, ptr [[ARR]], i32 [[IDX]]
+; CHECK-NEXT: store i32 0, ptr [[ADDR]], align 4
+; CHECK-NEXT: [[NEXT:%.*]] = icmp slt i32 [[IDX_NEXT]], 2147483647
+; CHECK-NEXT: [[TMP1:%.*]] = icmp slt i32 [[IDX_NEXT]], [[EXIT_MAINLOOP_AT]]
+; CHECK-NEXT: br i1 [[TMP1]], label [[LOOP]], label [[MAIN_EXIT_SELECTOR:%.*]]
+; CHECK: main.exit.selector:
+; CHECK-NEXT: [[IDX_NEXT_LCSSA:%.*]] = phi i32 [ [[IDX_NEXT]], [[IN_BOUNDS]] ]
+; CHECK-NEXT: [[TMP2:%.*]] = icmp slt i32 [[IDX_NEXT_LCSSA]], 2147483647
+; CHECK-NEXT: br i1 [[TMP2]], label [[MAIN_PSEUDO_EXIT]], label [[EXIT:%.*]]
+; CHECK: main.pseudo.exit:
+; CHECK-NEXT: [[IDX_COPY:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IDX_NEXT_LCSSA]], [[MAIN_EXIT_SELECTOR]] ]
+; CHECK-NEXT: [[INDVAR_END:%.*]] = phi i32 [ 0, [[ENTRY]] ], [ [[IDX_NEXT_LCSSA]], [[MAIN_EXIT_SELECTOR]] ]
+; CHECK-NEXT: br label [[POSTLOOP:%.*]]
+; CHECK: out.of.bounds.loopexit:
+; CHECK-NEXT: br label [[OUT_OF_BOUNDS:%.*]]
+; CHECK: out.of.bounds.loopexit1:
+; CHECK-NEXT: br label [[OUT_OF_BOUNDS]]
+; CHECK: out.of.bounds:
+; CHECK-NEXT: ret void
+; CHECK: exit.loopexit:
+; CHECK-NEXT: br label [[EXIT]]
+; CHECK: exit:
+; CHECK-NEXT: ret void
+; CHECK: postloop:
+; CHECK-NEXT: br label [[LOOP_POSTLOOP:%.*]]
+; CHECK: loop.postloop:
+; CHECK-NEXT: [[IDX_POSTLOOP:%.*]] = phi i32 [ [[IDX_COPY]], [[POSTLOOP]] ], [ [[IDX_NEXT_POSTLOOP:%.*]], [[IN_BOUNDS_POSTLOOP:%.*]] ]
+; CHECK-NEXT: [[IDX_NEXT_POSTLOOP]] = add i32 [[IDX_POSTLOOP]], 7
+; CHECK-NEXT: [[ABC_POSTLOOP:%.*]] = icmp slt i32 [[IDX_POSTLOOP]], [[EXIT_MAINLOOP_AT]]
+; CHECK-NEXT: br i1 [[ABC_POSTLOOP]], label [[IN_BOUNDS_POSTLOOP]], label [[OUT_OF_BOUNDS_LOOPEXIT:%.*]]
+; CHECK: in.bounds.postloop:
+; CHECK-NEXT: [[ADDR_POSTLOOP:%.*]] = getelementptr i32, ptr [[ARR]], i32 [[IDX_POSTLOOP]]
+; CHECK-NEXT: store i32 0, ptr [[ADDR_POSTLOOP]], align 4
+; CHECK-NEXT: [[NEXT_POSTLOOP:%.*]] = icmp slt i32 [[IDX_NEXT_POSTLOOP]], 2147483647
+; CHECK-NEXT: br i1 [[NEXT_POSTLOOP]], label [[LOOP_POSTLOOP]], label [[EXIT_LOOPEXIT:%.*]], !llvm.loop [[LOOP11:![0-9]+]], !irce.loop.clone !6
+;
- ; CHECK: main.exit.selector:
- ; CHECK: [[PSEUDO_PHI:%[^ ]+]] = phi i32 [ [[IDX_NEXT]], %in.bounds ]
- ; CHECK: [[COND:%[^ ]+]] = icmp slt i32 [[PSEUDO_PHI]], 2147483647
- ; CHECK: br i1 [[COND]], label %main.pseudo.exit, label %exit
- ; CHECK: loop.postloop:
- ; CHECK: [[IDX_POST:%[^ ]+]] = phi i32
- ; CHECK: [[COND_POST:%[^ ]+]] = icmp slt i32 [[IDX_POST]], %exit.mainloop.at
- ; CHECK: br i1 [[COND_POST]], label %in.bounds.postloop, label %out.of.bounds.loopexit
entry:
%len = load i32, ptr %a_len_ptr, !range !2
; IV = 100; IV >s -1; IV -= 7; 0 <= Len <= 50. IRCE is allowed.
define void @test_05(ptr %arr, ptr %a_len_ptr) {
-
-; CHECK: @test_05(
-; CHECK: entry:
-; CHECK-NEXT: %len = load i32, ptr %a_len_ptr
-; CHECK-NEXT: %exit.preloop.at = add nsw i32 %len, -1
-; CHECK-NEXT: [[COND1:%[^ ]+]] = icmp sgt i32 100, %exit.preloop.at
-; CHECK-NEXT: br i1 [[COND1]], label %loop.preloop.preheader, label %preloop.pseudo.exit
-; CHECK: loop.preloop.preheader:
-; CHECK-NEXT: br label %loop.preloop
-; CHECK: mainloop:
-; 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, -7
-; CHECK-NEXT: %abc = icmp slt i32 %idx, %len
-; CHECK-NEXT: br i1 true, label %in.bounds, label %out.of.bounds.loopexit1
-; CHECK: in.bounds:
-; CHECK-NEXT: %addr = getelementptr i32, ptr %arr, i32 %idx
-; CHECK-NEXT: store i32 0, ptr %addr
-; CHECK-NEXT: %next = icmp sgt i32 %idx.next, -1
-; CHECK-NEXT: br i1 %next, label %loop, label %exit.loopexit
-; CHECK: loop.preloop:
-; CHECK-NEXT: %idx.preloop = phi i32 [ %idx.next.preloop, %in.bounds.preloop ], [ 100, %loop.preloop.preheader ]
-; CHECK-NEXT: %idx.next.preloop = add i32 %idx.preloop, -7
-; CHECK-NEXT: %abc.preloop = icmp slt i32 %idx.preloop, %len
-; CHECK-NEXT: br i1 %abc.preloop, label %in.bounds.preloop, label %out.of.bounds.loopexit
-; CHECK: in.bounds.preloop:
-; CHECK-NEXT: %addr.preloop = getelementptr i32, ptr %arr, i32 %idx.preloop
-; CHECK-NEXT: store i32 0, ptr %addr.preloop
-; CHECK-NEXT: %next.preloop = icmp sgt i32 %idx.next.preloop, -1
-; CHECK-NEXT: [[COND2:%[^ ]+]] = icmp sgt i32 %idx.next.preloop, %exit.preloop.at
-; CHECK-NEXT: br i1 [[COND2]], label %loop.preloop, label %preloop.exit.selector
-; CHECK: preloop.exit.selector:
-; CHECK-NEXT: %idx.next.preloop.lcssa = phi i32 [ %idx.next.preloop, %in.bounds.preloop ]
-; CHECK-NEXT: [[COND3:%[^ ]+]] = icmp sgt i32 %idx.next.preloop.lcssa, -1
-; CHECK-NEXT: br i1 [[COND3]], label %preloop.pseudo.exit, label %exit
-; CHECK: preloop.pseudo.exit:
-; CHECK-NEXT: %idx.preloop.copy = phi i32 [ 100, %entry ], [ %idx.next.preloop.lcssa, %preloop.exit.selector ]
-; CHECK-NEXT: %indvar.end = phi i32 [ 100, %entry ], [ %idx.next.preloop.lcssa, %preloop.exit.selector ]
-; CHECK-NEXT: br label %mainloop
+; CHECK-LABEL: define void @test_05
+; CHECK-SAME: (ptr [[ARR:%.*]], ptr [[A_LEN_PTR:%.*]]) {
+; CHECK-NEXT: entry:
+; CHECK-NEXT: [[LEN:%.*]] = load i32, ptr [[A_LEN_PTR]], align 4, !range [[RNG0]]
+; CHECK-NEXT: [[EXIT_PRELOOP_AT:%.*]] = add nsw i32 [[LEN]], -1
+; CHECK-NEXT: [[TMP0:%.*]] = icmp sgt i32 100, [[EXIT_PRELOOP_AT]]
+; CHECK-NEXT: br i1 [[TMP0]], label [[LOOP_PRELOOP_PREHEADER:%.*]], label [[PRELOOP_PSEUDO_EXIT:%.*]]
+; CHECK: loop.preloop.preheader:
+; CHECK-NEXT: br label [[LOOP_PRELOOP:%.*]]
+; CHECK: mainloop:
+; 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]], -7
+; CHECK-NEXT: [[ABC:%.*]] = icmp slt i32 [[IDX]], [[LEN]]
+; CHECK-NEXT: br i1 true, label [[IN_BOUNDS]], label [[OUT_OF_BOUNDS_LOOPEXIT1:%.*]]
+; CHECK: in.bounds:
+; CHECK-NEXT: [[ADDR:%.*]] = getelementptr i32, ptr [[ARR]], i32 [[IDX]]
+; CHECK-NEXT: store i32 0, ptr [[ADDR]], align 4
+; CHECK-NEXT: [[NEXT:%.*]] = icmp sgt i32 [[IDX_NEXT]], -1
+; CHECK-NEXT: br i1 [[NEXT]], label [[LOOP]], label [[EXIT_LOOPEXIT:%.*]]
+; CHECK: out.of.bounds.loopexit:
+; CHECK-NEXT: br label [[OUT_OF_BOUNDS:%.*]]
+; CHECK: out.of.bounds.loopexit1:
+; CHECK-NEXT: br label [[OUT_OF_BOUNDS]]
+; CHECK: out.of.bounds:
+; CHECK-NEXT: ret void
+; CHECK: exit.loopexit:
+; CHECK-NEXT: br label [[EXIT:%.*]]
+; CHECK: exit:
+; CHECK-NEXT: ret void
+; CHECK: loop.preloop:
+; CHECK-NEXT: [[IDX_PRELOOP:%.*]] = phi i32 [ [[IDX_NEXT_PRELOOP:%.*]], [[IN_BOUNDS_PRELOOP:%.*]] ], [ 100, [[LOOP_PRELOOP_PREHEADER]] ]
+; CHECK-NEXT: [[IDX_NEXT_PRELOOP]] = add i32 [[IDX_PRELOOP]], -7
+; CHECK-NEXT: [[ABC_PRELOOP:%.*]] = icmp slt i32 [[IDX_PRELOOP]], [[LEN]]
+; CHECK-NEXT: br i1 [[ABC_PRELOOP]], label [[IN_BOUNDS_PRELOOP]], label [[OUT_OF_BOUNDS_LOOPEXIT:%.*]]
+; CHECK: in.bounds.preloop:
+; CHECK-NEXT: [[ADDR_PRELOOP:%.*]] = getelementptr i32, ptr [[ARR]], i32 [[IDX_PRELOOP]]
+; CHECK-NEXT: store i32 0, ptr [[ADDR_PRELOOP]], align 4
+; CHECK-NEXT: [[NEXT_PRELOOP:%.*]] = icmp sgt i32 [[IDX_NEXT_PRELOOP]], -1
+; CHECK-NEXT: [[TMP1:%.*]] = icmp sgt i32 [[IDX_NEXT_PRELOOP]], [[EXIT_PRELOOP_AT]]
+; CHECK-NEXT: br i1 [[TMP1]], label [[LOOP_PRELOOP]], label [[PRELOOP_EXIT_SELECTOR:%.*]], !llvm.loop [[LOOP12:![0-9]+]], !irce.loop.clone !6
+; CHECK: preloop.exit.selector:
+; CHECK-NEXT: [[IDX_NEXT_PRELOOP_LCSSA:%.*]] = phi i32 [ [[IDX_NEXT_PRELOOP]], [[IN_BOUNDS_PRELOOP]] ]
+; CHECK-NEXT: [[TMP2:%.*]] = icmp sgt i32 [[IDX_NEXT_PRELOOP_LCSSA]], -1
+; CHECK-NEXT: br i1 [[TMP2]], label [[PRELOOP_PSEUDO_EXIT]], label [[EXIT]]
+; CHECK: preloop.pseudo.exit:
+; CHECK-NEXT: [[IDX_PRELOOP_COPY]] = phi i32 [ 100, [[ENTRY:%.*]] ], [ [[IDX_NEXT_PRELOOP_LCSSA]], [[PRELOOP_EXIT_SELECTOR]] ]
+; CHECK-NEXT: [[INDVAR_END:%.*]] = phi i32 [ 100, [[ENTRY]] ], [ [[IDX_NEXT_PRELOOP_LCSSA]], [[PRELOOP_EXIT_SELECTOR]] ]
+; CHECK-NEXT: br label [[MAINLOOP]]
+;
entry:
%len = load i32, ptr %a_len_ptr, !range !0
; IV = MAX_INT - 7; IV >u 6; IV -= 7; 10 <= Len <= 50. IRCE is allowed.
define void @test_06(ptr %arr, ptr %a_len_ptr) {
-
-; CHECK: @test_06(
-; CHECK: entry:
-; CHECK-NEXT: %len = load i32, ptr %a_len_ptr
-; CHECK-NEXT: %exit.preloop.at = add nsw i32 %len, -1
-; CHECK-NEXT: [[COND1:%[^ ]+]] = icmp ugt i32 2147483640, %exit.preloop.at
-; CHECK-NEXT: br i1 [[COND1]], label %loop.preloop.preheader, label %preloop.pseudo.exit
-; CHECK: loop.preloop.preheader:
-; CHECK-NEXT: br label %loop.preloop
-; CHECK: mainloop:
-; 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, -7
-; CHECK-NEXT: %abc = icmp slt i32 %idx, %len
-; CHECK-NEXT: br i1 true, label %in.bounds, label %out.of.bounds.loopexit1
-; CHECK: in.bounds:
-; CHECK-NEXT: %addr = getelementptr i32, ptr %arr, i32 %idx
-; CHECK-NEXT: store i32 0, ptr %addr
-; CHECK-NEXT: %next = icmp ugt i32 %idx.next, 6
-; CHECK-NEXT: br i1 %next, label %loop, label %exit.loopexit
-; CHECK: loop.preloop:
-; CHECK-NEXT: %idx.preloop = phi i32 [ %idx.next.preloop, %in.bounds.preloop ], [ 2147483640, %loop.preloop.preheader ]
-; CHECK-NEXT: %idx.next.preloop = add i32 %idx.preloop, -7
-; CHECK-NEXT: %abc.preloop = icmp slt i32 %idx.preloop, %len
-; CHECK-NEXT: br i1 %abc.preloop, label %in.bounds.preloop, label %out.of.bounds.loopexit
-; CHECK: in.bounds.preloop:
-; CHECK-NEXT: %addr.preloop = getelementptr i32, ptr %arr, i32 %idx.preloop
-; CHECK-NEXT: store i32 0, ptr %addr.preloop
-; CHECK-NEXT: %next.preloop = icmp ugt i32 %idx.next.preloop, 6
-; CHECK-NEXT: [[COND2:%[^ ]+]] = icmp ugt i32 %idx.next.preloop, %exit.preloop.at
-; CHECK-NEXT: br i1 [[COND2]], label %loop.preloop, label %preloop.exit.selector
-; CHECK: preloop.exit.selector:
-; CHECK-NEXT: %idx.next.preloop.lcssa = phi i32 [ %idx.next.preloop, %in.bounds.preloop ]
-; CHECK-NEXT: [[COND3:%[^ ]+]] = icmp ugt i32 %idx.next.preloop.lcssa, 6
-; CHECK-NEXT: br i1 [[COND3]], label %preloop.pseudo.exit, label %exit
-; CHECK: preloop.pseudo.exit:
-; CHECK-NEXT: %idx.preloop.copy = phi i32 [ 2147483640, %entry ], [ %idx.next.preloop.lcssa, %preloop.exit.selector ]
-; CHECK-NEXT: %indvar.end = phi i32 [ 2147483640, %entry ], [ %idx.next.preloop.lcssa, %preloop.exit.selector ]
-; CHECK-NEXT: br label %mainloop
+; CHECK-LABEL: define void @test_06
+; CHECK-SAME: (ptr [[ARR:%.*]], ptr [[A_LEN_PTR:%.*]]) {
+; CHECK-NEXT: entry:
+; CHECK-NEXT: [[LEN:%.*]] = load i32, ptr [[A_LEN_PTR]], align 4, !range [[RNG13:![0-9]+]]
+; CHECK-NEXT: [[EXIT_PRELOOP_AT:%.*]] = add nsw i32 [[LEN]], -1
+; CHECK-NEXT: [[TMP0:%.*]] = icmp ugt i32 2147483640, [[EXIT_PRELOOP_AT]]
+; CHECK-NEXT: br i1 [[TMP0]], label [[LOOP_PRELOOP_PREHEADER:%.*]], label [[PRELOOP_PSEUDO_EXIT:%.*]]
+; CHECK: loop.preloop.preheader:
+; CHECK-NEXT: br label [[LOOP_PRELOOP:%.*]]
+; CHECK: mainloop:
+; 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]], -7
+; CHECK-NEXT: [[ABC:%.*]] = icmp slt i32 [[IDX]], [[LEN]]
+; CHECK-NEXT: br i1 true, label [[IN_BOUNDS]], label [[OUT_OF_BOUNDS_LOOPEXIT1:%.*]]
+; CHECK: in.bounds:
+; CHECK-NEXT: [[ADDR:%.*]] = getelementptr i32, ptr [[ARR]], i32 [[IDX]]
+; CHECK-NEXT: store i32 0, ptr [[ADDR]], align 4
+; CHECK-NEXT: [[NEXT:%.*]] = icmp ugt i32 [[IDX_NEXT]], 6
+; CHECK-NEXT: br i1 [[NEXT]], label [[LOOP]], label [[EXIT_LOOPEXIT:%.*]]
+; CHECK: out.of.bounds.loopexit:
+; CHECK-NEXT: br label [[OUT_OF_BOUNDS:%.*]]
+; CHECK: out.of.bounds.loopexit1:
+; CHECK-NEXT: br label [[OUT_OF_BOUNDS]]
+; CHECK: out.of.bounds:
+; CHECK-NEXT: ret void
+; CHECK: exit.loopexit:
+; CHECK-NEXT: br label [[EXIT:%.*]]
+; CHECK: exit:
+; CHECK-NEXT: ret void
+; CHECK: loop.preloop:
+; CHECK-NEXT: [[IDX_PRELOOP:%.*]] = phi i32 [ [[IDX_NEXT_PRELOOP:%.*]], [[IN_BOUNDS_PRELOOP:%.*]] ], [ 2147483640, [[LOOP_PRELOOP_PREHEADER]] ]
+; CHECK-NEXT: [[IDX_NEXT_PRELOOP]] = add i32 [[IDX_PRELOOP]], -7
+; CHECK-NEXT: [[ABC_PRELOOP:%.*]] = icmp slt i32 [[IDX_PRELOOP]], [[LEN]]
+; CHECK-NEXT: br i1 [[ABC_PRELOOP]], label [[IN_BOUNDS_PRELOOP]], label [[OUT_OF_BOUNDS_LOOPEXIT:%.*]]
+; CHECK: in.bounds.preloop:
+; CHECK-NEXT: [[ADDR_PRELOOP:%.*]] = getelementptr i32, ptr [[ARR]], i32 [[IDX_PRELOOP]]
+; CHECK-NEXT: store i32 0, ptr [[ADDR_PRELOOP]], align 4
+; CHECK-NEXT: [[NEXT_PRELOOP:%.*]] = icmp ugt i32 [[IDX_NEXT_PRELOOP]], 6
+; CHECK-NEXT: [[TMP1:%.*]] = icmp ugt i32 [[IDX_NEXT_PRELOOP]], [[EXIT_PRELOOP_AT]]
+; CHECK-NEXT: br i1 [[TMP1]], label [[LOOP_PRELOOP]], label [[PRELOOP_EXIT_SELECTOR:%.*]], !llvm.loop [[LOOP14:![0-9]+]], !irce.loop.clone !6
+; CHECK: preloop.exit.selector:
+; CHECK-NEXT: [[IDX_NEXT_PRELOOP_LCSSA:%.*]] = phi i32 [ [[IDX_NEXT_PRELOOP]], [[IN_BOUNDS_PRELOOP]] ]
+; CHECK-NEXT: [[TMP2:%.*]] = icmp ugt i32 [[IDX_NEXT_PRELOOP_LCSSA]], 6
+; CHECK-NEXT: br i1 [[TMP2]], label [[PRELOOP_PSEUDO_EXIT]], label [[EXIT]]
+; CHECK: preloop.pseudo.exit:
+; CHECK-NEXT: [[IDX_PRELOOP_COPY]] = phi i32 [ 2147483640, [[ENTRY:%.*]] ], [ [[IDX_NEXT_PRELOOP_LCSSA]], [[PRELOOP_EXIT_SELECTOR]] ]
+; CHECK-NEXT: [[INDVAR_END:%.*]] = phi i32 [ 2147483640, [[ENTRY]] ], [ [[IDX_NEXT_PRELOOP_LCSSA]], [[PRELOOP_EXIT_SELECTOR]] ]
+; CHECK-NEXT: br label [[MAINLOOP]]
+;
entry:
%len = load i32, ptr %a_len_ptr, !range !3
; IV = MAX_INT - 7; IV >u 5; IV -= 7; 10 <= Len <= 50. IRCE is not allowed,
; because we can cross the 0 border.
define void @test_07(ptr %arr, ptr %a_len_ptr) {
-
-; CHECK: @test_07(
+; CHECK-LABEL: define void @test_07
+; CHECK-SAME: (ptr [[ARR:%.*]], ptr [[A_LEN_PTR:%.*]]) {
+; CHECK-NEXT: entry:
+; CHECK-NEXT: [[LEN:%.*]] = load i32, ptr [[A_LEN_PTR]], align 4, !range [[RNG13]]
+; CHECK-NEXT: br label [[LOOP:%.*]]
+; CHECK: loop:
+; CHECK-NEXT: [[IDX:%.*]] = phi i32 [ 2147483640, [[ENTRY:%.*]] ], [ [[IDX_NEXT:%.*]], [[IN_BOUNDS:%.*]] ]
+; CHECK-NEXT: [[IDX_NEXT]] = add i32 [[IDX]], -7
+; CHECK-NEXT: [[ABC:%.*]] = icmp slt i32 [[IDX]], [[LEN]]
+; CHECK-NEXT: br i1 [[ABC]], label [[IN_BOUNDS]], label [[OUT_OF_BOUNDS:%.*]]
+; CHECK: in.bounds:
+; CHECK-NEXT: [[ADDR:%.*]] = getelementptr i32, ptr [[ARR]], i32 [[IDX]]
+; CHECK-NEXT: store i32 0, ptr [[ADDR]], align 4
+; CHECK-NEXT: [[NEXT:%.*]] = icmp ugt i32 [[IDX_NEXT]], 5
+; CHECK-NEXT: br i1 [[NEXT]], label [[LOOP]], label [[EXIT:%.*]]
+; CHECK: out.of.bounds:
+; CHECK-NEXT: ret void
+; CHECK: exit:
+; CHECK-NEXT: ret void
+;
entry:
%len = load i32, ptr %a_len_ptr, !range !3
; IV = MAX_INT; IV >u 6; IV -= 7; 10 <= Len <= 50. IRCE is allowed.
define void @test_08(ptr %arr, ptr %a_len_ptr) {
-
-; CHECK: @test_08(
-; CHECK: entry:
-; CHECK-NEXT: %len = load i32, ptr %a_len_ptr
-; CHECK-NEXT: %exit.preloop.at = add nsw i32 %len, -1
-; CHECK-NEXT: [[COND1:%[^ ]+]] = icmp ugt i32 2147483647, %exit.preloop.at
-; CHECK-NEXT: br i1 [[COND1]], label %loop.preloop.preheader, label %preloop.pseudo.exit
-; CHECK: loop.preloop.preheader:
-; CHECK-NEXT: br label %loop.preloop
-; CHECK: mainloop:
-; 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, -7
-; CHECK-NEXT: %abc = icmp slt i32 %idx, %len
-; CHECK-NEXT: br i1 true, label %in.bounds, label %out.of.bounds.loopexit1
-; CHECK: in.bounds:
-; CHECK-NEXT: %addr = getelementptr i32, ptr %arr, i32 %idx
-; CHECK-NEXT: store i32 0, ptr %addr
-; CHECK-NEXT: %next = icmp ugt i32 %idx.next, 6
-; CHECK-NEXT: br i1 %next, label %loop, label %exit.loopexit
-; CHECK: loop.preloop:
-; CHECK-NEXT: %idx.preloop = phi i32 [ %idx.next.preloop, %in.bounds.preloop ], [ 2147483647, %loop.preloop.preheader ]
-; CHECK-NEXT: %idx.next.preloop = add i32 %idx.preloop, -7
-; CHECK-NEXT: %abc.preloop = icmp slt i32 %idx.preloop, %len
-; CHECK-NEXT: br i1 %abc.preloop, label %in.bounds.preloop, label %out.of.bounds.loopexit
-; CHECK: in.bounds.preloop:
-; CHECK-NEXT: %addr.preloop = getelementptr i32, ptr %arr, i32 %idx.preloop
-; CHECK-NEXT: store i32 0, ptr %addr.preloop
-; CHECK-NEXT: %next.preloop = icmp ugt i32 %idx.next.preloop, 6
-; CHECK-NEXT: [[COND2:%[^ ]+]] = icmp ugt i32 %idx.next.preloop, %exit.preloop.at
-; CHECK-NEXT: br i1 [[COND2]], label %loop.preloop, label %preloop.exit.selector
-; CHECK: preloop.exit.selector:
-; CHECK-NEXT: %idx.next.preloop.lcssa = phi i32 [ %idx.next.preloop, %in.bounds.preloop ]
-; CHECK-NEXT: [[COND3:%[^ ]+]] = icmp ugt i32 %idx.next.preloop.lcssa, 6
-; CHECK-NEXT: br i1 [[COND3]], label %preloop.pseudo.exit, label %exit
-; CHECK: preloop.pseudo.exit:
-; CHECK-NEXT: %idx.preloop.copy = phi i32 [ 2147483647, %entry ], [ %idx.next.preloop.lcssa, %preloop.exit.selector ]
-; CHECK-NEXT: %indvar.end = phi i32 [ 2147483647, %entry ], [ %idx.next.preloop.lcssa, %preloop.exit.selector ]
-; CHECK-NEXT: br label %mainloop
+; CHECK-LABEL: define void @test_08
+; CHECK-SAME: (ptr [[ARR:%.*]], ptr [[A_LEN_PTR:%.*]]) {
+; CHECK-NEXT: entry:
+; CHECK-NEXT: [[LEN:%.*]] = load i32, ptr [[A_LEN_PTR]], align 4, !range [[RNG13]]
+; CHECK-NEXT: [[EXIT_PRELOOP_AT:%.*]] = add nsw i32 [[LEN]], -1
+; CHECK-NEXT: [[TMP0:%.*]] = icmp ugt i32 2147483647, [[EXIT_PRELOOP_AT]]
+; CHECK-NEXT: br i1 [[TMP0]], label [[LOOP_PRELOOP_PREHEADER:%.*]], label [[PRELOOP_PSEUDO_EXIT:%.*]]
+; CHECK: loop.preloop.preheader:
+; CHECK-NEXT: br label [[LOOP_PRELOOP:%.*]]
+; CHECK: mainloop:
+; 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]], -7
+; CHECK-NEXT: [[ABC:%.*]] = icmp slt i32 [[IDX]], [[LEN]]
+; CHECK-NEXT: br i1 true, label [[IN_BOUNDS]], label [[OUT_OF_BOUNDS_LOOPEXIT1:%.*]]
+; CHECK: in.bounds:
+; CHECK-NEXT: [[ADDR:%.*]] = getelementptr i32, ptr [[ARR]], i32 [[IDX]]
+; CHECK-NEXT: store i32 0, ptr [[ADDR]], align 4
+; CHECK-NEXT: [[NEXT:%.*]] = icmp ugt i32 [[IDX_NEXT]], 6
+; CHECK-NEXT: br i1 [[NEXT]], label [[LOOP]], label [[EXIT_LOOPEXIT:%.*]]
+; CHECK: out.of.bounds.loopexit:
+; CHECK-NEXT: br label [[OUT_OF_BOUNDS:%.*]]
+; CHECK: out.of.bounds.loopexit1:
+; CHECK-NEXT: br label [[OUT_OF_BOUNDS]]
+; CHECK: out.of.bounds:
+; CHECK-NEXT: ret void
+; CHECK: exit.loopexit:
+; CHECK-NEXT: br label [[EXIT:%.*]]
+; CHECK: exit:
+; CHECK-NEXT: ret void
+; CHECK: loop.preloop:
+; CHECK-NEXT: [[IDX_PRELOOP:%.*]] = phi i32 [ [[IDX_NEXT_PRELOOP:%.*]], [[IN_BOUNDS_PRELOOP:%.*]] ], [ 2147483647, [[LOOP_PRELOOP_PREHEADER]] ]
+; CHECK-NEXT: [[IDX_NEXT_PRELOOP]] = add i32 [[IDX_PRELOOP]], -7
+; CHECK-NEXT: [[ABC_PRELOOP:%.*]] = icmp slt i32 [[IDX_PRELOOP]], [[LEN]]
+; CHECK-NEXT: br i1 [[ABC_PRELOOP]], label [[IN_BOUNDS_PRELOOP]], label [[OUT_OF_BOUNDS_LOOPEXIT:%.*]]
+; CHECK: in.bounds.preloop:
+; CHECK-NEXT: [[ADDR_PRELOOP:%.*]] = getelementptr i32, ptr [[ARR]], i32 [[IDX_PRELOOP]]
+; CHECK-NEXT: store i32 0, ptr [[ADDR_PRELOOP]], align 4
+; CHECK-NEXT: [[NEXT_PRELOOP:%.*]] = icmp ugt i32 [[IDX_NEXT_PRELOOP]], 6
+; CHECK-NEXT: [[TMP1:%.*]] = icmp ugt i32 [[IDX_NEXT_PRELOOP]], [[EXIT_PRELOOP_AT]]
+; CHECK-NEXT: br i1 [[TMP1]], label [[LOOP_PRELOOP]], label [[PRELOOP_EXIT_SELECTOR:%.*]], !llvm.loop [[LOOP15:![0-9]+]], !irce.loop.clone !6
+; CHECK: preloop.exit.selector:
+; CHECK-NEXT: [[IDX_NEXT_PRELOOP_LCSSA:%.*]] = phi i32 [ [[IDX_NEXT_PRELOOP]], [[IN_BOUNDS_PRELOOP]] ]
+; CHECK-NEXT: [[TMP2:%.*]] = icmp ugt i32 [[IDX_NEXT_PRELOOP_LCSSA]], 6
+; CHECK-NEXT: br i1 [[TMP2]], label [[PRELOOP_PSEUDO_EXIT]], label [[EXIT]]
+; CHECK: preloop.pseudo.exit:
+; CHECK-NEXT: [[IDX_PRELOOP_COPY]] = phi i32 [ 2147483647, [[ENTRY:%.*]] ], [ [[IDX_NEXT_PRELOOP_LCSSA]], [[PRELOOP_EXIT_SELECTOR]] ]
+; CHECK-NEXT: [[INDVAR_END:%.*]] = phi i32 [ 2147483647, [[ENTRY]] ], [ [[IDX_NEXT_PRELOOP_LCSSA]], [[PRELOOP_EXIT_SELECTOR]] ]
+; CHECK-NEXT: br label [[MAINLOOP]]
+;
entry:
%len = load i32, ptr %a_len_ptr, !range !3
ret void
}
+; TODO: IRCE is legal here.
+; Here how it is done if the step was 1: https://godbolt.org/z/jEqWaseWc
+; It is also legal for step 4. Proof:
+; - Capacity check ensures that iv < limit <= SINT_MAX - 3, meaning that
+; iv <= SINT_MAX - 4.
+; - Because of this, iv.next is always computed w/o overflow.
+; - The loop goes to backedge as long as iv < capacity - 3 && iv < num.elements - 4.
+; - So iterating up to smin(capacity - 3, num.elements - 4) should be safe.
+; - Proof by alive2: https://alive2.llvm.org/ce/z/vEhMxa
+define i32 @test_09(ptr %p, ptr %capacity_p, ptr %num_elements_p) {
+; CHECK-LABEL: define i32 @test_09
+; CHECK-SAME: (ptr [[P:%.*]], ptr [[CAPACITY_P:%.*]], ptr [[NUM_ELEMENTS_P:%.*]]) {
+; CHECK-NEXT: entry:
+; CHECK-NEXT: [[CAPACITY:%.*]] = load i32, ptr [[CAPACITY_P]], align 4, !range [[RNG16:![0-9]+]]
+; CHECK-NEXT: [[NUM_ELEMENTS:%.*]] = load i32, ptr [[NUM_ELEMENTS_P]], align 4, !range [[RNG16]]
+; CHECK-NEXT: [[LIMIT:%.*]] = sub i32 [[CAPACITY]], 3
+; CHECK-NEXT: br label [[LOOP:%.*]]
+; CHECK: loop:
+; CHECK-NEXT: [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ]
+; CHECK-NEXT: [[CAPACITY_CHECK:%.*]] = icmp slt i32 [[IV]], [[LIMIT]]
+; CHECK-NEXT: br i1 [[CAPACITY_CHECK]], label [[BACKEDGE]], label [[OUT_OF_BOUNDS:%.*]], !prof [[PROF17:![0-9]+]]
+; CHECK: backedge:
+; CHECK-NEXT: [[IV_WIDE:%.*]] = zext i32 [[IV]] to i64
+; CHECK-NEXT: [[EL_PTR:%.*]] = getelementptr i32, ptr [[P]], i64 [[IV_WIDE]]
+; CHECK-NEXT: store i32 1, ptr [[EL_PTR]], align 4
+; CHECK-NEXT: [[IV_NEXT]] = add nuw nsw i32 [[IV]], 4
+; CHECK-NEXT: [[LOOP_COND:%.*]] = icmp slt i32 [[IV_NEXT]], [[NUM_ELEMENTS]]
+; CHECK-NEXT: br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT:%.*]]
+; CHECK: exit:
+; CHECK-NEXT: [[IV_LCSSA1:%.*]] = phi i32 [ [[IV]], [[BACKEDGE]] ]
+; CHECK-NEXT: ret i32 [[IV_LCSSA1]]
+; CHECK: out_of_bounds:
+; CHECK-NEXT: ret i32 -1
+;
+entry:
+ %capacity = load i32, ptr %capacity_p, !range !4
+ %num_elements = load i32, ptr %num_elements_p, !range !4
+ %limit = sub i32 %capacity, 3
+ br label %loop
+
+loop:
+ %iv = phi i32 [0, %entry], [%iv.next, %backedge]
+ %capacity_check = icmp slt i32 %iv, %limit
+ br i1 %capacity_check, label %backedge, label %out_of_bounds, !prof !5
+
+backedge:
+ %iv.wide = zext i32 %iv to i64
+ %el.ptr = getelementptr i32, ptr %p, i64 %iv.wide
+ store i32 1, ptr %el.ptr
+ %iv.next = add nuw nsw i32 %iv, 4
+ %loop_cond = icmp slt i32 %iv.next, %num_elements
+ br i1 %loop_cond, label %loop, label %exit
+
+exit:
+ ret i32 %iv
+
+out_of_bounds:
+ ret i32 -1
+}
+
!0 = !{i32 0, i32 50}
!1 = !{i32 0, i32 2147483640}
!2 = !{i32 0, i32 2147483641}
!3 = !{i32 10, i32 50}
+!4 = !{i32 1, i32 2147483648}
+!5 = !{!"branch_weights", i32 1000, i32 1}