| ; 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: define i32 @test_increasing_slt_slt_wide_simple_no_postloop() { |
| ; CHECK-NEXT: entry: |
| ; CHECK-NEXT: br label [[LOOP:%.*]] |
| ; CHECK: loop: |
| ; 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 |
| |
| loop: |
| %iv = phi i64 [ 0, %entry ], [ %iv.next, %backedge ] |
| %rc = icmp slt i64 %iv, 100 |
| br i1 %rc, label %backedge, label %check_failed |
| |
| backedge: |
| %iv.next = add i64 %iv, 1 |
| %narrow.iv = trunc i64 %iv.next to i32 |
| %latch.cond = icmp slt i32 %narrow.iv, 100 |
| br i1 %latch.cond, label %loop, label %exit |
| |
| exit: |
| ret i32 %narrow.iv |
| |
| check_failed: |
| ret i32 -1 |
| } |
| |
| ; This range check fails on the last iteration, so it needs a postloop. |
| define i32 @test_increasing_slt_slt_wide_simple_postloop() { |
| ; 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-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 |
| |
| loop: |
| %iv = phi i64 [ 0, %entry ], [ %iv.next, %backedge ] |
| %rc = icmp slt i64 %iv, 99 |
| br i1 %rc, label %backedge, label %check_failed |
| |
| backedge: |
| %iv.next = add i64 %iv, 1 |
| %narrow.iv = trunc i64 %iv.next to i32 |
| %latch.cond = icmp slt i32 %narrow.iv, 100 |
| br i1 %latch.cond, label %loop, label %exit |
| |
| exit: |
| ret i32 %narrow.iv |
| |
| check_failed: |
| ret i32 -1 |
| } |
| |
| ; 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: 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-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 |
| %M = load i64, ptr %m_ptr, !range !1 |
| br label %loop |
| |
| loop: |
| %iv = phi i64 [ 0, %entry ], [ %iv.next, %backedge ] |
| %rc = icmp slt i64 %iv, %M |
| br i1 %rc, label %backedge, label %check_failed |
| |
| backedge: |
| %iv.next = add i64 %iv, 1 |
| %narrow.iv = trunc i64 %iv.next to i32 |
| %latch.cond = icmp slt i32 %narrow.iv, %N |
| br i1 %latch.cond, label %loop, label %exit |
| |
| exit: |
| ret i32 %narrow.iv |
| |
| check_failed: |
| ret i32 -1 |
| } |
| |
| ; General case. Even though %M may be negative, we do not need a preloop because |
| ; 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: 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-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 |
| %M = load i64, ptr %m_ptr |
| br label %loop |
| |
| loop: |
| %iv = phi i64 [ 0, %entry ], [ %iv.next, %backedge ] |
| %rc = icmp slt i64 %iv, %M |
| br i1 %rc, label %backedge, label %check_failed |
| |
| backedge: |
| %iv.next = add i64 %iv, 1 |
| %narrow.iv = trunc i64 %iv.next to i32 |
| %latch.cond = icmp slt i32 %narrow.iv, %N |
| br i1 %latch.cond, label %loop, label %exit |
| |
| exit: |
| ret i32 %narrow.iv |
| |
| check_failed: |
| ret i32 -1 |
| } |
| |
| ; General case with preloop. |
| define i32 @test_increasing_slt_slt_wide_general_preloop(ptr %n_ptr, ptr %m_ptr) { |
| ; 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-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 |
| %M = load i64, ptr %m_ptr |
| br label %loop |
| |
| loop: |
| %iv = phi i64 [ 0, %entry ], [ %iv.next, %backedge ] |
| %rc = icmp slt i64 %iv, %M |
| br i1 %rc, label %backedge, label %check_failed |
| |
| backedge: |
| %iv.next = add i64 %iv, 1 |
| %narrow.iv = trunc i64 %iv to i32 |
| %latch.cond = icmp slt i32 %narrow.iv, %N |
| br i1 %latch.cond, label %loop, label %exit |
| |
| exit: |
| ret i32 %narrow.iv |
| |
| check_failed: |
| ret i32 -1 |
| } |
| |
| ; 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: 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-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 |
| %M1 = load i64, ptr %m1_ptr |
| %M2 = load i64, ptr %m2_ptr |
| %M3 = load i64, ptr %m3_ptr |
| %M4 = load i64, ptr %m4_ptr |
| br label %loop |
| |
| loop: |
| %iv = phi i64 [ 0, %entry ], [ %iv.next, %backedge ] |
| %rc1 = icmp slt i64 %iv, %M1 |
| %rc2 = icmp slt i64 %iv, %M2 |
| %rc3 = icmp slt i64 %iv, %M3 |
| %rc4 = icmp slt i64 %iv, %M4 |
| %c1 = and i1 %rc1, %rc2 |
| %c2 = and i1 %c1, %rc3 |
| %rc = and i1 %c2, %rc4 |
| br i1 %rc, label %backedge, label %check_failed |
| |
| backedge: |
| %iv.next = add i64 %iv, 1 |
| %narrow.iv = trunc i64 %iv.next to i32 |
| %latch.cond = icmp slt i32 %narrow.iv, %N |
| br i1 %latch.cond, label %loop, label %exit |
| |
| exit: |
| ret i32 %narrow.iv |
| |
| check_failed: |
| ret i32 -1 |
| } |
| |
| ; 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: 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 |
| |
| loop: |
| %iv = phi i64 [ 0, %entry ], [ %iv.next, %backedge ] |
| %narrow.iv = trunc i64 %iv to i32 |
| %rc = icmp slt i32 %narrow.iv, 101 |
| br i1 %rc, label %backedge, label %check_failed |
| |
| backedge: |
| %iv.next = add i64 %iv, 1 |
| %latch.cond = icmp slt i64 %iv, 100 |
| br i1 %latch.cond, label %loop, label %exit |
| |
| exit: |
| ret i32 %narrow.iv |
| |
| check_failed: |
| ret i32 -1 |
| } |
| |
| ; Check that we can remove trivially non-failing range check. |
| define i32 @test_increasing_ult_ult_wide_simple_no_postloop() { |
| ; CHECK-LABEL: define i32 @test_increasing_ult_ult_wide_simple_no_postloop() { |
| ; CHECK-NEXT: entry: |
| ; CHECK-NEXT: br label [[LOOP:%.*]] |
| ; CHECK: loop: |
| ; 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 |
| |
| loop: |
| %iv = phi i64 [ 0, %entry ], [ %iv.next, %backedge ] |
| %rc = icmp ult i64 %iv, 100 |
| br i1 %rc, label %backedge, label %check_failed |
| |
| backedge: |
| %iv.next = add i64 %iv, 1 |
| %narrow.iv = trunc i64 %iv.next to i32 |
| %latch.cond = icmp ult i32 %narrow.iv, 100 |
| br i1 %latch.cond, label %loop, label %exit |
| |
| exit: |
| ret i32 %narrow.iv |
| |
| check_failed: |
| ret i32 -1 |
| } |
| |
| ; This range check fails on the last iteration, so it needs a postloop. |
| define i32 @test_increasing_ult_ult_wide_simple_postloop() { |
| ; 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-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 |
| |
| loop: |
| %iv = phi i64 [ 0, %entry ], [ %iv.next, %backedge ] |
| %rc = icmp ult i64 %iv, 99 |
| br i1 %rc, label %backedge, label %check_failed |
| |
| backedge: |
| %iv.next = add i64 %iv, 1 |
| %narrow.iv = trunc i64 %iv.next to i32 |
| %latch.cond = icmp ult i32 %narrow.iv, 100 |
| br i1 %latch.cond, label %loop, label %exit |
| |
| exit: |
| ret i32 %narrow.iv |
| |
| check_failed: |
| ret i32 -1 |
| } |
| |
| ; 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: 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-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 |
| %M = load i64, ptr %m_ptr, !range !1 |
| br label %loop |
| |
| loop: |
| %iv = phi i64 [ 0, %entry ], [ %iv.next, %backedge ] |
| %rc = icmp ult i64 %iv, %M |
| br i1 %rc, label %backedge, label %check_failed |
| |
| backedge: |
| %iv.next = add i64 %iv, 1 |
| %narrow.iv = trunc i64 %iv.next to i32 |
| %latch.cond = icmp ult i32 %narrow.iv, %N |
| br i1 %latch.cond, label %loop, label %exit |
| |
| exit: |
| ret i32 %narrow.iv |
| |
| check_failed: |
| ret i32 -1 |
| } |
| |
| ; General case. Even though %M may be negative, we do not need a preloop because |
| ; 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: 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-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 |
| %M = load i64, ptr %m_ptr |
| br label %loop |
| |
| loop: |
| %iv = phi i64 [ 0, %entry ], [ %iv.next, %backedge ] |
| %rc = icmp ult i64 %iv, %M |
| br i1 %rc, label %backedge, label %check_failed |
| |
| backedge: |
| %iv.next = add i64 %iv, 1 |
| %narrow.iv = trunc i64 %iv.next to i32 |
| %latch.cond = icmp ult i32 %narrow.iv, %N |
| br i1 %latch.cond, label %loop, label %exit |
| |
| exit: |
| ret i32 %narrow.iv |
| |
| check_failed: |
| ret i32 -1 |
| } |
| |
| ; 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: 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-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 |
| %M1 = load i64, ptr %m1_ptr |
| %M2 = load i64, ptr %m2_ptr |
| %M3 = load i64, ptr %m3_ptr |
| %M4 = load i64, ptr %m4_ptr |
| br label %loop |
| |
| loop: |
| %iv = phi i64 [ 0, %entry ], [ %iv.next, %backedge ] |
| %rc1 = icmp ult i64 %iv, %M1 |
| %rc2 = icmp ult i64 %iv, %M2 |
| %rc3 = icmp ult i64 %iv, %M3 |
| %rc4 = icmp ult i64 %iv, %M4 |
| %c1 = and i1 %rc1, %rc2 |
| %c2 = and i1 %c1, %rc3 |
| %rc = and i1 %c2, %rc4 |
| br i1 %rc, label %backedge, label %check_failed |
| |
| backedge: |
| %iv.next = add i64 %iv, 1 |
| %narrow.iv = trunc i64 %iv.next to i32 |
| %latch.cond = icmp ult i32 %narrow.iv, %N |
| br i1 %latch.cond, label %loop, label %exit |
| |
| exit: |
| ret i32 %narrow.iv |
| |
| check_failed: |
| ret i32 -1 |
| } |
| |
| ; 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: 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 |
| |
| loop: |
| %iv = phi i64 [ 0, %entry ], [ %iv.next, %backedge ] |
| %narrow.iv = trunc i64 %iv to i32 |
| %rc = icmp ult i32 %narrow.iv, 101 |
| br i1 %rc, label %backedge, label %check_failed |
| |
| backedge: |
| %iv.next = add i64 %iv, 1 |
| %latch.cond = icmp ult i64 %iv, 100 |
| br i1 %latch.cond, label %loop, label %exit |
| |
| exit: |
| ret i32 %narrow.iv |
| |
| check_failed: |
| ret i32 -1 |
| } |
| |
| ; Check that fake wide exit doesn't inhibit the transform. |
| define i16 @test_fake_wide_exit(i64 %x) { |
| ; CHECK-LABEL: define i16 @test_fake_wide_exit |
| ; CHECK-SAME: (i64 [[X:%.*]]) { |
| ; CHECK-NEXT: entry: |
| ; CHECK-NEXT: br label [[LOOP:%.*]] |
| ; CHECK: loop: |
| ; CHECK-NEXT: [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ] |
| ; CHECK-NEXT: [[IV_WIDE:%.*]] = phi i64 [ 0, [[ENTRY]] ], [ [[IV_WIDE_NEXT:%.*]], [[BACKEDGE]] ] |
| ; CHECK-NEXT: [[RC:%.*]] = icmp slt i32 [[IV]], 100 |
| ; CHECK-NEXT: br i1 true, label [[CHECKED:%.*]], label [[CHECK_FAILED:%.*]] |
| ; CHECK: checked: |
| ; CHECK-NEXT: [[RC_WIDE:%.*]] = icmp ult i64 [[IV_WIDE]], [[X]] |
| ; CHECK-NEXT: br i1 [[RC_WIDE]], label [[BACKEDGE]], label [[CHECK_FAILED]] |
| ; CHECK: backedge: |
| ; CHECK-NEXT: [[IV_NEXT]] = add i32 [[IV]], 1 |
| ; CHECK-NEXT: [[IV_WIDE_NEXT]] = add i64 [[IV_WIDE]], 1 |
| ; CHECK-NEXT: [[NARROW_IV:%.*]] = trunc i32 [[IV_NEXT]] to i16 |
| ; CHECK-NEXT: [[LATCH_COND:%.*]] = icmp slt i16 [[NARROW_IV]], 100 |
| ; CHECK-NEXT: br i1 [[LATCH_COND]], label [[LOOP]], label [[EXIT:%.*]] |
| ; CHECK: exit: |
| ; CHECK-NEXT: [[NARROW_IV_LCSSA:%.*]] = phi i16 [ [[NARROW_IV]], [[BACKEDGE]] ] |
| ; CHECK-NEXT: ret i16 [[NARROW_IV_LCSSA]] |
| ; CHECK: check_failed: |
| ; CHECK-NEXT: ret i16 -1 |
| ; |
| entry: |
| br label %loop |
| |
| loop: |
| %iv = phi i32 [ 0, %entry ], [ %iv.next, %backedge ] |
| %iv.wide = phi i64 [ 0, %entry ], [ %iv.wide.next, %backedge ] |
| %rc = icmp slt i32 %iv, 100 |
| br i1 %rc, label %checked, label %check_failed |
| |
| checked: |
| %rc.wide = icmp ult i64 %iv.wide, %x |
| br i1 %rc.wide, label %backedge, label %check_failed |
| |
| backedge: |
| %iv.next = add i32 %iv, 1 |
| %iv.wide.next = add i64 %iv.wide, 1 |
| %narrow.iv = trunc i32 %iv.next to i16 |
| %latch.cond = icmp slt i16 %narrow.iv, 100 |
| br i1 %latch.cond, label %loop, label %exit |
| |
| exit: |
| ret i16 %narrow.iv |
| |
| check_failed: |
| ret i16 -1 |
| } |
| |
| |
| !0 = !{i32 0, i32 2147483647} |
| !1 = !{i64 0, i64 9223372036854775807} |
| !2 = !{i32 1, i32 2147483647} |