aboutsummaryrefslogtreecommitdiff
path: root/llvm/lib/Analysis/ValueTracking.cpp
diff options
context:
space:
mode:
authorNikita Popov <npopov@redhat.com>2022-02-23 12:40:31 +0100
committerNikita Popov <npopov@redhat.com>2022-02-23 12:45:16 +0100
commit6777ec9e4df79d88f179593e20d6cb58a3effba4 (patch)
tree14b5fa5c2f962420d1e8b220b93618ab1d78710d /llvm/lib/Analysis/ValueTracking.cpp
parentd6e008089c2d758dabefe71ae7cf18e46928b5ef (diff)
downloadllvm-6777ec9e4df79d88f179593e20d6cb58a3effba4.zip
llvm-6777ec9e4df79d88f179593e20d6cb58a3effba4.tar.gz
llvm-6777ec9e4df79d88f179593e20d6cb58a3effba4.tar.bz2
[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.
Diffstat (limited to 'llvm/lib/Analysis/ValueTracking.cpp')
-rw-r--r--llvm/lib/Analysis/ValueTracking.cpp24
1 files changed, 24 insertions, 0 deletions
diff --git a/llvm/lib/Analysis/ValueTracking.cpp b/llvm/lib/Analysis/ValueTracking.cpp
index ef84e0c..b8ff6be 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());
+ }
}
}
}