Files
clang-p2996/llvm/test/Transforms/IndVarSimplify/X86/eliminate-trunc.ll
Nikita Popov 0dda633317 [SCEV] Strength nowrap flags after constant folding
We should first try to constant fold the add expression and only
strengthen nowrap flags afterwards. This allows us to determine
stronger flags if e.g. only two operands are left after constant
folding (and thus "guaranteed no wrap region" code applies) or the
resulting operands are non-negative and thus nsw->nuw strengthening
applies.
2020-10-25 18:00:22 +01:00

684 lines
22 KiB
LLVM

; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
; RUN: opt -indvars -S -indvars-predicate-loops=0 < %s | FileCheck %s
target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
target triple = "x86_64-unknown-linux-gnu"
; General case: without extra knowledge, trunc cannot be eliminated.
define void @test_00(i64 %start, i32 %n) {
;
; CHECK-LABEL: @test_00(
; CHECK-NEXT: entry:
; CHECK-NEXT: br label [[LOOP:%.*]]
; CHECK: loop:
; CHECK-NEXT: [[IV:%.*]] = phi i64 [ [[START:%.*]], [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP]] ]
; CHECK-NEXT: [[IV_NEXT]] = add i64 [[IV]], 1
; CHECK-NEXT: [[NARROW_IV:%.*]] = trunc i64 [[IV]] to i32
; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 [[NARROW_IV]], [[N:%.*]]
; CHECK-NEXT: br i1 [[CMP]], label [[LOOP]], label [[EXIT:%.*]]
; CHECK: exit:
; CHECK-NEXT: ret void
;
entry:
br label %loop
loop:
%iv = phi i64 [ %start, %entry ], [ %iv.next, %loop ]
%iv.next = add i64 %iv, 1
%narrow.iv = trunc i64 %iv to i32
%cmp = icmp slt i32 %narrow.iv, %n
br i1 %cmp, label %loop, label %exit
exit:
ret void
}
define void @test_01(i32 %n) {
;
; CHECK-LABEL: @test_01(
; CHECK-NEXT: entry:
; CHECK-NEXT: [[TMP0:%.*]] = icmp sgt i32 [[N:%.*]], 0
; CHECK-NEXT: [[SMAX:%.*]] = select i1 [[TMP0]], i32 [[N]], i32 0
; CHECK-NEXT: [[TMP1:%.*]] = add nuw i32 [[SMAX]], 1
; CHECK-NEXT: [[WIDE_TRIP_COUNT:%.*]] = zext i32 [[TMP1]] to i64
; CHECK-NEXT: br label [[LOOP:%.*]]
; CHECK: loop:
; CHECK-NEXT: [[IV:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP]] ]
; CHECK-NEXT: [[IV_NEXT]] = add nuw nsw i64 [[IV]], 1
; CHECK-NEXT: [[EXITCOND:%.*]] = icmp ne i64 [[IV_NEXT]], [[WIDE_TRIP_COUNT]]
; CHECK-NEXT: br i1 [[EXITCOND]], label [[LOOP]], label [[EXIT:%.*]]
; CHECK: exit:
; CHECK-NEXT: ret void
;
entry:
br label %loop
loop:
%iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ]
%iv.next = add i64 %iv, 1
%narrow.iv = trunc i64 %iv to i32
%cmp = icmp slt i32 %narrow.iv, %n
br i1 %cmp, label %loop, label %exit
exit:
ret void
}
; Max value at which we can eliminate trunc: SINT_MAX - 1.
define void @test_02(i32 %n) {
;
; CHECK-LABEL: @test_02(
; CHECK-NEXT: entry:
; CHECK-NEXT: [[TMP0:%.*]] = icmp sgt i32 [[N:%.*]], 2147483646
; CHECK-NEXT: [[SMAX:%.*]] = select i1 [[TMP0]], i32 [[N]], i32 2147483646
; CHECK-NEXT: [[TMP1:%.*]] = add nuw i32 [[SMAX]], 1
; CHECK-NEXT: [[WIDE_TRIP_COUNT:%.*]] = zext i32 [[TMP1]] to i64
; CHECK-NEXT: br label [[LOOP:%.*]]
; CHECK: loop:
; CHECK-NEXT: [[IV:%.*]] = phi i64 [ 2147483646, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP]] ]
; CHECK-NEXT: [[IV_NEXT]] = add nuw nsw i64 [[IV]], 1
; CHECK-NEXT: [[EXITCOND:%.*]] = icmp ne i64 [[IV_NEXT]], [[WIDE_TRIP_COUNT]]
; CHECK-NEXT: br i1 [[EXITCOND]], label [[LOOP]], label [[EXIT:%.*]]
; CHECK: exit:
; CHECK-NEXT: ret void
;
entry:
br label %loop
loop:
%iv = phi i64 [ 2147483646, %entry ], [ %iv.next, %loop ]
%iv.next = add i64 %iv, 1
%narrow.iv = trunc i64 %iv to i32
%cmp = icmp slt i32 %narrow.iv, %n
br i1 %cmp, label %loop, label %exit
exit:
ret void
}
; If we start from SINT_MAX then the predicate is always false.
define void @test_03(i32 %n) {
;
; CHECK-LABEL: @test_03(
; CHECK-NEXT: entry:
; CHECK-NEXT: br label [[LOOP:%.*]]
; CHECK: loop:
; CHECK-NEXT: br i1 false, label [[LOOP]], label [[EXIT:%.*]]
; CHECK: exit:
; CHECK-NEXT: ret void
;
entry:
br label %loop
loop:
%iv = phi i64 [2147483647, %entry], [%iv.next, %loop]
%iv.next = add i64 %iv, 1
%narrow.iv = trunc i64 %iv to i32
%cmp = icmp slt i32 %narrow.iv, %n
br i1 %cmp, label %loop, label %exit
exit:
ret void
}
; Minimum value at which we can apply the transform: SINT_MIN + 1.
define void @test_04(i32 %n) {
;
; CHECK-LABEL: @test_04(
; CHECK-NEXT: entry:
; CHECK-NEXT: [[TMP0:%.*]] = icmp sgt i32 [[N:%.*]], -2147483647
; CHECK-NEXT: [[SMAX:%.*]] = select i1 [[TMP0]], i32 [[N]], i32 -2147483647
; CHECK-NEXT: [[TMP1:%.*]] = add i32 [[SMAX]], 1
; CHECK-NEXT: br label [[LOOP:%.*]]
; CHECK: loop:
; CHECK-NEXT: [[IV:%.*]] = phi i64 [ -2147483647, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP]] ]
; CHECK-NEXT: [[IV_NEXT]] = add nsw i64 [[IV]], 1
; CHECK-NEXT: [[LFTR_WIDEIV:%.*]] = trunc i64 [[IV_NEXT]] to i32
; CHECK-NEXT: [[EXITCOND:%.*]] = icmp ne i32 [[LFTR_WIDEIV]], [[TMP1]]
; CHECK-NEXT: br i1 [[EXITCOND]], label [[LOOP]], label [[EXIT:%.*]]
; CHECK: exit:
; CHECK-NEXT: ret void
;
entry:
br label %loop
loop:
%iv = phi i64 [ -2147483647, %entry ], [ %iv.next, %loop ]
%iv.next = add i64 %iv, 1
%narrow.iv = trunc i64 %iv to i32
%cmp = icmp slt i32 %narrow.iv, %n
br i1 %cmp, label %loop, label %exit
exit:
ret void
}
; FIXME: Harmful LFTR should be thrown away.
define void @test_05(i32 %n) {
;
; CHECK-LABEL: @test_05(
; CHECK-NEXT: entry:
; CHECK-NEXT: [[TMP0:%.*]] = add i32 [[N:%.*]], 1
; CHECK-NEXT: br label [[LOOP:%.*]]
; CHECK: loop:
; CHECK-NEXT: [[IV:%.*]] = phi i64 [ -2147483648, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP]] ]
; CHECK-NEXT: [[IV_NEXT]] = add nsw i64 [[IV]], 1
; CHECK-NEXT: [[LFTR_WIDEIV:%.*]] = trunc i64 [[IV_NEXT]] to i32
; CHECK-NEXT: [[EXITCOND:%.*]] = icmp ne i32 [[LFTR_WIDEIV]], [[TMP0]]
; CHECK-NEXT: br i1 [[EXITCOND]], label [[LOOP]], label [[EXIT:%.*]]
; CHECK: exit:
; CHECK-NEXT: ret void
;
entry:
br label %loop
loop:
%iv = phi i64 [ -2147483648, %entry ], [ %iv.next, %loop ]
%iv.next = add i64 %iv, 1
%narrow.iv = trunc i64 %iv to i32
%cmp = icmp slt i32 %narrow.iv, %n
br i1 %cmp, label %loop, label %exit
exit:
ret void
}
; Trunc changes the actual value of the IV, so it is invalid to remove it: SINT_MIN - 1.
define void @test_06(i32 %n) {
;
; CHECK-LABEL: @test_06(
; CHECK-NEXT: entry:
; CHECK-NEXT: br label [[LOOP:%.*]]
; CHECK: loop:
; CHECK-NEXT: br i1 false, label [[LOOP]], label [[EXIT:%.*]]
; CHECK: exit:
; CHECK-NEXT: ret void
;
entry:
br label %loop
loop:
%iv = phi i64 [ -2147483649, %entry ], [ %iv.next, %loop ]
%iv.next = add i64 %iv, 1
%narrow.iv = trunc i64 %iv to i32
%cmp = icmp slt i32 %narrow.iv, %n
br i1 %cmp, label %loop, label %exit
exit:
ret void
}
; General case: without extra knowledge, trunc cannot be eliminated.
define void @test_00_unsigned(i64 %start, i32 %n) {
; CHECK-LABEL: @test_00_unsigned(
; CHECK-NEXT: entry:
; CHECK-NEXT: br label [[LOOP:%.*]]
; CHECK: loop:
; CHECK-NEXT: [[IV:%.*]] = phi i64 [ [[START:%.*]], [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP]] ]
; CHECK-NEXT: [[IV_NEXT]] = add i64 [[IV]], 1
; CHECK-NEXT: [[NARROW_IV:%.*]] = trunc i64 [[IV]] to i32
; CHECK-NEXT: [[CMP:%.*]] = icmp ult i32 [[NARROW_IV]], [[N:%.*]]
; CHECK-NEXT: br i1 [[CMP]], label [[LOOP]], label [[EXIT:%.*]]
; CHECK: exit:
; CHECK-NEXT: ret void
;
entry:
br label %loop
loop:
%iv = phi i64 [ %start, %entry ], [ %iv.next, %loop ]
%iv.next = add i64 %iv, 1
%narrow.iv = trunc i64 %iv to i32
%cmp = icmp ult i32 %narrow.iv, %n
br i1 %cmp, label %loop, label %exit
exit:
ret void
}
; FIXME: Harmful LFTR should be thrown away.
define void @test_01_unsigned(i32 %n) {
; CHECK-LABEL: @test_01_unsigned(
; CHECK-NEXT: entry:
; CHECK-NEXT: [[TMP0:%.*]] = add i32 [[N:%.*]], 1
; CHECK-NEXT: br label [[LOOP:%.*]]
; CHECK: loop:
; CHECK-NEXT: [[IV:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP]] ]
; CHECK-NEXT: [[IV_NEXT]] = add nuw nsw i64 [[IV]], 1
; CHECK-NEXT: [[LFTR_WIDEIV:%.*]] = trunc i64 [[IV_NEXT]] to i32
; CHECK-NEXT: [[EXITCOND:%.*]] = icmp ne i32 [[LFTR_WIDEIV]], [[TMP0]]
; CHECK-NEXT: br i1 [[EXITCOND]], label [[LOOP]], label [[EXIT:%.*]]
; CHECK: exit:
; CHECK-NEXT: ret void
;
entry:
br label %loop
loop:
%iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ]
%iv.next = add i64 %iv, 1
%narrow.iv = trunc i64 %iv to i32
%cmp = icmp ult i32 %narrow.iv, %n
br i1 %cmp, label %loop, label %exit
exit:
ret void
}
; Max value at which we can eliminate trunc: UINT_MAX - 1.
define void @test_02_unsigned(i32 %n) {
; CHECK-LABEL: @test_02_unsigned(
; CHECK-NEXT: entry:
; CHECK-NEXT: [[TMP0:%.*]] = icmp ugt i32 [[N:%.*]], -2
; CHECK-NEXT: [[UMAX:%.*]] = select i1 [[TMP0]], i32 [[N]], i32 -2
; CHECK-NEXT: [[TMP1:%.*]] = add nsw i32 [[UMAX]], 1
; CHECK-NEXT: br label [[LOOP:%.*]]
; CHECK: loop:
; CHECK-NEXT: [[IV:%.*]] = phi i64 [ 4294967294, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP]] ]
; CHECK-NEXT: [[IV_NEXT]] = add nuw nsw i64 [[IV]], 1
; CHECK-NEXT: [[LFTR_WIDEIV:%.*]] = trunc i64 [[IV_NEXT]] to i32
; CHECK-NEXT: [[EXITCOND:%.*]] = icmp ne i32 [[LFTR_WIDEIV]], [[TMP1]]
; CHECK-NEXT: br i1 [[EXITCOND]], label [[LOOP]], label [[EXIT:%.*]]
; CHECK: exit:
; CHECK-NEXT: ret void
;
entry:
br label %loop
loop:
%iv = phi i64 [ 4294967294, %entry ], [ %iv.next, %loop ]
%iv.next = add i64 %iv, 1
%narrow.iv = trunc i64 %iv to i32
%cmp = icmp ult i32 %narrow.iv, %n
br i1 %cmp, label %loop, label %exit
exit:
ret void
}
; If we start from UINT_MAX then the predicate is always false.
define void @test_03_unsigned(i32 %n) {
; CHECK-LABEL: @test_03_unsigned(
; CHECK-NEXT: entry:
; CHECK-NEXT: br label [[LOOP:%.*]]
; CHECK: loop:
; CHECK-NEXT: br i1 false, label [[LOOP]], label [[EXIT:%.*]]
; CHECK: exit:
; CHECK-NEXT: ret void
;
entry:
br label %loop
loop:
%iv = phi i64 [ 4294967295, %entry ], [ %iv.next, %loop ]
%iv.next = add i64 %iv, 1
%narrow.iv = trunc i64 %iv to i32
%cmp = icmp ult i32 %narrow.iv, %n
br i1 %cmp, label %loop, label %exit
exit:
ret void
}
; Minimum value at which we can apply the transform: UINT_MIN.
define void @test_04_unsigned(i32 %n) {
; CHECK-LABEL: @test_04_unsigned(
; CHECK-NEXT: entry:
; CHECK-NEXT: [[TMP0:%.*]] = add i32 [[N:%.*]], 1
; CHECK-NEXT: br label [[LOOP:%.*]]
; CHECK: loop:
; CHECK-NEXT: [[IV:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP]] ]
; CHECK-NEXT: [[IV_NEXT]] = add nuw nsw i64 [[IV]], 1
; CHECK-NEXT: [[LFTR_WIDEIV:%.*]] = trunc i64 [[IV_NEXT]] to i32
; CHECK-NEXT: [[EXITCOND:%.*]] = icmp ne i32 [[LFTR_WIDEIV]], [[TMP0]]
; CHECK-NEXT: br i1 [[EXITCOND]], label [[LOOP]], label [[EXIT:%.*]]
; CHECK: exit:
; CHECK-NEXT: ret void
;
entry:
br label %loop
loop:
%iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ]
%iv.next = add i64 %iv, 1
%narrow.iv = trunc i64 %iv to i32
%cmp = icmp ult i32 %narrow.iv, %n
br i1 %cmp, label %loop, label %exit
exit:
ret void
}
; Start from 1.
define void @test_05_unsigned(i32 %n) {
; CHECK-LABEL: @test_05_unsigned(
; CHECK-NEXT: entry:
; CHECK-NEXT: [[TMP0:%.*]] = icmp ugt i32 [[N:%.*]], 1
; CHECK-NEXT: [[UMAX:%.*]] = select i1 [[TMP0]], i32 [[N]], i32 1
; CHECK-NEXT: [[TMP1:%.*]] = add i32 [[UMAX]], 1
; CHECK-NEXT: br label [[LOOP:%.*]]
; CHECK: loop:
; CHECK-NEXT: [[IV:%.*]] = phi i64 [ 1, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP]] ]
; CHECK-NEXT: [[IV_NEXT]] = add nuw nsw i64 [[IV]], 1
; CHECK-NEXT: [[LFTR_WIDEIV:%.*]] = trunc i64 [[IV_NEXT]] to i32
; CHECK-NEXT: [[EXITCOND:%.*]] = icmp ne i32 [[LFTR_WIDEIV]], [[TMP1]]
; CHECK-NEXT: br i1 [[EXITCOND]], label [[LOOP]], label [[EXIT:%.*]]
; CHECK: exit:
; CHECK-NEXT: ret void
;
entry:
br label %loop
loop:
%iv = phi i64 [ 1, %entry ], [ %iv.next, %loop ]
%iv.next = add i64 %iv, 1
%narrow.iv = trunc i64 %iv to i32
%cmp = icmp ult i32 %narrow.iv, %n
br i1 %cmp, label %loop, label %exit
exit:
ret void
}
; Trunc changes the actual value of the IV, so it is invalid to remove it: UINT_MIN - 1.
define void @test_06_unsigned(i32 %n) {
; CHECK-LABEL: @test_06_unsigned(
; CHECK-NEXT: entry:
; CHECK-NEXT: br label [[LOOP:%.*]]
; CHECK: loop:
; CHECK-NEXT: br i1 false, label [[LOOP]], label [[EXIT:%.*]]
; CHECK: exit:
; CHECK-NEXT: ret void
;
entry:
br label %loop
loop:
%iv = phi i64 [ -1, %entry ], [ %iv.next, %loop ]
%iv.next = add i64 %iv, 1
%narrow.iv = trunc i64 %iv to i32
%cmp = icmp ult i32 %narrow.iv, %n
br i1 %cmp, label %loop, label %exit
exit:
ret void
}
; Do not eliminate trunc if it is used by something different from icmp.
define void @test_07(i32* %p, i32 %n) {
; CHECK-LABEL: @test_07(
; CHECK-NEXT: entry:
; CHECK-NEXT: [[TMP0:%.*]] = icmp sgt i32 [[N:%.*]], 0
; CHECK-NEXT: [[SMAX:%.*]] = select i1 [[TMP0]], i32 [[N]], i32 0
; CHECK-NEXT: [[TMP1:%.*]] = add nuw i32 [[SMAX]], 1
; CHECK-NEXT: [[WIDE_TRIP_COUNT:%.*]] = zext i32 [[TMP1]] to i64
; CHECK-NEXT: br label [[LOOP:%.*]]
; CHECK: loop:
; CHECK-NEXT: [[IV:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP]] ]
; CHECK-NEXT: [[IV_NEXT]] = add nuw nsw i64 [[IV]], 1
; CHECK-NEXT: [[NARROW_IV:%.*]] = trunc i64 [[IV]] to i32
; CHECK-NEXT: store i32 [[NARROW_IV]], i32* [[P:%.*]], align 4
; CHECK-NEXT: [[EXITCOND:%.*]] = icmp ne i64 [[IV_NEXT]], [[WIDE_TRIP_COUNT]]
; CHECK-NEXT: br i1 [[EXITCOND]], label [[LOOP]], label [[EXIT:%.*]]
; CHECK: exit:
; CHECK-NEXT: ret void
;
entry:
br label %loop
loop:
%iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ]
%iv.next = add i64 %iv, 1
%narrow.iv = trunc i64 %iv to i32
store i32 %narrow.iv, i32* %p
%cmp = icmp slt i32 %narrow.iv, %n
br i1 %cmp, label %loop, label %exit
exit:
ret void
}
; Check that we can eliminate both signed and unsigned compare.
define void @test_08(i32 %n) {
; CHECK-LABEL: @test_08(
; CHECK-NEXT: entry:
; CHECK-NEXT: [[ZEXT:%.*]] = zext i32 [[N:%.*]] to i64
; CHECK-NEXT: [[SEXT:%.*]] = sext i32 [[N]] to i64
; CHECK-NEXT: br label [[LOOP:%.*]]
; CHECK: loop:
; CHECK-NEXT: [[IV:%.*]] = phi i64 [ 1, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP]] ]
; CHECK-NEXT: [[IV_NEXT]] = add nuw nsw i64 [[IV]], 1
; CHECK-NEXT: [[TMP0:%.*]] = icmp slt i64 [[IV]], [[SEXT]]
; CHECK-NEXT: [[TMP1:%.*]] = icmp ult i64 [[IV]], [[ZEXT]]
; CHECK-NEXT: [[CMP:%.*]] = and i1 [[TMP0]], [[TMP1]]
; CHECK-NEXT: br i1 [[CMP]], label [[LOOP]], label [[EXIT:%.*]]
; CHECK: exit:
; CHECK-NEXT: ret void
;
entry:
br label %loop
loop:
%iv = phi i64 [ 1, %entry ], [ %iv.next, %loop ]
%iv.next = add i64 %iv, 1
%narrow.iv = trunc i64 %iv to i32
%cmp1 = icmp slt i32 %narrow.iv, %n
%cmp2 = icmp ult i32 %narrow.iv, %n
%cmp = and i1 %cmp1, %cmp2
br i1 %cmp, label %loop, label %exit
exit:
ret void
}
; Widen NE as unsigned.
define void @test_09(i32 %n) {
; CHECK-LABEL: @test_09(
; CHECK-NEXT: entry:
; CHECK-NEXT: [[ZEXT:%.*]] = zext i32 [[N:%.*]] to i64
; CHECK-NEXT: br label [[LOOP:%.*]]
; CHECK: loop:
; CHECK-NEXT: [[IV:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP]] ]
; CHECK-NEXT: [[IV_NEXT]] = add nuw nsw i64 [[IV]], 1
; CHECK-NEXT: [[TMP0:%.*]] = icmp ne i64 [[IV]], [[ZEXT]]
; CHECK-NEXT: br i1 [[TMP0]], label [[LOOP]], label [[EXIT:%.*]]
; CHECK: exit:
; CHECK-NEXT: ret void
;
entry:
br label %loop
loop:
%iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ]
%iv.next = add i64 %iv, 1
%narrow.iv = trunc i64 %iv to i32
%cmp = icmp ne i32 %narrow.iv, %n
br i1 %cmp, label %loop, label %exit
exit:
ret void
}
; Widen NE as signed.
define void @test_10(i32 %n) {
; CHECK-LABEL: @test_10(
; CHECK-NEXT: entry:
; CHECK-NEXT: [[TMP0:%.*]] = add i32 [[N:%.*]], 100
; CHECK-NEXT: [[TMP1:%.*]] = zext i32 [[TMP0]] to i64
; CHECK-NEXT: [[TMP2:%.*]] = icmp ult i64 [[TMP1]], 90
; CHECK-NEXT: [[UMIN:%.*]] = select i1 [[TMP2]], i64 [[TMP1]], i64 90
; CHECK-NEXT: [[TMP3:%.*]] = add nuw nsw i64 [[UMIN]], -99
; CHECK-NEXT: br label [[LOOP:%.*]]
; CHECK: loop:
; CHECK-NEXT: [[IV:%.*]] = phi i64 [ -100, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP]] ]
; CHECK-NEXT: [[IV_NEXT]] = add nuw nsw i64 [[IV]], 1
; CHECK-NEXT: [[EXITCOND:%.*]] = icmp ne i64 [[IV_NEXT]], [[TMP3]]
; CHECK-NEXT: br i1 [[EXITCOND]], label [[LOOP]], label [[EXIT:%.*]]
; CHECK: exit:
; CHECK-NEXT: ret void
;
entry:
br label %loop
loop:
%iv = phi i64 [ -100, %entry ], [ %iv.next, %loop ]
%iv.next = add i64 %iv, 1
%narrow.iv = trunc i64 %iv to i32
%trunccmp = icmp ne i32 %narrow.iv, %n
%negcmp = icmp slt i64 %iv, -10
%cmp = and i1 %trunccmp, %negcmp
br i1 %cmp, label %loop, label %exit
exit:
ret void
}
define void @test_11() {
; CHECK-LABEL: @test_11(
; CHECK-NEXT: br label [[BB1:%.*]]
; CHECK: bb1:
; CHECK-NEXT: br i1 undef, label [[BB2:%.*]], label [[BB6:%.*]]
; CHECK: bb2:
; CHECK-NEXT: br i1 undef, label [[BB3:%.*]], label [[BB4:%.*]]
; CHECK: bb3:
; CHECK-NEXT: br label [[BB4]]
; CHECK: bb4:
; CHECK-NEXT: br label [[BB6]]
; CHECK: bb5:
; CHECK-NEXT: [[_TMP24:%.*]] = icmp slt i16 undef, 0
; CHECK-NEXT: br i1 [[_TMP24]], label [[BB5:%.*]], label [[BB5]]
; CHECK: bb6:
; CHECK-NEXT: br i1 false, label [[BB1]], label [[BB7:%.*]]
; CHECK: bb7:
; CHECK-NEXT: ret void
;
br label %bb1
bb1: ; preds = %bb6, %0
%e.5.0 = phi i32 [ 0, %0 ], [ %_tmp32, %bb6 ]
br i1 undef, label %bb2, label %bb6
bb2: ; preds = %bb1
%_tmp15 = trunc i32 %e.5.0 to i16
br i1 undef, label %bb3, label %bb4
bb3: ; preds = %bb2
br label %bb4
bb4: ; preds = %bb3, %bb2
br label %bb6
bb5: ; preds = %bb5, %bb5
%_tmp24 = icmp slt i16 %_tmp15, 0
br i1 %_tmp24, label %bb5, label %bb5
bb6: ; preds = %bb4, %bb1
%_tmp32 = add nuw nsw i32 %e.5.0, 1
br i1 false, label %bb1, label %bb7
bb7: ; preds = %bb6
ret void
}
; Show that we can turn signed comparison to unsigned and use zext while
; comparing non-negative values.
define void @test_12(i32* %p) {
; CHECK-LABEL: @test_12(
; CHECK-NEXT: entry:
; CHECK-NEXT: [[N:%.*]] = load i32, i32* [[P:%.*]], align 4, [[RNG0:!range !.*]]
; CHECK-NEXT: [[TMP0:%.*]] = icmp sgt i32 [[N]], 1
; CHECK-NEXT: [[SMAX:%.*]] = select i1 [[TMP0]], i32 [[N]], i32 1
; CHECK-NEXT: [[WIDE_TRIP_COUNT:%.*]] = zext i32 [[SMAX]] to i64
; CHECK-NEXT: br label [[LOOP:%.*]]
; CHECK: loop:
; CHECK-NEXT: [[IV:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP]] ]
; CHECK-NEXT: [[IV_NEXT]] = add nuw nsw i64 [[IV]], 1
; CHECK-NEXT: [[EXITCOND:%.*]] = icmp ne i64 [[IV_NEXT]], [[WIDE_TRIP_COUNT]]
; CHECK-NEXT: br i1 [[EXITCOND]], label [[LOOP]], label [[EXIT:%.*]]
; CHECK: exit:
; CHECK-NEXT: ret void
;
entry:
%n = load i32, i32* %p, !range !0
br label %loop
loop:
%iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ]
%iv.next = add i64 %iv, 1
%narrow.iv = trunc i64 %iv.next to i32
%cmp = icmp slt i32 %narrow.iv, %n
br i1 %cmp, label %loop, label %exit
exit:
ret void
}
define void @test_13a(i32 %n) {
;
; CHECK-LABEL: @test_13a(
; CHECK-NEXT: entry:
; CHECK-NEXT: [[ZEXT:%.*]] = zext i32 1024 to i64
; CHECK-NEXT: br label [[LOOP:%.*]]
; CHECK: loop:
; CHECK-NEXT: [[IV:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP]] ]
; CHECK-NEXT: [[IV_NEXT]] = add nuw nsw i64 [[IV]], 2
; CHECK-NEXT: [[TMP0:%.*]] = icmp ne i64 [[IV]], [[ZEXT]]
; CHECK-NEXT: br i1 [[TMP0]], label [[LOOP]], label [[EXIT:%.*]]
; CHECK: exit:
; CHECK-NEXT: ret void
;
entry:
br label %loop
loop:
%iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ]
%iv.next = add nsw nuw i64 %iv, 2
%narrow.iv = trunc i64 %iv to i32
%cmp = icmp ne i32 1024, %narrow.iv
br i1 %cmp, label %loop, label %exit
exit:
ret void
}
define void @test_13b(i32 %n) {
;
; CHECK-LABEL: @test_13b(
; CHECK-NEXT: entry:
; CHECK-NEXT: [[ZEXT:%.*]] = zext i32 1024 to i64
; CHECK-NEXT: br label [[LOOP:%.*]]
; CHECK: loop:
; CHECK-NEXT: [[IV:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP]] ]
; CHECK-NEXT: [[IV_NEXT]] = add nuw nsw i64 [[IV]], 2
; CHECK-NEXT: [[TMP0:%.*]] = icmp ult i64 [[IV]], [[ZEXT]]
; CHECK-NEXT: br i1 [[TMP0]], label [[LOOP]], label [[EXIT:%.*]]
; CHECK: exit:
; CHECK-NEXT: ret void
;
entry:
br label %loop
loop:
%iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ]
%iv.next = add nsw nuw i64 %iv, 2
%narrow.iv = trunc i64 %iv to i32
%cmp = icmp ugt i32 1024, %narrow.iv
br i1 %cmp, label %loop, label %exit
exit:
ret void
}
define void @test_13c(i32 %n) {
;
; CHECK-LABEL: @test_13c(
; CHECK-NEXT: entry:
; CHECK-NEXT: [[ZEXT:%.*]] = zext i32 1024 to i64
; CHECK-NEXT: br label [[LOOP:%.*]]
; CHECK: loop:
; CHECK-NEXT: [[IV:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP]] ]
; CHECK-NEXT: [[IV_NEXT]] = add nuw nsw i64 [[IV]], 2
; CHECK-NEXT: [[TMP0:%.*]] = icmp ult i64 [[IV]], [[ZEXT]]
; CHECK-NEXT: br i1 [[TMP0]], label [[LOOP]], label [[EXIT:%.*]]
; CHECK: exit:
; CHECK-NEXT: ret void
;
entry:
br label %loop
loop:
%iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ]
%iv.next = add nsw nuw i64 %iv, 2
%narrow.iv = trunc i64 %iv to i32
%cmp = icmp sgt i32 1024, %narrow.iv
br i1 %cmp, label %loop, label %exit
exit:
ret void
}
define void @test_13d(i32 %n) {
;
; CHECK-LABEL: @test_13d(
; CHECK-NEXT: entry:
; CHECK-NEXT: [[SEXT:%.*]] = sext i32 1024 to i64
; CHECK-NEXT: br label [[LOOP:%.*]]
; CHECK: loop:
; CHECK-NEXT: [[IV:%.*]] = phi i64 [ -20, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP]] ]
; CHECK-NEXT: [[IV_NEXT]] = add nsw i64 [[IV]], 2
; CHECK-NEXT: [[TMP0:%.*]] = icmp slt i64 [[IV]], [[SEXT]]
; CHECK-NEXT: br i1 [[TMP0]], label [[LOOP]], label [[EXIT:%.*]]
; CHECK: exit:
; CHECK-NEXT: ret void
;
entry:
br label %loop
loop:
%iv = phi i64 [ -20, %entry ], [ %iv.next, %loop ]
%iv.next = add nsw i64 %iv, 2
%narrow.iv = trunc i64 %iv to i32
%cmp = icmp sgt i32 1024, %narrow.iv
br i1 %cmp, label %loop, label %exit
exit:
ret void
}
!0 = !{i32 0, i32 1000}