I'm about to enable the new loop predication transform by default. It has the effect of completely destroying many read only loops - which happen to be a super common idiom in our test cases. So as to preserve test coverage of other transforms, disable the new transform where it would cause sharp test coverage regressions. (This is semantically part of the enabling commit. It's committed separate to ease revert if the actual flag flip gets reverted.)
661 lines
20 KiB
LLVM
661 lines
20 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: [[SEXT:%.*]] = sext 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 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 [ 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: [[SEXT:%.*]] = sext i32 [[N:%.*]] 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: [[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 [ 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: [[SEXT:%.*]] = sext i32 [[N:%.*]] to i64
|
|
; 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: [[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 [ -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: [[ZEXT:%.*]] = zext i32 [[N:%.*]] to i64
|
|
; 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: [[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 [ 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: [[ZEXT:%.*]] = zext 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 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 [ 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: 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:%.*]]
|
|
; 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 [ 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: [[SEXT:%.*]] = sext i32 [[N:%.*]] to i64
|
|
; 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: [[TMP0:%.*]] = icmp ne i64 [[IV]], [[SEXT]]
|
|
; CHECK-NEXT: [[NEGCMP:%.*]] = icmp slt i64 [[IV]], -10
|
|
; CHECK-NEXT: [[CMP:%.*]] = and i1 [[TMP0]], [[NEGCMP]]
|
|
; CHECK-NEXT: br i1 [[CMP]], 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:%.*]], !range !0
|
|
; 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 ult i64 [[IV_NEXT]], [[ZEXT]]
|
|
; CHECK-NEXT: br i1 [[TMP0]], 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}
|