blob: 0c24716d6aaaf8cb698b8582a11974795906de9d [file] [edit]
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 6
; RUN: opt -passes=indvars -S %s | FileCheck %s
define i8 @smax_exit_from_smin(i32 %start, i32 %limit) {
; CHECK-LABEL: define i8 @smax_exit_from_smin(
; CHECK-SAME: i32 [[START:%.*]], i32 [[LIMIT:%.*]]) {
; CHECK-NEXT: [[ENTRY:.*:]]
; CHECK-NEXT: [[CMP13:%.*]] = icmp slt i32 [[START]], 0
; CHECK-NEXT: br i1 [[CMP13]], label %[[PH1:.*]], label %[[EXIT_A:.*]]
; CHECK: [[PH1]]:
; CHECK-NEXT: [[CMP_NOT:%.*]] = icmp sgt i32 [[START]], [[LIMIT]]
; CHECK-NEXT: br i1 [[CMP_NOT]], label %[[EXIT_B:.*]], label %[[PH2:.*]]
; CHECK: [[PH2]]:
; CHECK-NEXT: [[SMIN:%.*]] = tail call i32 @llvm.smin.i32(i32 [[LIMIT]], i32 0)
; CHECK-NEXT: br label %[[LOOP:.*]]
; CHECK: [[LOOP]]:
; CHECK-NEXT: [[K:%.*]] = phi i32 [ [[INC:%.*]], %[[LOOP]] ], [ [[START]], %[[PH2]] ]
; CHECK-NEXT: call void @use()
; CHECK-NEXT: [[INC]] = add i32 [[K]], 1
; CHECK-NEXT: [[COND:%.*]] = icmp slt i32 [[K]], [[SMIN]]
; CHECK-NEXT: br i1 [[COND]], label %[[LOOP]], label %[[LOOP_EXIT:.*]]
; CHECK: [[LOOP_EXIT]]:
; CHECK-NEXT: ret i8 0
; CHECK: [[EXIT_B]]:
; CHECK-NEXT: ret i8 1
; CHECK: [[EXIT_A]]:
; CHECK-NEXT: ret i8 2
;
entry:
%cmp13 = icmp slt i32 %start, 0
br i1 %cmp13, label %ph1, label %exit.a
ph1:
%cmp.not = icmp sgt i32 %start, %limit
br i1 %cmp.not, label %exit.b, label %ph2
ph2:
%smin = tail call i32 @llvm.smin.i32(i32 %limit, i32 0)
br label %loop
loop:
%k = phi i32 [ %inc, %loop ], [ %start, %ph2 ]
call void @use()
%inc = add i32 %k, 1
%cond = icmp slt i32 %k, %smin
br i1 %cond, label %loop, label %loop.exit
loop.exit:
ret i8 0
exit.b:
ret i8 1
exit.a:
ret i8 2
}
; TODO: Unsigned counterpart of @smax_exit_from_smin; umax should be folded.
define i8 @umax_exit_from_umin(i32 %start, i32 %limit) {
; CHECK-LABEL: define i8 @umax_exit_from_umin(
; CHECK-SAME: i32 [[START:%.*]], i32 [[LIMIT:%.*]]) {
; CHECK-NEXT: [[ENTRY:.*:]]
; CHECK-NEXT: [[CMP13:%.*]] = icmp ult i32 [[START]], 100
; CHECK-NEXT: br i1 [[CMP13]], label %[[PH1:.*]], label %[[EXIT_A:.*]]
; CHECK: [[PH1]]:
; CHECK-NEXT: [[CMP_NOT:%.*]] = icmp ugt i32 [[START]], [[LIMIT]]
; CHECK-NEXT: br i1 [[CMP_NOT]], label %[[EXIT_B:.*]], label %[[PH2:.*]]
; CHECK: [[PH2]]:
; CHECK-NEXT: [[UMIN:%.*]] = tail call i32 @llvm.umin.i32(i32 [[LIMIT]], i32 100)
; CHECK-NEXT: br label %[[LOOP:.*]]
; CHECK: [[LOOP]]:
; CHECK-NEXT: [[K:%.*]] = phi i32 [ [[INC:%.*]], %[[LOOP]] ], [ [[START]], %[[PH2]] ]
; CHECK-NEXT: call void @use()
; CHECK-NEXT: [[INC]] = add i32 [[K]], 1
; CHECK-NEXT: [[COND:%.*]] = icmp ult i32 [[K]], [[UMIN]]
; CHECK-NEXT: br i1 [[COND]], label %[[LOOP]], label %[[LOOP_EXIT:.*]]
; CHECK: [[LOOP_EXIT]]:
; CHECK-NEXT: ret i8 0
; CHECK: [[EXIT_B]]:
; CHECK-NEXT: ret i8 1
; CHECK: [[EXIT_A]]:
; CHECK-NEXT: ret i8 2
;
entry:
%cmp13 = icmp ult i32 %start, 100
br i1 %cmp13, label %ph1, label %exit.a
ph1:
%cmp.not = icmp ugt i32 %start, %limit
br i1 %cmp.not, label %exit.b, label %ph2
ph2:
%umin = tail call i32 @llvm.umin.i32(i32 %limit, i32 100)
br label %loop
loop:
%k = phi i32 [ %inc, %loop ], [ %start, %ph2 ]
call void @use()
%inc = add i32 %k, 1
%cond = icmp ult i32 %k, %umin
br i1 %cond, label %loop, label %loop.exit
loop.exit:
ret i8 0
exit.b:
ret i8 1
exit.a:
ret i8 2
}
; Negative test: signed exit with an unsigned-max bound must not be folded.
define i8 @signed_exit_not_eliminated_from_umax(i32 %start, i32 %a, i32 %b) {
; CHECK-LABEL: define i8 @signed_exit_not_eliminated_from_umax(
; CHECK-SAME: i32 [[START:%.*]], i32 [[A:%.*]], i32 [[B:%.*]]) {
; CHECK-NEXT: [[ENTRY:.*:]]
; CHECK-NEXT: [[G:%.*]] = icmp sgt i32 [[START]], [[A]]
; CHECK-NEXT: br i1 [[G]], label %[[EXIT_B:.*]], label %[[PH2:.*]]
; CHECK: [[PH2]]:
; CHECK-NEXT: [[UMAX:%.*]] = call i32 @llvm.umax.i32(i32 [[A]], i32 [[B]])
; CHECK-NEXT: [[PRE:%.*]] = icmp slt i32 [[START]], [[UMAX]]
; CHECK-NEXT: br i1 [[PRE]], label %[[LOOP_PREHEADER:.*]], label %[[EXIT_B]]
; CHECK: [[LOOP_PREHEADER]]:
; CHECK-NEXT: br label %[[LOOP:.*]]
; CHECK: [[LOOP]]:
; CHECK-NEXT: [[K:%.*]] = phi i32 [ [[INC:%.*]], %[[LOOP]] ], [ [[START]], %[[LOOP_PREHEADER]] ]
; CHECK-NEXT: call void @use()
; CHECK-NEXT: [[INC]] = add i32 [[K]], 1
; CHECK-NEXT: [[COND:%.*]] = icmp slt i32 [[K]], [[UMAX]]
; CHECK-NEXT: br i1 [[COND]], label %[[LOOP]], label %[[LOOP_EXIT:.*]]
; CHECK: [[LOOP_EXIT]]:
; CHECK-NEXT: ret i8 0
; CHECK: [[EXIT_B]]:
; CHECK-NEXT: ret i8 1
;
entry:
%g = icmp sgt i32 %start, %a
br i1 %g, label %exit.b, label %ph2
ph2:
%umax = call i32 @llvm.umax.i32(i32 %a, i32 %b)
%pre = icmp slt i32 %start, %umax
br i1 %pre, label %loop, label %exit.b
loop:
%k = phi i32 [ %inc, %loop ], [ %start, %ph2 ]
call void @use()
%inc = add i32 %k, 1
%cond = icmp slt i32 %k, %umax
br i1 %cond, label %loop, label %loop.exit
loop.exit:
ret i8 0
exit.b:
ret i8 1
}
declare void @use()