[llvm] 1470ce4 - [InstSimplify] fold min/max with matching min/max operands

Sanjay Patel via llvm-commits llvm-commits at lists.llvm.org
Tue Aug 11 08:24:23 PDT 2020


Author: Sanjay Patel
Date: 2020-08-11T11:23:15-04:00
New Revision: 1470ce4a76fc56729fb15dab0ca9877e25d26d58

URL: https://github.com/llvm/llvm-project/commit/1470ce4a76fc56729fb15dab0ca9877e25d26d58
DIFF: https://github.com/llvm/llvm-project/commit/1470ce4a76fc56729fb15dab0ca9877e25d26d58.diff

LOG: [InstSimplify] fold min/max with matching min/max operands

I think this is the last remaining translation of an existing
instcombine transform for the corresponding cmp+sel idiom.

This interpretation is more general though - we can remove
mismatched signed/unsigned combinations in addition to the
more obvious cases.

min/max(X, Y) must produce X or Y as the result, so this is
just another clause in the existing transform that was already
matching a min/max of min/max.

Added: 
    

Modified: 
    llvm/include/llvm/IR/PatternMatch.h
    llvm/lib/Analysis/InstructionSimplify.cpp
    llvm/test/Transforms/InstSimplify/maxmin_intrinsics.ll

Removed: 
    


################################################################################
diff  --git a/llvm/include/llvm/IR/PatternMatch.h b/llvm/include/llvm/IR/PatternMatch.h
index 6333613eb065..78a311de0657 100644
--- a/llvm/include/llvm/IR/PatternMatch.h
+++ b/llvm/include/llvm/IR/PatternMatch.h
@@ -1714,6 +1714,17 @@ inline MaxMin_match<ICmpInst, LHS, RHS, umin_pred_ty> m_UMin(const LHS &L,
   return MaxMin_match<ICmpInst, LHS, RHS, umin_pred_ty>(L, R);
 }
 
+template <typename LHS, typename RHS>
+inline match_combine_or<
+    match_combine_or<MaxMin_match<ICmpInst, LHS, RHS, smax_pred_ty>,
+                     MaxMin_match<ICmpInst, LHS, RHS, smin_pred_ty>>,
+    match_combine_or<MaxMin_match<ICmpInst, LHS, RHS, umax_pred_ty>,
+                     MaxMin_match<ICmpInst, LHS, RHS, umin_pred_ty>>>
+m_MaxOrMin(const LHS &L, const RHS &R) {
+  return m_CombineOr(m_CombineOr(m_SMax(L, R), m_SMin(L, R)),
+                     m_CombineOr(m_UMax(L, R), m_UMin(L, R)));
+}
+
 /// Match an 'ordered' floating point maximum function.
 /// Floating point has one special value 'NaN'. Therefore, there is no total
 /// order. However, if we can ignore the 'NaN' value (for example, because of a
@@ -2106,6 +2117,17 @@ m_c_UMax(const LHS &L, const RHS &R) {
   return MaxMin_match<ICmpInst, LHS, RHS, umax_pred_ty, true>(L, R);
 }
 
+template <typename LHS, typename RHS>
+inline match_combine_or<
+    match_combine_or<MaxMin_match<ICmpInst, LHS, RHS, smax_pred_ty, true>,
+                     MaxMin_match<ICmpInst, LHS, RHS, smin_pred_ty, true>>,
+    match_combine_or<MaxMin_match<ICmpInst, LHS, RHS, umax_pred_ty, true>,
+                     MaxMin_match<ICmpInst, LHS, RHS, umin_pred_ty, true>>>
+m_c_MaxOrMin(const LHS &L, const RHS &R) {
+  return m_CombineOr(m_CombineOr(m_c_SMax(L, R), m_c_SMin(L, R)),
+                     m_CombineOr(m_c_UMax(L, R), m_c_UMin(L, R)));
+}
+
 /// Matches FAdd with LHS and RHS in either order.
 template <typename LHS, typename RHS>
 inline BinaryOp_match<LHS, RHS, Instruction::FAdd, true>

diff  --git a/llvm/lib/Analysis/InstructionSimplify.cpp b/llvm/lib/Analysis/InstructionSimplify.cpp
index cc81b32b3ce6..20d0184a718f 100644
--- a/llvm/lib/Analysis/InstructionSimplify.cpp
+++ b/llvm/lib/Analysis/InstructionSimplify.cpp
@@ -5220,29 +5220,26 @@ static APInt getMaxMinLimit(Intrinsic::ID IID, unsigned BitWidth) {
   }
 }
 
