diff options
author | Craig Topper <craig.topper@intel.com> | 2018-08-22 23:27:50 +0000 |
---|---|---|
committer | Craig Topper <craig.topper@intel.com> | 2018-08-22 23:27:50 +0000 |
commit | bec15b6516466a1f3eeb2a52e5584b5d4f5b713e (patch) | |
tree | 67c86d1ebe8b3b72c392fc6bf98a15596e7456c5 /llvm/lib/Analysis/ValueTracking.cpp | |
parent | 2b3900643364f568c2308b178a30e8926b779c70 (diff) | |
download | llvm-bec15b6516466a1f3eeb2a52e5584b5d4f5b713e.zip llvm-bec15b6516466a1f3eeb2a52e5584b5d4f5b713e.tar.gz llvm-bec15b6516466a1f3eeb2a52e5584b5d4f5b713e.tar.bz2 |
[ValueTracking] Teach computeNumSignBits to understand min/max clamp patterns with constant/splat values
If we have a min/max pair we can do a better job of counting sign bits if we look at them together. This is similar to what is done in the SelectionDAG version of computeNumSignBits for ISD::SMAX/SMIN.
Differential Revision: https://reviews.llvm.org/D51112
llvm-svn: 340480
Diffstat (limited to 'llvm/lib/Analysis/ValueTracking.cpp')
-rw-r--r-- | llvm/lib/Analysis/ValueTracking.cpp | 38 |
1 files changed, 37 insertions, 1 deletions
diff --git a/llvm/lib/Analysis/ValueTracking.cpp b/llvm/lib/Analysis/ValueTracking.cpp index 48d48f2..322d5c2 100644 --- a/llvm/lib/Analysis/ValueTracking.cpp +++ b/llvm/lib/Analysis/ValueTracking.cpp @@ -2209,6 +2209,34 @@ bool MaskedValueIsZero(const Value *V, const APInt &Mask, unsigned Depth, return Mask.isSubsetOf(Known.Zero); } +// Match a signed min+max clamp pattern like smax(smin(In, CHigh), CLow). +// Returns the input and lower/upper bounds. +static bool isSignedMinMaxClamp(const Value *Select, const Value *&In, + const APInt *&CLow, const APInt *&CHigh) { + assert(isa<SelectInst>(Select) && "Input should be a SelectInst!"); + + const Value *LHS, *RHS, *LHS2, *RHS2; + SelectPatternFlavor SPF = matchSelectPattern(Select, LHS, RHS).Flavor; + if (SPF != SPF_SMAX && SPF != SPF_SMIN) + return false; + + if (!match(RHS, m_APInt(CLow))) + return false; + + SelectPatternFlavor SPF2 = matchSelectPattern(LHS, LHS2, RHS2).Flavor; + if (getInverseMinMaxFlavor(SPF) != SPF2) + return false; + + if (!match(RHS2, m_APInt(CHigh))) + return false; + + if (SPF == SPF_SMIN) + std::swap(CLow, CHigh); + + In = LHS2; + 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 @@ -2370,11 +2398,19 @@ static unsigned ComputeNumSignBitsImpl(const Value *V, unsigned Depth, } break; - case Instruction::Select: + case Instruction::Select: { + // If we have a clamp pattern, we know that the number of sign bits will be + // the minimum of the clamp min/max range. + const Value *X; + const APInt *CLow, *CHigh; + if (isSignedMinMaxClamp(U, X, CLow, CHigh)) + return std::min(CLow->getNumSignBits(), CHigh->getNumSignBits()); + Tmp = ComputeNumSignBits(U->getOperand(1), Depth + 1, Q); if (Tmp == 1) break; Tmp2 = ComputeNumSignBits(U->getOperand(2), Depth + 1, Q); return std::min(Tmp, Tmp2); + } case Instruction::Add: // Add can have at most one carry bit. Thus we know that the output |