+; 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 -irce-allow-narrow-latch=true -S < %s 2>&1 | FileCheck %s
; RUN: opt -verify-loop-info -irce-print-changed-loops -passes='require<branch-prob>,irce' -irce-allow-narrow-latch=true -S < %s 2>&1 | FileCheck %s
; Check that we can remove trivially non-failing range check.
define i32 @test_increasing_slt_slt_wide_simple_no_postloop() {
-
-; CHECK-LABEL: @test_increasing_slt_slt_wide_simple_no_postloop(
-; CHECK-NOT: preloop
-; CHECK-NOT: postloop
+; CHECK-LABEL: define i32 @test_increasing_slt_slt_wide_simple_no_postloop() {
+; CHECK-NEXT: entry:
+; CHECK-NEXT: br label [[LOOP:%.*]]
; CHECK: loop:
-; CHECK: br i1 true, label %backedge, label %check_failed
+; CHECK-NEXT: [[IV:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ]
+; CHECK-NEXT: [[RC:%.*]] = icmp slt i64 [[IV]], 100
+; CHECK-NEXT: br i1 true, label [[BACKEDGE]], label [[CHECK_FAILED:%.*]]
+; CHECK: backedge:
+; CHECK-NEXT: [[IV_NEXT]] = add i64 [[IV]], 1
+; CHECK-NEXT: [[NARROW_IV:%.*]] = trunc i64 [[IV_NEXT]] to i32
+; CHECK-NEXT: [[LATCH_COND:%.*]] = icmp slt i32 [[NARROW_IV]], 100
+; CHECK-NEXT: br i1 [[LATCH_COND]], label [[LOOP]], label [[EXIT:%.*]]
+; CHECK: exit:
+; CHECK-NEXT: [[NARROW_IV_LCSSA:%.*]] = phi i32 [ [[NARROW_IV]], [[BACKEDGE]] ]
+; CHECK-NEXT: ret i32 [[NARROW_IV_LCSSA]]
+; CHECK: check_failed:
+; CHECK-NEXT: ret i32 -1
+;
entry:
br label %loop
; This range check fails on the last iteration, so it needs a postloop.
define i32 @test_increasing_slt_slt_wide_simple_postloop() {
-
-; CHECK-LABEL: @test_increasing_slt_slt_wide_simple_postloop(
-; CHECK-NOT: preloop
+; CHECK-LABEL: define i32 @test_increasing_slt_slt_wide_simple_postloop() {
+; CHECK-NEXT: entry:
+; CHECK-NEXT: br i1 true, label [[LOOP_PREHEADER:%.*]], label [[MAIN_PSEUDO_EXIT:%.*]]
+; CHECK: loop.preheader:
+; CHECK-NEXT: br label [[LOOP:%.*]]
; CHECK: loop:
-; CHECK: br i1 true, label %backedge, label %check_failed
-; CHECK: backedge
-; CHECK: [[COND:%[^ ]+]] = icmp slt i64 %wide.narrow.iv, 99
-; CHECK: br i1 [[COND]], label %loop, label %main.exit.selector
-; CHECK: postloop
+; CHECK-NEXT: [[IV:%.*]] = phi i64 [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ], [ 0, [[LOOP_PREHEADER]] ]
+; CHECK-NEXT: [[RC:%.*]] = icmp slt i64 [[IV]], 99
+; CHECK-NEXT: br i1 true, label [[BACKEDGE]], label [[CHECK_FAILED_LOOPEXIT2:%.*]]
+; CHECK: backedge:
+; CHECK-NEXT: [[IV_NEXT]] = add i64 [[IV]], 1
+; CHECK-NEXT: [[NARROW_IV:%.*]] = trunc i64 [[IV_NEXT]] to i32
+; CHECK-NEXT: [[LATCH_COND:%.*]] = icmp slt i32 [[NARROW_IV]], 100
+; CHECK-NEXT: [[WIDE_NARROW_IV:%.*]] = sext i32 [[NARROW_IV]] to i64
+; CHECK-NEXT: [[TMP0:%.*]] = icmp slt i64 [[WIDE_NARROW_IV]], 99
+; CHECK-NEXT: br i1 [[TMP0]], label [[LOOP]], label [[MAIN_EXIT_SELECTOR:%.*]]
+; CHECK: main.exit.selector:
+; CHECK-NEXT: [[IV_NEXT_LCSSA:%.*]] = phi i64 [ [[IV_NEXT]], [[BACKEDGE]] ]
+; CHECK-NEXT: [[NARROW_IV_LCSSA1:%.*]] = phi i32 [ [[NARROW_IV]], [[BACKEDGE]] ]
+; CHECK-NEXT: [[WIDE_NARROW_IV_LCSSA:%.*]] = phi i64 [ [[WIDE_NARROW_IV]], [[BACKEDGE]] ]
+; CHECK-NEXT: [[TMP1:%.*]] = icmp slt i64 [[WIDE_NARROW_IV_LCSSA]], 100
+; CHECK-NEXT: br i1 [[TMP1]], label [[MAIN_PSEUDO_EXIT]], label [[EXIT:%.*]]
+; CHECK: main.pseudo.exit:
+; CHECK-NEXT: [[IV_COPY:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT_LCSSA]], [[MAIN_EXIT_SELECTOR]] ]
+; CHECK-NEXT: [[INDVAR_END:%.*]] = phi i64 [ 0, [[ENTRY]] ], [ [[WIDE_NARROW_IV_LCSSA]], [[MAIN_EXIT_SELECTOR]] ]
+; CHECK-NEXT: br label [[POSTLOOP:%.*]]
+; CHECK: exit.loopexit:
+; CHECK-NEXT: [[NARROW_IV_LCSSA_PH:%.*]] = phi i32 [ [[NARROW_IV_POSTLOOP:%.*]], [[BACKEDGE_POSTLOOP:%.*]] ]
+; CHECK-NEXT: br label [[EXIT]]
+; CHECK: exit:
+; CHECK-NEXT: [[NARROW_IV_LCSSA:%.*]] = phi i32 [ [[NARROW_IV_LCSSA1]], [[MAIN_EXIT_SELECTOR]] ], [ [[NARROW_IV_LCSSA_PH]], [[EXIT_LOOPEXIT:%.*]] ]
+; CHECK-NEXT: ret i32 [[NARROW_IV_LCSSA]]
+; CHECK: check_failed.loopexit:
+; CHECK-NEXT: br label [[CHECK_FAILED:%.*]]
+; CHECK: check_failed.loopexit2:
+; CHECK-NEXT: br label [[CHECK_FAILED]]
+; CHECK: check_failed:
+; CHECK-NEXT: ret i32 -1
+; CHECK: postloop:
+; CHECK-NEXT: br label [[LOOP_POSTLOOP:%.*]]
+; CHECK: loop.postloop:
+; CHECK-NEXT: [[IV_POSTLOOP:%.*]] = phi i64 [ [[IV_COPY]], [[POSTLOOP]] ], [ [[IV_NEXT_POSTLOOP:%.*]], [[BACKEDGE_POSTLOOP]] ]
+; CHECK-NEXT: [[RC_POSTLOOP:%.*]] = icmp slt i64 [[IV_POSTLOOP]], 99
+; CHECK-NEXT: br i1 [[RC_POSTLOOP]], label [[BACKEDGE_POSTLOOP]], label [[CHECK_FAILED_LOOPEXIT:%.*]]
+; CHECK: backedge.postloop:
+; CHECK-NEXT: [[IV_NEXT_POSTLOOP]] = add i64 [[IV_POSTLOOP]], 1
+; CHECK-NEXT: [[NARROW_IV_POSTLOOP]] = trunc i64 [[IV_NEXT_POSTLOOP]] to i32
+; CHECK-NEXT: [[LATCH_COND_POSTLOOP:%.*]] = icmp slt i32 [[NARROW_IV_POSTLOOP]], 100
+; CHECK-NEXT: br i1 [[LATCH_COND_POSTLOOP]], label [[LOOP_POSTLOOP]], label [[EXIT_LOOPEXIT]], !llvm.loop [[LOOP0:![0-9]+]], !irce.loop.clone !5
+;
entry:
br label %loop
; General case. If both %N and %M are non-negative, we do not need a preloop.
define i32 @test_increasing_slt_slt_wide_non-negative(ptr %n_ptr, ptr %m_ptr) {
-
-; CHECK-LABEL: @test_increasing_slt_slt_wide_non-negative(
-; CHECK-NOT: preloop
+; CHECK-LABEL: define i32 @test_increasing_slt_slt_wide_non-negative
+; CHECK-SAME: (ptr [[N_PTR:%.*]], ptr [[M_PTR:%.*]]) {
+; CHECK-NEXT: entry:
+; CHECK-NEXT: [[N:%.*]] = load i32, ptr [[N_PTR]], align 4, !range [[RNG6:![0-9]+]]
+; CHECK-NEXT: [[M:%.*]] = load i64, ptr [[M_PTR]], align 4, !range [[RNG7:![0-9]+]]
+; CHECK-NEXT: [[TMP0:%.*]] = zext i32 [[N]] to i64
+; CHECK-NEXT: [[EXIT_MAINLOOP_AT:%.*]] = call i64 @llvm.smin.i64(i64 [[M]], i64 [[TMP0]])
+; CHECK-NEXT: [[TMP1:%.*]] = icmp slt i64 0, [[EXIT_MAINLOOP_AT]]
+; CHECK-NEXT: br i1 [[TMP1]], label [[LOOP_PREHEADER:%.*]], label [[MAIN_PSEUDO_EXIT:%.*]]
+; CHECK: loop.preheader:
+; CHECK-NEXT: br label [[LOOP:%.*]]
; CHECK: loop:
-; CHECK: br i1 true, label %backedge, label %check_failed
-; CHECK: backedge
-; CHECK: [[COND:%[^ ]+]] = icmp slt i64 %wide.narrow.iv, %exit.mainloop.at
-; CHECK: br i1 [[COND]], label %loop, label %main.exit.selector
-; CHECK: postloop
+; CHECK-NEXT: [[IV:%.*]] = phi i64 [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ], [ 0, [[LOOP_PREHEADER]] ]
+; CHECK-NEXT: [[RC:%.*]] = icmp slt i64 [[IV]], [[M]]
+; CHECK-NEXT: br i1 true, label [[BACKEDGE]], label [[CHECK_FAILED_LOOPEXIT2:%.*]]
+; CHECK: backedge:
+; CHECK-NEXT: [[IV_NEXT]] = add i64 [[IV]], 1
+; CHECK-NEXT: [[NARROW_IV:%.*]] = trunc i64 [[IV_NEXT]] to i32
+; CHECK-NEXT: [[LATCH_COND:%.*]] = icmp slt i32 [[NARROW_IV]], [[N]]
+; CHECK-NEXT: [[WIDE_NARROW_IV:%.*]] = sext i32 [[NARROW_IV]] to i64
+; CHECK-NEXT: [[TMP2:%.*]] = icmp slt i64 [[WIDE_NARROW_IV]], [[EXIT_MAINLOOP_AT]]
+; CHECK-NEXT: br i1 [[TMP2]], label [[LOOP]], label [[MAIN_EXIT_SELECTOR:%.*]]
+; CHECK: main.exit.selector:
+; CHECK-NEXT: [[IV_NEXT_LCSSA:%.*]] = phi i64 [ [[IV_NEXT]], [[BACKEDGE]] ]
+; CHECK-NEXT: [[NARROW_IV_LCSSA1:%.*]] = phi i32 [ [[NARROW_IV]], [[BACKEDGE]] ]
+; CHECK-NEXT: [[WIDE_NARROW_IV_LCSSA:%.*]] = phi i64 [ [[WIDE_NARROW_IV]], [[BACKEDGE]] ]
+; CHECK-NEXT: [[WIDE_N:%.*]] = sext i32 [[N]] to i64
+; CHECK-NEXT: [[TMP3:%.*]] = icmp slt i64 [[WIDE_NARROW_IV_LCSSA]], [[WIDE_N]]
+; CHECK-NEXT: br i1 [[TMP3]], label [[MAIN_PSEUDO_EXIT]], label [[EXIT:%.*]]
+; CHECK: main.pseudo.exit:
+; CHECK-NEXT: [[IV_COPY:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT_LCSSA]], [[MAIN_EXIT_SELECTOR]] ]
+; CHECK-NEXT: [[INDVAR_END:%.*]] = phi i64 [ 0, [[ENTRY]] ], [ [[WIDE_NARROW_IV_LCSSA]], [[MAIN_EXIT_SELECTOR]] ]
+; CHECK-NEXT: br label [[POSTLOOP:%.*]]
+; CHECK: exit.loopexit:
+; CHECK-NEXT: [[NARROW_IV_LCSSA_PH:%.*]] = phi i32 [ [[NARROW_IV_POSTLOOP:%.*]], [[BACKEDGE_POSTLOOP:%.*]] ]
+; CHECK-NEXT: br label [[EXIT]]
+; CHECK: exit:
+; CHECK-NEXT: [[NARROW_IV_LCSSA:%.*]] = phi i32 [ [[NARROW_IV_LCSSA1]], [[MAIN_EXIT_SELECTOR]] ], [ [[NARROW_IV_LCSSA_PH]], [[EXIT_LOOPEXIT:%.*]] ]
+; CHECK-NEXT: ret i32 [[NARROW_IV_LCSSA]]
+; CHECK: check_failed.loopexit:
+; CHECK-NEXT: br label [[CHECK_FAILED:%.*]]
+; CHECK: check_failed.loopexit2:
+; CHECK-NEXT: br label [[CHECK_FAILED]]
+; CHECK: check_failed:
+; CHECK-NEXT: ret i32 -1
+; CHECK: postloop:
+; CHECK-NEXT: br label [[LOOP_POSTLOOP:%.*]]
+; CHECK: loop.postloop:
+; CHECK-NEXT: [[IV_POSTLOOP:%.*]] = phi i64 [ [[IV_COPY]], [[POSTLOOP]] ], [ [[IV_NEXT_POSTLOOP:%.*]], [[BACKEDGE_POSTLOOP]] ]
+; CHECK-NEXT: [[RC_POSTLOOP:%.*]] = icmp slt i64 [[IV_POSTLOOP]], [[M]]
+; CHECK-NEXT: br i1 [[RC_POSTLOOP]], label [[BACKEDGE_POSTLOOP]], label [[CHECK_FAILED_LOOPEXIT:%.*]]
+; CHECK: backedge.postloop:
+; CHECK-NEXT: [[IV_NEXT_POSTLOOP]] = add i64 [[IV_POSTLOOP]], 1
+; CHECK-NEXT: [[NARROW_IV_POSTLOOP]] = trunc i64 [[IV_NEXT_POSTLOOP]] to i32
+; CHECK-NEXT: [[LATCH_COND_POSTLOOP:%.*]] = icmp slt i32 [[NARROW_IV_POSTLOOP]], [[N]]
+; CHECK-NEXT: br i1 [[LATCH_COND_POSTLOOP]], label [[LOOP_POSTLOOP]], label [[EXIT_LOOPEXIT]], !llvm.loop [[LOOP8:![0-9]+]], !irce.loop.clone !5
+;
entry:
%N = load i32, ptr %n_ptr, !range !2
; we make a non-negativity runtime check against M and do not go to main loop if
; M was negative.
define i32 @test_increasing_slt_slt_wide_general(ptr %n_ptr, ptr %m_ptr) {
-
-; CHECK-LABEL: @test_increasing_slt_slt_wide_general(
-; CHECK-NOT: preloop
+; CHECK-LABEL: define i32 @test_increasing_slt_slt_wide_general
+; CHECK-SAME: (ptr [[N_PTR:%.*]], ptr [[M_PTR:%.*]]) {
+; CHECK-NEXT: entry:
+; CHECK-NEXT: [[N:%.*]] = load i32, ptr [[N_PTR]], align 4, !range [[RNG6]]
+; CHECK-NEXT: [[M:%.*]] = load i64, ptr [[M_PTR]], align 4
+; CHECK-NEXT: [[TMP0:%.*]] = add i64 [[M]], -9223372036854775807
+; CHECK-NEXT: [[SMAX:%.*]] = call i64 @llvm.smax.i64(i64 [[TMP0]], i64 0)
+; CHECK-NEXT: [[TMP1:%.*]] = sub i64 [[M]], [[SMAX]]
+; CHECK-NEXT: [[SMIN:%.*]] = call i64 @llvm.smin.i64(i64 [[M]], i64 0)
+; CHECK-NEXT: [[SMAX1:%.*]] = call i64 @llvm.smax.i64(i64 [[SMIN]], i64 -1)
+; CHECK-NEXT: [[TMP2:%.*]] = add nsw i64 [[SMAX1]], 1
+; CHECK-NEXT: [[TMP3:%.*]] = mul i64 [[TMP1]], [[TMP2]]
+; CHECK-NEXT: [[TMP4:%.*]] = zext i32 [[N]] to i64
+; CHECK-NEXT: [[SMIN2:%.*]] = call i64 @llvm.smin.i64(i64 [[TMP3]], i64 [[TMP4]])
+; CHECK-NEXT: [[EXIT_MAINLOOP_AT:%.*]] = call i64 @llvm.smax.i64(i64 [[SMIN2]], i64 0)
+; CHECK-NEXT: [[TMP5:%.*]] = icmp slt i64 0, [[EXIT_MAINLOOP_AT]]
+; CHECK-NEXT: br i1 [[TMP5]], label [[LOOP_PREHEADER:%.*]], label [[MAIN_PSEUDO_EXIT:%.*]]
+; CHECK: loop.preheader:
+; CHECK-NEXT: br label [[LOOP:%.*]]
; CHECK: loop:
-; CHECK: br i1 true, label %backedge, label %check_failed
-; CHECK: backedge
-; CHECK: [[COND:%[^ ]+]] = icmp slt i64
-; CHECK: br i1 [[COND]], label %loop, label %main.exit.selector
-; CHECK: postloop
+; CHECK-NEXT: [[IV:%.*]] = phi i64 [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ], [ 0, [[LOOP_PREHEADER]] ]
+; CHECK-NEXT: [[RC:%.*]] = icmp slt i64 [[IV]], [[M]]
+; CHECK-NEXT: br i1 true, label [[BACKEDGE]], label [[CHECK_FAILED_LOOPEXIT5:%.*]]
+; CHECK: backedge:
+; CHECK-NEXT: [[IV_NEXT]] = add i64 [[IV]], 1
+; CHECK-NEXT: [[NARROW_IV:%.*]] = trunc i64 [[IV_NEXT]] to i32
+; CHECK-NEXT: [[LATCH_COND:%.*]] = icmp slt i32 [[NARROW_IV]], [[N]]
+; CHECK-NEXT: [[WIDE_NARROW_IV:%.*]] = sext i32 [[NARROW_IV]] to i64
+; CHECK-NEXT: [[TMP6:%.*]] = icmp slt i64 [[WIDE_NARROW_IV]], [[EXIT_MAINLOOP_AT]]
+; CHECK-NEXT: br i1 [[TMP6]], label [[LOOP]], label [[MAIN_EXIT_SELECTOR:%.*]]
+; CHECK: main.exit.selector:
+; CHECK-NEXT: [[IV_NEXT_LCSSA:%.*]] = phi i64 [ [[IV_NEXT]], [[BACKEDGE]] ]
+; CHECK-NEXT: [[NARROW_IV_LCSSA4:%.*]] = phi i32 [ [[NARROW_IV]], [[BACKEDGE]] ]
+; CHECK-NEXT: [[WIDE_NARROW_IV_LCSSA:%.*]] = phi i64 [ [[WIDE_NARROW_IV]], [[BACKEDGE]] ]
+; CHECK-NEXT: [[WIDE_N:%.*]] = sext i32 [[N]] to i64
+; CHECK-NEXT: [[TMP7:%.*]] = icmp slt i64 [[WIDE_NARROW_IV_LCSSA]], [[WIDE_N]]
+; CHECK-NEXT: br i1 [[TMP7]], label [[MAIN_PSEUDO_EXIT]], label [[EXIT:%.*]]
+; CHECK: main.pseudo.exit:
+; CHECK-NEXT: [[IV_COPY:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT_LCSSA]], [[MAIN_EXIT_SELECTOR]] ]
+; CHECK-NEXT: [[INDVAR_END:%.*]] = phi i64 [ 0, [[ENTRY]] ], [ [[WIDE_NARROW_IV_LCSSA]], [[MAIN_EXIT_SELECTOR]] ]
+; CHECK-NEXT: br label [[POSTLOOP:%.*]]
+; CHECK: exit.loopexit:
+; CHECK-NEXT: [[NARROW_IV_LCSSA_PH:%.*]] = phi i32 [ [[NARROW_IV_POSTLOOP:%.*]], [[BACKEDGE_POSTLOOP:%.*]] ]
+; CHECK-NEXT: br label [[EXIT]]
+; CHECK: exit:
+; CHECK-NEXT: [[NARROW_IV_LCSSA:%.*]] = phi i32 [ [[NARROW_IV_LCSSA4]], [[MAIN_EXIT_SELECTOR]] ], [ [[NARROW_IV_LCSSA_PH]], [[EXIT_LOOPEXIT:%.*]] ]
+; CHECK-NEXT: ret i32 [[NARROW_IV_LCSSA]]
+; CHECK: check_failed.loopexit:
+; CHECK-NEXT: br label [[CHECK_FAILED:%.*]]
+; CHECK: check_failed.loopexit5:
+; CHECK-NEXT: br label [[CHECK_FAILED]]
+; CHECK: check_failed:
+; CHECK-NEXT: ret i32 -1
+; CHECK: postloop:
+; CHECK-NEXT: br label [[LOOP_POSTLOOP:%.*]]
+; CHECK: loop.postloop:
+; CHECK-NEXT: [[IV_POSTLOOP:%.*]] = phi i64 [ [[IV_COPY]], [[POSTLOOP]] ], [ [[IV_NEXT_POSTLOOP:%.*]], [[BACKEDGE_POSTLOOP]] ]
+; CHECK-NEXT: [[RC_POSTLOOP:%.*]] = icmp slt i64 [[IV_POSTLOOP]], [[M]]
+; CHECK-NEXT: br i1 [[RC_POSTLOOP]], label [[BACKEDGE_POSTLOOP]], label [[CHECK_FAILED_LOOPEXIT:%.*]]
+; CHECK: backedge.postloop:
+; CHECK-NEXT: [[IV_NEXT_POSTLOOP]] = add i64 [[IV_POSTLOOP]], 1
+; CHECK-NEXT: [[NARROW_IV_POSTLOOP]] = trunc i64 [[IV_NEXT_POSTLOOP]] to i32
+; CHECK-NEXT: [[LATCH_COND_POSTLOOP:%.*]] = icmp slt i32 [[NARROW_IV_POSTLOOP]], [[N]]
+; CHECK-NEXT: br i1 [[LATCH_COND_POSTLOOP]], label [[LOOP_POSTLOOP]], label [[EXIT_LOOPEXIT]], !llvm.loop [[LOOP9:![0-9]+]], !irce.loop.clone !5
+;
entry:
%N = load i32, ptr %n_ptr, !range !2
; General case with preloop.
define i32 @test_increasing_slt_slt_wide_general_preloop(ptr %n_ptr, ptr %m_ptr) {
-
-; CHECK-LABEL: @test_increasing_slt_slt_wide_general_preloop(
+; CHECK-LABEL: define i32 @test_increasing_slt_slt_wide_general_preloop
+; CHECK-SAME: (ptr [[N_PTR:%.*]], ptr [[M_PTR:%.*]]) {
+; CHECK-NEXT: entry:
+; CHECK-NEXT: [[N:%.*]] = load i32, ptr [[N_PTR]], align 4, !range [[RNG6]]
+; CHECK-NEXT: [[M:%.*]] = load i64, ptr [[M_PTR]], align 4
+; CHECK-NEXT: [[SMIN:%.*]] = call i64 @llvm.smin.i64(i64 [[M]], i64 0)
+; CHECK-NEXT: [[SMAX:%.*]] = call i64 @llvm.smax.i64(i64 [[SMIN]], i64 -1)
+; CHECK-NEXT: [[EXIT_PRELOOP_AT:%.*]] = sub i64 -1, [[SMAX]]
+; CHECK-NEXT: [[TMP0:%.*]] = add i64 [[M]], -9223372036854775807
+; CHECK-NEXT: [[SMAX1:%.*]] = call i64 @llvm.smax.i64(i64 [[TMP0]], i64 1)
+; CHECK-NEXT: [[TMP1:%.*]] = sub i64 [[M]], [[SMAX1]]
+; CHECK-NEXT: [[TMP2:%.*]] = add nsw i64 [[SMAX]], 1
+; CHECK-NEXT: [[TMP3:%.*]] = mul i64 [[TMP1]], [[TMP2]]
+; CHECK-NEXT: [[TMP4:%.*]] = zext i32 [[N]] to i64
+; CHECK-NEXT: [[SMIN2:%.*]] = call i64 @llvm.smin.i64(i64 [[TMP3]], i64 [[TMP4]])
+; CHECK-NEXT: [[EXIT_MAINLOOP_AT:%.*]] = call i64 @llvm.smax.i64(i64 [[SMIN2]], i64 -1)
+; CHECK-NEXT: [[TMP5:%.*]] = icmp slt i64 -1, [[EXIT_PRELOOP_AT]]
+; CHECK-NEXT: br i1 [[TMP5]], label [[LOOP_PRELOOP_PREHEADER:%.*]], label [[PRELOOP_PSEUDO_EXIT:%.*]]
+; CHECK: loop.preloop.preheader:
+; CHECK-NEXT: br label [[LOOP_PRELOOP:%.*]]
+; CHECK: mainloop:
+; CHECK-NEXT: [[TMP6:%.*]] = icmp slt i64 [[INDVAR_END:%.*]], [[EXIT_MAINLOOP_AT]]
+; CHECK-NEXT: br i1 [[TMP6]], label [[LOOP_PREHEADER:%.*]], label [[MAIN_PSEUDO_EXIT:%.*]]
+; CHECK: loop.preheader:
+; CHECK-NEXT: br label [[LOOP:%.*]]
; CHECK: loop:
-; CHECK: br i1 true, label %backedge, label %check_failed
-; CHECK: backedge
-; CHECK: [[COND:%[^ ]+]] = icmp slt i64
-; CHECK: br i1 [[COND]], label %loop, label %main.exit.selector
-; CHECK: preloop
-; CHECK: postloop
+; CHECK-NEXT: [[IV:%.*]] = phi i64 [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ], [ [[IV_PRELOOP_COPY:%.*]], [[LOOP_PREHEADER]] ]
+; CHECK-NEXT: [[RC:%.*]] = icmp slt i64 [[IV]], [[M]]
+; CHECK-NEXT: br i1 true, label [[BACKEDGE]], label [[CHECK_FAILED_LOOPEXIT8:%.*]]
+; CHECK: backedge:
+; CHECK-NEXT: [[IV_NEXT]] = add i64 [[IV]], 1
+; CHECK-NEXT: [[NARROW_IV:%.*]] = trunc i64 [[IV]] to i32
+; CHECK-NEXT: [[LATCH_COND:%.*]] = icmp slt i32 [[NARROW_IV]], [[N]]
+; CHECK-NEXT: [[WIDE_NARROW_IV:%.*]] = sext i32 [[NARROW_IV]] to i64
+; CHECK-NEXT: [[TMP7:%.*]] = icmp slt i64 [[WIDE_NARROW_IV]], [[EXIT_MAINLOOP_AT]]
+; CHECK-NEXT: br i1 [[TMP7]], label [[LOOP]], label [[MAIN_EXIT_SELECTOR:%.*]]
+; CHECK: main.exit.selector:
+; CHECK-NEXT: [[IV_NEXT_LCSSA:%.*]] = phi i64 [ [[IV_NEXT]], [[BACKEDGE]] ]
+; CHECK-NEXT: [[NARROW_IV_LCSSA7:%.*]] = phi i32 [ [[NARROW_IV]], [[BACKEDGE]] ]
+; CHECK-NEXT: [[WIDE_NARROW_IV_LCSSA:%.*]] = phi i64 [ [[WIDE_NARROW_IV]], [[BACKEDGE]] ]
+; CHECK-NEXT: [[WIDE_N4:%.*]] = sext i32 [[N]] to i64
+; CHECK-NEXT: [[TMP8:%.*]] = icmp slt i64 [[WIDE_NARROW_IV_LCSSA]], [[WIDE_N4]]
+; CHECK-NEXT: br i1 [[TMP8]], label [[MAIN_PSEUDO_EXIT]], label [[EXIT:%.*]]
+; CHECK: main.pseudo.exit:
+; CHECK-NEXT: [[IV_COPY:%.*]] = phi i64 [ [[IV_PRELOOP_COPY]], [[MAINLOOP:%.*]] ], [ [[IV_NEXT_LCSSA]], [[MAIN_EXIT_SELECTOR]] ]
+; CHECK-NEXT: [[INDVAR_END5:%.*]] = phi i64 [ [[INDVAR_END]], [[MAINLOOP]] ], [ [[WIDE_NARROW_IV_LCSSA]], [[MAIN_EXIT_SELECTOR]] ]
+; CHECK-NEXT: br label [[POSTLOOP:%.*]]
+; CHECK: exit.loopexit:
+; CHECK-NEXT: [[NARROW_IV_LCSSA_PH:%.*]] = phi i32 [ [[NARROW_IV_POSTLOOP:%.*]], [[BACKEDGE_POSTLOOP:%.*]] ]
+; CHECK-NEXT: br label [[EXIT]]
+; CHECK: exit:
+; CHECK-NEXT: [[NARROW_IV_LCSSA:%.*]] = phi i32 [ [[NARROW_IV_LCSSA7]], [[MAIN_EXIT_SELECTOR]] ], [ [[NARROW_IV_PRELOOP_LCSSA:%.*]], [[PRELOOP_EXIT_SELECTOR:%.*]] ], [ [[NARROW_IV_LCSSA_PH]], [[EXIT_LOOPEXIT:%.*]] ]
+; CHECK-NEXT: ret i32 [[NARROW_IV_LCSSA]]
+; CHECK: check_failed.loopexit:
+; CHECK-NEXT: br label [[CHECK_FAILED:%.*]]
+; CHECK: check_failed.loopexit6:
+; CHECK-NEXT: br label [[CHECK_FAILED]]
+; CHECK: check_failed.loopexit8:
+; CHECK-NEXT: br label [[CHECK_FAILED]]
+; CHECK: check_failed:
+; CHECK-NEXT: ret i32 -1
+; CHECK: loop.preloop:
+; CHECK-NEXT: [[IV_PRELOOP:%.*]] = phi i64 [ [[IV_NEXT_PRELOOP:%.*]], [[BACKEDGE_PRELOOP:%.*]] ], [ 0, [[LOOP_PRELOOP_PREHEADER]] ]
+; CHECK-NEXT: [[RC_PRELOOP:%.*]] = icmp slt i64 [[IV_PRELOOP]], [[M]]
+; CHECK-NEXT: br i1 [[RC_PRELOOP]], label [[BACKEDGE_PRELOOP]], label [[CHECK_FAILED_LOOPEXIT:%.*]]
+; CHECK: backedge.preloop:
+; CHECK-NEXT: [[IV_NEXT_PRELOOP]] = add i64 [[IV_PRELOOP]], 1
+; CHECK-NEXT: [[NARROW_IV_PRELOOP:%.*]] = trunc i64 [[IV_PRELOOP]] to i32
+; CHECK-NEXT: [[LATCH_COND_PRELOOP:%.*]] = icmp slt i32 [[NARROW_IV_PRELOOP]], [[N]]
+; CHECK-NEXT: [[WIDE_NARROW_IV_PRELOOP:%.*]] = sext i32 [[NARROW_IV_PRELOOP]] to i64
+; CHECK-NEXT: [[TMP9:%.*]] = icmp slt i64 [[WIDE_NARROW_IV_PRELOOP]], [[EXIT_PRELOOP_AT]]
+; CHECK-NEXT: br i1 [[TMP9]], label [[LOOP_PRELOOP]], label [[PRELOOP_EXIT_SELECTOR]], !llvm.loop [[LOOP10:![0-9]+]], !irce.loop.clone !5
+; CHECK: preloop.exit.selector:
+; CHECK-NEXT: [[IV_NEXT_PRELOOP_LCSSA:%.*]] = phi i64 [ [[IV_NEXT_PRELOOP]], [[BACKEDGE_PRELOOP]] ]
+; CHECK-NEXT: [[NARROW_IV_PRELOOP_LCSSA]] = phi i32 [ [[NARROW_IV_PRELOOP]], [[BACKEDGE_PRELOOP]] ]
+; CHECK-NEXT: [[WIDE_NARROW_IV_PRELOOP_LCSSA:%.*]] = phi i64 [ [[WIDE_NARROW_IV_PRELOOP]], [[BACKEDGE_PRELOOP]] ]
+; CHECK-NEXT: [[WIDE_N:%.*]] = sext i32 [[N]] to i64
+; CHECK-NEXT: [[TMP10:%.*]] = icmp slt i64 [[WIDE_NARROW_IV_PRELOOP_LCSSA]], [[WIDE_N]]
+; CHECK-NEXT: br i1 [[TMP10]], label [[PRELOOP_PSEUDO_EXIT]], label [[EXIT]]
+; CHECK: preloop.pseudo.exit:
+; CHECK-NEXT: [[IV_PRELOOP_COPY]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT_PRELOOP_LCSSA]], [[PRELOOP_EXIT_SELECTOR]] ]
+; CHECK-NEXT: [[INDVAR_END]] = phi i64 [ -1, [[ENTRY]] ], [ [[WIDE_NARROW_IV_PRELOOP_LCSSA]], [[PRELOOP_EXIT_SELECTOR]] ]
+; CHECK-NEXT: br label [[MAINLOOP]]
+; CHECK: postloop:
+; CHECK-NEXT: br label [[LOOP_POSTLOOP:%.*]]
+; CHECK: loop.postloop:
+; CHECK-NEXT: [[IV_POSTLOOP:%.*]] = phi i64 [ [[IV_COPY]], [[POSTLOOP]] ], [ [[IV_NEXT_POSTLOOP:%.*]], [[BACKEDGE_POSTLOOP]] ]
+; CHECK-NEXT: [[RC_POSTLOOP:%.*]] = icmp slt i64 [[IV_POSTLOOP]], [[M]]
+; CHECK-NEXT: br i1 [[RC_POSTLOOP]], label [[BACKEDGE_POSTLOOP]], label [[CHECK_FAILED_LOOPEXIT6:%.*]]
+; CHECK: backedge.postloop:
+; CHECK-NEXT: [[IV_NEXT_POSTLOOP]] = add i64 [[IV_POSTLOOP]], 1
+; CHECK-NEXT: [[NARROW_IV_POSTLOOP]] = trunc i64 [[IV_POSTLOOP]] to i32
+; CHECK-NEXT: [[LATCH_COND_POSTLOOP:%.*]] = icmp slt i32 [[NARROW_IV_POSTLOOP]], [[N]]
+; CHECK-NEXT: br i1 [[LATCH_COND_POSTLOOP]], label [[LOOP_POSTLOOP]], label [[EXIT_LOOPEXIT]], !llvm.loop [[LOOP11:![0-9]+]], !irce.loop.clone !5
+;
entry:
%N = load i32, ptr %n_ptr, !range !2
; Same as above, multiple checks.
define i32 @test_increasing_slt_slt_wide_multiple_checks(ptr %n_ptr, ptr %m1_ptr, ptr %m2_ptr, ptr %m3_ptr, ptr %m4_ptr) {
-; CHECK-LABEL: @test_increasing_slt_slt_wide_multiple_checks(
-; CHECK-NOT: preloop
+; CHECK-LABEL: define i32 @test_increasing_slt_slt_wide_multiple_checks
+; CHECK-SAME: (ptr [[N_PTR:%.*]], ptr [[M1_PTR:%.*]], ptr [[M2_PTR:%.*]], ptr [[M3_PTR:%.*]], ptr [[M4_PTR:%.*]]) {
+; CHECK-NEXT: entry:
+; CHECK-NEXT: [[N:%.*]] = load i32, ptr [[N_PTR]], align 4, !range [[RNG6]]
+; CHECK-NEXT: [[M1:%.*]] = load i64, ptr [[M1_PTR]], align 4
+; CHECK-NEXT: [[M2:%.*]] = load i64, ptr [[M2_PTR]], align 4
+; CHECK-NEXT: [[M3:%.*]] = load i64, ptr [[M3_PTR]], align 4
+; CHECK-NEXT: [[M4:%.*]] = load i64, ptr [[M4_PTR]], align 4
+; CHECK-NEXT: [[TMP0:%.*]] = add i64 [[M2]], -9223372036854775807
+; CHECK-NEXT: [[SMAX:%.*]] = call i64 @llvm.smax.i64(i64 [[TMP0]], i64 0)
+; CHECK-NEXT: [[TMP1:%.*]] = sub i64 [[M2]], [[SMAX]]
+; CHECK-NEXT: [[SMIN:%.*]] = call i64 @llvm.smin.i64(i64 [[M2]], i64 0)
+; CHECK-NEXT: [[SMAX1:%.*]] = call i64 @llvm.smax.i64(i64 [[SMIN]], i64 -1)
+; CHECK-NEXT: [[TMP2:%.*]] = add nsw i64 [[SMAX1]], 1
+; CHECK-NEXT: [[TMP3:%.*]] = mul i64 [[TMP1]], [[TMP2]]
+; CHECK-NEXT: [[TMP4:%.*]] = add i64 [[M1]], -9223372036854775807
+; CHECK-NEXT: [[SMAX2:%.*]] = call i64 @llvm.smax.i64(i64 [[TMP4]], i64 0)
+; CHECK-NEXT: [[TMP5:%.*]] = sub i64 [[M1]], [[SMAX2]]
+; CHECK-NEXT: [[SMIN3:%.*]] = call i64 @llvm.smin.i64(i64 [[M1]], i64 0)
+; CHECK-NEXT: [[SMAX4:%.*]] = call i64 @llvm.smax.i64(i64 [[SMIN3]], i64 -1)
+; CHECK-NEXT: [[TMP6:%.*]] = add nsw i64 [[SMAX4]], 1
+; CHECK-NEXT: [[TMP7:%.*]] = mul i64 [[TMP5]], [[TMP6]]
+; CHECK-NEXT: [[SMIN5:%.*]] = call i64 @llvm.smin.i64(i64 [[TMP3]], i64 [[TMP7]])
+; CHECK-NEXT: [[TMP8:%.*]] = add i64 [[M3]], -9223372036854775807
+; CHECK-NEXT: [[SMAX6:%.*]] = call i64 @llvm.smax.i64(i64 [[TMP8]], i64 0)
+; CHECK-NEXT: [[TMP9:%.*]] = sub i64 [[M3]], [[SMAX6]]
+; CHECK-NEXT: [[SMIN7:%.*]] = call i64 @llvm.smin.i64(i64 [[M3]], i64 0)
+; CHECK-NEXT: [[SMAX8:%.*]] = call i64 @llvm.smax.i64(i64 [[SMIN7]], i64 -1)
+; CHECK-NEXT: [[TMP10:%.*]] = add nsw i64 [[SMAX8]], 1
+; CHECK-NEXT: [[TMP11:%.*]] = mul i64 [[TMP9]], [[TMP10]]
+; CHECK-NEXT: [[SMIN9:%.*]] = call i64 @llvm.smin.i64(i64 [[SMIN5]], i64 [[TMP11]])
+; CHECK-NEXT: [[TMP12:%.*]] = add i64 [[M4]], -9223372036854775807
+; CHECK-NEXT: [[SMAX10:%.*]] = call i64 @llvm.smax.i64(i64 [[TMP12]], i64 0)
+; CHECK-NEXT: [[TMP13:%.*]] = sub i64 [[M4]], [[SMAX10]]
+; CHECK-NEXT: [[SMIN11:%.*]] = call i64 @llvm.smin.i64(i64 [[M4]], i64 0)
+; CHECK-NEXT: [[SMAX12:%.*]] = call i64 @llvm.smax.i64(i64 [[SMIN11]], i64 -1)
+; CHECK-NEXT: [[TMP14:%.*]] = add nsw i64 [[SMAX12]], 1
+; CHECK-NEXT: [[TMP15:%.*]] = mul i64 [[TMP13]], [[TMP14]]
+; CHECK-NEXT: [[SMIN13:%.*]] = call i64 @llvm.smin.i64(i64 [[SMIN9]], i64 [[TMP15]])
+; CHECK-NEXT: [[TMP16:%.*]] = zext i32 [[N]] to i64
+; CHECK-NEXT: [[SMIN14:%.*]] = call i64 @llvm.smin.i64(i64 [[SMIN13]], i64 [[TMP16]])
+; CHECK-NEXT: [[EXIT_MAINLOOP_AT:%.*]] = call i64 @llvm.smax.i64(i64 [[SMIN14]], i64 0)
+; CHECK-NEXT: [[TMP17:%.*]] = icmp slt i64 0, [[EXIT_MAINLOOP_AT]]
+; CHECK-NEXT: br i1 [[TMP17]], label [[LOOP_PREHEADER:%.*]], label [[MAIN_PSEUDO_EXIT:%.*]]
+; CHECK: loop.preheader:
+; CHECK-NEXT: br label [[LOOP:%.*]]
; CHECK: loop:
-; CHECK: %c1 = and i1 true, true
-; CHECK: %c2 = and i1 %c1, true
-; CHECK: %rc = and i1 %c2, true
-; CHECK: br i1 %rc, label %backedge, label %check_failed.loopexit
-; CHECK: backedge
-; CHECK: [[COND:%[^ ]+]] = icmp slt i64
-; CHECK: br i1 [[COND]], label %loop, label %main.exit.selector
-; CHECK: postloop
+; CHECK-NEXT: [[IV:%.*]] = phi i64 [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ], [ 0, [[LOOP_PREHEADER]] ]
+; CHECK-NEXT: [[RC1:%.*]] = icmp slt i64 [[IV]], [[M1]]
+; CHECK-NEXT: [[RC2:%.*]] = icmp slt i64 [[IV]], [[M2]]
+; CHECK-NEXT: [[RC3:%.*]] = icmp slt i64 [[IV]], [[M3]]
+; CHECK-NEXT: [[RC4:%.*]] = icmp slt i64 [[IV]], [[M4]]
+; CHECK-NEXT: [[C1:%.*]] = and i1 true, true
+; CHECK-NEXT: [[C2:%.*]] = and i1 [[C1]], true
+; CHECK-NEXT: [[RC:%.*]] = and i1 [[C2]], true
+; CHECK-NEXT: br i1 [[RC]], label [[BACKEDGE]], label [[CHECK_FAILED_LOOPEXIT17:%.*]]
+; CHECK: backedge:
+; CHECK-NEXT: [[IV_NEXT]] = add i64 [[IV]], 1
+; CHECK-NEXT: [[NARROW_IV:%.*]] = trunc i64 [[IV_NEXT]] to i32
+; CHECK-NEXT: [[LATCH_COND:%.*]] = icmp slt i32 [[NARROW_IV]], [[N]]
+; CHECK-NEXT: [[WIDE_NARROW_IV:%.*]] = sext i32 [[NARROW_IV]] to i64
+; CHECK-NEXT: [[TMP18:%.*]] = icmp slt i64 [[WIDE_NARROW_IV]], [[EXIT_MAINLOOP_AT]]
+; CHECK-NEXT: br i1 [[TMP18]], label [[LOOP]], label [[MAIN_EXIT_SELECTOR:%.*]]
+; CHECK: main.exit.selector:
+; CHECK-NEXT: [[IV_NEXT_LCSSA:%.*]] = phi i64 [ [[IV_NEXT]], [[BACKEDGE]] ]
+; CHECK-NEXT: [[NARROW_IV_LCSSA16:%.*]] = phi i32 [ [[NARROW_IV]], [[BACKEDGE]] ]
+; CHECK-NEXT: [[WIDE_NARROW_IV_LCSSA:%.*]] = phi i64 [ [[WIDE_NARROW_IV]], [[BACKEDGE]] ]
+; CHECK-NEXT: [[WIDE_N:%.*]] = sext i32 [[N]] to i64
+; CHECK-NEXT: [[TMP19:%.*]] = icmp slt i64 [[WIDE_NARROW_IV_LCSSA]], [[WIDE_N]]
+; CHECK-NEXT: br i1 [[TMP19]], label [[MAIN_PSEUDO_EXIT]], label [[EXIT:%.*]]
+; CHECK: main.pseudo.exit:
+; CHECK-NEXT: [[IV_COPY:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT_LCSSA]], [[MAIN_EXIT_SELECTOR]] ]
+; CHECK-NEXT: [[INDVAR_END:%.*]] = phi i64 [ 0, [[ENTRY]] ], [ [[WIDE_NARROW_IV_LCSSA]], [[MAIN_EXIT_SELECTOR]] ]
+; CHECK-NEXT: br label [[POSTLOOP:%.*]]
+; CHECK: exit.loopexit:
+; CHECK-NEXT: [[NARROW_IV_LCSSA_PH:%.*]] = phi i32 [ [[NARROW_IV_POSTLOOP:%.*]], [[BACKEDGE_POSTLOOP:%.*]] ]
+; CHECK-NEXT: br label [[EXIT]]
+; CHECK: exit:
+; CHECK-NEXT: [[NARROW_IV_LCSSA:%.*]] = phi i32 [ [[NARROW_IV_LCSSA16]], [[MAIN_EXIT_SELECTOR]] ], [ [[NARROW_IV_LCSSA_PH]], [[EXIT_LOOPEXIT:%.*]] ]
+; CHECK-NEXT: ret i32 [[NARROW_IV_LCSSA]]
+; CHECK: check_failed.loopexit:
+; CHECK-NEXT: br label [[CHECK_FAILED:%.*]]
+; CHECK: check_failed.loopexit17:
+; CHECK-NEXT: br label [[CHECK_FAILED]]
+; CHECK: check_failed:
+; CHECK-NEXT: ret i32 -1
+; CHECK: postloop:
+; CHECK-NEXT: br label [[LOOP_POSTLOOP:%.*]]
+; CHECK: loop.postloop:
+; CHECK-NEXT: [[IV_POSTLOOP:%.*]] = phi i64 [ [[IV_COPY]], [[POSTLOOP]] ], [ [[IV_NEXT_POSTLOOP:%.*]], [[BACKEDGE_POSTLOOP]] ]
+; CHECK-NEXT: [[RC1_POSTLOOP:%.*]] = icmp slt i64 [[IV_POSTLOOP]], [[M1]]
+; CHECK-NEXT: [[RC2_POSTLOOP:%.*]] = icmp slt i64 [[IV_POSTLOOP]], [[M2]]
+; CHECK-NEXT: [[RC3_POSTLOOP:%.*]] = icmp slt i64 [[IV_POSTLOOP]], [[M3]]
+; CHECK-NEXT: [[RC4_POSTLOOP:%.*]] = icmp slt i64 [[IV_POSTLOOP]], [[M4]]
+; CHECK-NEXT: [[C1_POSTLOOP:%.*]] = and i1 [[RC1_POSTLOOP]], [[RC2_POSTLOOP]]
+; CHECK-NEXT: [[C2_POSTLOOP:%.*]] = and i1 [[C1_POSTLOOP]], [[RC3_POSTLOOP]]
+; CHECK-NEXT: [[RC_POSTLOOP:%.*]] = and i1 [[C2_POSTLOOP]], [[RC4_POSTLOOP]]
+; CHECK-NEXT: br i1 [[RC_POSTLOOP]], label [[BACKEDGE_POSTLOOP]], label [[CHECK_FAILED_LOOPEXIT:%.*]]
+; CHECK: backedge.postloop:
+; CHECK-NEXT: [[IV_NEXT_POSTLOOP]] = add i64 [[IV_POSTLOOP]], 1
+; CHECK-NEXT: [[NARROW_IV_POSTLOOP]] = trunc i64 [[IV_NEXT_POSTLOOP]] to i32
+; CHECK-NEXT: [[LATCH_COND_POSTLOOP:%.*]] = icmp slt i32 [[NARROW_IV_POSTLOOP]], [[N]]
+; CHECK-NEXT: br i1 [[LATCH_COND_POSTLOOP]], label [[LOOP_POSTLOOP]], label [[EXIT_LOOPEXIT]], !llvm.loop [[LOOP12:![0-9]+]], !irce.loop.clone !5
+;
entry:
%N = load i32, ptr %n_ptr, !range !2
; Wide IV against narrow range check. We don't currently support it.
define i32 @test_increasing_slt_slt_wide_simple_negtest_narrow_rc() {
-
-; CHECK-LABEL: @test_increasing_slt_slt_wide_simple_negtest_narrow_rc(
-; CHECK-NOT: i1 true
-; CHECK-NOT: main
+; CHECK-LABEL: define i32 @test_increasing_slt_slt_wide_simple_negtest_narrow_rc() {
+; CHECK-NEXT: entry:
+; CHECK-NEXT: br label [[LOOP:%.*]]
+; CHECK: loop:
+; CHECK-NEXT: [[IV:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ]
+; CHECK-NEXT: [[NARROW_IV:%.*]] = trunc i64 [[IV]] to i32
+; CHECK-NEXT: [[RC:%.*]] = icmp slt i32 [[NARROW_IV]], 101
+; CHECK-NEXT: br i1 [[RC]], label [[BACKEDGE]], label [[CHECK_FAILED:%.*]]
+; CHECK: backedge:
+; CHECK-NEXT: [[IV_NEXT]] = add i64 [[IV]], 1
+; CHECK-NEXT: [[LATCH_COND:%.*]] = icmp slt i64 [[IV]], 100
+; CHECK-NEXT: br i1 [[LATCH_COND]], label [[LOOP]], label [[EXIT:%.*]]
+; CHECK: exit:
+; CHECK-NEXT: [[NARROW_IV_LCSSA1:%.*]] = phi i32 [ [[NARROW_IV]], [[BACKEDGE]] ]
+; CHECK-NEXT: ret i32 [[NARROW_IV_LCSSA1]]
+; CHECK: check_failed:
+; CHECK-NEXT: ret i32 -1
+;
entry:
br label %loop
; Check that we can remove trivially non-failing range check.
define i32 @test_increasing_ult_ult_wide_simple_no_postloop() {
-
-; CHECK-LABEL: @test_increasing_ult_ult_wide_simple_no_postloop(
-; CHECK-NOT: preloop
-; CHECK-NOT: postloop
+; CHECK-LABEL: define i32 @test_increasing_ult_ult_wide_simple_no_postloop() {
+; CHECK-NEXT: entry:
+; CHECK-NEXT: br label [[LOOP:%.*]]
; CHECK: loop:
-; CHECK: br i1 true, label %backedge, label %check_failed
+; CHECK-NEXT: [[IV:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ]
+; CHECK-NEXT: [[RC:%.*]] = icmp ult i64 [[IV]], 100
+; CHECK-NEXT: br i1 true, label [[BACKEDGE]], label [[CHECK_FAILED:%.*]]
+; CHECK: backedge:
+; CHECK-NEXT: [[IV_NEXT]] = add i64 [[IV]], 1
+; CHECK-NEXT: [[NARROW_IV:%.*]] = trunc i64 [[IV_NEXT]] to i32
+; CHECK-NEXT: [[LATCH_COND:%.*]] = icmp ult i32 [[NARROW_IV]], 100
+; CHECK-NEXT: br i1 [[LATCH_COND]], label [[LOOP]], label [[EXIT:%.*]]
+; CHECK: exit:
+; CHECK-NEXT: [[NARROW_IV_LCSSA:%.*]] = phi i32 [ [[NARROW_IV]], [[BACKEDGE]] ]
+; CHECK-NEXT: ret i32 [[NARROW_IV_LCSSA]]
+; CHECK: check_failed:
+; CHECK-NEXT: ret i32 -1
+;
entry:
br label %loop
; This range check fails on the last iteration, so it needs a postloop.
define i32 @test_increasing_ult_ult_wide_simple_postloop() {
-
-; CHECK-LABEL: @test_increasing_ult_ult_wide_simple_postloop(
-; CHECK-NOT: preloop
+; CHECK-LABEL: define i32 @test_increasing_ult_ult_wide_simple_postloop() {
+; CHECK-NEXT: entry:
+; CHECK-NEXT: br i1 true, label [[LOOP_PREHEADER:%.*]], label [[MAIN_PSEUDO_EXIT:%.*]]
+; CHECK: loop.preheader:
+; CHECK-NEXT: br label [[LOOP:%.*]]
; CHECK: loop:
-; CHECK: br i1 true, label %backedge, label %check_failed
-; CHECK: backedge
-; CHECK: [[COND:%[^ ]+]] = icmp ult i64 %wide.narrow.iv, 99
-; CHECK: br i1 [[COND]], label %loop, label %main.exit.selector
-; CHECK: postloop
+; CHECK-NEXT: [[IV:%.*]] = phi i64 [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ], [ 0, [[LOOP_PREHEADER]] ]
+; CHECK-NEXT: [[RC:%.*]] = icmp ult i64 [[IV]], 99
+; CHECK-NEXT: br i1 true, label [[BACKEDGE]], label [[CHECK_FAILED_LOOPEXIT2:%.*]]
+; CHECK: backedge:
+; CHECK-NEXT: [[IV_NEXT]] = add i64 [[IV]], 1
+; CHECK-NEXT: [[NARROW_IV:%.*]] = trunc i64 [[IV_NEXT]] to i32
+; CHECK-NEXT: [[LATCH_COND:%.*]] = icmp ult i32 [[NARROW_IV]], 100
+; CHECK-NEXT: [[WIDE_NARROW_IV:%.*]] = zext i32 [[NARROW_IV]] to i64
+; CHECK-NEXT: [[TMP0:%.*]] = icmp ult i64 [[WIDE_NARROW_IV]], 99
+; CHECK-NEXT: br i1 [[TMP0]], label [[LOOP]], label [[MAIN_EXIT_SELECTOR:%.*]]
+; CHECK: main.exit.selector:
+; CHECK-NEXT: [[IV_NEXT_LCSSA:%.*]] = phi i64 [ [[IV_NEXT]], [[BACKEDGE]] ]
+; CHECK-NEXT: [[NARROW_IV_LCSSA1:%.*]] = phi i32 [ [[NARROW_IV]], [[BACKEDGE]] ]
+; CHECK-NEXT: [[WIDE_NARROW_IV_LCSSA:%.*]] = phi i64 [ [[WIDE_NARROW_IV]], [[BACKEDGE]] ]
+; CHECK-NEXT: [[TMP1:%.*]] = icmp ult i64 [[WIDE_NARROW_IV_LCSSA]], 100
+; CHECK-NEXT: br i1 [[TMP1]], label [[MAIN_PSEUDO_EXIT]], label [[EXIT:%.*]]
+; CHECK: main.pseudo.exit:
+; CHECK-NEXT: [[IV_COPY:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT_LCSSA]], [[MAIN_EXIT_SELECTOR]] ]
+; CHECK-NEXT: [[INDVAR_END:%.*]] = phi i64 [ 0, [[ENTRY]] ], [ [[WIDE_NARROW_IV_LCSSA]], [[MAIN_EXIT_SELECTOR]] ]
+; CHECK-NEXT: br label [[POSTLOOP:%.*]]
+; CHECK: exit.loopexit:
+; CHECK-NEXT: [[NARROW_IV_LCSSA_PH:%.*]] = phi i32 [ [[NARROW_IV_POSTLOOP:%.*]], [[BACKEDGE_POSTLOOP:%.*]] ]
+; CHECK-NEXT: br label [[EXIT]]
+; CHECK: exit:
+; CHECK-NEXT: [[NARROW_IV_LCSSA:%.*]] = phi i32 [ [[NARROW_IV_LCSSA1]], [[MAIN_EXIT_SELECTOR]] ], [ [[NARROW_IV_LCSSA_PH]], [[EXIT_LOOPEXIT:%.*]] ]
+; CHECK-NEXT: ret i32 [[NARROW_IV_LCSSA]]
+; CHECK: check_failed.loopexit:
+; CHECK-NEXT: br label [[CHECK_FAILED:%.*]]
+; CHECK: check_failed.loopexit2:
+; CHECK-NEXT: br label [[CHECK_FAILED]]
+; CHECK: check_failed:
+; CHECK-NEXT: ret i32 -1
+; CHECK: postloop:
+; CHECK-NEXT: br label [[LOOP_POSTLOOP:%.*]]
+; CHECK: loop.postloop:
+; CHECK-NEXT: [[IV_POSTLOOP:%.*]] = phi i64 [ [[IV_COPY]], [[POSTLOOP]] ], [ [[IV_NEXT_POSTLOOP:%.*]], [[BACKEDGE_POSTLOOP]] ]
+; CHECK-NEXT: [[RC_POSTLOOP:%.*]] = icmp ult i64 [[IV_POSTLOOP]], 99
+; CHECK-NEXT: br i1 [[RC_POSTLOOP]], label [[BACKEDGE_POSTLOOP]], label [[CHECK_FAILED_LOOPEXIT:%.*]]
+; CHECK: backedge.postloop:
+; CHECK-NEXT: [[IV_NEXT_POSTLOOP]] = add i64 [[IV_POSTLOOP]], 1
+; CHECK-NEXT: [[NARROW_IV_POSTLOOP]] = trunc i64 [[IV_NEXT_POSTLOOP]] to i32
+; CHECK-NEXT: [[LATCH_COND_POSTLOOP:%.*]] = icmp ult i32 [[NARROW_IV_POSTLOOP]], 100
+; CHECK-NEXT: br i1 [[LATCH_COND_POSTLOOP]], label [[LOOP_POSTLOOP]], label [[EXIT_LOOPEXIT]], !llvm.loop [[LOOP13:![0-9]+]], !irce.loop.clone !5
+;
entry:
br label %loop
; General case. If both %N and %M are non-negative, we do not need a preloop.
define i32 @test_increasing_ult_ult_wide_non-negative(ptr %n_ptr, ptr %m_ptr) {
-
-; CHECK-LABEL: @test_increasing_ult_ult_wide_non-negative(
-; CHECK-NOT: preloop
+; CHECK-LABEL: define i32 @test_increasing_ult_ult_wide_non-negative
+; CHECK-SAME: (ptr [[N_PTR:%.*]], ptr [[M_PTR:%.*]]) {
+; CHECK-NEXT: entry:
+; CHECK-NEXT: [[N:%.*]] = load i32, ptr [[N_PTR]], align 4, !range [[RNG6]]
+; CHECK-NEXT: [[M:%.*]] = load i64, ptr [[M_PTR]], align 4, !range [[RNG7]]
+; CHECK-NEXT: [[TMP0:%.*]] = zext i32 [[N]] to i64
+; CHECK-NEXT: [[EXIT_MAINLOOP_AT:%.*]] = call i64 @llvm.umin.i64(i64 [[M]], i64 [[TMP0]])
+; CHECK-NEXT: [[TMP1:%.*]] = icmp ult i64 0, [[EXIT_MAINLOOP_AT]]
+; CHECK-NEXT: br i1 [[TMP1]], label [[LOOP_PREHEADER:%.*]], label [[MAIN_PSEUDO_EXIT:%.*]]
+; CHECK: loop.preheader:
+; CHECK-NEXT: br label [[LOOP:%.*]]
; CHECK: loop:
-; CHECK: br i1 true, label %backedge, label %check_failed
-; CHECK: backedge
-; CHECK: [[COND:%[^ ]+]] = icmp ult i64 %wide.narrow.iv, %exit.mainloop.at
-; CHECK: br i1 [[COND]], label %loop, label %main.exit.selector
-; CHECK: postloop
+; CHECK-NEXT: [[IV:%.*]] = phi i64 [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ], [ 0, [[LOOP_PREHEADER]] ]
+; CHECK-NEXT: [[RC:%.*]] = icmp ult i64 [[IV]], [[M]]
+; CHECK-NEXT: br i1 true, label [[BACKEDGE]], label [[CHECK_FAILED_LOOPEXIT2:%.*]]
+; CHECK: backedge:
+; CHECK-NEXT: [[IV_NEXT]] = add i64 [[IV]], 1
+; CHECK-NEXT: [[NARROW_IV:%.*]] = trunc i64 [[IV_NEXT]] to i32
+; CHECK-NEXT: [[LATCH_COND:%.*]] = icmp ult i32 [[NARROW_IV]], [[N]]
+; CHECK-NEXT: [[WIDE_NARROW_IV:%.*]] = zext i32 [[NARROW_IV]] to i64
+; CHECK-NEXT: [[TMP2:%.*]] = icmp ult i64 [[WIDE_NARROW_IV]], [[EXIT_MAINLOOP_AT]]
+; CHECK-NEXT: br i1 [[TMP2]], label [[LOOP]], label [[MAIN_EXIT_SELECTOR:%.*]]
+; CHECK: main.exit.selector:
+; CHECK-NEXT: [[IV_NEXT_LCSSA:%.*]] = phi i64 [ [[IV_NEXT]], [[BACKEDGE]] ]
+; CHECK-NEXT: [[NARROW_IV_LCSSA1:%.*]] = phi i32 [ [[NARROW_IV]], [[BACKEDGE]] ]
+; CHECK-NEXT: [[WIDE_NARROW_IV_LCSSA:%.*]] = phi i64 [ [[WIDE_NARROW_IV]], [[BACKEDGE]] ]
+; CHECK-NEXT: [[WIDE_N:%.*]] = zext i32 [[N]] to i64
+; CHECK-NEXT: [[TMP3:%.*]] = icmp ult i64 [[WIDE_NARROW_IV_LCSSA]], [[WIDE_N]]
+; CHECK-NEXT: br i1 [[TMP3]], label [[MAIN_PSEUDO_EXIT]], label [[EXIT:%.*]]
+; CHECK: main.pseudo.exit:
+; CHECK-NEXT: [[IV_COPY:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT_LCSSA]], [[MAIN_EXIT_SELECTOR]] ]
+; CHECK-NEXT: [[INDVAR_END:%.*]] = phi i64 [ 0, [[ENTRY]] ], [ [[WIDE_NARROW_IV_LCSSA]], [[MAIN_EXIT_SELECTOR]] ]
+; CHECK-NEXT: br label [[POSTLOOP:%.*]]
+; CHECK: exit.loopexit:
+; CHECK-NEXT: [[NARROW_IV_LCSSA_PH:%.*]] = phi i32 [ [[NARROW_IV_POSTLOOP:%.*]], [[BACKEDGE_POSTLOOP:%.*]] ]
+; CHECK-NEXT: br label [[EXIT]]
+; CHECK: exit:
+; CHECK-NEXT: [[NARROW_IV_LCSSA:%.*]] = phi i32 [ [[NARROW_IV_LCSSA1]], [[MAIN_EXIT_SELECTOR]] ], [ [[NARROW_IV_LCSSA_PH]], [[EXIT_LOOPEXIT:%.*]] ]
+; CHECK-NEXT: ret i32 [[NARROW_IV_LCSSA]]
+; CHECK: check_failed.loopexit:
+; CHECK-NEXT: br label [[CHECK_FAILED:%.*]]
+; CHECK: check_failed.loopexit2:
+; CHECK-NEXT: br label [[CHECK_FAILED]]
+; CHECK: check_failed:
+; CHECK-NEXT: ret i32 -1
+; CHECK: postloop:
+; CHECK-NEXT: br label [[LOOP_POSTLOOP:%.*]]
+; CHECK: loop.postloop:
+; CHECK-NEXT: [[IV_POSTLOOP:%.*]] = phi i64 [ [[IV_COPY]], [[POSTLOOP]] ], [ [[IV_NEXT_POSTLOOP:%.*]], [[BACKEDGE_POSTLOOP]] ]
+; CHECK-NEXT: [[RC_POSTLOOP:%.*]] = icmp ult i64 [[IV_POSTLOOP]], [[M]]
+; CHECK-NEXT: br i1 [[RC_POSTLOOP]], label [[BACKEDGE_POSTLOOP]], label [[CHECK_FAILED_LOOPEXIT:%.*]]
+; CHECK: backedge.postloop:
+; CHECK-NEXT: [[IV_NEXT_POSTLOOP]] = add i64 [[IV_POSTLOOP]], 1
+; CHECK-NEXT: [[NARROW_IV_POSTLOOP]] = trunc i64 [[IV_NEXT_POSTLOOP]] to i32
+; CHECK-NEXT: [[LATCH_COND_POSTLOOP:%.*]] = icmp ult i32 [[NARROW_IV_POSTLOOP]], [[N]]
+; CHECK-NEXT: br i1 [[LATCH_COND_POSTLOOP]], label [[LOOP_POSTLOOP]], label [[EXIT_LOOPEXIT]], !llvm.loop [[LOOP14:![0-9]+]], !irce.loop.clone !5
+;
entry:
%N = load i32, ptr %n_ptr, !range !2
; we make a non-negativity runtime check against M and do not go to main loop if
; M was negative.
define i32 @test_increasing_ult_ult_wide_general(ptr %n_ptr, ptr %m_ptr) {
-
-; CHECK-LABEL: @test_increasing_ult_ult_wide_general(
-; CHECK-NOT: preloop
+; CHECK-LABEL: define i32 @test_increasing_ult_ult_wide_general
+; CHECK-SAME: (ptr [[N_PTR:%.*]], ptr [[M_PTR:%.*]]) {
+; CHECK-NEXT: entry:
+; CHECK-NEXT: [[N:%.*]] = load i32, ptr [[N_PTR]], align 4, !range [[RNG6]]
+; CHECK-NEXT: [[M:%.*]] = load i64, ptr [[M_PTR]], align 4
+; CHECK-NEXT: [[SMIN:%.*]] = call i64 @llvm.smin.i64(i64 [[M]], i64 0)
+; CHECK-NEXT: [[TMP0:%.*]] = sub i64 [[M]], [[SMIN]]
+; CHECK-NEXT: [[SMAX:%.*]] = call i64 @llvm.smax.i64(i64 [[SMIN]], i64 -1)
+; CHECK-NEXT: [[TMP1:%.*]] = add nsw i64 [[SMAX]], 1
+; CHECK-NEXT: [[TMP2:%.*]] = mul i64 [[TMP0]], [[TMP1]]
+; CHECK-NEXT: [[TMP3:%.*]] = zext i32 [[N]] to i64
+; CHECK-NEXT: [[EXIT_MAINLOOP_AT:%.*]] = call i64 @llvm.umin.i64(i64 [[TMP2]], i64 [[TMP3]])
+; CHECK-NEXT: [[TMP4:%.*]] = icmp ult i64 0, [[EXIT_MAINLOOP_AT]]
+; CHECK-NEXT: br i1 [[TMP4]], label [[LOOP_PREHEADER:%.*]], label [[MAIN_PSEUDO_EXIT:%.*]]
+; CHECK: loop.preheader:
+; CHECK-NEXT: br label [[LOOP:%.*]]
; CHECK: loop:
-; CHECK: br i1 true, label %backedge, label %check_failed
-; CHECK: backedge
-; CHECK: [[COND:%[^ ]+]] = icmp ult i64
-; CHECK: br i1 [[COND]], label %loop, label %main.exit.selector
-; CHECK: postloop
+; CHECK-NEXT: [[IV:%.*]] = phi i64 [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ], [ 0, [[LOOP_PREHEADER]] ]
+; CHECK-NEXT: [[RC:%.*]] = icmp ult i64 [[IV]], [[M]]
+; CHECK-NEXT: br i1 true, label [[BACKEDGE]], label [[CHECK_FAILED_LOOPEXIT2:%.*]]
+; CHECK: backedge:
+; CHECK-NEXT: [[IV_NEXT]] = add i64 [[IV]], 1
+; CHECK-NEXT: [[NARROW_IV:%.*]] = trunc i64 [[IV_NEXT]] to i32
+; CHECK-NEXT: [[LATCH_COND:%.*]] = icmp ult i32 [[NARROW_IV]], [[N]]
+; CHECK-NEXT: [[WIDE_NARROW_IV:%.*]] = zext i32 [[NARROW_IV]] to i64
+; CHECK-NEXT: [[TMP5:%.*]] = icmp ult i64 [[WIDE_NARROW_IV]], [[EXIT_MAINLOOP_AT]]
+; CHECK-NEXT: br i1 [[TMP5]], label [[LOOP]], label [[MAIN_EXIT_SELECTOR:%.*]]
+; CHECK: main.exit.selector:
+; CHECK-NEXT: [[IV_NEXT_LCSSA:%.*]] = phi i64 [ [[IV_NEXT]], [[BACKEDGE]] ]
+; CHECK-NEXT: [[NARROW_IV_LCSSA1:%.*]] = phi i32 [ [[NARROW_IV]], [[BACKEDGE]] ]
+; CHECK-NEXT: [[WIDE_NARROW_IV_LCSSA:%.*]] = phi i64 [ [[WIDE_NARROW_IV]], [[BACKEDGE]] ]
+; CHECK-NEXT: [[WIDE_N:%.*]] = zext i32 [[N]] to i64
+; CHECK-NEXT: [[TMP6:%.*]] = icmp ult i64 [[WIDE_NARROW_IV_LCSSA]], [[WIDE_N]]
+; CHECK-NEXT: br i1 [[TMP6]], label [[MAIN_PSEUDO_EXIT]], label [[EXIT:%.*]]
+; CHECK: main.pseudo.exit:
+; CHECK-NEXT: [[IV_COPY:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT_LCSSA]], [[MAIN_EXIT_SELECTOR]] ]
+; CHECK-NEXT: [[INDVAR_END:%.*]] = phi i64 [ 0, [[ENTRY]] ], [ [[WIDE_NARROW_IV_LCSSA]], [[MAIN_EXIT_SELECTOR]] ]
+; CHECK-NEXT: br label [[POSTLOOP:%.*]]
+; CHECK: exit.loopexit:
+; CHECK-NEXT: [[NARROW_IV_LCSSA_PH:%.*]] = phi i32 [ [[NARROW_IV_POSTLOOP:%.*]], [[BACKEDGE_POSTLOOP:%.*]] ]
+; CHECK-NEXT: br label [[EXIT]]
+; CHECK: exit:
+; CHECK-NEXT: [[NARROW_IV_LCSSA:%.*]] = phi i32 [ [[NARROW_IV_LCSSA1]], [[MAIN_EXIT_SELECTOR]] ], [ [[NARROW_IV_LCSSA_PH]], [[EXIT_LOOPEXIT:%.*]] ]
+; CHECK-NEXT: ret i32 [[NARROW_IV_LCSSA]]
+; CHECK: check_failed.loopexit:
+; CHECK-NEXT: br label [[CHECK_FAILED:%.*]]
+; CHECK: check_failed.loopexit2:
+; CHECK-NEXT: br label [[CHECK_FAILED]]
+; CHECK: check_failed:
+; CHECK-NEXT: ret i32 -1
+; CHECK: postloop:
+; CHECK-NEXT: br label [[LOOP_POSTLOOP:%.*]]
+; CHECK: loop.postloop:
+; CHECK-NEXT: [[IV_POSTLOOP:%.*]] = phi i64 [ [[IV_COPY]], [[POSTLOOP]] ], [ [[IV_NEXT_POSTLOOP:%.*]], [[BACKEDGE_POSTLOOP]] ]
+; CHECK-NEXT: [[RC_POSTLOOP:%.*]] = icmp ult i64 [[IV_POSTLOOP]], [[M]]
+; CHECK-NEXT: br i1 [[RC_POSTLOOP]], label [[BACKEDGE_POSTLOOP]], label [[CHECK_FAILED_LOOPEXIT:%.*]]
+; CHECK: backedge.postloop:
+; CHECK-NEXT: [[IV_NEXT_POSTLOOP]] = add i64 [[IV_POSTLOOP]], 1
+; CHECK-NEXT: [[NARROW_IV_POSTLOOP]] = trunc i64 [[IV_NEXT_POSTLOOP]] to i32
+; CHECK-NEXT: [[LATCH_COND_POSTLOOP:%.*]] = icmp ult i32 [[NARROW_IV_POSTLOOP]], [[N]]
+; CHECK-NEXT: br i1 [[LATCH_COND_POSTLOOP]], label [[LOOP_POSTLOOP]], label [[EXIT_LOOPEXIT]], !llvm.loop [[LOOP15:![0-9]+]], !irce.loop.clone !5
+;
entry:
%N = load i32, ptr %n_ptr, !range !2
; Same as above, multiple checks.
define i32 @test_increasing_ult_ult_wide_multiple_checks(ptr %n_ptr, ptr %m1_ptr, ptr %m2_ptr, ptr %m3_ptr, ptr %m4_ptr) {
-; CHECK-LABEL: @test_increasing_ult_ult_wide_multiple_checks(
-; CHECK-NOT: preloop
+; CHECK-LABEL: define i32 @test_increasing_ult_ult_wide_multiple_checks
+; CHECK-SAME: (ptr [[N_PTR:%.*]], ptr [[M1_PTR:%.*]], ptr [[M2_PTR:%.*]], ptr [[M3_PTR:%.*]], ptr [[M4_PTR:%.*]]) {
+; CHECK-NEXT: entry:
+; CHECK-NEXT: [[N:%.*]] = load i32, ptr [[N_PTR]], align 4, !range [[RNG6]]
+; CHECK-NEXT: [[M1:%.*]] = load i64, ptr [[M1_PTR]], align 4
+; CHECK-NEXT: [[M2:%.*]] = load i64, ptr [[M2_PTR]], align 4
+; CHECK-NEXT: [[M3:%.*]] = load i64, ptr [[M3_PTR]], align 4
+; CHECK-NEXT: [[M4:%.*]] = load i64, ptr [[M4_PTR]], align 4
+; CHECK-NEXT: [[SMIN:%.*]] = call i64 @llvm.smin.i64(i64 [[M2]], i64 0)
+; CHECK-NEXT: [[TMP0:%.*]] = sub i64 [[M2]], [[SMIN]]
+; CHECK-NEXT: [[SMAX:%.*]] = call i64 @llvm.smax.i64(i64 [[SMIN]], i64 -1)
+; CHECK-NEXT: [[TMP1:%.*]] = add nsw i64 [[SMAX]], 1
+; CHECK-NEXT: [[TMP2:%.*]] = mul i64 [[TMP0]], [[TMP1]]
+; CHECK-NEXT: [[SMIN1:%.*]] = call i64 @llvm.smin.i64(i64 [[M1]], i64 0)
+; CHECK-NEXT: [[TMP3:%.*]] = sub i64 [[M1]], [[SMIN1]]
+; CHECK-NEXT: [[SMAX2:%.*]] = call i64 @llvm.smax.i64(i64 [[SMIN1]], i64 -1)
+; CHECK-NEXT: [[TMP4:%.*]] = add nsw i64 [[SMAX2]], 1
+; CHECK-NEXT: [[TMP5:%.*]] = mul i64 [[TMP3]], [[TMP4]]
+; CHECK-NEXT: [[UMIN:%.*]] = call i64 @llvm.umin.i64(i64 [[TMP2]], i64 [[TMP5]])
+; CHECK-NEXT: [[SMIN3:%.*]] = call i64 @llvm.smin.i64(i64 [[M3]], i64 0)
+; CHECK-NEXT: [[TMP6:%.*]] = sub i64 [[M3]], [[SMIN3]]
+; CHECK-NEXT: [[SMAX4:%.*]] = call i64 @llvm.smax.i64(i64 [[SMIN3]], i64 -1)
+; CHECK-NEXT: [[TMP7:%.*]] = add nsw i64 [[SMAX4]], 1
+; CHECK-NEXT: [[TMP8:%.*]] = mul i64 [[TMP6]], [[TMP7]]
+; CHECK-NEXT: [[UMIN5:%.*]] = call i64 @llvm.umin.i64(i64 [[UMIN]], i64 [[TMP8]])
+; CHECK-NEXT: [[SMIN6:%.*]] = call i64 @llvm.smin.i64(i64 [[M4]], i64 0)
+; CHECK-NEXT: [[TMP9:%.*]] = sub i64 [[M4]], [[SMIN6]]
+; CHECK-NEXT: [[SMAX7:%.*]] = call i64 @llvm.smax.i64(i64 [[SMIN6]], i64 -1)
+; CHECK-NEXT: [[TMP10:%.*]] = add nsw i64 [[SMAX7]], 1
+; CHECK-NEXT: [[TMP11:%.*]] = mul i64 [[TMP9]], [[TMP10]]
+; CHECK-NEXT: [[UMIN8:%.*]] = call i64 @llvm.umin.i64(i64 [[UMIN5]], i64 [[TMP11]])
+; CHECK-NEXT: [[TMP12:%.*]] = zext i32 [[N]] to i64
+; CHECK-NEXT: [[EXIT_MAINLOOP_AT:%.*]] = call i64 @llvm.umin.i64(i64 [[UMIN8]], i64 [[TMP12]])
+; CHECK-NEXT: [[TMP13:%.*]] = icmp ult i64 0, [[EXIT_MAINLOOP_AT]]
+; CHECK-NEXT: br i1 [[TMP13]], label [[LOOP_PREHEADER:%.*]], label [[MAIN_PSEUDO_EXIT:%.*]]
+; CHECK: loop.preheader:
+; CHECK-NEXT: br label [[LOOP:%.*]]
; CHECK: loop:
-; CHECK: %c1 = and i1 true, true
-; CHECK: %c2 = and i1 %c1, true
-; CHECK: %rc = and i1 %c2, true
-; CHECK: br i1 %rc, label %backedge, label %check_failed.loopexit
-; CHECK: backedge
-; CHECK: [[COND:%[^ ]+]] = icmp ult i64
-; CHECK: br i1 [[COND]], label %loop, label %main.exit.selector
-; CHECK: postloop
+; CHECK-NEXT: [[IV:%.*]] = phi i64 [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ], [ 0, [[LOOP_PREHEADER]] ]
+; CHECK-NEXT: [[RC1:%.*]] = icmp ult i64 [[IV]], [[M1]]
+; CHECK-NEXT: [[RC2:%.*]] = icmp ult i64 [[IV]], [[M2]]
+; CHECK-NEXT: [[RC3:%.*]] = icmp ult i64 [[IV]], [[M3]]
+; CHECK-NEXT: [[RC4:%.*]] = icmp ult i64 [[IV]], [[M4]]
+; CHECK-NEXT: [[C1:%.*]] = and i1 true, true
+; CHECK-NEXT: [[C2:%.*]] = and i1 [[C1]], true
+; CHECK-NEXT: [[RC:%.*]] = and i1 [[C2]], true
+; CHECK-NEXT: br i1 [[RC]], label [[BACKEDGE]], label [[CHECK_FAILED_LOOPEXIT11:%.*]]
+; CHECK: backedge:
+; CHECK-NEXT: [[IV_NEXT]] = add i64 [[IV]], 1
+; CHECK-NEXT: [[NARROW_IV:%.*]] = trunc i64 [[IV_NEXT]] to i32
+; CHECK-NEXT: [[LATCH_COND:%.*]] = icmp ult i32 [[NARROW_IV]], [[N]]
+; CHECK-NEXT: [[WIDE_NARROW_IV:%.*]] = zext i32 [[NARROW_IV]] to i64
+; CHECK-NEXT: [[TMP14:%.*]] = icmp ult i64 [[WIDE_NARROW_IV]], [[EXIT_MAINLOOP_AT]]
+; CHECK-NEXT: br i1 [[TMP14]], label [[LOOP]], label [[MAIN_EXIT_SELECTOR:%.*]]
+; CHECK: main.exit.selector:
+; CHECK-NEXT: [[IV_NEXT_LCSSA:%.*]] = phi i64 [ [[IV_NEXT]], [[BACKEDGE]] ]
+; CHECK-NEXT: [[NARROW_IV_LCSSA10:%.*]] = phi i32 [ [[NARROW_IV]], [[BACKEDGE]] ]
+; CHECK-NEXT: [[WIDE_NARROW_IV_LCSSA:%.*]] = phi i64 [ [[WIDE_NARROW_IV]], [[BACKEDGE]] ]
+; CHECK-NEXT: [[WIDE_N:%.*]] = zext i32 [[N]] to i64
+; CHECK-NEXT: [[TMP15:%.*]] = icmp ult i64 [[WIDE_NARROW_IV_LCSSA]], [[WIDE_N]]
+; CHECK-NEXT: br i1 [[TMP15]], label [[MAIN_PSEUDO_EXIT]], label [[EXIT:%.*]]
+; CHECK: main.pseudo.exit:
+; CHECK-NEXT: [[IV_COPY:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT_LCSSA]], [[MAIN_EXIT_SELECTOR]] ]
+; CHECK-NEXT: [[INDVAR_END:%.*]] = phi i64 [ 0, [[ENTRY]] ], [ [[WIDE_NARROW_IV_LCSSA]], [[MAIN_EXIT_SELECTOR]] ]
+; CHECK-NEXT: br label [[POSTLOOP:%.*]]
+; CHECK: exit.loopexit:
+; CHECK-NEXT: [[NARROW_IV_LCSSA_PH:%.*]] = phi i32 [ [[NARROW_IV_POSTLOOP:%.*]], [[BACKEDGE_POSTLOOP:%.*]] ]
+; CHECK-NEXT: br label [[EXIT]]
+; CHECK: exit:
+; CHECK-NEXT: [[NARROW_IV_LCSSA:%.*]] = phi i32 [ [[NARROW_IV_LCSSA10]], [[MAIN_EXIT_SELECTOR]] ], [ [[NARROW_IV_LCSSA_PH]], [[EXIT_LOOPEXIT:%.*]] ]
+; CHECK-NEXT: ret i32 [[NARROW_IV_LCSSA]]
+; CHECK: check_failed.loopexit:
+; CHECK-NEXT: br label [[CHECK_FAILED:%.*]]
+; CHECK: check_failed.loopexit11:
+; CHECK-NEXT: br label [[CHECK_FAILED]]
+; CHECK: check_failed:
+; CHECK-NEXT: ret i32 -1
+; CHECK: postloop:
+; CHECK-NEXT: br label [[LOOP_POSTLOOP:%.*]]
+; CHECK: loop.postloop:
+; CHECK-NEXT: [[IV_POSTLOOP:%.*]] = phi i64 [ [[IV_COPY]], [[POSTLOOP]] ], [ [[IV_NEXT_POSTLOOP:%.*]], [[BACKEDGE_POSTLOOP]] ]
+; CHECK-NEXT: [[RC1_POSTLOOP:%.*]] = icmp ult i64 [[IV_POSTLOOP]], [[M1]]
+; CHECK-NEXT: [[RC2_POSTLOOP:%.*]] = icmp ult i64 [[IV_POSTLOOP]], [[M2]]
+; CHECK-NEXT: [[RC3_POSTLOOP:%.*]] = icmp ult i64 [[IV_POSTLOOP]], [[M3]]
+; CHECK-NEXT: [[RC4_POSTLOOP:%.*]] = icmp ult i64 [[IV_POSTLOOP]], [[M4]]
+; CHECK-NEXT: [[C1_POSTLOOP:%.*]] = and i1 [[RC1_POSTLOOP]], [[RC2_POSTLOOP]]
+; CHECK-NEXT: [[C2_POSTLOOP:%.*]] = and i1 [[C1_POSTLOOP]], [[RC3_POSTLOOP]]
+; CHECK-NEXT: [[RC_POSTLOOP:%.*]] = and i1 [[C2_POSTLOOP]], [[RC4_POSTLOOP]]
+; CHECK-NEXT: br i1 [[RC_POSTLOOP]], label [[BACKEDGE_POSTLOOP]], label [[CHECK_FAILED_LOOPEXIT:%.*]]
+; CHECK: backedge.postloop:
+; CHECK-NEXT: [[IV_NEXT_POSTLOOP]] = add i64 [[IV_POSTLOOP]], 1
+; CHECK-NEXT: [[NARROW_IV_POSTLOOP]] = trunc i64 [[IV_NEXT_POSTLOOP]] to i32
+; CHECK-NEXT: [[LATCH_COND_POSTLOOP:%.*]] = icmp ult i32 [[NARROW_IV_POSTLOOP]], [[N]]
+; CHECK-NEXT: br i1 [[LATCH_COND_POSTLOOP]], label [[LOOP_POSTLOOP]], label [[EXIT_LOOPEXIT]], !llvm.loop [[LOOP16:![0-9]+]], !irce.loop.clone !5
+;
entry:
%N = load i32, ptr %n_ptr, !range !2
; Wide IV against narrow range check. We don't currently support it.
define i32 @test_increasing_ult_ult_wide_simple_negtest_narrow_rc() {
-
-; CHECK-LABEL: @test_increasing_ult_ult_wide_simple_negtest_narrow_rc(
-; CHECK-NOT: i1 true
-; CHECK-NOT: main
+; CHECK-LABEL: define i32 @test_increasing_ult_ult_wide_simple_negtest_narrow_rc() {
+; CHECK-NEXT: entry:
+; CHECK-NEXT: br label [[LOOP:%.*]]
+; CHECK: loop:
+; CHECK-NEXT: [[IV:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ]
+; CHECK-NEXT: [[NARROW_IV:%.*]] = trunc i64 [[IV]] to i32
+; CHECK-NEXT: [[RC:%.*]] = icmp ult i32 [[NARROW_IV]], 101
+; CHECK-NEXT: br i1 [[RC]], label [[BACKEDGE]], label [[CHECK_FAILED:%.*]]
+; CHECK: backedge:
+; CHECK-NEXT: [[IV_NEXT]] = add i64 [[IV]], 1
+; CHECK-NEXT: [[LATCH_COND:%.*]] = icmp ult i64 [[IV]], 100
+; CHECK-NEXT: br i1 [[LATCH_COND]], label [[LOOP]], label [[EXIT:%.*]]
+; CHECK: exit:
+; CHECK-NEXT: [[NARROW_IV_LCSSA1:%.*]] = phi i32 [ [[NARROW_IV]], [[BACKEDGE]] ]
+; CHECK-NEXT: ret i32 [[NARROW_IV_LCSSA1]]
+; CHECK: check_failed:
+; CHECK-NEXT: ret i32 -1
+;
entry:
br label %loop