llvm/test/Transforms/InstCombine/smin-icmp.ll
Sanjay Patel 8ca87b1e6e [InstCombine] add folds for icmp (smin X, Y), X
Min/max canonicalization (r287585) exposes the fact that we're missing combines for min/max patterns. 
This patch won't solve the example that was attached to that thread, so something else still needs fixing.

The line between InstCombine and InstSimplify gets blurry here because sometimes the icmp instruction that
we want to fold to already exists, but sometimes it's the swapped form of what we want.

Corresponding changes for smax/umin/umax to follow.

Differential Revision: https://reviews.llvm.org/D27531


git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@289855 91177308-0d34-0410-b5e6-96231b3b80d8
2016-12-15 19:13:37 +00:00

334 lines
8.4 KiB
LLVM

; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
; RUN: opt -S -instcombine < %s | FileCheck %s
; If we have an smin feeding a signed or equality icmp that shares an
; operand with the smin, the compare should always be folded.
; Test all 6 foldable predicates (eq,ne,sge,sgt,sle,slt) * 4 commutation
; possibilities for each predicate. Note that folds to true/false or
; folds to an existing instruction may be handled by InstSimplify.
; smin(X, Y) == X --> X <= Y
define i1 @eq_smin1(i32 %x, i32 %y) {
; CHECK-LABEL: @eq_smin1(
; CHECK-NEXT: [[CMP2:%.*]] = icmp sle i32 %x, %y
; CHECK-NEXT: ret i1 [[CMP2]]
;
%cmp1 = icmp slt i32 %x, %y
%sel = select i1 %cmp1, i32 %x, i32 %y
%cmp2 = icmp eq i32 %sel, %x
ret i1 %cmp2
}
; Commute min operands.
define i1 @eq_smin2(i32 %x, i32 %y) {
; CHECK-LABEL: @eq_smin2(
; CHECK-NEXT: [[CMP2:%.*]] = icmp sle i32 %x, %y
; CHECK-NEXT: ret i1 [[CMP2]]
;
%cmp1 = icmp slt i32 %y, %x
%sel = select i1 %cmp1, i32 %y, i32 %x
%cmp2 = icmp eq i32 %sel, %x
ret i1 %cmp2
}
; Disguise the icmp predicate by commuting the min op to the RHS.
define i1 @eq_smin3(i32 %a, i32 %y) {
; CHECK-LABEL: @eq_smin3(
; CHECK-NEXT: [[X:%.*]] = add i32 %a, 3
; CHECK-NEXT: [[CMP2:%.*]] = icmp sle i32 [[X]], %y
; CHECK-NEXT: ret i1 [[CMP2]]
;
%x = add i32 %a, 3 ; thwart complexity-based canonicalization
%cmp1 = icmp slt i32 %x, %y
%sel = select i1 %cmp1, i32 %x, i32 %y
%cmp2 = icmp eq i32 %x, %sel
ret i1 %cmp2
}
; Commute min operands.
define i1 @eq_smin4(i32 %a, i32 %y) {
; CHECK-LABEL: @eq_smin4(
; CHECK-NEXT: [[X:%.*]] = add i32 %a, 3
; CHECK-NEXT: [[CMP2:%.*]] = icmp sle i32 [[X]], %y
; CHECK-NEXT: ret i1 [[CMP2]]
;
%x = add i32 %a, 3 ; thwart complexity-based canonicalization
%cmp1 = icmp slt i32 %y, %x
%sel = select i1 %cmp1, i32 %y, i32 %x
%cmp2 = icmp eq i32 %x, %sel
ret i1 %cmp2
}
; smin(X, Y) >= X --> X <= Y
define i1 @sge_smin1(i32 %x, i32 %y) {
; CHECK-LABEL: @sge_smin1(
; CHECK-NEXT: [[CMP2:%.*]] = icmp sle i32 %x, %y
; CHECK-NEXT: ret i1 [[CMP2]]
;
%cmp1 = icmp slt i32 %x, %y
%sel = select i1 %cmp1, i32 %x, i32 %y
%cmp2 = icmp sge i32 %sel, %x
ret i1 %cmp2
}
; Commute min operands.
define i1 @sge_smin2(i32 %x, i32 %y) {
; CHECK-LABEL: @sge_smin2(
; CHECK-NEXT: [[CMP2:%.*]] = icmp sle i32 %x, %y
; CHECK-NEXT: ret i1 [[CMP2]]
;
%cmp1 = icmp slt i32 %y, %x
%sel = select i1 %cmp1, i32 %y, i32 %x
%cmp2 = icmp sge i32 %sel, %x
ret i1 %cmp2
}
; Disguise the icmp predicate by commuting the min op to the RHS.
define i1 @sge_smin3(i32 %a, i32 %y) {
; CHECK-LABEL: @sge_smin3(
; CHECK-NEXT: [[X:%.*]] = add i32 %a, 3
; CHECK-NEXT: [[CMP2:%.*]] = icmp sle i32 [[X]], %y
; CHECK-NEXT: ret i1 [[CMP2]]
;
%x = add i32 %a, 3 ; thwart complexity-based canonicalization
%cmp1 = icmp slt i32 %x, %y
%sel = select i1 %cmp1, i32 %x, i32 %y
%cmp2 = icmp sle i32 %x, %sel
ret i1 %cmp2
}
; Commute min operands.
define i1 @sge_smin4(i32 %a, i32 %y) {
; CHECK-LABEL: @sge_smin4(
; CHECK-NEXT: [[X:%.*]] = add i32 %a, 3
; CHECK-NEXT: [[CMP2:%.*]] = icmp sle i32 [[X]], %y
; CHECK-NEXT: ret i1 [[CMP2]]
;
%x = add i32 %a, 3 ; thwart complexity-based canonicalization
%cmp1 = icmp slt i32 %y, %x
%sel = select i1 %cmp1, i32 %y, i32 %x
%cmp2 = icmp sle i32 %x, %sel
ret i1 %cmp2
}
; smin(X, Y) != X --> X > Y
define i1 @ne_smin1(i32 %x, i32 %y) {
; CHECK-LABEL: @ne_smin1(
; CHECK-NEXT: [[CMP2:%.*]] = icmp sgt i32 %x, %y
; CHECK-NEXT: ret i1 [[CMP2]]
;
%cmp1 = icmp slt i32 %x, %y
%sel = select i1 %cmp1, i32 %x, i32 %y
%cmp2 = icmp ne i32 %sel, %x
ret i1 %cmp2
}
; Commute min operands.
define i1 @ne_smin2(i32 %x, i32 %y) {
; CHECK-LABEL: @ne_smin2(
; CHECK-NEXT: [[CMP1:%.*]] = icmp slt i32 %y, %x
; CHECK-NEXT: ret i1 [[CMP1]]
;
%cmp1 = icmp slt i32 %y, %x
%sel = select i1 %cmp1, i32 %y, i32 %x
%cmp2 = icmp ne i32 %sel, %x
ret i1 %cmp2
}
; Disguise the icmp predicate by commuting the min op to the RHS.
define i1 @ne_smin3(i32 %a, i32 %y) {
; CHECK-LABEL: @ne_smin3(
; CHECK-NEXT: [[X:%.*]] = add i32 %a, 3
; CHECK-NEXT: [[CMP2:%.*]] = icmp sgt i32 [[X]], %y
; CHECK-NEXT: ret i1 [[CMP2]]
;
%x = add i32 %a, 3 ; thwart complexity-based canonicalization
%cmp1 = icmp slt i32 %x, %y
%sel = select i1 %cmp1, i32 %x, i32 %y
%cmp2 = icmp ne i32 %x, %sel
ret i1 %cmp2
}
; Commute min operands.
define i1 @ne_smin4(i32 %a, i32 %y) {
; CHECK-LABEL: @ne_smin4(
; CHECK-NEXT: [[X:%.*]] = add i32 %a, 3
; CHECK-NEXT: [[CMP1:%.*]] = icmp sgt i32 [[X]], %y
; CHECK-NEXT: ret i1 [[CMP1]]
;
%x = add i32 %a, 3 ; thwart complexity-based canonicalization
%cmp1 = icmp slt i32 %y, %x
%sel = select i1 %cmp1, i32 %y, i32 %x
%cmp2 = icmp ne i32 %x, %sel
ret i1 %cmp2
}
; smin(X, Y) < X --> X > Y
define i1 @slt_smin1(i32 %x, i32 %y) {
; CHECK-LABEL: @slt_smin1(
; CHECK-NEXT: [[CMP2:%.*]] = icmp sgt i32 %x, %y
; CHECK-NEXT: ret i1 [[CMP2]]
;
%cmp1 = icmp slt i32 %x, %y
%sel = select i1 %cmp1, i32 %x, i32 %y
%cmp2 = icmp slt i32 %sel, %x
ret i1 %cmp2
}
; Commute min operands.
define i1 @slt_smin2(i32 %x, i32 %y) {
; CHECK-LABEL: @slt_smin2(
; CHECK-NEXT: [[CMP1:%.*]] = icmp slt i32 %y, %x
; CHECK-NEXT: ret i1 [[CMP1]]
;
%cmp1 = icmp slt i32 %y, %x
%sel = select i1 %cmp1, i32 %y, i32 %x
%cmp2 = icmp slt i32 %sel, %x
ret i1 %cmp2
}
; Disguise the icmp predicate by commuting the min op to the RHS.
define i1 @slt_smin3(i32 %a, i32 %y) {
; CHECK-LABEL: @slt_smin3(
; CHECK-NEXT: [[X:%.*]] = add i32 %a, 3
; CHECK-NEXT: [[CMP2:%.*]] = icmp sgt i32 [[X]], %y
; CHECK-NEXT: ret i1 [[CMP2]]
;
%x = add i32 %a, 3 ; thwart complexity-based canonicalization
%cmp1 = icmp slt i32 %x, %y
%sel = select i1 %cmp1, i32 %x, i32 %y
%cmp2 = icmp sgt i32 %x, %sel
ret i1 %cmp2
}
; Commute min operands.
define i1 @slt_smin4(i32 %a, i32 %y) {
; CHECK-LABEL: @slt_smin4(
; CHECK-NEXT: [[X:%.*]] = add i32 %a, 3
; CHECK-NEXT: [[CMP1:%.*]] = icmp sgt i32 [[X]], %y
; CHECK-NEXT: ret i1 [[CMP1]]
;
%x = add i32 %a, 3 ; thwart complexity-based canonicalization
%cmp1 = icmp slt i32 %y, %x
%sel = select i1 %cmp1, i32 %y, i32 %x
%cmp2 = icmp sgt i32 %x, %sel
ret i1 %cmp2
}
; smin(X, Y) <= X --> true
define i1 @sle_smin1(i32 %x, i32 %y) {
; CHECK-LABEL: @sle_smin1(
; CHECK-NEXT: ret i1 true
;
%cmp1 = icmp slt i32 %x, %y
%sel = select i1 %cmp1, i32 %x, i32 %y
%cmp2 = icmp sle i32 %sel, %x
ret i1 %cmp2
}
; Commute min operands.
define i1 @sle_smin2(i32 %x, i32 %y) {
; CHECK-LABEL: @sle_smin2(
; CHECK-NEXT: ret i1 true
;
%cmp1 = icmp slt i32 %y, %x
%sel = select i1 %cmp1, i32 %y, i32 %x
%cmp2 = icmp sle i32 %sel, %x
ret i1 %cmp2
}
; Disguise the icmp predicate by commuting the min op to the RHS.
define i1 @sle_smin3(i32 %a, i32 %y) {
; CHECK-LABEL: @sle_smin3(
; CHECK-NEXT: ret i1 true
;
%x = add i32 %a, 3 ; thwart complexity-based canonicalization
%cmp1 = icmp slt i32 %x, %y
%sel = select i1 %cmp1, i32 %x, i32 %y
%cmp2 = icmp sge i32 %x, %sel
ret i1 %cmp2
}
; Commute min operands.
define i1 @sle_smin4(i32 %a, i32 %y) {
; CHECK-LABEL: @sle_smin4(
; CHECK-NEXT: ret i1 true
;
%x = add i32 %a, 3 ; thwart complexity-based canonicalization
%cmp1 = icmp slt i32 %y, %x
%sel = select i1 %cmp1, i32 %y, i32 %x
%cmp2 = icmp sge i32 %x, %sel
ret i1 %cmp2
}
; smin(X, Y) > X --> false
define i1 @sgt_smin1(i32 %x, i32 %y) {
; CHECK-LABEL: @sgt_smin1(
; CHECK-NEXT: ret i1 false
;
%cmp1 = icmp slt i32 %x, %y
%sel = select i1 %cmp1, i32 %x, i32 %y
%cmp2 = icmp sgt i32 %sel, %x
ret i1 %cmp2
}
; Commute min operands.
define i1 @sgt_smin2(i32 %x, i32 %y) {
; CHECK-LABEL: @sgt_smin2(
; CHECK-NEXT: ret i1 false
;
%cmp1 = icmp slt i32 %y, %x
%sel = select i1 %cmp1, i32 %y, i32 %x
%cmp2 = icmp sgt i32 %sel, %x
ret i1 %cmp2
}
; Disguise the icmp predicate by commuting the min op to the RHS.
define i1 @sgt_smin3(i32 %a, i32 %y) {
; CHECK-LABEL: @sgt_smin3(
; CHECK-NEXT: ret i1 false
;
%x = add i32 %a, 3 ; thwart complexity-based canonicalization
%cmp1 = icmp slt i32 %x, %y
%sel = select i1 %cmp1, i32 %x, i32 %y
%cmp2 = icmp slt i32 %x, %sel
ret i1 %cmp2
}
; Commute min operands.
define i1 @sgt_smin4(i32 %a, i32 %y) {
; CHECK-LABEL: @sgt_smin4(
; CHECK-NEXT: ret i1 false
;
%x = add i32 %a, 3 ; thwart complexity-based canonicalization
%cmp1 = icmp slt i32 %y, %x
%sel = select i1 %cmp1, i32 %y, i32 %x
%cmp2 = icmp slt i32 %x, %sel
ret i1 %cmp2
}