
While sinking instructions (that are loop invariant) from preheader to the exit block, we are skipping instructions due to decrementing instruction iterator twice.
1095 lines
40 KiB
LLVM
1095 lines
40 KiB
LLVM
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
|
|
; RUN: opt -passes=indvars -S < %s -indvars-predicate-loops=0 | FileCheck %s
|
|
|
|
; A collection of tests which domonstrate cases where we can use properties
|
|
; of the loop (i.e. single exit, finite, mustprogress) to optimize conditions
|
|
; and extends we couldn't otherwise handle.
|
|
|
|
target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64"
|
|
|
|
define void @slt_constant_rhs(i16 %n.raw, i8 %start) mustprogress {
|
|
; CHECK-LABEL: @slt_constant_rhs(
|
|
; CHECK-NEXT: entry:
|
|
; CHECK-NEXT: [[TMP0:%.*]] = trunc i16 254 to i8
|
|
; CHECK-NEXT: br label [[FOR_BODY:%.*]]
|
|
; CHECK: for.body:
|
|
; CHECK-NEXT: [[IV:%.*]] = phi i8 [ [[IV_NEXT:%.*]], [[FOR_BODY]] ], [ [[START:%.*]], [[ENTRY:%.*]] ]
|
|
; CHECK-NEXT: [[IV_NEXT]] = add i8 [[IV]], 1
|
|
; CHECK-NEXT: [[CMP:%.*]] = icmp ult i8 [[IV_NEXT]], [[TMP0]]
|
|
; CHECK-NEXT: br i1 [[CMP]], label [[FOR_BODY]], label [[FOR_END:%.*]]
|
|
; CHECK: for.end:
|
|
; CHECK-NEXT: ret void
|
|
;
|
|
entry:
|
|
br label %for.body
|
|
|
|
for.body: ; preds = %entry, %for.body
|
|
%iv = phi i8 [ %iv.next, %for.body ], [ %start, %entry ]
|
|
%iv.next = add i8 %iv, 1
|
|
%zext = zext i8 %iv.next to i16
|
|
%cmp = icmp slt i16 %zext, 254
|
|
br i1 %cmp, label %for.body, label %for.end
|
|
|
|
for.end: ; preds = %for.body, %entry
|
|
ret void
|
|
}
|
|
|
|
;; Range logic doesn't depend on must execute
|
|
define void @slt_constant_rhs_maythrow(i16 %n.raw, i8 %start) mustprogress {
|
|
; CHECK-LABEL: @slt_constant_rhs_maythrow(
|
|
; CHECK-NEXT: entry:
|
|
; CHECK-NEXT: [[TMP0:%.*]] = trunc i16 254 to i8
|
|
; CHECK-NEXT: br label [[FOR_BODY:%.*]]
|
|
; CHECK: for.body:
|
|
; CHECK-NEXT: [[IV:%.*]] = phi i8 [ [[IV_NEXT:%.*]], [[FOR_BODY]] ], [ [[START:%.*]], [[ENTRY:%.*]] ]
|
|
; CHECK-NEXT: [[IV_NEXT]] = add i8 [[IV]], 1
|
|
; CHECK-NEXT: call void @unknown()
|
|
; CHECK-NEXT: [[CMP:%.*]] = icmp ult i8 [[IV_NEXT]], [[TMP0]]
|
|
; CHECK-NEXT: br i1 [[CMP]], label [[FOR_BODY]], label [[FOR_END:%.*]]
|
|
; CHECK: for.end:
|
|
; CHECK-NEXT: ret void
|
|
;
|
|
entry:
|
|
br label %for.body
|
|
|
|
for.body: ; preds = %entry, %for.body
|
|
%iv = phi i8 [ %iv.next, %for.body ], [ %start, %entry ]
|
|
%iv.next = add i8 %iv, 1
|
|
call void @unknown()
|
|
%zext = zext i8 %iv.next to i16
|
|
%cmp = icmp slt i16 %zext, 254
|
|
br i1 %cmp, label %for.body, label %for.end
|
|
|
|
for.end: ; preds = %for.body, %entry
|
|
ret void
|
|
}
|
|
|
|
;; Range logic doesn't depend on must execute
|
|
define void @slt_constant_rhs_multiexit(i16 %n.raw, i8 %start, i1 %c) mustprogress {
|
|
; CHECK-LABEL: @slt_constant_rhs_multiexit(
|
|
; CHECK-NEXT: entry:
|
|
; CHECK-NEXT: [[TMP0:%.*]] = trunc i16 254 to i8
|
|
; CHECK-NEXT: br label [[FOR_BODY:%.*]]
|
|
; CHECK: for.body:
|
|
; CHECK-NEXT: [[IV:%.*]] = phi i8 [ [[IV_NEXT:%.*]], [[LATCH:%.*]] ], [ [[START:%.*]], [[ENTRY:%.*]] ]
|
|
; CHECK-NEXT: [[IV_NEXT]] = add i8 [[IV]], 1
|
|
; CHECK-NEXT: br i1 [[C:%.*]], label [[LATCH]], label [[FOR_END:%.*]]
|
|
; CHECK: latch:
|
|
; CHECK-NEXT: [[CMP:%.*]] = icmp ult i8 [[IV_NEXT]], [[TMP0]]
|
|
; CHECK-NEXT: br i1 [[CMP]], label [[FOR_BODY]], label [[FOR_END]]
|
|
; CHECK: for.end:
|
|
; CHECK-NEXT: ret void
|
|
;
|
|
entry:
|
|
br label %for.body
|
|
|
|
for.body: ; preds = %entry, %for.body
|
|
%iv = phi i8 [ %iv.next, %latch ], [ %start, %entry ]
|
|
%iv.next = add i8 %iv, 1
|
|
br i1 %c, label %latch, label %for.end
|
|
|
|
latch:
|
|
%zext = zext i8 %iv.next to i16
|
|
%cmp = icmp slt i16 %zext, 254
|
|
br i1 %cmp, label %for.body, label %for.end
|
|
|
|
for.end: ; preds = %for.body, %entry
|
|
ret void
|
|
}
|
|
|
|
define void @slt_non_constant_rhs(i16 %n) mustprogress {
|
|
; CHECK-LABEL: @slt_non_constant_rhs(
|
|
; CHECK-NEXT: entry:
|
|
; CHECK-NEXT: br label [[FOR_BODY:%.*]]
|
|
; CHECK: for.body:
|
|
; CHECK-NEXT: [[IV:%.*]] = phi i8 [ [[IV_NEXT:%.*]], [[FOR_BODY]] ], [ 0, [[ENTRY:%.*]] ]
|
|
; CHECK-NEXT: [[IV_NEXT]] = add i8 [[IV]], 1
|
|
; CHECK-NEXT: [[ZEXT:%.*]] = zext i8 [[IV_NEXT]] to i16
|
|
; CHECK-NEXT: [[CMP:%.*]] = icmp slt i16 [[ZEXT]], [[N:%.*]]
|
|
; CHECK-NEXT: br i1 [[CMP]], label [[FOR_BODY]], label [[FOR_END:%.*]]
|
|
; CHECK: for.end:
|
|
; CHECK-NEXT: ret void
|
|
;
|
|
entry:
|
|
br label %for.body
|
|
|
|
for.body: ; preds = %entry, %for.body
|
|
%iv = phi i8 [ %iv.next, %for.body ], [ 0, %entry ]
|
|
%iv.next = add i8 %iv, 1
|
|
%zext = zext i8 %iv.next to i16
|
|
%cmp = icmp slt i16 %zext, %n
|
|
br i1 %cmp, label %for.body, label %for.end
|
|
|
|
for.end: ; preds = %for.body, %entry
|
|
ret void
|
|
}
|
|
|
|
; Case where we could prove this using range facts, but not must exit reasoning
|
|
define void @slt_non_constant_rhs_no_mustprogress(i16 %n.raw) {
|
|
; CHECK-LABEL: @slt_non_constant_rhs_no_mustprogress(
|
|
; CHECK-NEXT: entry:
|
|
; CHECK-NEXT: [[N:%.*]] = and i16 [[N_RAW:%.*]], 255
|
|
; CHECK-NEXT: [[SMAX:%.*]] = call i16 @llvm.smax.i16(i16 [[N]], i16 1)
|
|
; CHECK-NEXT: br label [[FOR_BODY:%.*]]
|
|
; CHECK: for.body:
|
|
; CHECK-NEXT: [[INDVARS_IV:%.*]] = phi i16 [ [[INDVARS_IV_NEXT:%.*]], [[FOR_BODY]] ], [ 0, [[ENTRY:%.*]] ]
|
|
; CHECK-NEXT: [[INDVARS_IV_NEXT]] = add nuw nsw i16 [[INDVARS_IV]], 1
|
|
; CHECK-NEXT: [[EXITCOND:%.*]] = icmp ne i16 [[INDVARS_IV_NEXT]], [[SMAX]]
|
|
; CHECK-NEXT: br i1 [[EXITCOND]], label [[FOR_BODY]], label [[FOR_END:%.*]]
|
|
; CHECK: for.end:
|
|
; CHECK-NEXT: ret void
|
|
;
|
|
entry:
|
|
%n = and i16 %n.raw, 255
|
|
br label %for.body
|
|
|
|
for.body: ; preds = %entry, %for.body
|
|
%iv = phi i8 [ %iv.next, %for.body ], [ 0, %entry ]
|
|
%iv.next = add i8 %iv, 1
|
|
%zext = zext i8 %iv.next to i16
|
|
%cmp = icmp slt i16 %zext, %n
|
|
br i1 %cmp, label %for.body, label %for.end
|
|
|
|
for.end: ; preds = %for.body, %entry
|
|
ret void
|
|
}
|
|
|
|
; Fact holds for exiting branch, but not for earlier use
|
|
; We could recognize the unreachable loop here, but don't currently. Its
|
|
; also not terribly interesting, because EarlyCSE will fold condition.
|
|
define void @slt_neg_multiple_use(i8 %start) mustprogress {
|
|
; CHECK-LABEL: @slt_neg_multiple_use(
|
|
; CHECK-NEXT: entry:
|
|
; CHECK-NEXT: [[ZEXT:%.*]] = zext i8 [[START:%.*]] to i16
|
|
; CHECK-NEXT: [[CMP:%.*]] = icmp slt i16 [[ZEXT]], 254
|
|
; CHECK-NEXT: br i1 [[CMP]], label [[FOR_BODY_PREHEADER:%.*]], label [[FOR_END:%.*]]
|
|
; CHECK: for.body.preheader:
|
|
; CHECK-NEXT: br label [[FOR_BODY:%.*]]
|
|
; CHECK: for.body:
|
|
; CHECK-NEXT: br i1 [[CMP]], label [[FOR_BODY]], label [[FOR_END_LOOPEXIT:%.*]]
|
|
; CHECK: for.end.loopexit:
|
|
; CHECK-NEXT: br label [[FOR_END]]
|
|
; CHECK: for.end:
|
|
; CHECK-NEXT: ret void
|
|
;
|
|
entry:
|
|
%zext = zext i8 %start to i16
|
|
%cmp = icmp slt i16 %zext, 254
|
|
br i1 %cmp, label %for.body, label %for.end
|
|
|
|
for.body: ; preds = %entry, %for.body
|
|
br i1 %cmp, label %for.body, label %for.end
|
|
|
|
for.end: ; preds = %for.body, %entry
|
|
ret void
|
|
}
|
|
|
|
define void @slt_neg_multiple_use2(i8 %start, i16 %n) mustprogress {
|
|
; CHECK-LABEL: @slt_neg_multiple_use2(
|
|
; CHECK-NEXT: entry:
|
|
; CHECK-NEXT: [[ZEXT:%.*]] = zext i8 [[START:%.*]] to i16
|
|
; CHECK-NEXT: [[CMP:%.*]] = icmp slt i16 [[ZEXT]], [[N:%.*]]
|
|
; CHECK-NEXT: br i1 [[CMP]], label [[FOR_BODY_PREHEADER:%.*]], label [[FOR_END:%.*]]
|
|
; CHECK: for.body.preheader:
|
|
; CHECK-NEXT: br label [[FOR_BODY:%.*]]
|
|
; CHECK: for.body:
|
|
; CHECK-NEXT: br i1 [[CMP]], label [[FOR_BODY]], label [[FOR_END_LOOPEXIT:%.*]]
|
|
; CHECK: for.end.loopexit:
|
|
; CHECK-NEXT: br label [[FOR_END]]
|
|
; CHECK: for.end:
|
|
; CHECK-NEXT: ret void
|
|
;
|
|
entry:
|
|
%zext = zext i8 %start to i16
|
|
%cmp = icmp slt i16 %zext, %n
|
|
br i1 %cmp, label %for.body, label %for.end
|
|
|
|
for.body: ; preds = %entry, %for.body
|
|
br i1 %cmp, label %for.body, label %for.end
|
|
|
|
for.end: ; preds = %for.body, %entry
|
|
ret void
|
|
}
|
|
|
|
@G = external global i8
|
|
|
|
; Negative case where the loop could be infinite and make progress
|
|
define void @slt_neg_well_defined_infinite(i16 %n) mustprogress {
|
|
; CHECK-LABEL: @slt_neg_well_defined_infinite(
|
|
; CHECK-NEXT: entry:
|
|
; CHECK-NEXT: br label [[FOR_BODY:%.*]]
|
|
; CHECK: for.body:
|
|
; CHECK-NEXT: [[IV:%.*]] = phi i8 [ [[IV_NEXT:%.*]], [[FOR_BODY]] ], [ 0, [[ENTRY:%.*]] ]
|
|
; CHECK-NEXT: store volatile i8 [[IV]], ptr @G, align 1
|
|
; CHECK-NEXT: [[IV_NEXT]] = add i8 [[IV]], 1
|
|
; CHECK-NEXT: [[ZEXT:%.*]] = zext i8 [[IV_NEXT]] to i16
|
|
; CHECK-NEXT: [[CMP:%.*]] = icmp slt i16 [[ZEXT]], [[N:%.*]]
|
|
; CHECK-NEXT: br i1 [[CMP]], label [[FOR_BODY]], label [[FOR_END:%.*]]
|
|
; CHECK: for.end:
|
|
; CHECK-NEXT: ret void
|
|
;
|
|
entry:
|
|
br label %for.body
|
|
|
|
for.body: ; preds = %entry, %for.body
|
|
%iv = phi i8 [ %iv.next, %for.body ], [ 0, %entry ]
|
|
store volatile i8 %iv, ptr @G
|
|
%iv.next = add i8 %iv, 1
|
|
%zext = zext i8 %iv.next to i16
|
|
%cmp = icmp slt i16 %zext, %n
|
|
br i1 %cmp, label %for.body, label %for.end
|
|
|
|
for.end: ; preds = %for.body, %entry
|
|
ret void
|
|
}
|
|
|
|
; Negative case with no mustprogress rsltuirement
|
|
define void @slt_neg_no_mustprogress(i16 %n) {
|
|
; CHECK-LABEL: @slt_neg_no_mustprogress(
|
|
; CHECK-NEXT: entry:
|
|
; CHECK-NEXT: br label [[FOR_BODY:%.*]]
|
|
; CHECK: for.body:
|
|
; CHECK-NEXT: [[IV:%.*]] = phi i8 [ [[IV_NEXT:%.*]], [[FOR_BODY]] ], [ 0, [[ENTRY:%.*]] ]
|
|
; CHECK-NEXT: [[IV_NEXT]] = add i8 [[IV]], 1
|
|
; CHECK-NEXT: [[ZEXT:%.*]] = zext i8 [[IV_NEXT]] to i16
|
|
; CHECK-NEXT: [[CMP:%.*]] = icmp slt i16 [[ZEXT]], [[N:%.*]]
|
|
; CHECK-NEXT: br i1 [[CMP]], label [[FOR_BODY]], label [[FOR_END:%.*]]
|
|
; CHECK: for.end:
|
|
; CHECK-NEXT: ret void
|
|
;
|
|
entry:
|
|
br label %for.body
|
|
|
|
for.body: ; preds = %entry, %for.body
|
|
%iv = phi i8 [ %iv.next, %for.body ], [ 0, %entry ]
|
|
%iv.next = add i8 %iv, 1
|
|
%zext = zext i8 %iv.next to i16
|
|
%cmp = icmp slt i16 %zext, %n
|
|
br i1 %cmp, label %for.body, label %for.end
|
|
|
|
for.end: ; preds = %for.body, %entry
|
|
ret void
|
|
}
|
|
|
|
declare void @unknown()
|
|
|
|
define void @slt_neg_abnormal_exit(i16 %n) mustprogress {
|
|
; CHECK-LABEL: @slt_neg_abnormal_exit(
|
|
; CHECK-NEXT: entry:
|
|
; CHECK-NEXT: br label [[FOR_BODY:%.*]]
|
|
; CHECK: for.body:
|
|
; CHECK-NEXT: [[IV:%.*]] = phi i8 [ [[IV_NEXT:%.*]], [[FOR_BODY]] ], [ 0, [[ENTRY:%.*]] ]
|
|
; CHECK-NEXT: [[IV_NEXT]] = add i8 [[IV]], 1
|
|
; CHECK-NEXT: call void @unknown()
|
|
; CHECK-NEXT: [[ZEXT:%.*]] = zext i8 [[IV_NEXT]] to i16
|
|
; CHECK-NEXT: [[CMP:%.*]] = icmp slt i16 [[ZEXT]], [[N:%.*]]
|
|
; CHECK-NEXT: br i1 [[CMP]], label [[FOR_BODY]], label [[FOR_END:%.*]]
|
|
; CHECK: for.end:
|
|
; CHECK-NEXT: ret void
|
|
;
|
|
entry:
|
|
br label %for.body
|
|
|
|
for.body: ; preds = %entry, %for.body
|
|
%iv = phi i8 [ %iv.next, %for.body ], [ 0, %entry ]
|
|
%iv.next = add i8 %iv, 1
|
|
call void @unknown()
|
|
%zext = zext i8 %iv.next to i16
|
|
%cmp = icmp slt i16 %zext, %n
|
|
br i1 %cmp, label %for.body, label %for.end
|
|
|
|
for.end: ; preds = %for.body, %entry
|
|
ret void
|
|
}
|
|
|
|
; For the other comparison flavors, we only bother to repeat the positive
|
|
; tests since the negative variants are mostly the same.
|
|
|
|
define void @ne_constant_rhs(i16 %n.raw, i8 %start) mustprogress {
|
|
; CHECK-LABEL: @ne_constant_rhs(
|
|
; CHECK-NEXT: entry:
|
|
; CHECK-NEXT: br label [[FOR_BODY:%.*]]
|
|
; CHECK: for.body:
|
|
; CHECK-NEXT: [[IV:%.*]] = phi i8 [ [[IV_NEXT:%.*]], [[FOR_BODY]] ], [ [[START:%.*]], [[ENTRY:%.*]] ]
|
|
; CHECK-NEXT: [[IV_NEXT]] = add i8 [[IV]], 1
|
|
; CHECK-NEXT: [[ZEXT:%.*]] = zext i8 [[IV_NEXT]] to i16
|
|
; CHECK-NEXT: [[CMP:%.*]] = icmp ne i16 [[ZEXT]], 254
|
|
; CHECK-NEXT: br i1 [[CMP]], label [[FOR_BODY]], label [[FOR_END:%.*]]
|
|
; CHECK: for.end:
|
|
; CHECK-NEXT: ret void
|
|
;
|
|
entry:
|
|
br label %for.body
|
|
|
|
for.body: ; preds = %entry, %for.body
|
|
%iv = phi i8 [ %iv.next, %for.body ], [ %start, %entry ]
|
|
%iv.next = add i8 %iv, 1
|
|
%zext = zext i8 %iv.next to i16
|
|
%cmp = icmp ne i16 %zext, 254
|
|
br i1 %cmp, label %for.body, label %for.end
|
|
|
|
for.end: ; preds = %for.body, %entry
|
|
ret void
|
|
}
|
|
|
|
define void @ne_non_constant_rhs(i16 %n) mustprogress {
|
|
; CHECK-LABEL: @ne_non_constant_rhs(
|
|
; CHECK-NEXT: entry:
|
|
; CHECK-NEXT: br label [[FOR_BODY:%.*]]
|
|
; CHECK: for.body:
|
|
; CHECK-NEXT: [[IV:%.*]] = phi i8 [ [[IV_NEXT:%.*]], [[FOR_BODY]] ], [ 0, [[ENTRY:%.*]] ]
|
|
; CHECK-NEXT: [[IV_NEXT]] = add i8 [[IV]], 1
|
|
; CHECK-NEXT: [[ZEXT:%.*]] = zext i8 [[IV_NEXT]] to i16
|
|
; CHECK-NEXT: [[CMP:%.*]] = icmp ne i16 [[ZEXT]], [[N:%.*]]
|
|
; CHECK-NEXT: br i1 [[CMP]], label [[FOR_BODY]], label [[FOR_END:%.*]]
|
|
; CHECK: for.end:
|
|
; CHECK-NEXT: ret void
|
|
;
|
|
entry:
|
|
br label %for.body
|
|
|
|
for.body: ; preds = %entry, %for.body
|
|
%iv = phi i8 [ %iv.next, %for.body ], [ 0, %entry ]
|
|
%iv.next = add i8 %iv, 1
|
|
%zext = zext i8 %iv.next to i16
|
|
%cmp = icmp ne i16 %zext, %n
|
|
br i1 %cmp, label %for.body, label %for.end
|
|
|
|
for.end: ; preds = %for.body, %entry
|
|
ret void
|
|
}
|
|
|
|
define void @eq_constant_rhs(i16 %n.raw, i8 %start) mustprogress {
|
|
; CHECK-LABEL: @eq_constant_rhs(
|
|
; CHECK-NEXT: entry:
|
|
; CHECK-NEXT: br label [[FOR_BODY:%.*]]
|
|
; CHECK: for.body:
|
|
; CHECK-NEXT: [[IV:%.*]] = phi i8 [ [[IV_NEXT:%.*]], [[FOR_BODY]] ], [ [[START:%.*]], [[ENTRY:%.*]] ]
|
|
; CHECK-NEXT: [[IV_NEXT]] = add i8 [[IV]], 1
|
|
; CHECK-NEXT: [[ZEXT:%.*]] = zext i8 [[IV_NEXT]] to i16
|
|
; CHECK-NEXT: [[CMP:%.*]] = icmp eq i16 [[ZEXT]], 254
|
|
; CHECK-NEXT: br i1 [[CMP]], label [[FOR_BODY]], label [[FOR_END:%.*]]
|
|
; CHECK: for.end:
|
|
; CHECK-NEXT: ret void
|
|
;
|
|
entry:
|
|
br label %for.body
|
|
|
|
for.body: ; preds = %entry, %for.body
|
|
%iv = phi i8 [ %iv.next, %for.body ], [ %start, %entry ]
|
|
%iv.next = add i8 %iv, 1
|
|
%zext = zext i8 %iv.next to i16
|
|
%cmp = icmp eq i16 %zext, 254
|
|
br i1 %cmp, label %for.body, label %for.end
|
|
|
|
for.end: ; preds = %for.body, %entry
|
|
ret void
|
|
}
|
|
|
|
define void @eq_non_constant_rhs(i16 %n) mustprogress {
|
|
; CHECK-LABEL: @eq_non_constant_rhs(
|
|
; CHECK-NEXT: entry:
|
|
; CHECK-NEXT: br label [[FOR_BODY:%.*]]
|
|
; CHECK: for.body:
|
|
; CHECK-NEXT: [[IV:%.*]] = phi i8 [ [[IV_NEXT:%.*]], [[FOR_BODY]] ], [ 0, [[ENTRY:%.*]] ]
|
|
; CHECK-NEXT: [[IV_NEXT]] = add i8 [[IV]], 1
|
|
; CHECK-NEXT: [[ZEXT:%.*]] = zext i8 [[IV_NEXT]] to i16
|
|
; CHECK-NEXT: [[CMP:%.*]] = icmp eq i16 [[ZEXT]], [[N:%.*]]
|
|
; CHECK-NEXT: br i1 [[CMP]], label [[FOR_BODY]], label [[FOR_END:%.*]]
|
|
; CHECK: for.end:
|
|
; CHECK-NEXT: ret void
|
|
;
|
|
entry:
|
|
br label %for.body
|
|
|
|
for.body: ; preds = %entry, %for.body
|
|
%iv = phi i8 [ %iv.next, %for.body ], [ 0, %entry ]
|
|
%iv.next = add i8 %iv, 1
|
|
%zext = zext i8 %iv.next to i16
|
|
%cmp = icmp eq i16 %zext, %n
|
|
br i1 %cmp, label %for.body, label %for.end
|
|
|
|
for.end: ; preds = %for.body, %entry
|
|
ret void
|
|
}
|
|
|
|
define void @sgt_constant_rhs(i16 %n.raw, i8 %start) mustprogress {
|
|
; CHECK-LABEL: @sgt_constant_rhs(
|
|
; CHECK-NEXT: entry:
|
|
; CHECK-NEXT: [[TMP0:%.*]] = trunc i16 254 to i8
|
|
; CHECK-NEXT: br label [[FOR_BODY:%.*]]
|
|
; CHECK: for.body:
|
|
; CHECK-NEXT: [[IV:%.*]] = phi i8 [ [[IV_NEXT:%.*]], [[FOR_BODY]] ], [ [[START:%.*]], [[ENTRY:%.*]] ]
|
|
; CHECK-NEXT: [[IV_NEXT]] = add i8 [[IV]], 1
|
|
; CHECK-NEXT: [[CMP:%.*]] = icmp ugt i8 [[IV_NEXT]], [[TMP0]]
|
|
; CHECK-NEXT: br i1 [[CMP]], label [[FOR_BODY]], label [[FOR_END:%.*]]
|
|
; CHECK: for.end:
|
|
; CHECK-NEXT: ret void
|
|
;
|
|
entry:
|
|
br label %for.body
|
|
|
|
for.body: ; preds = %entry, %for.body
|
|
%iv = phi i8 [ %iv.next, %for.body ], [ %start, %entry ]
|
|
%iv.next = add i8 %iv, 1
|
|
%zext = zext i8 %iv.next to i16
|
|
%cmp = icmp sgt i16 %zext, 254
|
|
br i1 %cmp, label %for.body, label %for.end
|
|
|
|
for.end: ; preds = %for.body, %entry
|
|
ret void
|
|
}
|
|
|
|
define void @sgt_non_constant_rhs(i16 %n) mustprogress {
|
|
; CHECK-LABEL: @sgt_non_constant_rhs(
|
|
; CHECK-NEXT: entry:
|
|
; CHECK-NEXT: br label [[FOR_BODY:%.*]]
|
|
; CHECK: for.body:
|
|
; CHECK-NEXT: [[IV:%.*]] = phi i8 [ [[IV_NEXT:%.*]], [[FOR_BODY]] ], [ 0, [[ENTRY:%.*]] ]
|
|
; CHECK-NEXT: [[IV_NEXT]] = add i8 [[IV]], 1
|
|
; CHECK-NEXT: [[ZEXT:%.*]] = zext i8 [[IV_NEXT]] to i16
|
|
; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i16 [[ZEXT]], [[N:%.*]]
|
|
; CHECK-NEXT: br i1 [[CMP]], label [[FOR_BODY]], label [[FOR_END:%.*]]
|
|
; CHECK: for.end:
|
|
; CHECK-NEXT: ret void
|
|
;
|
|
entry:
|
|
br label %for.body
|
|
|
|
for.body: ; preds = %entry, %for.body
|
|
%iv = phi i8 [ %iv.next, %for.body ], [ 0, %entry ]
|
|
%iv.next = add i8 %iv, 1
|
|
%zext = zext i8 %iv.next to i16
|
|
%cmp = icmp sgt i16 %zext, %n
|
|
br i1 %cmp, label %for.body, label %for.end
|
|
|
|
for.end: ; preds = %for.body, %entry
|
|
ret void
|
|
}
|
|
|
|
define void @sle_constant_rhs(i16 %n.raw, i8 %start) mustprogress {
|
|
; CHECK-LABEL: @sle_constant_rhs(
|
|
; CHECK-NEXT: entry:
|
|
; CHECK-NEXT: [[TMP0:%.*]] = trunc i16 254 to i8
|
|
; CHECK-NEXT: br label [[FOR_BODY:%.*]]
|
|
; CHECK: for.body:
|
|
; CHECK-NEXT: [[IV:%.*]] = phi i8 [ [[IV_NEXT:%.*]], [[FOR_BODY]] ], [ [[START:%.*]], [[ENTRY:%.*]] ]
|
|
; CHECK-NEXT: [[IV_NEXT]] = add i8 [[IV]], 1
|
|
; CHECK-NEXT: [[CMP:%.*]] = icmp ule i8 [[IV_NEXT]], [[TMP0]]
|
|
; CHECK-NEXT: br i1 [[CMP]], label [[FOR_BODY]], label [[FOR_END:%.*]]
|
|
; CHECK: for.end:
|
|
; CHECK-NEXT: ret void
|
|
;
|
|
entry:
|
|
br label %for.body
|
|
|
|
for.body: ; preds = %entry, %for.body
|
|
%iv = phi i8 [ %iv.next, %for.body ], [ %start, %entry ]
|
|
%iv.next = add i8 %iv, 1
|
|
%zext = zext i8 %iv.next to i16
|
|
%cmp = icmp sle i16 %zext, 254
|
|
br i1 %cmp, label %for.body, label %for.end
|
|
|
|
for.end: ; preds = %for.body, %entry
|
|
ret void
|
|
}
|
|
|
|
define void @sle_non_constant_rhs(i16 %n) mustprogress {
|
|
; CHECK-LABEL: @sle_non_constant_rhs(
|
|
; CHECK-NEXT: entry:
|
|
; CHECK-NEXT: br label [[FOR_BODY:%.*]]
|
|
; CHECK: for.body:
|
|
; CHECK-NEXT: [[IV:%.*]] = phi i8 [ [[IV_NEXT:%.*]], [[FOR_BODY]] ], [ 0, [[ENTRY:%.*]] ]
|
|
; CHECK-NEXT: [[IV_NEXT]] = add i8 [[IV]], 1
|
|
; CHECK-NEXT: [[ZEXT:%.*]] = zext i8 [[IV_NEXT]] to i16
|
|
; CHECK-NEXT: [[CMP:%.*]] = icmp sle i16 [[ZEXT]], [[N:%.*]]
|
|
; CHECK-NEXT: br i1 [[CMP]], label [[FOR_BODY]], label [[FOR_END:%.*]]
|
|
; CHECK: for.end:
|
|
; CHECK-NEXT: ret void
|
|
;
|
|
entry:
|
|
br label %for.body
|
|
|
|
for.body: ; preds = %entry, %for.body
|
|
%iv = phi i8 [ %iv.next, %for.body ], [ 0, %entry ]
|
|
%iv.next = add i8 %iv, 1
|
|
%zext = zext i8 %iv.next to i16
|
|
%cmp = icmp sle i16 %zext, %n
|
|
br i1 %cmp, label %for.body, label %for.end
|
|
|
|
for.end: ; preds = %for.body, %entry
|
|
ret void
|
|
}
|
|
|
|
define void @sge_constant_rhs(i16 %n.raw, i8 %start) mustprogress {
|
|
; CHECK-LABEL: @sge_constant_rhs(
|
|
; CHECK-NEXT: entry:
|
|
; CHECK-NEXT: [[TMP0:%.*]] = trunc i16 254 to i8
|
|
; CHECK-NEXT: br label [[FOR_BODY:%.*]]
|
|
; CHECK: for.body:
|
|
; CHECK-NEXT: [[IV:%.*]] = phi i8 [ [[IV_NEXT:%.*]], [[FOR_BODY]] ], [ [[START:%.*]], [[ENTRY:%.*]] ]
|
|
; CHECK-NEXT: [[IV_NEXT]] = add i8 [[IV]], 1
|
|
; CHECK-NEXT: [[CMP:%.*]] = icmp uge i8 [[IV_NEXT]], [[TMP0]]
|
|
; CHECK-NEXT: br i1 [[CMP]], label [[FOR_BODY]], label [[FOR_END:%.*]]
|
|
; CHECK: for.end:
|
|
; CHECK-NEXT: ret void
|
|
;
|
|
entry:
|
|
br label %for.body
|
|
|
|
for.body: ; preds = %entry, %for.body
|
|
%iv = phi i8 [ %iv.next, %for.body ], [ %start, %entry ]
|
|
%iv.next = add i8 %iv, 1
|
|
%zext = zext i8 %iv.next to i16
|
|
%cmp = icmp sge i16 %zext, 254
|
|
br i1 %cmp, label %for.body, label %for.end
|
|
|
|
for.end: ; preds = %for.body, %entry
|
|
ret void
|
|
}
|
|
|
|
define void @sge_non_constant_rhs(i16 %n) mustprogress {
|
|
; CHECK-LABEL: @sge_non_constant_rhs(
|
|
; CHECK-NEXT: entry:
|
|
; CHECK-NEXT: br label [[FOR_BODY:%.*]]
|
|
; CHECK: for.body:
|
|
; CHECK-NEXT: [[IV:%.*]] = phi i8 [ [[IV_NEXT:%.*]], [[FOR_BODY]] ], [ 0, [[ENTRY:%.*]] ]
|
|
; CHECK-NEXT: [[IV_NEXT]] = add i8 [[IV]], 1
|
|
; CHECK-NEXT: [[ZEXT:%.*]] = zext i8 [[IV_NEXT]] to i16
|
|
; CHECK-NEXT: [[CMP:%.*]] = icmp sge i16 [[ZEXT]], [[N:%.*]]
|
|
; CHECK-NEXT: br i1 [[CMP]], label [[FOR_BODY]], label [[FOR_END:%.*]]
|
|
; CHECK: for.end:
|
|
; CHECK-NEXT: ret void
|
|
;
|
|
entry:
|
|
br label %for.body
|
|
|
|
for.body: ; preds = %entry, %for.body
|
|
%iv = phi i8 [ %iv.next, %for.body ], [ 0, %entry ]
|
|
%iv.next = add i8 %iv, 1
|
|
%zext = zext i8 %iv.next to i16
|
|
%cmp = icmp sge i16 %zext, %n
|
|
br i1 %cmp, label %for.body, label %for.end
|
|
|
|
for.end: ; preds = %for.body, %entry
|
|
ret void
|
|
}
|
|
|
|
define void @ult_constant_rhs(i16 %n.raw, i8 %start) mustprogress {
|
|
; CHECK-LABEL: @ult_constant_rhs(
|
|
; CHECK-NEXT: entry:
|
|
; CHECK-NEXT: [[TMP0:%.*]] = trunc i16 254 to i8
|
|
; CHECK-NEXT: br label [[FOR_BODY:%.*]]
|
|
; CHECK: for.body:
|
|
; CHECK-NEXT: [[IV:%.*]] = phi i8 [ [[IV_NEXT:%.*]], [[FOR_BODY]] ], [ [[START:%.*]], [[ENTRY:%.*]] ]
|
|
; CHECK-NEXT: [[IV_NEXT]] = add i8 [[IV]], 1
|
|
; CHECK-NEXT: [[CMP:%.*]] = icmp ult i8 [[IV_NEXT]], [[TMP0]]
|
|
; CHECK-NEXT: br i1 [[CMP]], label [[FOR_BODY]], label [[FOR_END:%.*]]
|
|
; CHECK: for.end:
|
|
; CHECK-NEXT: ret void
|
|
;
|
|
entry:
|
|
br label %for.body
|
|
|
|
for.body: ; preds = %entry, %for.body
|
|
%iv = phi i8 [ %iv.next, %for.body ], [ %start, %entry ]
|
|
%iv.next = add i8 %iv, 1
|
|
%zext = zext i8 %iv.next to i16
|
|
%cmp = icmp ult i16 %zext, 254
|
|
br i1 %cmp, label %for.body, label %for.end
|
|
|
|
for.end: ; preds = %for.body, %entry
|
|
ret void
|
|
}
|
|
|
|
define void @ult_non_constant_rhs(i16 %n) mustprogress {
|
|
; CHECK-LABEL: @ult_non_constant_rhs(
|
|
; CHECK-NEXT: entry:
|
|
; CHECK-NEXT: br label [[FOR_BODY:%.*]]
|
|
; CHECK: for.body:
|
|
; CHECK-NEXT: [[IV:%.*]] = phi i8 [ [[IV_NEXT:%.*]], [[FOR_BODY]] ], [ 0, [[ENTRY:%.*]] ]
|
|
; CHECK-NEXT: [[IV_NEXT]] = add i8 [[IV]], 1
|
|
; CHECK-NEXT: [[ZEXT:%.*]] = zext i8 [[IV_NEXT]] to i16
|
|
; CHECK-NEXT: [[CMP:%.*]] = icmp ult i16 [[ZEXT]], [[N:%.*]]
|
|
; CHECK-NEXT: br i1 [[CMP]], label [[FOR_BODY]], label [[FOR_END:%.*]]
|
|
; CHECK: for.end:
|
|
; CHECK-NEXT: ret void
|
|
;
|
|
entry:
|
|
br label %for.body
|
|
|
|
for.body: ; preds = %entry, %for.body
|
|
%iv = phi i8 [ %iv.next, %for.body ], [ 0, %entry ]
|
|
%iv.next = add i8 %iv, 1
|
|
%zext = zext i8 %iv.next to i16
|
|
%cmp = icmp ult i16 %zext, %n
|
|
br i1 %cmp, label %for.body, label %for.end
|
|
|
|
for.end: ; preds = %for.body, %entry
|
|
ret void
|
|
}
|
|
|
|
define void @ugt_constant_rhs(i16 %n.raw, i8 %start) mustprogress {
|
|
; CHECK-LABEL: @ugt_constant_rhs(
|
|
; CHECK-NEXT: entry:
|
|
; CHECK-NEXT: [[TMP0:%.*]] = trunc i16 254 to i8
|
|
; CHECK-NEXT: br label [[FOR_BODY:%.*]]
|
|
; CHECK: for.body:
|
|
; CHECK-NEXT: [[IV:%.*]] = phi i8 [ [[IV_NEXT:%.*]], [[FOR_BODY]] ], [ [[START:%.*]], [[ENTRY:%.*]] ]
|
|
; CHECK-NEXT: [[IV_NEXT]] = add i8 [[IV]], 1
|
|
; CHECK-NEXT: [[CMP:%.*]] = icmp ugt i8 [[IV_NEXT]], [[TMP0]]
|
|
; CHECK-NEXT: br i1 [[CMP]], label [[FOR_BODY]], label [[FOR_END:%.*]]
|
|
; CHECK: for.end:
|
|
; CHECK-NEXT: ret void
|
|
;
|
|
entry:
|
|
br label %for.body
|
|
|
|
for.body: ; preds = %entry, %for.body
|
|
%iv = phi i8 [ %iv.next, %for.body ], [ %start, %entry ]
|
|
%iv.next = add i8 %iv, 1
|
|
%zext = zext i8 %iv.next to i16
|
|
%cmp = icmp ugt i16 %zext, 254
|
|
br i1 %cmp, label %for.body, label %for.end
|
|
|
|
for.end: ; preds = %for.body, %entry
|
|
ret void
|
|
}
|
|
|
|
define void @ugt_neg_non_loop(i16 %n.raw, i8 %start) mustprogress {
|
|
; CHECK-LABEL: @ugt_neg_non_loop(
|
|
; CHECK-NEXT: entry:
|
|
; CHECK-NEXT: br label [[FOR_BODY:%.*]]
|
|
; CHECK: for.body:
|
|
; CHECK-NEXT: [[IV:%.*]] = phi i8 [ [[IV_NEXT:%.*]], [[FOR_BODY]] ], [ [[START:%.*]], [[ENTRY:%.*]] ]
|
|
; CHECK-NEXT: [[IV_NEXT]] = add i8 [[IV]], 1
|
|
; CHECK-NEXT: [[ZEXT:%.*]] = zext i8 [[IV_NEXT]] to i16
|
|
; CHECK-NEXT: [[CMP:%.*]] = icmp ugt i16 [[ZEXT]], -2
|
|
; CHECK-NEXT: br i1 [[CMP]], label [[FOR_BODY]], label [[FOR_END:%.*]]
|
|
; CHECK: for.end:
|
|
; CHECK-NEXT: ret void
|
|
;
|
|
entry:
|
|
br label %for.body
|
|
|
|
for.body: ; preds = %entry, %for.body
|
|
%iv = phi i8 [ %iv.next, %for.body ], [ %start, %entry ]
|
|
%iv.next = add i8 %iv, 1
|
|
%zext = zext i8 %iv.next to i16
|
|
%cmp = icmp ugt i16 %zext, -2
|
|
br i1 %cmp, label %for.body, label %for.end
|
|
|
|
for.end: ; preds = %for.body, %entry
|
|
ret void
|
|
}
|
|
|
|
define void @ugt_non_constant_rhs(i16 %n) mustprogress {
|
|
; CHECK-LABEL: @ugt_non_constant_rhs(
|
|
; CHECK-NEXT: entry:
|
|
; CHECK-NEXT: br label [[FOR_BODY:%.*]]
|
|
; CHECK: for.body:
|
|
; CHECK-NEXT: [[IV:%.*]] = phi i8 [ [[IV_NEXT:%.*]], [[FOR_BODY]] ], [ 0, [[ENTRY:%.*]] ]
|
|
; CHECK-NEXT: [[IV_NEXT]] = add i8 [[IV]], 1
|
|
; CHECK-NEXT: [[ZEXT:%.*]] = zext i8 [[IV_NEXT]] to i16
|
|
; CHECK-NEXT: [[CMP:%.*]] = icmp ugt i16 [[ZEXT]], [[N:%.*]]
|
|
; CHECK-NEXT: br i1 [[CMP]], label [[FOR_BODY]], label [[FOR_END:%.*]]
|
|
; CHECK: for.end:
|
|
; CHECK-NEXT: ret void
|
|
;
|
|
entry:
|
|
br label %for.body
|
|
|
|
for.body: ; preds = %entry, %for.body
|
|
%iv = phi i8 [ %iv.next, %for.body ], [ 0, %entry ]
|
|
%iv.next = add i8 %iv, 1
|
|
%zext = zext i8 %iv.next to i16
|
|
%cmp = icmp ugt i16 %zext, %n
|
|
br i1 %cmp, label %for.body, label %for.end
|
|
|
|
for.end: ; preds = %for.body, %entry
|
|
ret void
|
|
}
|
|
|
|
define void @ule_constant_rhs(i16 %n.raw, i8 %start) mustprogress {
|
|
; CHECK-LABEL: @ule_constant_rhs(
|
|
; CHECK-NEXT: entry:
|
|
; CHECK-NEXT: [[TMP0:%.*]] = trunc i16 254 to i8
|
|
; CHECK-NEXT: br label [[FOR_BODY:%.*]]
|
|
; CHECK: for.body:
|
|
; CHECK-NEXT: [[IV:%.*]] = phi i8 [ [[IV_NEXT:%.*]], [[FOR_BODY]] ], [ [[START:%.*]], [[ENTRY:%.*]] ]
|
|
; CHECK-NEXT: [[IV_NEXT]] = add i8 [[IV]], 1
|
|
; CHECK-NEXT: [[CMP:%.*]] = icmp ule i8 [[IV_NEXT]], [[TMP0]]
|
|
; CHECK-NEXT: br i1 [[CMP]], label [[FOR_BODY]], label [[FOR_END:%.*]]
|
|
; CHECK: for.end:
|
|
; CHECK-NEXT: ret void
|
|
;
|
|
entry:
|
|
br label %for.body
|
|
|
|
for.body: ; preds = %entry, %for.body
|
|
%iv = phi i8 [ %iv.next, %for.body ], [ %start, %entry ]
|
|
%iv.next = add i8 %iv, 1
|
|
%zext = zext i8 %iv.next to i16
|
|
%cmp = icmp ule i16 %zext, 254
|
|
br i1 %cmp, label %for.body, label %for.end
|
|
|
|
for.end: ; preds = %for.body, %entry
|
|
ret void
|
|
}
|
|
|
|
define void @ule_non_constant_rhs(i16 %n) mustprogress {
|
|
; CHECK-LABEL: @ule_non_constant_rhs(
|
|
; CHECK-NEXT: entry:
|
|
; CHECK-NEXT: br label [[FOR_BODY:%.*]]
|
|
; CHECK: for.body:
|
|
; CHECK-NEXT: [[IV:%.*]] = phi i8 [ [[IV_NEXT:%.*]], [[FOR_BODY]] ], [ 0, [[ENTRY:%.*]] ]
|
|
; CHECK-NEXT: [[IV_NEXT]] = add i8 [[IV]], 1
|
|
; CHECK-NEXT: [[ZEXT:%.*]] = zext i8 [[IV_NEXT]] to i16
|
|
; CHECK-NEXT: [[CMP:%.*]] = icmp ule i16 [[ZEXT]], [[N:%.*]]
|
|
; CHECK-NEXT: br i1 [[CMP]], label [[FOR_BODY]], label [[FOR_END:%.*]]
|
|
; CHECK: for.end:
|
|
; CHECK-NEXT: ret void
|
|
;
|
|
entry:
|
|
br label %for.body
|
|
|
|
for.body: ; preds = %entry, %for.body
|
|
%iv = phi i8 [ %iv.next, %for.body ], [ 0, %entry ]
|
|
%iv.next = add i8 %iv, 1
|
|
%zext = zext i8 %iv.next to i16
|
|
%cmp = icmp ule i16 %zext, %n
|
|
br i1 %cmp, label %for.body, label %for.end
|
|
|
|
for.end: ; preds = %for.body, %entry
|
|
ret void
|
|
}
|
|
|
|
define void @uge_constant_rhs(i16 %n.raw, i8 %start) mustprogress {
|
|
; CHECK-LABEL: @uge_constant_rhs(
|
|
; CHECK-NEXT: entry:
|
|
; CHECK-NEXT: [[TMP0:%.*]] = trunc i16 254 to i8
|
|
; CHECK-NEXT: br label [[FOR_BODY:%.*]]
|
|
; CHECK: for.body:
|
|
; CHECK-NEXT: [[IV:%.*]] = phi i8 [ [[IV_NEXT:%.*]], [[FOR_BODY]] ], [ [[START:%.*]], [[ENTRY:%.*]] ]
|
|
; CHECK-NEXT: [[IV_NEXT]] = add i8 [[IV]], 1
|
|
; CHECK-NEXT: [[CMP:%.*]] = icmp uge i8 [[IV_NEXT]], [[TMP0]]
|
|
; CHECK-NEXT: br i1 [[CMP]], label [[FOR_BODY]], label [[FOR_END:%.*]]
|
|
; CHECK: for.end:
|
|
; CHECK-NEXT: ret void
|
|
;
|
|
entry:
|
|
br label %for.body
|
|
|
|
for.body: ; preds = %entry, %for.body
|
|
%iv = phi i8 [ %iv.next, %for.body ], [ %start, %entry ]
|
|
%iv.next = add i8 %iv, 1
|
|
%zext = zext i8 %iv.next to i16
|
|
%cmp = icmp uge i16 %zext, 254
|
|
br i1 %cmp, label %for.body, label %for.end
|
|
|
|
for.end: ; preds = %for.body, %entry
|
|
ret void
|
|
}
|
|
|
|
define void @uge_non_constant_rhs(i16 %n) mustprogress {
|
|
; CHECK-LABEL: @uge_non_constant_rhs(
|
|
; CHECK-NEXT: entry:
|
|
; CHECK-NEXT: br label [[FOR_BODY:%.*]]
|
|
; CHECK: for.body:
|
|
; CHECK-NEXT: [[IV:%.*]] = phi i8 [ [[IV_NEXT:%.*]], [[FOR_BODY]] ], [ 0, [[ENTRY:%.*]] ]
|
|
; CHECK-NEXT: [[IV_NEXT]] = add i8 [[IV]], 1
|
|
; CHECK-NEXT: [[ZEXT:%.*]] = zext i8 [[IV_NEXT]] to i16
|
|
; CHECK-NEXT: [[CMP:%.*]] = icmp uge i16 [[ZEXT]], [[N:%.*]]
|
|
; CHECK-NEXT: br i1 [[CMP]], label [[FOR_BODY]], label [[FOR_END:%.*]]
|
|
; CHECK: for.end:
|
|
; CHECK-NEXT: ret void
|
|
;
|
|
entry:
|
|
br label %for.body
|
|
|
|
for.body: ; preds = %entry, %for.body
|
|
%iv = phi i8 [ %iv.next, %for.body ], [ 0, %entry ]
|
|
%iv.next = add i8 %iv, 1
|
|
%zext = zext i8 %iv.next to i16
|
|
%cmp = icmp uge i16 %zext, %n
|
|
br i1 %cmp, label %for.body, label %for.end
|
|
|
|
for.end: ; preds = %for.body, %entry
|
|
ret void
|
|
}
|
|
|
|
; Show that these transformatios also work with inverted operands
|
|
; We only both to do this with slt/ult, but it applies to all predicates.
|
|
|
|
define void @slt_constant_lhs(i16 %n.raw, i8 %start) mustprogress {
|
|
; CHECK-LABEL: @slt_constant_lhs(
|
|
; CHECK-NEXT: entry:
|
|
; CHECK-NEXT: [[TMP0:%.*]] = trunc i16 254 to i8
|
|
; CHECK-NEXT: br label [[FOR_BODY:%.*]]
|
|
; CHECK: for.body:
|
|
; CHECK-NEXT: [[IV:%.*]] = phi i8 [ [[IV_NEXT:%.*]], [[FOR_BODY]] ], [ [[START:%.*]], [[ENTRY:%.*]] ]
|
|
; CHECK-NEXT: [[IV_NEXT]] = add i8 [[IV]], 1
|
|
; CHECK-NEXT: [[CMP:%.*]] = icmp ult i8 [[TMP0]], [[IV_NEXT]]
|
|
; CHECK-NEXT: br i1 [[CMP]], label [[FOR_BODY]], label [[FOR_END:%.*]]
|
|
; CHECK: for.end:
|
|
; CHECK-NEXT: ret void
|
|
;
|
|
entry:
|
|
br label %for.body
|
|
|
|
for.body: ; preds = %entry, %for.body
|
|
%iv = phi i8 [ %iv.next, %for.body ], [ %start, %entry ]
|
|
%iv.next = add i8 %iv, 1
|
|
%zext = zext i8 %iv.next to i16
|
|
%cmp = icmp slt i16 254, %zext
|
|
br i1 %cmp, label %for.body, label %for.end
|
|
|
|
for.end: ; preds = %for.body, %entry
|
|
ret void
|
|
}
|
|
|
|
define void @slt_non_constant_lhs(i16 %n) mustprogress {
|
|
; CHECK-LABEL: @slt_non_constant_lhs(
|
|
; CHECK-NEXT: entry:
|
|
; CHECK-NEXT: br label [[FOR_BODY:%.*]]
|
|
; CHECK: for.body:
|
|
; CHECK-NEXT: [[IV:%.*]] = phi i8 [ [[IV_NEXT:%.*]], [[FOR_BODY]] ], [ 0, [[ENTRY:%.*]] ]
|
|
; CHECK-NEXT: [[IV_NEXT]] = add i8 [[IV]], 1
|
|
; CHECK-NEXT: [[ZEXT:%.*]] = zext i8 [[IV_NEXT]] to i16
|
|
; CHECK-NEXT: [[CMP:%.*]] = icmp slt i16 [[N:%.*]], [[ZEXT]]
|
|
; CHECK-NEXT: br i1 [[CMP]], label [[FOR_BODY]], label [[FOR_END:%.*]]
|
|
; CHECK: for.end:
|
|
; CHECK-NEXT: ret void
|
|
;
|
|
entry:
|
|
br label %for.body
|
|
|
|
for.body: ; preds = %entry, %for.body
|
|
%iv = phi i8 [ %iv.next, %for.body ], [ 0, %entry ]
|
|
%iv.next = add i8 %iv, 1
|
|
%zext = zext i8 %iv.next to i16
|
|
%cmp = icmp slt i16 %n, %zext
|
|
br i1 %cmp, label %for.body, label %for.end
|
|
|
|
for.end: ; preds = %for.body, %entry
|
|
ret void
|
|
}
|
|
|
|
define void @ult_constant_lhs(i16 %n.raw, i8 %start) mustprogress {
|
|
; CHECK-LABEL: @ult_constant_lhs(
|
|
; CHECK-NEXT: entry:
|
|
; CHECK-NEXT: [[TMP0:%.*]] = trunc i16 254 to i8
|
|
; CHECK-NEXT: br label [[FOR_BODY:%.*]]
|
|
; CHECK: for.body:
|
|
; CHECK-NEXT: [[IV:%.*]] = phi i8 [ [[IV_NEXT:%.*]], [[FOR_BODY]] ], [ [[START:%.*]], [[ENTRY:%.*]] ]
|
|
; CHECK-NEXT: [[IV_NEXT]] = add i8 [[IV]], 1
|
|
; CHECK-NEXT: [[CMP:%.*]] = icmp ult i8 [[TMP0]], [[IV_NEXT]]
|
|
; CHECK-NEXT: br i1 [[CMP]], label [[FOR_BODY]], label [[FOR_END:%.*]]
|
|
; CHECK: for.end:
|
|
; CHECK-NEXT: ret void
|
|
;
|
|
entry:
|
|
br label %for.body
|
|
|
|
for.body: ; preds = %entry, %for.body
|
|
%iv = phi i8 [ %iv.next, %for.body ], [ %start, %entry ]
|
|
%iv.next = add i8 %iv, 1
|
|
%zext = zext i8 %iv.next to i16
|
|
%cmp = icmp ult i16 254, %zext
|
|
br i1 %cmp, label %for.body, label %for.end
|
|
|
|
for.end: ; preds = %for.body, %entry
|
|
ret void
|
|
}
|
|
|
|
define void @ult_non_constant_lhs(i16 %n) mustprogress {
|
|
; CHECK-LABEL: @ult_non_constant_lhs(
|
|
; CHECK-NEXT: entry:
|
|
; CHECK-NEXT: br label [[FOR_BODY:%.*]]
|
|
; CHECK: for.body:
|
|
; CHECK-NEXT: [[IV:%.*]] = phi i8 [ [[IV_NEXT:%.*]], [[FOR_BODY]] ], [ 0, [[ENTRY:%.*]] ]
|
|
; CHECK-NEXT: [[IV_NEXT]] = add i8 [[IV]], 1
|
|
; CHECK-NEXT: [[ZEXT:%.*]] = zext i8 [[IV_NEXT]] to i16
|
|
; CHECK-NEXT: [[CMP:%.*]] = icmp ult i16 [[N:%.*]], [[ZEXT]]
|
|
; CHECK-NEXT: br i1 [[CMP]], label [[FOR_BODY]], label [[FOR_END:%.*]]
|
|
; CHECK: for.end:
|
|
; CHECK-NEXT: ret void
|
|
;
|
|
entry:
|
|
br label %for.body
|
|
|
|
for.body: ; preds = %entry, %for.body
|
|
%iv = phi i8 [ %iv.next, %for.body ], [ 0, %entry ]
|
|
%iv.next = add i8 %iv, 1
|
|
%zext = zext i8 %iv.next to i16
|
|
%cmp = icmp ult i16 %n, %zext
|
|
br i1 %cmp, label %for.body, label %for.end
|
|
|
|
for.end: ; preds = %for.body, %entry
|
|
ret void
|
|
}
|
|
|
|
define i16 @ult_multiuse_profit(i16 %n.raw, i8 %start) mustprogress {
|
|
; CHECK-LABEL: @ult_multiuse_profit(
|
|
; CHECK-NEXT: entry:
|
|
; CHECK-NEXT: [[TMP0:%.*]] = trunc i16 254 to i8
|
|
; CHECK-NEXT: br label [[FOR_BODY:%.*]]
|
|
; CHECK: for.body:
|
|
; CHECK-NEXT: [[IV:%.*]] = phi i8 [ [[IV_NEXT:%.*]], [[FOR_BODY]] ], [ [[START]], [[ENTRY:%.*]] ]
|
|
; CHECK-NEXT: [[IV_NEXT]] = add i8 [[IV]], 1
|
|
; CHECK-NEXT: [[CMP:%.*]] = icmp ult i8 [[IV_NEXT]], [[TMP0]]
|
|
; CHECK-NEXT: br i1 [[CMP]], label [[FOR_BODY]], label [[FOR_END:%.*]]
|
|
; CHECK: for.end:
|
|
; CHECK-NEXT: [[TMP1:%.*]] = add i8 [[START:%.*]], 1
|
|
; CHECK-NEXT: [[TMP2:%.*]] = zext i8 [[TMP1]] to i16
|
|
; CHECK-NEXT: [[UMAX:%.*]] = call i16 @llvm.umax.i16(i16 [[TMP2]], i16 254)
|
|
; CHECK-NEXT: ret i16 [[UMAX]]
|
|
;
|
|
entry:
|
|
br label %for.body
|
|
|
|
for.body: ; preds = %entry, %for.body
|
|
%iv = phi i8 [ %iv.next, %for.body ], [ %start, %entry ]
|
|
%iv.next = add i8 %iv, 1
|
|
%zext = zext i8 %iv.next to i16
|
|
%cmp = icmp ult i16 %zext, 254
|
|
br i1 %cmp, label %for.body, label %for.end
|
|
|
|
for.end: ; preds = %for.body, %entry
|
|
ret i16 %zext
|
|
}
|
|
|
|
define i16 @ult_multiuse_profit2(i16 %n.raw, i8 %start) mustprogress {
|
|
; CHECK-LABEL: @ult_multiuse_profit2(
|
|
; CHECK-NEXT: entry:
|
|
; CHECK-NEXT: [[TMP0:%.*]] = trunc i16 254 to i8
|
|
; CHECK-NEXT: br label [[FOR_BODY:%.*]]
|
|
; CHECK: for.body:
|
|
; CHECK-NEXT: [[IV:%.*]] = phi i8 [ [[IV_NEXT:%.*]], [[FOR_BODY]] ], [ [[START:%.*]], [[ENTRY:%.*]] ]
|
|
; CHECK-NEXT: [[IV2:%.*]] = phi i16 [ [[ZEXT:%.*]], [[FOR_BODY]] ], [ 0, [[ENTRY]] ]
|
|
; CHECK-NEXT: [[IV_NEXT]] = add i8 [[IV]], 1
|
|
; CHECK-NEXT: [[ZEXT]] = zext i8 [[IV_NEXT]] to i16
|
|
; CHECK-NEXT: [[CMP:%.*]] = icmp ult i8 [[IV_NEXT]], [[TMP0]]
|
|
; CHECK-NEXT: br i1 [[CMP]], label [[FOR_BODY]], label [[FOR_END:%.*]]
|
|
; CHECK: for.end:
|
|
; CHECK-NEXT: [[IV2_LCSSA:%.*]] = phi i16 [ [[IV2]], [[FOR_BODY]] ]
|
|
; CHECK-NEXT: ret i16 [[IV2_LCSSA]]
|
|
;
|
|
entry:
|
|
br label %for.body
|
|
|
|
for.body: ; preds = %entry, %for.body
|
|
%iv = phi i8 [ %iv.next, %for.body ], [ %start, %entry ]
|
|
%iv2 = phi i16 [%zext, %for.body], [0, %entry]
|
|
%iv.next = add i8 %iv, 1
|
|
%zext = zext i8 %iv.next to i16
|
|
%cmp = icmp ult i16 %zext, 254
|
|
br i1 %cmp, label %for.body, label %for.end
|
|
|
|
for.end: ; preds = %for.body, %entry
|
|
ret i16 %iv2
|
|
}
|
|
|
|
define void @slt_restricted_rhs(i16 %n.raw) mustprogress {
|
|
; CHECK-LABEL: @slt_restricted_rhs(
|
|
; CHECK-NEXT: entry:
|
|
; CHECK-NEXT: [[N:%.*]] = and i16 [[N_RAW:%.*]], 255
|
|
; CHECK-NEXT: [[SMAX:%.*]] = call i16 @llvm.smax.i16(i16 [[N]], i16 1)
|
|
; CHECK-NEXT: br label [[FOR_BODY:%.*]]
|
|
; CHECK: for.body:
|
|
; CHECK-NEXT: [[INDVARS_IV:%.*]] = phi i16 [ [[INDVARS_IV_NEXT:%.*]], [[FOR_BODY]] ], [ 0, [[ENTRY:%.*]] ]
|
|
; CHECK-NEXT: [[INDVARS_IV_NEXT]] = add nuw nsw i16 [[INDVARS_IV]], 1
|
|
; CHECK-NEXT: [[EXITCOND:%.*]] = icmp ne i16 [[INDVARS_IV_NEXT]], [[SMAX]]
|
|
; CHECK-NEXT: br i1 [[EXITCOND]], label [[FOR_BODY]], label [[FOR_END:%.*]]
|
|
; CHECK: for.end:
|
|
; CHECK-NEXT: ret void
|
|
;
|
|
entry:
|
|
%n = and i16 %n.raw, 255
|
|
br label %for.body
|
|
|
|
for.body: ; preds = %entry, %for.body
|
|
%iv = phi i8 [ %iv.next, %for.body ], [ 0, %entry ]
|
|
%iv.next = add i8 %iv, 1
|
|
%zext = zext i8 %iv.next to i16
|
|
%cmp = icmp slt i16 %zext, %n
|
|
br i1 %cmp, label %for.body, label %for.end
|
|
|
|
for.end: ; preds = %for.body, %entry
|
|
ret void
|
|
}
|
|
|
|
define void @slt_guarded_rhs(i16 %n) mustprogress {
|
|
; CHECK-LABEL: @slt_guarded_rhs(
|
|
; CHECK-NEXT: entry:
|
|
; CHECK-NEXT: [[IN_RANGE:%.*]] = icmp ult i16 [[N:%.*]], 256
|
|
; CHECK-NEXT: br i1 [[IN_RANGE]], label [[FOR_BODY_PREHEADER:%.*]], label [[FOR_END:%.*]]
|
|
; CHECK: for.body.preheader:
|
|
; CHECK-NEXT: [[TMP0:%.*]] = trunc i16 [[N]] to i8
|
|
; CHECK-NEXT: br label [[FOR_BODY:%.*]]
|
|
; CHECK: for.body:
|
|
; CHECK-NEXT: [[IV:%.*]] = phi i8 [ [[IV_NEXT:%.*]], [[FOR_BODY]] ], [ 0, [[FOR_BODY_PREHEADER]] ]
|
|
; CHECK-NEXT: [[IV_NEXT]] = add nuw i8 [[IV]], 1
|
|
; CHECK-NEXT: [[CMP:%.*]] = icmp ult i8 [[IV_NEXT]], [[TMP0]]
|
|
; CHECK-NEXT: br i1 [[CMP]], label [[FOR_BODY]], label [[FOR_END_LOOPEXIT:%.*]]
|
|
; CHECK: for.end.loopexit:
|
|
; CHECK-NEXT: br label [[FOR_END]]
|
|
; CHECK: for.end:
|
|
; CHECK-NEXT: ret void
|
|
;
|
|
entry:
|
|
%in_range = icmp ult i16 %n, 256
|
|
br i1 %in_range, label %for.body, label %for.end
|
|
|
|
for.body: ; preds = %entry, %for.body
|
|
%iv = phi i8 [ %iv.next, %for.body ], [ 0, %entry ]
|
|
%iv.next = add i8 %iv, 1
|
|
%zext = zext i8 %iv.next to i16
|
|
%cmp = icmp slt i16 %zext, %n
|
|
br i1 %cmp, label %for.body, label %for.end
|
|
|
|
for.end: ; preds = %for.body, %entry
|
|
ret void
|
|
}
|
|
|
|
define i8 @test_drop_icmp_samesign(i1 %cond, i32 range(i32 0, 32) %x) {
|
|
; CHECK-LABEL: @test_drop_icmp_samesign(
|
|
; CHECK-NEXT: entry:
|
|
; CHECK-NEXT: br i1 [[COND:%.*]], label [[FOR_BODY_PREHEADER:%.*]], label [[ELSE:%.*]]
|
|
; CHECK: for.body.preheader:
|
|
; CHECK-NEXT: [[TMP0:%.*]] = trunc i32 [[X:%.*]] to i8
|
|
; CHECK-NEXT: br label [[FOR_BODY:%.*]]
|
|
; CHECK: else:
|
|
; CHECK-NEXT: [[CALL1:%.*]] = call i8 @callee()
|
|
; CHECK-NEXT: br label [[EXIT:%.*]]
|
|
; CHECK: for.body:
|
|
; CHECK-NEXT: [[CALL2:%.*]] = call i8 @callee()
|
|
; CHECK-NEXT: [[COND2:%.*]] = icmp ugt i8 [[TMP0]], [[CALL2]]
|
|
; CHECK-NEXT: br i1 [[COND2]], label [[FOR_BODY]], label [[EXIT_LOOPEXIT:%.*]]
|
|
; CHECK: exit.loopexit:
|
|
; CHECK-NEXT: [[CALL2_LCSSA:%.*]] = phi i8 [ [[CALL2]], [[FOR_BODY]] ]
|
|
; CHECK-NEXT: br label [[EXIT]]
|
|
; CHECK: exit:
|
|
; CHECK-NEXT: [[RES:%.*]] = phi i8 [ [[CALL1]], [[ELSE]] ], [ [[CALL2_LCSSA]], [[EXIT_LOOPEXIT]] ]
|
|
; CHECK-NEXT: ret i8 [[RES]]
|
|
;
|
|
entry:
|
|
br i1 %cond, label %for.body, label %else
|
|
|
|
else:
|
|
%call1 = call i8 @callee()
|
|
br label %exit
|
|
|
|
for.body:
|
|
%call2 = call i8 @callee()
|
|
%ext = zext i8 %call2 to i32
|
|
%cond2 = icmp samesign ugt i32 %x, %ext
|
|
br i1 %cond2, label %for.body, label %exit
|
|
|
|
exit:
|
|
%res = phi i8 [ %call1, %else ], [ %call2, %for.body ]
|
|
ret i8 %res
|
|
}
|
|
|
|
declare i8 @callee()
|