-static bool isMinMax(Intrinsic::ID IID) {
-  return IID == Intrinsic::smax || IID == Intrinsic::smin ||
-         IID == Intrinsic::umax || IID == Intrinsic::umin;
-}
-
 /// Given a min/max intrinsic, see if it can be removed based on having an
 /// operand that is another min/max intrinsic with shared operand(s). The caller
 /// is expected to swap the operand arguments to handle commutation.
 static Value *foldMinMaxSharedOp(Intrinsic::ID IID, Value *Op0, Value *Op1) {
-  assert(isMinMax(IID) && "Expected min/max intrinsic");
-  auto *InnerMM = dyn_cast<IntrinsicInst>(Op0);
-  if (!InnerMM)
+  Value *X, *Y;
+  if (!match(Op0, m_MaxOrMin(m_Value(X), m_Value(Y))))
     return nullptr;
-  Intrinsic::ID InnerID = InnerMM->getIntrinsicID();
-  if (!isMinMax(InnerID))
+
+  auto *MM0 = dyn_cast<IntrinsicInst>(Op0);
+  if (!MM0)
     return nullptr;
+  Intrinsic::ID IID0 = MM0->getIntrinsicID();
 
-  if (Op1 == InnerMM->getOperand(0) || Op1 == InnerMM->getOperand(1)) {
+  if (Op1 == X || Op1 == Y ||
+      match(Op1, m_c_MaxOrMin(m_Specific(X), m_Specific(Y)))) {
     // max (max X, Y), X --> max X, Y
-    if (InnerID == IID)
-      return InnerMM;
+    if (IID0 == IID)
+      return MM0;
     // max (min X, Y), X --> X
-    if (InnerID == getMaxMinOpposite(IID))
+    if (IID0 == getMaxMinOpposite(IID))
       return Op1;
   }
   return nullptr;

diff  --git a/llvm/test/Transforms/InstSimplify/maxmin_intrinsics.ll b/llvm/test/Transforms/InstSimplify/maxmin_intrinsics.ll
index 51b71d287b11..3f8d529fbce1 100644
--- a/llvm/test/Transforms/InstSimplify/maxmin_intrinsics.ll
+++ b/llvm/test/Transforms/InstSimplify/maxmin_intrinsics.ll
@@ -1089,9 +1089,7 @@ define i1 @umax_eq_commute(i8 %x, i8 %y) {
 define i8 @smax_smax_smax(i8 %x, i8 %y) {
 ; CHECK-LABEL: @smax_smax_smax(
 ; CHECK-NEXT:    [[M1:%.*]] = call i8 @llvm.smax.i8(i8 [[X:%.*]], i8 [[Y:%.*]])
-; CHECK-NEXT:    [[M2:%.*]] = call i8 @llvm.smax.i8(i8 [[Y]], i8 [[X]])
-; CHECK-NEXT:    [[R:%.*]] = call i8 @llvm.smax.i8(i8 [[M1]], i8 [[M2]])
-; CHECK-NEXT:    ret i8 [[R]]
+; CHECK-NEXT:    ret i8 [[M1]]
 ;
   %m1 = call i8 @llvm.smax.i8(i8 %x, i8 %y)
   %m2 = call i8 @llvm.smax.i8(i8 %y, i8 %x)
@@ -1102,9 +1100,7 @@ define i8 @smax_smax_smax(i8 %x, i8 %y) {
 define i8 @smax_smax_smin(i8 %x, i8 %y) {
 ; CHECK-LABEL: @smax_smax_smin(
 ; CHECK-NEXT:    [[M1:%.*]] = call i8 @llvm.smax.i8(i8 [[X:%.*]], i8 [[Y:%.*]])
-; CHECK-NEXT:    [[M2:%.*]] = call i8 @llvm.smin.i8(i8 [[Y]], i8 [[X]])
-; CHECK-NEXT:    [[R:%.*]] = call i8 @llvm.smax.i8(i8 [[M1]], i8 [[M2]])
-; CHECK-NEXT:    ret i8 [[R]]
+; CHECK-NEXT:    ret i8 [[M1]]
 ;
   %m1 = call i8 @llvm.smax.i8(i8 %x, i8 %y)
   %m2 = call i8 @llvm.smin.i8(i8 %y, i8 %x)
@@ -1115,9 +1111,7 @@ define i8 @smax_smax_smin(i8 %x, i8 %y) {
 define i8 @smax_smax_umax(i8 %x, i8 %y) {
 ; CHECK-LABEL: @smax_smax_umax(
 ; CHECK-NEXT:    [[M1:%.*]] = call i8 @llvm.smax.i8(i8 [[X:%.*]], i8 [[Y:%.*]])
-; CHECK-NEXT:    [[M2:%.*]] = call i8 @llvm.umax.i8(i8 [[Y]], i8 [[X]])
-; CHECK-NEXT:    [[R:%.*]] = call i8 @llvm.smax.i8(i8 [[M1]], i8 [[M2]])
-; CHECK-NEXT:    ret i8 [[R]]
+; CHECK-NEXT:    ret i8 [[M1]]
 ;
   %m1 = call i8 @llvm.smax.i8(i8 %x, i8 %y)
   %m2 = call i8 @llvm.umax.i8(i8 %y, i8 %x)
@@ -1128,9 +1122,7 @@ define i8 @smax_smax_umax(i8 %x, i8 %y) {
 define i8 @smax_smax_umin(i8 %x, i8 %y) {
 ; CHECK-LABEL: @smax_smax_umin(
 ; CHECK-NEXT:    [[M1:%.*]] = call i8 @llvm.smax.i8(i8 [[X:%.*]], i8 [[Y:%.*]])
-; CHECK-NEXT:    [[M2:%.*]] = call i8 @llvm.umin.i8(i8 [[Y]], i8 [[X]])
-; CHECK-NEXT:    [[R:%.*]] = call i8 @llvm.smax.i8(i8 [[M1]], i8 [[M2]])
-; CHECK-NEXT:    ret i8 [[R]]
+; CHECK-NEXT:    ret i8 [[M1]]
 ;
   %m1 = call i8 @llvm.smax.i8(i8 %x, i8 %y)
   %m2 = call i8 @llvm.umin.i8(i8 %y, i8 %x)
@@ -1140,10 +1132,8 @@ define i8 @smax_smax_umin(i8 %x, i8 %y) {
 
 define i8 @smax_smin_smax(i8 %x, i8 %y) {
 ; CHECK-LABEL: @smax_smin_smax(
-; CHECK-NEXT:    [[M1:%.*]] = call i8 @llvm.smin.i8(i8 [[X:%.*]], i8 [[Y:%.*]])
-; CHECK-NEXT:    [[M2:%.*]] = call i8 @llvm.smax.i8(i8 [[Y]], i8 [[X]])
-; CHECK-NEXT:    [[R:%.*]] = call i8 @llvm.smax.i8(i8 [[M1]], i8 [[M2]])
-; CHECK-NEXT:    ret i8 [[R]]
+; CHECK-NEXT:    [[M2:%.*]] = call i8 @llvm.smax.i8(i8 [[Y:%.*]], i8 [[X:%.*]])
+; CHECK-NEXT:    ret i8 [[M2]]
 ;
   %m1 = call i8 @llvm.smin.i8(i8 %x, i8 %y)
   %m2 = call i8 @llvm.smax.i8(i8 %y, i8 %x)
@@ -1153,10 +1143,8 @@ define i8 @smax_smin_smax(i8 %x, i8 %y) {
 
 define i8 @smax_smin_smin(i8 %x, i8 %y) {
 ; CHECK-LABEL: @smax_smin_smin(
-; CHECK-NEXT:    [[M1:%.*]] = call i8 @llvm.smin.i8(i8 [[X:%.*]], i8 [[Y:%.*]])
-; CHECK-NEXT:    [[M2:%.*]] = call i8 @llvm.smin.i8(i8 [[Y]], i8 [[X]])
-; CHECK-NEXT:    [[R:%.*]] = call i8 @llvm.smax.i8(i8 [[M1]], i8 [[M2]])
-; CHECK-NEXT:    ret i8 [[R]]
+; CHECK-NEXT:    [[M2:%.*]] = call i8 @llvm.smin.i8(i8 [[Y:%.*]], i8 [[X:%.*]])
+; CHECK-NEXT:    ret i8 [[M2]]
 ;
   %m1 = call i8 @llvm.smin.i8(i8 %x, i8 %y)
   %m2 = call i8 @llvm.smin.i8(i8 %y, i8 %x)
@@ -1166,10 +1154,8 @@ define i8 @smax_smin_smin(i8 %x, i8 %y) {
 
 define i8 @smax_smin_umax(i8 %x, i8 %y) {
 ; CHECK-LABEL: @smax_smin_umax(
-; CHECK-NEXT:    [[M1:%.*]] = call i8 @llvm.smin.i8(i8 [[X:%.*]], i8 [[Y:%.*]])
-; CHECK-NEXT:    [[M2:%.*]] = call i8 @llvm.umax.i8(i8 [[Y]], i8 [[X]])
-; CHECK-NEXT:    [[R:%.*]] = call i8 @llvm.smax.i8(i8 [[M1]], i8 [[M2]])
-; CHECK-NEXT:    ret i8 [[R]]
+; CHECK-NEXT:    [[M2:%.*]] = call i8 @llvm.umax.i8(i8 [[Y:%.*]], i8 [[X:%.*]])
+; CHECK-NEXT:    ret i8 [[M2]]
 ;
   %m1 = call i8 @llvm.smin.i8(i8 %x, i8 %y)
   %m2 = call i8 @llvm.umax.i8(i8 %y, i8 %x)
@@ -1179,10 +1165,8 @@ define i8 @smax_smin_umax(i8 %x, i8 %y) {
 
 define i8 @smax_smin_umin(i8 %x, i8 %y) {
 ; CHECK-LABEL: @smax_smin_umin(
-; CHECK-NEXT:    [[M1:%.*]] = call i8 @llvm.smin.i8(i8 [[X:%.*]], i8 [[Y:%.*]])
-; CHECK-NEXT:    [[M2:%.*]] = call i8 @llvm.umin.i8(i8 [[Y]], i8 [[X]])
-; CHECK-NEXT:    [[R:%.*]] = call i8 @llvm.smax.i8(i8 [[M1]], i8 [[M2]])
-; CHECK-NEXT:    ret i8 [[R]]
+; CHECK-NEXT:    [[M2:%.*]] = call i8 @llvm.umin.i8(i8 [[Y:%.*]], i8 [[X:%.*]])
+; CHECK-NEXT:    ret i8 [[M2]]
 ;
   %m1 = call i8 @llvm.smin.i8(i8 %x, i8 %y)
   %m2 = call i8 @llvm.umin.i8(i8 %y, i8 %x)
@@ -1192,10 +1176,8 @@ define i8 @smax_smin_umin(i8 %x, i8 %y) {
 
 define i8 @smax_umax_smax(i8 %x, i8 %y) {
 ; CHECK-LABEL: @smax_umax_smax(
-; CHECK-NEXT:    [[M1:%.*]] = call i8 @llvm.umax.i8(i8 [[X:%.*]], i8 [[Y:%.*]])
-; CHECK-NEXT:    [[M2:%.*]] = call i8 @llvm.smax.i8(i8 [[Y]], i8 [[X]])
-; CHECK-NEXT:    [[R:%.*]] = call i8 @llvm.smax.i8(i8 [[M1]], i8 [[M2]])
-; CHECK-NEXT:    ret i8 [[R]]
+; CHECK-NEXT:    [[M2:%.*]] = call i8 @llvm.smax.i8(i8 [[Y:%.*]], i8 [[X:%.*]])
+; CHECK-NEXT:    ret i8 [[M2]]
 ;
   %m1 = call i8 @llvm.umax.i8(i8 %x, i8 %y)
   %m2 = call i8 @llvm.smax.i8(i8 %y, i8 %x)
@@ -1206,9 +1188,7 @@ define i8 @smax_umax_smax(i8 %x, i8 %y) {
 define i8 @smax_umax_smin(i8 %x, i8 %y) {
 ; CHECK-LABEL: @smax_umax_smin(
 ; CHECK-NEXT:    [[M1:%.*]] = call i8 @llvm.umax.i8(i8 [[X:%.*]], i8 [[Y:%.*]])
-; CHECK-NEXT:    [[M2:%.*]] = call i8 @llvm.smin.i8(i8 [[Y]], i8 [[X]])
-; CHECK-NEXT:    [[R:%.*]] = call i8 @llvm.smax.i8(i8 [[M1]], i8 [[M2]])
-; CHECK-NEXT:    ret i8 [[R]]
+; CHECK-NEXT:    ret i8 [[M1]]
 ;
   %m1 = call i8 @llvm.umax.i8(i8 %x, i8 %y)
   %m2 = call i8 @llvm.smin.i8(i8 %y, i8 %x)
@@ -1216,6 +1196,8 @@ define i8 @smax_umax_smin(i8 %x, i8 %y) {
   ret i8 %r
 }
 
+; This could simplify (commuted min/max op).
+
 define i8 @smax_umax_umax(i8 %x, i8 %y) {
 ; CHECK-LABEL: @smax_umax_umax(
 ; CHECK-NEXT:    [[M1:%.*]] = call i8 @llvm.umax.i8(i8 [[X:%.*]], i8 [[Y:%.*]])
@@ -1229,6 +1211,8 @@ define i8 @smax_umax_umax(i8 %x, i8 %y) {
   ret i8 %r
 }
 
+; This could combine - smax(x,y) - but does not simplify.
+
 define i8 @smax_umax_umin(i8 %x, i8 %y) {
 ; CHECK-LABEL: @smax_umax_umin(
 ; CHECK-NEXT:    [[M1:%.*]] = call i8 @llvm.umax.i8(i8 [[X:%.*]], i8 [[Y:%.*]])
@@ -1244,10 +1228,8 @@ define i8 @smax_umax_umin(i8 %x, i8 %y) {
 
 define i8 @smax_umin_smax(i8 %x, i8 %y) {
 ; CHECK-LABEL: @smax_umin_smax(
-; CHECK-NEXT:    [[M1:%.*]] = call i8 @llvm.umin.i8(i8 [[X:%.*]], i8 [[Y:%.*]])
-; CHECK-NEXT:    [[M2:%.*]] = call i8 @llvm.smax.i8(i8 [[Y]], i8 [[X]])
-; CHECK-NEXT:    [[R:%.*]] = call i8 @llvm.smax.i8(i8 [[M1]], i8 [[M2]])
-; CHECK-NEXT:    ret i8 [[R]]
+; CHECK-NEXT:    [[M2:%.*]] = call i8 @llvm.smax.i8(i8 [[Y:%.*]], i8 [[X:%.*]])
+; CHECK-NEXT:    ret i8 [[M2]]
 ;
   %m1 = call i8 @llvm.umin.i8(i8 %x, i8 %y)
   %m2 = call i8 @llvm.smax.i8(i8 %y, i8 %x)
@@ -1258,9 +1240,7 @@ define i8 @smax_umin_smax(i8 %x, i8 %y) {
 define i8 @smax_umin_smin(i8 %x, i8 %y) {
 ; CHECK-LABEL: @smax_umin_smin(
 ; CHECK-NEXT:    [[M1:%.*]] = call i8 @llvm.umin.i8(i8 [[X:%.*]], i8 [[Y:%.*]])
-; CHECK-NEXT:    [[M2:%.*]] = call i8 @llvm.smin.i8(i8 [[Y]], i8 [[X]])
-; CHECK-NEXT:    [[R:%.*]] = call i8 @llvm.smax.i8(i8 [[M1]], i8 [[M2]])
-; CHECK-NEXT:    ret i8 [[R]]
+; CHECK-NEXT:    ret i8 [[M1]]
 ;
   %m1 = call i8 @llvm.umin.i8(i8 %x, i8 %y)
   %m2 = call i8 @llvm.smin.i8(i8 %y, i8 %x)
@@ -1268,6 +1248,8 @@ define i8 @smax_umin_smin(i8 %x, i8 %y) {
   ret i8 %r
 }
 
+; This could combine - smax(x,y) - but does not simplify.
+
 define i8 @smax_umin_umax(i8 %x, i8 %y) {
 ; CHECK-LABEL: @smax_umin_umax(
 ; CHECK-NEXT:    [[M1:%.*]] = call i8 @llvm.umin.i8(i8 [[X:%.*]], i8 [[Y:%.*]])
@@ -1281,6 +1263,8 @@ define i8 @smax_umin_umax(i8 %x, i8 %y) {
   ret i8 %r
 }
 
+; This could simplify (commuted min/max op).
+
 define i8 @smax_umin_umin(i8 %x, i8 %y) {
 ; CHECK-LABEL: @smax_umin_umin(
 ; CHECK-NEXT:    [[M1:%.*]] = call i8 @llvm.umin.i8(i8 [[X:%.*]], i8 [[Y:%.*]])
@@ -1296,10 +1280,8 @@ define i8 @smax_umin_umin(i8 %x, i8 %y) {
 
 define i8 @smin_smax_smax(i8 %x, i8 %y) {
 ; CHECK-LABEL: @smin_smax_smax(
-; CHECK-NEXT:    [[M1:%.*]] = call i8 @llvm.smax.i8(i8 [[X:%.*]], i8 [[Y:%.*]])
-; CHECK-NEXT:    [[M2:%.*]] = call i8 @llvm.smax.i8(i8 [[Y]], i8 [[X]])
-; CHECK-NEXT:    [[R:%.*]] = call i8 @llvm.smin.i8(i8 [[M1]], i8 [[M2]])
-; CHECK-NEXT:    ret i8 [[R]]
+; CHECK-NEXT:    [[M2:%.*]] = call i8 @llvm.smax.i8(i8 [[Y:%.*]], i8 [[X:%.*]])
+; CHECK-NEXT:    ret i8 [[M2]]
 ;
   %m1 = call i8 @llvm.smax.i8(i8 %x, i8 %y)
   %m2 = call i8 @llvm.smax.i8(i8 %y, i8 %x)
@@ -1309,10 +1291,8 @@ define i8 @smin_smax_smax(i8 %x, i8 %y) {
 
 define i8 @smin_smax_smin(i8 %x, i8 %y) {
 ; CHECK-LABEL: @smin_smax_smin(
-; CHECK-NEXT:    [[M1:%.*]] = call i8 @llvm.smax.i8(i8 [[X:%.*]], i8 [[Y:%.*]])
-; CHECK-NEXT:    [[M2:%.*]] = call i8 @llvm.smin.i8(i8 [[Y]], i8 [[X]])
-; CHECK-NEXT:    [[R:%.*]] = call i8 @llvm.smin.i8(i8 [[M1]], i8 [[M2]])
-; CHECK-NEXT:    ret i8 [[R]]
+; CHECK-NEXT:    [[M2:%.*]] = call i8 @llvm.smin.i8(i8 [[Y:%.*]], i8 [[X:%.*]])
+; CHECK-NEXT:    ret i8 [[M2]]
 ;
   %m1 = call i8 @llvm.smax.i8(i8 %x, i8 %y)
   %m2 = call i8 @llvm.smin.i8(i8 %y, i8 %x)
@@ -1322,10 +1302,8 @@ define i8 @smin_smax_smin(i8 %x, i8 %y) {
 
 define i8 @smin_smax_umax(i8 %x, i8 %y) {
 ; CHECK-LABEL: @smin_smax_umax(
-; CHECK-NEXT:    [[M1:%.*]] = call i8 @llvm.smax.i8(i8 [[X:%.*]], i8 [[Y:%.*]])
-; CHECK-NEXT:    [[M2:%.*]] = call i8 @llvm.umax.i8(i8 [[Y]], i8 [[X]])
-; CHECK-NEXT:    [[R:%.*]] = call i8 @llvm.smin.i8(i8 [[M1]], i8 [[M2]])
-; CHECK-NEXT:    ret i8 [[R]]
+; CHECK-NEXT:    [[M2:%.*]] = call i8 @llvm.umax.i8(i8 [[Y:%.*]], i8 [[X:%.*]])
+; CHECK-NEXT:    ret i8 [[M2]]
 ;
   %m1 = call i8 @llvm.smax.i8(i8 %x, i8 %y)
   %m2 = call i8 @llvm.umax.i8(i8 %y, i8 %x)
@@ -1335,10 +1313,8 @@ define i8 @smin_smax_umax(i8 %x, i8 %y) {
 
 define i8 @smin_smax_umin(i8 %x, i8 %y) {
 ; CHECK-LABEL: @smin_smax_umin(
-; CHECK-NEXT:    [[M1:%.*]] = call i8 @llvm.smax.i8(i8 [[X:%.*]], i8 [[Y:%.*]])
-; CHECK-NEXT:    [[M2:%.*]] = call i8 @llvm.umin.i8(i8 [[Y]], i8 [[X]])
-; CHECK-NEXT:    [[R:%.*]] = call i8 @llvm.smin.i8(i8 [[M1]], i8 [[M2]])
-; CHECK-NEXT:    ret i8 [[R]]
+; CHECK-NEXT:    [[M2:%.*]] = call i8 @llvm.umin.i8(i8 [[Y:%.*]], i8 [[X:%.*]])
+; CHECK-NEXT:    ret i8 [[M2]]
 ;
   %m1 = call i8 @llvm.smax.i8(i8 %x, i8 %y)
   %m2 = call i8 @llvm.umin.i8(i8 %y, i8 %x)
@@ -1349,9 +1325,7 @@ define i8 @smin_smax_umin(i8 %x, i8 %y) {
 define i8 @smin_smin_smax(i8 %x, i8 %y) {
 ; CHECK-LABEL: @smin_smin_smax(
 ; CHECK-NEXT:    [[M1:%.*]] = call i8 @llvm.smin.i8(i8 [[X:%.*]], i8 [[Y:%.*]])
-; CHECK-NEXT:    [[M2:%.*]] = call i8 @llvm.smax.i8(i8 [[Y]], i8 [[X]])
-; CHECK-NEXT:    [[R:%.*]] = call i8 @llvm.smin.i8(i8 [[M1]], i8 [[M2]])
-; CHECK-NEXT:    ret i8 [[R]]
+; CHECK-NEXT:    ret i8 [[M1]]
 ;
   %m1 = call i8 @llvm.smin.i8(i8 %x, i8 %y)
   %m2 = call i8 @llvm.smax.i8(i8 %y, i8 %x)
@@ -1362,9 +1336,7 @@ define i8 @smin_smin_smax(i8 %x, i8 %y) {
 define i8 @smin_smin_smin(i8 %x, i8 %y) {
 ; CHECK-LABEL: @smin_smin_smin(
 ; CHECK-NEXT:    [[M1:%.*]] = call i8 @llvm.smin.i8(i8 [[X:%.*]], i8 [[Y:%.*]])
-; CHECK-NEXT:    [[M2:%.*]] = call i8 @llvm.smin.i8(i8 [[Y]], i8 [[X]])
-; CHECK-NEXT:    [[R:%.*]] = call i8 @llvm.smin.i8(i8 [[M1]], i8 [[M2]])
-; CHECK-NEXT:    ret i8 [[R]]
+; CHECK-NEXT:    ret i8 [[M1]]
 ;
   %m1 = call i8 @llvm.smin.i8(i8 %x, i8 %y)
   %m2 = call i8 @llvm.smin.i8(i8 %y, i8 %x)
@@ -1375,9 +1347,7 @@ define i8 @smin_smin_smin(i8 %x, i8 %y) {
 define i8 @smin_smin_umax(i8 %x, i8 %y) {
 ; CHECK-LABEL: @smin_smin_umax(
 ; CHECK-NEXT:    [[M1:%.*]] = call i8 @llvm.smin.i8(i8 [[X:%.*]], i8 [[Y:%.*]])
-; CHECK-NEXT:    [[M2:%.*]] = call i8 @llvm.umax.i8(i8 [[Y]], i8 [[X]])
-; CHECK-NEXT:    [[R:%.*]] = call i8 @llvm.smin.i8(i8 [[M1]], i8 [[M2]])
-; CHECK-NEXT:    ret i8 [[R]]
+; CHECK-NEXT:    ret i8 [[M1]]
 ;
   %m1 = call i8 @llvm.smin.i8(i8 %x, i8 %y)
   %m2 = call i8 @llvm.umax.i8(i8 %y, i8 %x)
@@ -1388,9 +1358,7 @@ define i8 @smin_smin_umax(i8 %x, i8 %y) {
 define i8 @smin_smin_umin(i8 %x, i8 %y) {
 ; CHECK-LABEL: @smin_smin_umin(
 ; CHECK-NEXT:    [[M1:%.*]] = call i8 @llvm.smin.i8(i8 [[X:%.*]], i8 [[Y:%.*]])
-; CHECK-NEXT:    [[M2:%.*]] = call i8 @llvm.umin.i8(i8 [[Y]], i8 [[X]])
-; CHECK-NEXT:    [[R:%.*]] = call i8 @llvm.smin.i8(i8 [[M1]], i8 [[M2]])
-; CHECK-NEXT:    ret i8 [[R]]
+; CHECK-NEXT:    ret i8 [[M1]]
 ;
   %m1 = call i8 @llvm.smin.i8(i8 %x, i8 %y)
   %m2 = call i8 @llvm.umin.i8(i8 %y, i8 %x)
@@ -1401,9 +1369,7 @@ define i8 @smin_smin_umin(i8 %x, i8 %y) {
 define i8 @smin_umax_smax(i8 %x, i8 %y) {
 ; CHECK-LABEL: @smin_umax_smax(
 ; CHECK-NEXT:    [[M1:%.*]] = call i8 @llvm.umax.i8(i8 [[X:%.*]], i8 [[Y:%.*]])
-; CHECK-NEXT:    [[M2:%.*]] = call i8 @llvm.smax.i8(i8 [[Y]], i8 [[X]])
-; CHECK-NEXT:    [[R:%.*]] = call i8 @llvm.smin.i8(i8 [[M1]], i8 [[M2]])
-; CHECK-NEXT:    ret i8 [[R]]
+; CHECK-NEXT:    ret i8 [[M1]]
 ;
   %m1 = call i8 @llvm.umax.i8(i8 %x, i8 %y)
   %m2 = call i8 @llvm.smax.i8(i8 %y, i8 %x)
@@ -1413,10 +1379,8 @@ define i8 @smin_umax_smax(i8 %x, i8 %y) {
 
 define i8 @smin_umax_smin(i8 %x, i8 %y) {
 ; CHECK-LABEL: @smin_umax_smin(
-; CHECK-NEXT:    [[M1:%.*]] = call i8 @llvm.umax.i8(i8 [[X:%.*]], i8 [[Y:%.*]])
-; CHECK-NEXT:    [[M2:%.*]] = call i8 @llvm.smin.i8(i8 [[Y]], i8 [[X]])
-; CHECK-NEXT:    [[R:%.*]] = call i8 @llvm.smin.i8(i8 [[M1]], i8 [[M2]])
-; CHECK-NEXT:    ret i8 [[R]]
+; CHECK-NEXT:    [[M2:%.*]] = call i8 @llvm.smin.i8(i8 [[Y:%.*]], i8 [[X:%.*]])
+; CHECK-NEXT:    ret i8 [[M2]]
 ;
   %m1 = call i8 @llvm.umax.i8(i8 %x, i8 %y)
   %m2 = call i8 @llvm.smin.i8(i8 %y, i8 %x)
@@ -1424,6 +1388,8 @@ define i8 @smin_umax_smin(i8 %x, i8 %y) {
   ret i8 %r
 }
 
+; This could simplify (commuted min/max op).
+
 define i8 @smin_umax_umax(i8 %x, i8 %y) {
 ; CHECK-LABEL: @smin_umax_umax(
 ; CHECK-NEXT:    [[M1:%.*]] = call i8 @llvm.umax.i8(i8 [[X:%.*]], i8 [[Y:%.*]])
@@ -1437,6 +1403,8 @@ define i8 @smin_umax_umax(i8 %x, i8 %y) {
   ret i8 %r
 }
 
+; This could combine - smin(x,y) - but does not simplify.
+
 define i8 @smin_umax_umin(i8 %x, i8 %y) {
 ; CHECK-LABEL: @smin_umax_umin(
 ; CHECK-NEXT:    [[M1:%.*]] = call i8 @llvm.umax.i8(i8 [[X:%.*]], i8 [[Y:%.*]])
@@ -1453,9 +1421,7 @@ define i8 @smin_umax_umin(i8 %x, i8 %y) {
 define i8 @smin_umin_smax(i8 %x, i8 %y) {
 ; CHECK-LABEL: @smin_umin_smax(
 ; CHECK-NEXT:    [[M1:%.*]] = call i8 @llvm.umin.i8(i8 [[X:%.*]], i8 [[Y:%.*]])
-; CHECK-NEXT:    [[M2:%.*]] = call i8 @llvm.smax.i8(i8 [[Y]], i8 [[X]])
-; CHECK-NEXT:    [[R:%.*]] = call i8 @llvm.smin.i8(i8 [[M1]], i8 [[M2]])
-; CHECK-NEXT:    ret i8 [[R]]
+; CHECK-NEXT:    ret i8 [[M1]]
 ;
   %m1 = call i8 @llvm.umin.i8(i8 %x, i8 %y)
   %m2 = call i8 @llvm.smax.i8(i8 %y, i8 %x)
@@ -1465,10 +1431,8 @@ define i8 @smin_umin_smax(i8 %x, i8 %y) {
 
 define i8 @smin_umin_smin(i8 %x, i8 %y) {
 ; CHECK-LABEL: @smin_umin_smin(
-; CHECK-NEXT:    [[M1:%.*]] = call i8 @llvm.umin.i8(i8 [[X:%.*]], i8 [[Y:%.*]])
-; CHECK-NEXT:    [[M2:%.*]] = call i8 @llvm.smin.i8(i8 [[Y]], i8 [[X]])
-; CHECK-NEXT:    [[R:%.*]] = call i8 @llvm.smin.i8(i8 [[M1]], i8 [[M2]])
-; CHECK-NEXT:    ret i8 [[R]]
+; CHECK-NEXT:    [[M2:%.*]] = call i8 @llvm.smin.i8(i8 [[Y:%.*]], i8 [[X:%.*]])
+; CHECK-NEXT:    ret i8 [[M2]]
 ;
   %m1 = call i8 @llvm.umin.i8(i8 %x, i8 %y)
   %m2 = call i8 @llvm.smin.i8(i8 %y, i8 %x)
@@ -1476,6 +1440,8 @@ define i8 @smin_umin_smin(i8 %x, i8 %y) {
   ret i8 %r
 }
 
+; This could combine - smin(x,y) - but does not simplify.
+
 define i8 @smin_umin_umax(i8 %x, i8 %y) {
 ; CHECK-LABEL: @smin_umin_umax(
 ; CHECK-NEXT:    [[M1:%.*]] = call i8 @llvm.umin.i8(i8 [[X:%.*]], i8 [[Y:%.*]])
@@ -1489,6 +1455,8 @@ define i8 @smin_umin_umax(i8 %x, i8 %y) {
   ret i8 %r
 }
 
+; This could simplify (commuted min/max op).
+
 define i8 @smin_umin_umin(i8 %x, i8 %y) {
 ; CHECK-LABEL: @smin_umin_umin(
 ; CHECK-NEXT:    [[M1:%.*]] = call i8 @llvm.umin.i8(i8 [[X:%.*]], i8 [[Y:%.*]])
@@ -1502,6 +1470,8 @@ define i8 @smin_umin_umin(i8 %x, i8 %y) {
   ret i8 %r
 }
 
+; This could simplify (commuted min/max op).
+
 define i8 @umax_smax_smax(i8 %x, i8 %y) {
 ; CHECK-LABEL: @umax_smax_smax(
 ; CHECK-NEXT:    [[M1:%.*]] = call i8 @llvm.smax.i8(i8 [[X:%.*]], i8 [[Y:%.*]])
@@ -1515,6 +1485,8 @@ define i8 @umax_smax_smax(i8 %x, i8 %y) {
   ret i8 %r
 }
 
+; This could combine - umax(x,y) - but does not simplify.
+
 define i8 @umax_smax_smin(i8 %x, i8 %y) {
 ; CHECK-LABEL: @umax_smax_smin(
 ; CHECK-NEXT:    [[M1:%.*]] = call i8 @llvm.smax.i8(i8 [[X:%.*]], i8 [[Y:%.*]])
@@ -1530,10 +1502,8 @@ define i8 @umax_smax_smin(i8 %x, i8 %y) {
 
 define i8 @umax_smax_umax(i8 %x, i8 %y) {
 ; CHECK-LABEL: @umax_smax_umax(
-; CHECK-NEXT:    [[M1:%.*]] = call i8 @llvm.smax.i8(i8 [[X:%.*]], i8 [[Y:%.*]])
-; CHECK-NEXT:    [[M2:%.*]] = call i8 @llvm.umax.i8(i8 [[Y]], i8 [[X]])
-; CHECK-NEXT:    [[R:%.*]] = call i8 @llvm.umax.i8(i8 [[M1]], i8 [[M2]])
-; CHECK-NEXT:    ret i8 [[R]]
+; CHECK-NEXT:    [[M2:%.*]] = call i8 @llvm.umax.i8(i8 [[Y:%.*]], i8 [[X:%.*]])
+; CHECK-NEXT:    ret i8 [[M2]]
 ;
   %m1 = call i8 @llvm.smax.i8(i8 %x, i8 %y)
   %m2 = call i8 @llvm.umax.i8(i8 %y, i8 %x)
@@ -1544,9 +1514,7 @@ define i8 @umax_smax_umax(i8 %x, i8 %y) {
 define i8 @umax_smax_umin(i8 %x, i8 %y) {
 ; CHECK-LABEL: @umax_smax_umin(
 ; CHECK-NEXT:    [[M1:%.*]] = call i8 @llvm.smax.i8(i8 [[X:%.*]], i8 [[Y:%.*]])
-; CHECK-NEXT:    [[M2:%.*]] = call i8 @llvm.umin.i8(i8 [[Y]], i8 [[X]])
-; CHECK-NEXT:    [[R:%.*]] = call i8 @llvm.umax.i8(i8 [[M1]], i8 [[M2]])
-; CHECK-NEXT:    ret i8 [[R]]
+; CHECK-NEXT:    ret i8 [[M1]]
 ;
   %m1 = call i8 @llvm.smax.i8(i8 %x, i8 %y)
   %m2 = call i8 @llvm.umin.i8(i8 %y, i8 %x)
@@ -1554,6 +1522,8 @@ define i8 @umax_smax_umin(i8 %x, i8 %y) {
   ret i8 %r
 }
 
+; This could combine - umax(x,y) - but does not simplify.
+
 define i8 @umax_smin_smax(i8 %x, i8 %y) {
 ; CHECK-LABEL: @umax_smin_smax(
 ; CHECK-NEXT:    [[M1:%.*]] = call i8 @llvm.smin.i8(i8 [[X:%.*]], i8 [[Y:%.*]])
@@ -1567,6 +1537,8 @@ define i8 @umax_smin_smax(i8 %x, i8 %y) {
   ret i8 %r
 }
 
+; This could simplify (commuted min/max op).
+
 define i8 @umax_smin_smin(i8 %x, i8 %y) {
 ; CHECK-LABEL: @umax_smin_smin(
 ; CHECK-NEXT:    [[M1:%.*]] = call i8 @llvm.smin.i8(i8 [[X:%.*]], i8 [[Y:%.*]])
@@ -1582,10 +1554,8 @@ define i8 @umax_smin_smin(i8 %x, i8 %y) {
 
 define i8 @umax_smin_umax(i8 %x, i8 %y) {
 ; CHECK-LABEL: @umax_smin_umax(
-; CHECK-NEXT:    [[M1:%.*]] = call i8 @llvm.smin.i8(i8 [[X:%.*]], i8 [[Y:%.*]])
-; CHECK-NEXT:    [[M2:%.*]] = call i8 @llvm.umax.i8(i8 [[Y]], i8 [[X]])
-; CHECK-NEXT:    [[R:%.*]] = call i8 @llvm.umax.i8(i8 [[M1]], i8 [[M2]])
-; CHECK-NEXT:    ret i8 [[R]]
+; CHECK-NEXT:    [[M2:%.*]] = call i8 @llvm.umax.i8(i8 [[Y:%.*]], i8 [[X:%.*]])
+; CHECK-NEXT:    ret i8 [[M2]]
 ;
   %m1 = call i8 @llvm.smin.i8(i8 %x, i8 %y)
   %m2 = call i8 @llvm.umax.i8(i8 %y, i8 %x)
@@ -1596,9 +1566,7 @@ define i8 @umax_smin_umax(i8 %x, i8 %y) {
 define i8 @umax_smin_umin(i8 %x, i8 %y) {
 ; CHECK-LABEL: @umax_smin_umin(
 ; CHECK-NEXT:    [[M1:%.*]] = call i8 @llvm.smin.i8(i8 [[X:%.*]], i8 [[Y:%.*]])
-; CHECK-NEXT:    [[M2:%.*]] = call i8 @llvm.umin.i8(i8 [[Y]], i8 [[X]])
-; CHECK-NEXT:    [[R:%.*]] = call i8 @llvm.umax.i8(i8 [[M1]], i8 [[M2]])
-; CHECK-NEXT:    ret i8 [[R]]
+; CHECK-NEXT:    ret i8 [[M1]]
 ;
   %m1 = call i8 @llvm.smin.i8(i8 %x, i8 %y)
   %m2 = call i8 @llvm.umin.i8(i8 %y, i8 %x)
@@ -1609,9 +1577,7 @@ define i8 @umax_smin_umin(i8 %x, i8 %y) {
 define i8 @umax_umax_smax(i8 %x, i8 %y) {
 ; CHECK-LABEL: @umax_umax_smax(
 ; CHECK-NEXT:    [[M1:%.*]] = call i8 @llvm.umax.i8(i8 [[X:%.*]], i8 [[Y:%.*]])
-; CHECK-NEXT:    [[M2:%.*]] = call i8 @llvm.smax.i8(i8 [[Y]], i8 [[X]])
-; CHECK-NEXT:    [[R:%.*]] = call i8 @llvm.umax.i8(i8 [[M1]], i8 [[M2]])
-; CHECK-NEXT:    ret i8 [[R]]
+; CHECK-NEXT:    ret i8 [[M1]]
 ;
   %m1 = call i8 @llvm.umax.i8(i8 %x, i8 %y)
   %m2 = call i8 @llvm.smax.i8(i8 %y, i8 %x)
@@ -1622,9 +1588,7 @@ define i8 @umax_umax_smax(i8 %x, i8 %y) {
 define i8 @umax_umax_smin(i8 %x, i8 %y) {
 ; CHECK-LABEL: @umax_umax_smin(
 ; CHECK-NEXT:    [[M1:%.*]] = call i8 @llvm.umax.i8(i8 [[X:%.*]], i8 [[Y:%.*]])
-; CHECK-NEXT:    [[M2:%.*]] = call i8 @llvm.smin.i8(i8 [[Y]], i8 [[X]])
-; CHECK-NEXT:    [[R:%.*]] = call i8 @llvm.umax.i8(i8 [[M1]], i8 [[M2]])
-; CHECK-NEXT:    ret i8 [[R]]
+; CHECK-NEXT:    ret i8 [[M1]]
 ;
   %m1 = call i8 @llvm.umax.i8(i8 %x, i8 %y)
   %m2 = call i8 @llvm.smin.i8(i8 %y, i8 %x)
@@ -1635,9 +1599,7 @@ define i8 @umax_umax_smin(i8 %x, i8 %y) {
 define i8 @umax_umax_umax(i8 %x, i8 %y) {
 ; CHECK-LABEL: @umax_umax_umax(
 ; CHECK-NEXT:    [[M1:%.*]] = call i8 @llvm.umax.i8(i8 [[X:%.*]], i8 [[Y:%.*]])
-; CHECK-NEXT:    [[M2:%.*]] = call i8 @llvm.umax.i8(i8 [[Y]], i8 [[X]])
-; CHECK-NEXT:    [[R:%.*]] = call i8 @llvm.umax.i8(i8 [[M1]], i8 [[M2]])
-; CHECK-NEXT:    ret i8 [[R]]
+; CHECK-NEXT:    ret i8 [[M1]]
 ;
   %m1 = call i8 @llvm.umax.i8(i8 %x, i8 %y)
   %m2 = call i8 @llvm.umax.i8(i8 %y, i8 %x)
@@ -1648,9 +1610,7 @@ define i8 @umax_umax_umax(i8 %x, i8 %y) {
 define i8 @umax_umax_umin(i8 %x, i8 %y) {
 ; CHECK-LABEL: @umax_umax_umin(
 ; CHECK-NEXT:    [[M1:%.*]] = call i8 @llvm.umax.i8(i8 [[X:%.*]], i8 [[Y:%.*]])
-; CHECK-NEXT:    [[M2:%.*]] = call i8 @llvm.umin.i8(i8 [[Y]], i8 [[X]])
-; CHECK-NEXT:    [[R:%.*]] = call i8 @llvm.umax.i8(i8 [[M1]], i8 [[M2]])
-; CHECK-NEXT:    ret i8 [[R]]
+; CHECK-NEXT:    ret i8 [[M1]]
 ;
   %m1 = call i8 @llvm.umax.i8(i8 %x, i8 %y)
   %m2 = call i8 @llvm.umin.i8(i8 %y, i8 %x)
@@ -1660,10 +1620,8 @@ define i8 @umax_umax_umin(i8 %x, i8 %y) {
 
 define i8 @umax_umin_smax(i8 %x, i8 %y) {
 ; CHECK-LABEL: @umax_umin_smax(
-; CHECK-NEXT:    [[M1:%.*]] = call i8 @llvm.umin.i8(i8 [[X:%.*]], i8 [[Y:%.*]])
-; CHECK-NEXT:    [[M2:%.*]] = call i8 @llvm.smax.i8(i8 [[Y]], i8 [[X]])
-; CHECK-NEXT:    [[R:%.*]] = call i8 @llvm.umax.i8(i8 [[M1]], i8 [[M2]])
-; CHECK-NEXT:    ret i8 [[R]]
+; CHECK-NEXT:    [[M2:%.*]] = call i8 @llvm.smax.i8(i8 [[Y:%.*]], i8 [[X:%.*]])
+; CHECK-NEXT:    ret i8 [[M2]]
 ;
   %m1 = call i8 @llvm.umin.i8(i8 %x, i8 %y)
   %m2 = call i8 @llvm.smax.i8(i8 %y, i8 %x)
@@ -1673,10 +1631,8 @@ define i8 @umax_umin_smax(i8 %x, i8 %y) {
 
 define i8 @umax_umin_smin(i8 %x, i8 %y) {
 ; CHECK-LABEL: @umax_umin_smin(
-; CHECK-NEXT:    [[M1:%.*]] = call i8 @llvm.umin.i8(i8 [[X:%.*]], i8 [[Y:%.*]])
-; CHECK-NEXT:    [[M2:%.*]] = call i8 @llvm.smin.i8(i8 [[Y]], i8 [[X]])
-; CHECK-NEXT:    [[R:%.*]] = call i8 @llvm.umax.i8(i8 [[M1]], i8 [[M2]])
-; CHECK-NEXT:    ret i8 [[R]]
+; CHECK-NEXT:    [[M2:%.*]] = call i8 @llvm.smin.i8(i8 [[Y:%.*]], i8 [[X:%.*]])
+; CHECK-NEXT:    ret i8 [[M2]]
 ;
   %m1 = call i8 @llvm.umin.i8(i8 %x, i8 %y)
   %m2 = call i8 @llvm.smin.i8(i8 %y, i8 %x)
@@ -1686,10 +1642,8 @@ define i8 @umax_umin_smin(i8 %x, i8 %y) {
 
 define i8 @umax_umin_umax(i8 %x, i8 %y) {
 ; CHECK-LABEL: @umax_umin_umax(
-; CHECK-NEXT:    [[M1:%.*]] = call i8 @llvm.umin.i8(i8 [[X:%.*]], i8 [[Y:%.*]])
-; CHECK-NEXT:    [[M2:%.*]] = call i8 @llvm.umax.i8(i8 [[Y]], i8 [[X]])
-; CHECK-NEXT:    [[R:%.*]] = call i8 @llvm.umax.i8(i8 [[M1]], i8 [[M2]])
-; CHECK-NEXT:    ret i8 [[R]]
+; CHECK-NEXT:    [[M2:%.*]] = call i8 @llvm.umax.i8(i8 [[Y:%.*]], i8 [[X:%.*]])
+; CHECK-NEXT:    ret i8 [[M2]]
 ;
   %m1 = call i8 @llvm.umin.i8(i8 %x, i8 %y)
   %m2 = call i8 @llvm.umax.i8(i8 %y, i8 %x)
@@ -1699,10 +1653,8 @@ define i8 @umax_umin_umax(i8 %x, i8 %y) {
 
 define i8 @umax_umin_umin(i8 %x, i8 %y) {
 ; CHECK-LABEL: @umax_umin_umin(
-; CHECK-NEXT:    [[M1:%.*]] = call i8 @llvm.umin.i8(i8 [[X:%.*]], i8 [[Y:%.*]])
-; CHECK-NEXT:    [[M2:%.*]] = call i8 @llvm.umin.i8(i8 [[Y]], i8 [[X]])
-; CHECK-NEXT:    [[R:%.*]] = call i8 @llvm.umax.i8(i8 [[M1]], i8 [[M2]])
-; CHECK-NEXT:    ret i8 [[R]]
+; CHECK-NEXT:    [[M2:%.*]] = call i8 @llvm.umin.i8(i8 [[Y:%.*]], i8 [[X:%.*]])
+; CHECK-NEXT:    ret i8 [[M2]]
 ;
   %m1 = call i8 @llvm.umin.i8(i8 %x, i8 %y)
   %m2 = call i8 @llvm.umin.i8(i8 %y, i8 %x)
@@ -1710,6 +1662,8 @@ define i8 @umax_umin_umin(i8 %x, i8 %y) {
   ret i8 %r
 }
 
+; This could simplify (commuted min/max op).
+
 define i8 @umin_smax_smax(i8 %x, i8 %y) {
 ; CHECK-LABEL: @umin_smax_smax(
 ; CHECK-NEXT:    [[M1:%.*]] = call i8 @llvm.smax.i8(i8 [[X:%.*]], i8 [[Y:%.*]])
@@ -1723,6 +1677,8 @@ define i8 @umin_smax_smax(i8 %x, i8 %y) {
   ret i8 %r
 }
 
+; This could combine - umin(x,y) - but does not simplify.
+
 define i8 @umin_smax_smin(i8 %x, i8 %y) {
 ; CHECK-LABEL: @umin_smax_smin(
 ; CHECK-NEXT:    [[M1:%.*]] = call i8 @llvm.smax.i8(i8 [[X:%.*]], i8 [[Y:%.*]])
@@ -1739,9 +1695,7 @@ define i8 @umin_smax_smin(i8 %x, i8 %y) {
 define i8 @umin_smax_umax(i8 %x, i8 %y) {
 ; CHECK-LABEL: @umin_smax_umax(
 ; CHECK-NEXT:    [[M1:%.*]] = call i8 @llvm.smax.i8(i8 [[X:%.*]], i8 [[Y:%.*]])
-; CHECK-NEXT:    [[M2:%.*]] = call i8 @llvm.umax.i8(i8 [[Y]], i8 [[X]])
-; CHECK-NEXT:    [[R:%.*]] = call i8 @llvm.umin.i8(i8 [[M1]], i8 [[M2]])
-; CHECK-NEXT:    ret i8 [[R]]
+; CHECK-NEXT:    ret i8 [[M1]]
 ;
   %m1 = call i8 @llvm.smax.i8(i8 %x, i8 %y)
   %m2 = call i8 @llvm.umax.i8(i8 %y, i8 %x)
@@ -1751,10 +1705,8 @@ define i8 @umin_smax_umax(i8 %x, i8 %y) {
 
 define i8 @umin_smax_umin(i8 %x, i8 %y) {
 ; CHECK-LABEL: @umin_smax_umin(
-; CHECK-NEXT:    [[M1:%.*]] = call i8 @llvm.smax.i8(i8 [[X:%.*]], i8 [[Y:%.*]])
-; CHECK-NEXT:    [[M2:%.*]] = call i8 @llvm.umin.i8(i8 [[Y]], i8 [[X]])
-; CHECK-NEXT:    [[R:%.*]] = call i8 @llvm.umin.i8(i8 [[M1]], i8 [[M2]])
-; CHECK-NEXT:    ret i8 [[R]]
+; CHECK-NEXT:    [[M2:%.*]] = call i8 @llvm.umin.i8(i8 [[Y:%.*]], i8 [[X:%.*]])
+; CHECK-NEXT:    ret i8 [[M2]]
 ;
   %m1 = call i8 @llvm.smax.i8(i8 %x, i8 %y)
   %m2 = call i8 @llvm.umin.i8(i8 %y, i8 %x)
@@ -1762,6 +1714,8 @@ define i8 @umin_smax_umin(i8 %x, i8 %y) {
   ret i8 %r
 }
 
+; This could combine - umin(x,y) - but does not simplify.
+
 define i8 @umin_smin_smax(i8 %x, i8 %y) {
 ; CHECK-LABEL: @umin_smin_smax(
 ; CHECK-NEXT:    [[M1:%.*]] = call i8 @llvm.smin.i8(i8 [[X:%.*]], i8 [[Y:%.*]])
@@ -1775,6 +1729,8 @@ define i8 @umin_smin_smax(i8 %x, i8 %y) {
   ret i8 %r
 }
 
+; This could simplify (commuted min/max op).
+
 define i8 @umin_smin_smin(i8 %x, i8 %y) {
 ; CHECK-LABEL: @umin_smin_smin(
 ; CHECK-NEXT:    [[M1:%.*]] = call i8 @llvm.smin.i8(i8 [[X:%.*]], i8 [[Y:%.*]])
@@ -1791,9 +1747,7 @@ define i8 @umin_smin_smin(i8 %x, i8 %y) {
 define i8 @umin_smin_umax(i8 %x, i8 %y) {
 ; CHECK-LABEL: @umin_smin_umax(
 ; CHECK-NEXT:    [[M1:%.*]] = call i8 @llvm.smin.i8(i8 [[X:%.*]], i8 [[Y:%.*]])
-; CHECK-NEXT:    [[M2:%.*]] = call i8 @llvm.umax.i8(i8 [[Y]], i8 [[X]])
-; CHECK-NEXT:    [[R:%.*]] = call i8 @llvm.umin.i8(i8 [[M1]], i8 [[M2]])
-; CHECK-NEXT:    ret i8 [[R]]
+; CHECK-NEXT:    ret i8 [[M1]]
 ;
   %m1 = call i8 @llvm.smin.i8(i8 %x, i8 %y)
   %m2 = call i8 @llvm.umax.i8(i8 %y, i8 %x)
@@ -1803,10 +1757,8 @@ define i8 @umin_smin_umax(i8 %x, i8 %y) {
 
 define i8 @umin_smin_umin(i8 %x, i8 %y) {
 ; CHECK-LABEL: @umin_smin_umin(
-; CHECK-NEXT:    [[M1:%.*]] = call i8 @llvm.smin.i8(i8 [[X:%.*]], i8 [[Y:%.*]])
-; CHECK-NEXT:    [[M2:%.*]] = call i8 @llvm.umin.i8(i8 [[Y]], i8 [[X]])
-; CHECK-NEXT:    [[R:%.*]] = call i8 @llvm.umin.i8(i8 [[M1]], i8 [[M2]])
-; CHECK-NEXT:    ret i8 [[R]]
+; CHECK-NEXT:    [[M2:%.*]] = call i8 @llvm.umin.i8(i8 [[Y:%.*]], i8 [[X:%.*]])
+; CHECK-NEXT:    ret i8 [[M2]]
 ;
   %m1 = call i8 @llvm.smin.i8(i8 %x, i8 %y)
   %m2 = call i8 @llvm.umin.i8(i8 %y, i8 %x)
@@ -1816,10 +1768,8 @@ define i8 @umin_smin_umin(i8 %x, i8 %y) {
 
 define i8 @umin_umax_smax(i8 %x, i8 %y) {
 ; CHECK-LABEL: @umin_umax_smax(
-; CHECK-NEXT:    [[M1:%.*]] = call i8 @llvm.umax.i8(i8 [[X:%.*]], i8 [[Y:%.*]])
-; CHECK-NEXT:    [[M2:%.*]] = call i8 @llvm.smax.i8(i8 [[Y]], i8 [[X]])
-; CHECK-NEXT:    [[R:%.*]] = call i8 @llvm.umin.i8(i8 [[M1]], i8 [[M2]])
-; CHECK-NEXT:    ret i8 [[R]]
+; CHECK-NEXT:    [[M2:%.*]] = call i8 @llvm.smax.i8(i8 [[Y:%.*]], i8 [[X:%.*]])
+; CHECK-NEXT:    ret i8 [[M2]]
 ;
   %m1 = call i8 @llvm.umax.i8(i8 %x, i8 %y)
   %m2 = call i8 @llvm.smax.i8(i8 %y, i8 %x)
@@ -1829,10 +1779,8 @@ define i8 @umin_umax_smax(i8 %x, i8 %y) {
 
 define i8 @umin_umax_smin(i8 %x, i8 %y) {
 ; CHECK-LABEL: @umin_umax_smin(
-; CHECK-NEXT:    [[M1:%.*]] = call i8 @llvm.umax.i8(i8 [[X:%.*]], i8 [[Y:%.*]])
-; CHECK-NEXT:    [[M2:%.*]] = call i8 @llvm.smin.i8(i8 [[Y]], i8 [[X]])
-; CHECK-NEXT:    [[R:%.*]] = call i8 @llvm.umin.i8(i8 [[M1]], i8 [[M2]])
-; CHECK-NEXT:    ret i8 [[R]]
+; CHECK-NEXT:    [[M2:%.*]] = call i8 @llvm.smin.i8(i8 [[Y:%.*]], i8 [[X:%.*]])
+; CHECK-NEXT:    ret i8 [[M2]]
 ;
   %m1 = call i8 @llvm.umax.i8(i8 %x, i8 %y)
   %m2 = call i8 @llvm.smin.i8(i8 %y, i8 %x)
@@ -1842,10 +1790,8 @@ define i8 @umin_umax_smin(i8 %x, i8 %y) {
 
 define i8 @umin_umax_umax(i8 %x, i8 %y) {
 ; CHECK-LABEL: @umin_umax_umax(
-; CHECK-NEXT:    [[M1:%.*]] = call i8 @llvm.umax.i8(i8 [[X:%.*]], i8 [[Y:%.*]])
-; CHECK-NEXT:    [[M2:%.*]] = call i8 @llvm.umax.i8(i8 [[Y]], i8 [[X]])
-; CHECK-NEXT:    [[R:%.*]] = call i8 @llvm.umin.i8(i8 [[M1]], i8 [[M2]])
-; CHECK-NEXT:    ret i8 [[R]]
+; CHECK-NEXT:    [[M2:%.*]] = call i8 @llvm.umax.i8(i8 [[Y:%.*]], i8 [[X:%.*]])
+; CHECK-NEXT:    ret i8 [[M2]]
 ;
   %m1 = call i8 @llvm.umax.i8(i8 %x, i8 %y)
   %m2 = call i8 @llvm.umax.i8(i8 %y, i8 %x)
@@ -1855,10 +1801,8 @@ define i8 @umin_umax_umax(i8 %x, i8 %y) {
 
 define i8 @umin_umax_umin(i8 %x, i8 %y) {
 ; CHECK-LABEL: @umin_umax_umin(
-; CHECK-NEXT:    [[M1:%.*]] = call i8 @llvm.umax.i8(i8 [[X:%.*]], i8 [[Y:%.*]])
-; CHECK-NEXT:    [[M2:%.*]] = call i8 @llvm.umin.i8(i8 [[Y]], i8 [[X]])
-; CHECK-NEXT:    [[R:%.*]] = call i8 @llvm.umin.i8(i8 [[M1]], i8 [[M2]])
-; CHECK-NEXT:    ret i8 [[R]]
+; CHECK-NEXT:    [[M2:%.*]] = call i8 @llvm.umin.i8(i8 [[Y:%.*]], i8 [[X:%.*]])
+; CHECK-NEXT:    ret i8 [[M2]]
 ;
   %m1 = call i8 @llvm.umax.i8(i8 %x, i8 %y)
   %m2 = call i8 @llvm.umin.i8(i8 %y, i8 %x)
@@ -1869,9 +1813,7 @@ define i8 @umin_umax_umin(i8 %x, i8 %y) {
 define i8 @umin_umin_smax(i8 %x, i8 %y) {
 ; CHECK-LABEL: @umin_umin_smax(
 ; CHECK-NEXT:    [[M1:%.*]] = call i8 @llvm.umin.i8(i8 [[X:%.*]], i8 [[Y:%.*]])
-; CHECK-NEXT:    [[M2:%.*]] = call i8 @llvm.smax.i8(i8 [[Y]], i8 [[X]])
-; CHECK-NEXT:    [[R:%.*]] = call i8 @llvm.umin.i8(i8 [[M1]], i8 [[M2]])
-; CHECK-NEXT:    ret i8 [[R]]
+; CHECK-NEXT:    ret i8 [[M1]]
 ;
   %m1 = call i8 @llvm.umin.i8(i8 %x, i8 %y)
   %m2 = call i8 @llvm.smax.i8(i8 %y, i8 %x)
@@ -1882,9 +1824,7 @@ define i8 @umin_umin_smax(i8 %x, i8 %y) {
 define i8 @umin_umin_smin(i8 %x, i8 %y) {
 ; CHECK-LABEL: @umin_umin_smin(
 ; CHECK-NEXT:    [[M1:%.*]] = call i8 @llvm.umin.i8(i8 [[X:%.*]], i8 [[Y:%.*]])
-; CHECK-NEXT:    [[M2:%.*]] = call i8 @llvm.smin.i8(i8 [[Y]], i8 [[X]])
-; CHECK-NEXT:    [[R:%.*]] = call i8 @llvm.umin.i8(i8 [[M1]], i8 [[M2]])
-; CHECK-NEXT:    ret i8 [[R]]
+; CHECK-NEXT:    ret i8 [[M1]]
 ;
   %m1 = call i8 @llvm.umin.i8(i8 %x, i8 %y)
   %m2 = call i8 @llvm.smin.i8(i8 %y, i8 %x)
@@ -1895,9 +1835,7 @@ define i8 @umin_umin_smin(i8 %x, i8 %y) {
 define i8 @umin_umin_umax(i8 %x, i8 %y) {
 ; CHECK-LABEL: @umin_umin_umax(
 ; CHECK-NEXT:    [[M1:%.*]] = call i8 @llvm.umin.i8(i8 [[X:%.*]], i8 [[Y:%.*]])
-; CHECK-NEXT:    [[M2:%.*]] = call i8 @llvm.umax.i8(i8 [[Y]], i8 [[X]])
-; CHECK-NEXT:    [[R:%.*]] = call i8 @llvm.umin.i8(i8 [[M1]], i8 [[M2]])
-; CHECK-NEXT:    ret i8 [[R]]
+; CHECK-NEXT:    ret i8 [[M1]]
 ;
   %m1 = call i8 @llvm.umin.i8(i8 %x, i8 %y)
   %m2 = call i8 @llvm.umax.i8(i8 %y, i8 %x)
@@ -1908,9 +1846,7 @@ define i8 @umin_umin_umax(i8 %x, i8 %y) {
 define i8 @umin_umin_umin(i8 %x, i8 %y) {
 ; CHECK-LABEL: @umin_umin_umin(
 ; CHECK-NEXT:    [[M1:%.*]] = call i8 @llvm.umin.i8(i8 [[X:%.*]], i8 [[Y:%.*]])
-; CHECK-NEXT:    [[M2:%.*]] = call i8 @llvm.umin.i8(i8 [[Y]], i8 [[X]])
-; CHECK-NEXT:    [[R:%.*]] = call i8 @llvm.umin.i8(i8 [[M1]], i8 [[M2]])
-; CHECK-NEXT:    ret i8 [[R]]
+; CHECK-NEXT:    ret i8 [[M1]]
 ;
   %m1 = call i8 @llvm.umin.i8(i8 %x, i8 %y)
   %m2 = call i8 @llvm.umin.i8(i8 %y, i8 %x)


        


More information about the llvm-commits mailing list