[llvm-branch-commits] [llvm] f4006c5 - [InstSimplify] fold min/max with limit constant

Tom Stellard via llvm-branch-commits llvm-branch-commits at lists.llvm.org
Mon Aug 16 11:35:58 PDT 2021


Author: Sanjay Patel
Date: 2021-08-16T11:35:29-07:00
New Revision: f4006c59497d425f5a3df5e68da5add21f8e467d

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

LOG: [InstSimplify] fold min/max with limit constant

This is already done within InstCombine:
https://alive2.llvm.org/ce/z/MiGE22

...but leaving it out of analysis makes it
harder to avoid infinite loops there.

(cherry picked from commit e260e10c4a21784c146c94a2a14b7e78b09a9cf7)

Added: 
    

Modified: 
    llvm/include/llvm/Analysis/ValueTracking.h
    llvm/lib/Analysis/InstructionSimplify.cpp
    llvm/lib/Analysis/ValueTracking.cpp
    llvm/test/Transforms/InstSimplify/maxmin.ll

Removed: 
    


################################################################################
diff  --git a/llvm/include/llvm/Analysis/ValueTracking.h b/llvm/include/llvm/Analysis/ValueTracking.h
index 90ec742f18e67..f46e66641c082 100644
--- a/llvm/include/llvm/Analysis/ValueTracking.h
+++ b/llvm/include/llvm/Analysis/ValueTracking.h
@@ -744,6 +744,10 @@ constexpr unsigned MaxAnalysisRecursionDepth = 6;
   /// minimum/maximum flavor.
   CmpInst::Predicate getInverseMinMaxPred(SelectPatternFlavor SPF);
 
+  /// Return the minimum or maximum constant value for the specified integer
+  /// min/max flavor and type.
+  APInt getMinMaxLimit(SelectPatternFlavor SPF, unsigned BitWidth);
+
   /// Check if the values in \p VL are select instructions that can be converted
   /// to a min or max (vector) intrinsic. Returns the intrinsic ID, if such a
   /// conversion is possible, together with a bool indicating whether all select

diff  --git a/llvm/lib/Analysis/InstructionSimplify.cpp b/llvm/lib/Analysis/InstructionSimplify.cpp
index 23083bc8178e7..69ab0052b0a74 100644
--- a/llvm/lib/Analysis/InstructionSimplify.cpp
+++ b/llvm/lib/Analysis/InstructionSimplify.cpp
@@ -4080,6 +4080,22 @@ static Value *simplifySelectWithICmpCond(Value *CondVal, Value *TrueVal,
     std::swap(TrueVal, FalseVal);
   }
 
