[llvm] 6777ec9 - [ValueTracking] Support signed intrinsic clamp

Nikita Popov via llvm-commits llvm-commits at lists.llvm.org
Wed Feb 23 03:45:25 PST 2022


Author: Nikita Popov
Date: 2022-02-23T12:45:16+01:00
New Revision: 6777ec9e4df79d88f179593e20d6cb58a3effba4

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

LOG: [ValueTracking] Support signed intrinsic clamp

This is the same special logic we apply for SPF signed clamps
when computing the number of sign bits, just for intrinsics.

This just uses the same logic as the select case, but there's
multiple directions this could be improved in: We could also use
the num sign bits from the clamped value, we could do this during
constant range calculation, and there's probably unsigned analogues
for the constant range case at least.

Added: 
    

Modified: 
    llvm/lib/Analysis/ValueTracking.cpp
    llvm/test/Transforms/InstCombine/max_known_bits.ll

Removed: 
    


################################################################################
diff  --git a/llvm/lib/Analysis/ValueTracking.cpp b/llvm/lib/Analysis/ValueTracking.cpp
index ef84e0c69b3c..b8ff6beccae5 100644
--- a/llvm/lib/Analysis/ValueTracking.cpp
+++ b/llvm/lib/Analysis/ValueTracking.cpp
@@ -2902,6 +2902,24 @@ static bool isSignedMinMaxClamp(const Value *Select, const Value *&In,
   return CLow->sle(*CHigh);
 }
 
+static bool isSignedMinMaxIntrinsicClamp(const IntrinsicInst *II,
+                                         const APInt *&CLow,
+                                         const APInt *&CHigh) {
+  assert((II->getIntrinsicID() == Intrinsic::smin ||
+          II->getIntrinsicID() == Intrinsic::smax) && "Must be smin/smax");
+
+  Intrinsic::ID InverseID = getInverseMinMaxIntrinsic(II->getIntrinsicID());
+  auto *InnerII = dyn_cast<IntrinsicInst>(II->getArgOperand(0));
+  if (!InnerII || InnerII->getIntrinsicID() != InverseID ||
+      !match(II->getArgOperand(1), m_APInt(CLow)) ||
+      !match(InnerII->getArgOperand(1), m_APInt(CHigh)))
+    return false;
+
+  if (II->getIntrinsicID() == Intrinsic::smin)
+    std::swap(CLow, CHigh);
+  return CLow->sle(*CHigh);
+}
+
 /// For vector constants, loop over the elements and find the constant with the
 /// minimum number of sign bits. Return 0 if the value is not a vector constant
 /// or if any element was not analyzed; otherwise, return the count for the
@@ -3242,6 +3260,12 @@ static unsigned ComputeNumSignBitsImpl(const Value *V,
 
           // Absolute value reduces number of sign bits by at most 1.
           return Tmp - 1;
+        case Intrinsic::smin:
+        case Intrinsic::smax: {
+          const APInt *CLow, *CHigh;
+          if (isSignedMinMaxIntrinsicClamp(II, CLow, CHigh))
+            return std::min(CLow->getNumSignBits(), CHigh->getNumSignBits());
+        }
         }
       }
     }

diff  --git a/llvm/test/Transforms/InstCombine/max_known_bits.ll b/llvm/test/Transforms/InstCombine/max_known_bits.ll
index a9f5795f9e8c..7ae179d843c1 100644
--- a/llvm/test/Transforms/InstCombine/max_known_bits.ll
+++ b/llvm/test/Transforms/InstCombine/max_known_bits.ll
@@ -116,7 +116,7 @@ define i16 @min_max_clamp_intrinsic_2(i16 %x) {
 ; CHECK-LABEL: @min_max_clamp_intrinsic_2(
 ; CHECK-NEXT:    [[A:%.*]] = call i16 @llvm.smin.i16(i16 [[X:%.*]], i16 2047)
 ; CHECK-NEXT:    [[B:%.*]] = call i16 @llvm.smax.i16(i16 [[A]], i16 -2048)
-; CHECK-NEXT:    [[C:%.*]] = add i16 [[B]], 1
+; CHECK-NEXT:    [[C:%.*]] = add nsw i16 [[B]], 1
 ; CHECK-NEXT:    ret i16 [[C]]
 ;
   %a = call i16 @llvm.smin.i16(i16 %x, i16 2047)
@@ -144,10 +144,8 @@ define i32 @min_max_clamp_intrinsic_4(i16 %x) {
 ; CHECK-LABEL: @min_max_clamp_intrinsic_4(
 ; CHECK-NEXT:    [[A:%.*]] = call i16 @llvm.smin.i16(i16 [[X:%.*]], i16 2047)
 ; CHECK-NEXT:    [[B:%.*]] = call i16 @llvm.smax.i16(i16 [[A]], i16 -2048)
-; CHECK-NEXT:    [[C:%.*]] = add i16 [[B]], 1
-; CHECK-NEXT:    [[D:%.*]] = sext i16 [[C]] to i32
-; CHECK-NEXT:    [[E:%.*]] = add nsw i32 [[D]], -1
-; CHECK-NEXT:    ret i32 [[E]]
+; CHECK-NEXT:    [[TMP1:%.*]] = sext i16 [[B]] to i32
+; CHECK-NEXT:    ret i32 [[TMP1]]
 ;
   %a = call i16 @llvm.smin.i16(i16 %x, i16 2047)
   %b = call i16 @llvm.smax.i16(i16 %a, i16 -2048)


        


More information about the llvm-commits mailing list