[llvm] r290111 - [InstCombine] add folds for icmp (smax X, Y), X

Sanjay Patel via llvm-commits llvm-commits at lists.llvm.org
Mon Dec 19 08:28:53 PST 2016


Author: spatel
Date: Mon Dec 19 10:28:53 2016
New Revision: 290111

URL: http://llvm.org/viewvc/llvm-project?rev=290111&view=rev
Log:
[InstCombine] add folds for icmp (smax X, Y), X

This is a follow-up to:
https://reviews.llvm.org/rL289855 (D27531)


Modified:
    llvm/trunk/include/llvm/IR/PatternMatch.h
    llvm/trunk/lib/Transforms/InstCombine/InstCombineCompares.cpp
    llvm/trunk/test/Transforms/InstCombine/smax-icmp.ll

Modified: llvm/trunk/include/llvm/IR/PatternMatch.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/IR/PatternMatch.h?rev=290111&r1=290110&r2=290111&view=diff
==============================================================================
--- llvm/trunk/include/llvm/IR/PatternMatch.h (original)
+++ llvm/trunk/include/llvm/IR/PatternMatch.h Mon Dec 19 10:28:53 2016
@@ -1349,15 +1349,22 @@ m_c_Xor(const LHS &L, const RHS &R) {
   return m_CombineOr(m_Xor(L, R), m_Xor(R, L));
 }
 
-// TODO: Add the related SMax, UMax, UMin commuted matchers.
+// TODO: Add the related UMax and UMin commuted matchers.
 
 /// Matches an SMin with LHS and RHS in either order.
-template<typename LHS, typename RHS>
+template <typename LHS, typename RHS>
 inline match_combine_or<MaxMin_match<ICmpInst, LHS, RHS, smin_pred_ty>,
                         MaxMin_match<ICmpInst, RHS, LHS, smin_pred_ty>>
 m_c_SMin(const LHS &L, const RHS &R) {
   return m_CombineOr(m_SMin(L, R), m_SMin(R, L));
 }
+/// Matches an SMax with LHS and RHS in either order.
+template <typename LHS, typename RHS>
+inline match_combine_or<MaxMin_match<ICmpInst, LHS, RHS, smax_pred_ty>,
+                        MaxMin_match<ICmpInst, RHS, LHS, smax_pred_ty>>
+m_c_SMax(const LHS &L, const RHS &R) {
+  return m_CombineOr(m_SMax(L, R), m_SMax(R, L));
+}
 
 } // end namespace PatternMatch
 } // end namespace llvm

Modified: llvm/trunk/lib/Transforms/InstCombine/InstCombineCompares.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/InstCombine/InstCombineCompares.cpp?rev=290111&r1=290110&r2=290111&view=diff
==============================================================================
--- llvm/trunk/lib/Transforms/InstCombine/InstCombineCompares.cpp (original)
+++ llvm/trunk/lib/Transforms/InstCombine/InstCombineCompares.cpp Mon Dec 19 10:28:53 2016
@@ -3030,37 +3030,55 @@ Instruction *InstCombiner::foldICmpBinOp
   return nullptr;
 }
 