+  // Check for integer min/max with a limit constant:
+  // X > MIN_INT ? X : MIN_INT --> X
+  // X < MAX_INT ? X : MAX_INT --> X
+  if (TrueVal->getType()->isIntOrIntVectorTy()) {
+    Value *X, *Y;
+    SelectPatternFlavor SPF =
+        matchDecomposedSelectPattern(cast<ICmpInst>(CondVal), TrueVal, FalseVal,
+                                     X, Y).Flavor;
+    if (SelectPatternResult::isMinOrMax(SPF) && Pred == getMinMaxPred(SPF)) {
+      APInt LimitC = getMinMaxLimit(getInverseMinMaxFlavor(SPF),
+                                    X->getType()->getScalarSizeInBits());
+      if (match(Y, m_SpecificInt(LimitC)))
+        return X;
+    }
+  }
+
   if (Pred == ICmpInst::ICMP_EQ && match(CmpRHS, m_Zero())) {
     Value *X;
     const APInt *Y;

diff  --git a/llvm/lib/Analysis/ValueTracking.cpp b/llvm/lib/Analysis/ValueTracking.cpp
index 522d21812c6a5..6e3ca5c4e08ae 100644
--- a/llvm/lib/Analysis/ValueTracking.cpp
+++ b/llvm/lib/Analysis/ValueTracking.cpp
@@ -6253,6 +6253,16 @@ CmpInst::Predicate llvm::getInverseMinMaxPred(SelectPatternFlavor SPF) {
   return getMinMaxPred(getInverseMinMaxFlavor(SPF));
 }
 
+APInt llvm::getMinMaxLimit(SelectPatternFlavor SPF, unsigned BitWidth) {
+  switch (SPF) {
+  case SPF_SMAX: return APInt::getSignedMaxValue(BitWidth);
+  case SPF_SMIN: return APInt::getSignedMinValue(BitWidth);
+  case SPF_UMAX: return APInt::getMaxValue(BitWidth);
+  case SPF_UMIN: return APInt::getMinValue(BitWidth);
+  default: llvm_unreachable("Unexpected flavor");
+  }
+}
+
 std::pair<Intrinsic::ID, bool>
 llvm::canConvertToMinOrMaxIntrinsic(ArrayRef<Value *> VL) {
   // Check if VL contains select instructions that can be folded into a min/max

diff  --git a/llvm/test/Transforms/InstSimplify/maxmin.ll b/llvm/test/Transforms/InstSimplify/maxmin.ll
index e9fff33f63114..1dea800e6ecd0 100644
--- a/llvm/test/Transforms/InstSimplify/maxmin.ll
+++ b/llvm/test/Transforms/InstSimplify/maxmin.ll
@@ -3,9 +3,7 @@
 
 define i8 @smax_min_limit(i8 %x) {
 ; CHECK-LABEL: @smax_min_limit(
-; CHECK-NEXT:    [[CMP:%.*]] = icmp sgt i8 [[X:%.*]], -128
-; CHECK-NEXT:    [[SEL:%.*]] = select i1 [[CMP]], i8 [[X]], i8 -128
-; CHECK-NEXT:    ret i8 [[SEL]]
+; CHECK-NEXT:    ret i8 [[X:%.*]]
 ;
   %cmp = icmp sgt i8 %x, -128
   %sel = select i1 %cmp, i8 %x, i8 -128
@@ -14,9 +12,7 @@ define i8 @smax_min_limit(i8 %x) {
 
 define i8 @smin_max_limit(i8 %x) {
 ; CHECK-LABEL: @smin_max_limit(
-; CHECK-NEXT:    [[CMP:%.*]] = icmp slt i8 [[X:%.*]], 127
-; CHECK-NEXT:    [[SEL:%.*]] = select i1 [[CMP]], i8 [[X]], i8 127
-; CHECK-NEXT:    ret i8 [[SEL]]
+; CHECK-NEXT:    ret i8 [[X:%.*]]
 ;
   %cmp = icmp slt i8 %x, 127
   %sel = select i1 %cmp, i8 %x, i8 127
@@ -25,9 +21,7 @@ define i8 @smin_max_limit(i8 %x) {
 
 define <2 x i8> @umax_min_limit(<2 x i8> %x) {
 ; CHECK-LABEL: @umax_min_limit(
-; CHECK-NEXT:    [[CMP:%.*]] = icmp ugt <2 x i8> [[X:%.*]], zeroinitializer
-; CHECK-NEXT:    [[SEL:%.*]] = select <2 x i1> [[CMP]], <2 x i8> [[X]], <2 x i8> zeroinitializer
-; CHECK-NEXT:    ret <2 x i8> [[SEL]]
+; CHECK-NEXT:    ret <2 x i8> [[X:%.*]]
 ;
   %cmp = icmp ugt <2 x i8> %x, zeroinitializer
   %sel = select <2 x i1> %cmp, <2 x i8> %x, <2 x i8> zeroinitializer
@@ -36,15 +30,15 @@ define <2 x i8> @umax_min_limit(<2 x i8> %x) {
 
 define i8 @umin_max_limit(i8 %x) {
 ; CHECK-LABEL: @umin_max_limit(
-; CHECK-NEXT:    [[CMP:%.*]] = icmp ult i8 [[X:%.*]], -1
-; CHECK-NEXT:    [[SEL:%.*]] = select i1 [[CMP]], i8 [[X]], i8 -1
-; CHECK-NEXT:    ret i8 [[SEL]]
+; CHECK-NEXT:    ret i8 [[X:%.*]]
 ;
   %cmp = icmp ult i8 %x, 255
   %sel = select i1 %cmp, i8 %x, i8 255
   ret i8 %sel
 }
 
+; negative test - wrong limit
+
 define i8 @smax_not_min_limit(i8 %x) {
 ; CHECK-LABEL: @smax_not_min_limit(
 ; CHECK-NEXT:    [[CMP:%.*]] = icmp sgt i8 [[X:%.*]], -127
@@ -56,6 +50,8 @@ define i8 @smax_not_min_limit(i8 %x) {
   ret i8 %sel
 }
 
+; negative test - wrong limit
+
 define i8 @smin_not_min_limit(i8 %x) {
 ; CHECK-LABEL: @smin_not_min_limit(
 ; CHECK-NEXT:    [[CMP:%.*]] = icmp slt i8 [[X:%.*]], 0


        


More information about the llvm-branch-commits mailing list