-/// Fold icmp Pred smin(X, Y), X.
-static Instruction *foldICmpWithSMin(ICmpInst &Cmp) {
+/// Fold icmp Pred smin|smax(X, Y), X.
+static Instruction *foldICmpWithSMinMax(ICmpInst &Cmp) {
   ICmpInst::Predicate Pred = Cmp.getPredicate();
   Value *Op0 = Cmp.getOperand(0);
   Value *X = Cmp.getOperand(1);
 
-  // TODO: This should be expanded to handle smax/umax/umin.
+  // TODO: This should be expanded to handle umax/umin.
 
   // Canonicalize minimum operand to LHS of the icmp.
-  if (match(X, m_c_SMin(m_Specific(Op0), m_Value()))) {
+  if (match(X, m_c_SMin(m_Specific(Op0), m_Value())) ||
+      match(X, m_c_SMax(m_Specific(Op0), m_Value()))) {
     std::swap(Op0, X);
     Pred = Cmp.getSwappedPredicate();
   }
 
   Value *Y;
-  if (!match(Op0, m_c_SMin(m_Specific(X), m_Value(Y))))
+  if (match(Op0, m_c_SMin(m_Specific(X), m_Value(Y)))) {
+    // smin(X, Y) == X --> X <= Y
+    // smin(X, Y) >= X --> X <= Y
+    if (Pred == CmpInst::ICMP_EQ || Pred == CmpInst::ICMP_SGE)
+      return new ICmpInst(ICmpInst::ICMP_SLE, X, Y);
+
+    // smin(X, Y) != X --> X > Y
+    // smin(X, Y) <  X --> X > Y
+    if (Pred == CmpInst::ICMP_NE || Pred == CmpInst::ICMP_SLT)
+      return new ICmpInst(ICmpInst::ICMP_SGT, X, Y);
+
+    // These cases should be handled in InstSimplify:
+    // smin(X, Y) <= X --> true
+    // smin(X, Y) > X --> false
     return nullptr;
+  }
+  if (match(Op0, m_c_SMax(m_Specific(X), m_Value(Y)))) {
+    // smax(X, Y) == X --> X >= Y
+    // smax(X, Y) <= X --> X >= Y
+    if (Pred == CmpInst::ICMP_EQ || Pred == CmpInst::ICMP_SLE)
+      return new ICmpInst(ICmpInst::ICMP_SGE, X, Y);
+
+    // smax(X, Y) != X --> X < Y
+    // smax(X, Y) >  X --> X < Y
+    if (Pred == CmpInst::ICMP_NE || Pred == CmpInst::ICMP_SGT)
+      return new ICmpInst(ICmpInst::ICMP_SLT, X, Y);
+
+    // These cases should be handled in InstSimplify:
+    // smax(X, Y) >= X --> true
+    // smax(X, Y) < X --> false
+    return nullptr;
+  }
 
-  // smin(X, Y) == X --> X <= Y
-  // smin(X, Y) >= X --> X <= Y
-  if (Pred == CmpInst::ICMP_EQ || Pred == CmpInst::ICMP_SGE)
-    return new ICmpInst(ICmpInst::ICMP_SLE, X, Y);
-
-  // smin(X, Y) != X --> X > Y
-  // smin(X, Y) <  X --> X > Y
-  if (Pred == CmpInst::ICMP_NE || Pred == CmpInst::ICMP_SLT)
-    return new ICmpInst(ICmpInst::ICMP_SGT, X, Y);
-
-  // These cases should be handled in InstSimplify:
-  // smin(X, Y) <= X --> true
-  // smin(X, Y) > X --> false
   return nullptr;
 }
 
@@ -4311,7 +4329,7 @@ Instruction *InstCombiner::visitICmpInst
   if (Instruction *Res = foldICmpBinOp(I))
     return Res;
 
-  if (Instruction *Res = foldICmpWithSMin(I))
+  if (Instruction *Res = foldICmpWithSMinMax(I))
     return Res;
 
   {

Modified: llvm/trunk/test/Transforms/InstCombine/smax-icmp.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/InstCombine/smax-icmp.ll?rev=290111&r1=290110&r2=290111&view=diff
==============================================================================
--- llvm/trunk/test/Transforms/InstCombine/smax-icmp.ll (original)
+++ llvm/trunk/test/Transforms/InstCombine/smax-icmp.ll Mon Dec 19 10:28:53 2016
@@ -12,9 +12,7 @@
 
 define i1 @eq_smax1(i32 %x, i32 %y) {
 ; CHECK-LABEL: @eq_smax1(
-; CHECK-NEXT:    [[CMP1:%.*]] = icmp sgt i32 %x, %y
-; CHECK-NEXT:    [[SEL:%.*]] = select i1 [[CMP1]], i32 %x, i32 %y
-; CHECK-NEXT:    [[CMP2:%.*]] = icmp eq i32 [[SEL]], %x
+; CHECK-NEXT:    [[CMP2:%.*]] = icmp sge i32 %x, %y
 ; CHECK-NEXT:    ret i1 [[CMP2]]
 ;
   %cmp1 = icmp sgt i32 %x, %y
@@ -27,9 +25,7 @@ define i1 @eq_smax1(i32 %x, i32 %y) {
 
 define i1 @eq_smax2(i32 %x, i32 %y) {
 ; CHECK-LABEL: @eq_smax2(
-; CHECK-NEXT:    [[CMP1:%.*]] = icmp sgt i32 %y, %x
-; CHECK-NEXT:    [[SEL:%.*]] = select i1 [[CMP1]], i32 %y, i32 %x
-; CHECK-NEXT:    [[CMP2:%.*]] = icmp eq i32 [[SEL]], %x
+; CHECK-NEXT:    [[CMP2:%.*]] = icmp sge i32 %x, %y
 ; CHECK-NEXT:    ret i1 [[CMP2]]
 ;
   %cmp1 = icmp sgt i32 %y, %x
@@ -43,9 +39,7 @@ define i1 @eq_smax2(i32 %x, i32 %y) {
 define i1 @eq_smax3(i32 %a, i32 %y) {
 ; CHECK-LABEL: @eq_smax3(
 ; CHECK-NEXT:    [[X:%.*]] = add i32 %a, 3
-; CHECK-NEXT:    [[CMP1:%.*]] = icmp sgt i32 [[X]], %y
-; CHECK-NEXT:    [[SEL:%.*]] = select i1 [[CMP1]], i32 [[X]], i32 %y
-; CHECK-NEXT:    [[CMP2:%.*]] = icmp eq i32 [[X]], [[SEL]]
+; CHECK-NEXT:    [[CMP2:%.*]] = icmp sge i32 [[X]], %y
 ; CHECK-NEXT:    ret i1 [[CMP2]]
 ;
   %x = add i32 %a, 3 ; thwart complexity-based canonicalization
@@ -60,9 +54,7 @@ define i1 @eq_smax3(i32 %a, i32 %y) {
 define i1 @eq_smax4(i32 %a, i32 %y) {
 ; CHECK-LABEL: @eq_smax4(
 ; CHECK-NEXT:    [[X:%.*]] = add i32 %a, 3
-; CHECK-NEXT:    [[CMP1:%.*]] = icmp slt i32 [[X]], %y
-; CHECK-NEXT:    [[SEL:%.*]] = select i1 [[CMP1]], i32 %y, i32 [[X]]
-; CHECK-NEXT:    [[CMP2:%.*]] = icmp eq i32 [[X]], [[SEL]]
+; CHECK-NEXT:    [[CMP2:%.*]] = icmp sge i32 [[X]], %y
 ; CHECK-NEXT:    ret i1 [[CMP2]]
 ;
   %x = add i32 %a, 3 ; thwart complexity-based canonicalization
@@ -76,9 +68,7 @@ define i1 @eq_smax4(i32 %a, i32 %y) {
 
 define i1 @sle_smax1(i32 %x, i32 %y) {
 ; CHECK-LABEL: @sle_smax1(
-; CHECK-NEXT:    [[CMP1:%.*]] = icmp sgt i32 %x, %y
-; CHECK-NEXT:    [[SEL:%.*]] = select i1 [[CMP1]], i32 %x, i32 %y
-; CHECK-NEXT:    [[CMP2:%.*]] = icmp sle i32 [[SEL]], %x
+; CHECK-NEXT:    [[CMP2:%.*]] = icmp sge i32 %x, %y
 ; CHECK-NEXT:    ret i1 [[CMP2]]
 ;
   %cmp1 = icmp sgt i32 %x, %y
@@ -91,9 +81,7 @@ define i1 @sle_smax1(i32 %x, i32 %y) {
 
 define i1 @sle_smax2(i32 %x, i32 %y) {
 ; CHECK-LABEL: @sle_smax2(
-; CHECK-NEXT:    [[CMP1:%.*]] = icmp sgt i32 %y, %x
-; CHECK-NEXT:    [[SEL:%.*]] = select i1 [[CMP1]], i32 %y, i32 %x
-; CHECK-NEXT:    [[CMP2:%.*]] = icmp sle i32 [[SEL]], %x
+; CHECK-NEXT:    [[CMP2:%.*]] = icmp sge i32 %x, %y
 ; CHECK-NEXT:    ret i1 [[CMP2]]
 ;
   %cmp1 = icmp sgt i32 %y, %x
@@ -107,9 +95,7 @@ define i1 @sle_smax2(i32 %x, i32 %y) {
 define i1 @sle_smax3(i32 %a, i32 %y) {
 ; CHECK-LABEL: @sle_smax3(
 ; CHECK-NEXT:    [[X:%.*]] = add i32 %a, 3
-; CHECK-NEXT:    [[CMP1:%.*]] = icmp sgt i32 [[X]], %y
-; CHECK-NEXT:    [[SEL:%.*]] = select i1 [[CMP1]], i32 [[X]], i32 %y
-; CHECK-NEXT:    [[CMP2:%.*]] = icmp sge i32 [[X]], [[SEL]]
+; CHECK-NEXT:    [[CMP2:%.*]] = icmp sge i32 [[X]], %y
 ; CHECK-NEXT:    ret i1 [[CMP2]]
 ;
   %x = add i32 %a, 3 ; thwart complexity-based canonicalization
@@ -124,9 +110,7 @@ define i1 @sle_smax3(i32 %a, i32 %y) {
 define i1 @sle_smax4(i32 %a, i32 %y) {
 ; CHECK-LABEL: @sle_smax4(
 ; CHECK-NEXT:    [[X:%.*]] = add i32 %a, 3
-; CHECK-NEXT:    [[CMP1:%.*]] = icmp slt i32 [[X]], %y
-; CHECK-NEXT:    [[SEL:%.*]] = select i1 [[CMP1]], i32 %y, i32 [[X]]
-; CHECK-NEXT:    [[CMP2:%.*]] = icmp sge i32 [[X]], [[SEL]]
+; CHECK-NEXT:    [[CMP2:%.*]] = icmp sge i32 [[X]], %y
 ; CHECK-NEXT:    ret i1 [[CMP2]]
 ;
   %x = add i32 %a, 3 ; thwart complexity-based canonicalization
@@ -140,9 +124,7 @@ define i1 @sle_smax4(i32 %a, i32 %y) {
 
 define i1 @ne_smax1(i32 %x, i32 %y) {
 ; CHECK-LABEL: @ne_smax1(
-; CHECK-NEXT:    [[CMP1:%.*]] = icmp sgt i32 %x, %y
-; CHECK-NEXT:    [[SEL:%.*]] = select i1 [[CMP1]], i32 %x, i32 %y
-; CHECK-NEXT:    [[CMP2:%.*]] = icmp ne i32 [[SEL]], %x
+; CHECK-NEXT:    [[CMP2:%.*]] = icmp slt i32 %x, %y
 ; CHECK-NEXT:    ret i1 [[CMP2]]
 ;
   %cmp1 = icmp sgt i32 %x, %y
@@ -169,9 +151,7 @@ define i1 @ne_smax2(i32 %x, i32 %y) {
 define i1 @ne_smax3(i32 %a, i32 %y) {
 ; CHECK-LABEL: @ne_smax3(
 ; CHECK-NEXT:    [[X:%.*]] = add i32 %a, 3
-; CHECK-NEXT:    [[CMP1:%.*]] = icmp sgt i32 [[X]], %y
-; CHECK-NEXT:    [[SEL:%.*]] = select i1 [[CMP1]], i32 [[X]], i32 %y
-; CHECK-NEXT:    [[CMP2:%.*]] = icmp ne i32 [[X]], [[SEL]]
+; CHECK-NEXT:    [[CMP2:%.*]] = icmp slt i32 [[X]], %y
 ; CHECK-NEXT:    ret i1 [[CMP2]]
 ;
   %x = add i32 %a, 3 ; thwart complexity-based canonicalization
@@ -200,9 +180,7 @@ define i1 @ne_smax4(i32 %a, i32 %y) {
 
 define i1 @sgt_smax1(i32 %x, i32 %y) {
 ; CHECK-LABEL: @sgt_smax1(
-; CHECK-NEXT:    [[CMP1:%.*]] = icmp sgt i32 %x, %y
-; CHECK-NEXT:    [[SEL:%.*]] = select i1 [[CMP1]], i32 %x, i32 %y
-; CHECK-NEXT:    [[CMP2:%.*]] = icmp sgt i32 [[SEL]], %x
+; CHECK-NEXT:    [[CMP2:%.*]] = icmp slt i32 %x, %y
 ; CHECK-NEXT:    ret i1 [[CMP2]]
 ;
   %cmp1 = icmp sgt i32 %x, %y
@@ -229,9 +207,7 @@ define i1 @sgt_smax2(i32 %x, i32 %y) {
 define i1 @sgt_smax3(i32 %a, i32 %y) {
 ; CHECK-LABEL: @sgt_smax3(
 ; CHECK-NEXT:    [[X:%.*]] = add i32 %a, 3
-; CHECK-NEXT:    [[CMP1:%.*]] = icmp sgt i32 [[X]], %y
-; CHECK-NEXT:    [[SEL:%.*]] = select i1 [[CMP1]], i32 [[X]], i32 %y
-; CHECK-NEXT:    [[CMP2:%.*]] = icmp slt i32 [[X]], [[SEL]]
+; CHECK-NEXT:    [[CMP2:%.*]] = icmp slt i32 [[X]], %y
 ; CHECK-NEXT:    ret i1 [[CMP2]]
 ;
   %x = add i32 %a, 3 ; thwart complexity-based canonicalization




More information about the llvm-commits mailing list