aboutsummaryrefslogtreecommitdiff
path: root/llvm/lib/Analysis/ValueTracking.cpp
diff options
context:
space:
mode:
authorSanjay Patel <spatel@rotateright.com>2016-06-22 19:20:59 +0000
committerSanjay Patel <spatel@rotateright.com>2016-06-22 19:20:59 +0000
commita06d98955245dc27fc1995192000f0f240f45d85 (patch)
treef80c4256a0103d5e5edf5bf111ad8c95e669f8c1 /llvm/lib/Analysis/ValueTracking.cpp
parent8c106bcbe8d25ac9f1aa7dc4ab89fe6c31618967 (diff)
downloadllvm-a06d98955245dc27fc1995192000f0f240f45d85.zip
llvm-a06d98955245dc27fc1995192000f0f240f45d85.tar.gz
llvm-a06d98955245dc27fc1995192000f0f240f45d85.tar.bz2
[ValueTracking] improve ComputeNumSignBits for vector constants
This is similar to the computeKnownBits improvement in rL268479. There's probably more we can do for vector logic instructions, but this should let us see non-splat constant masking ops that can become vector selects instead of and/andn/or sequences. Differential Revision: http://reviews.llvm.org/D21610 llvm-svn: 273459
Diffstat (limited to 'llvm/lib/Analysis/ValueTracking.cpp')
-rw-r--r--llvm/lib/Analysis/ValueTracking.cpp37
1 files changed, 33 insertions, 4 deletions
diff --git a/llvm/lib/Analysis/ValueTracking.cpp b/llvm/lib/Analysis/ValueTracking.cpp
index 7109ff84..97b3692 100644
--- a/llvm/lib/Analysis/ValueTracking.cpp
+++ b/llvm/lib/Analysis/ValueTracking.cpp
@@ -1918,16 +1918,39 @@ bool MaskedValueIsZero(Value *V, const APInt &Mask, unsigned Depth,
return (KnownZero & Mask) == Mask;
}
+/// 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
+/// element with the minimum number of sign bits.
+static unsigned computeNumSignBitsVectorConstant(Value *V, unsigned TyBits) {
+ auto *CV = dyn_cast<Constant>(V);
+ if (!CV || !CV->getType()->isVectorTy())
+ return 0;
+
+ unsigned MinSignBits = TyBits;
+ unsigned NumElts = CV->getType()->getVectorNumElements();
+ for (unsigned i = 0; i != NumElts; ++i) {
+ // If we find a non-ConstantInt, bail out.
+ auto *Elt = dyn_cast_or_null<ConstantInt>(CV->getAggregateElement(i));
+ if (!Elt)
+ return 0;
+
+ // If the sign bit is 1, flip the bits, so we always count leading zeros.
+ APInt EltVal = Elt->getValue();
+ if (EltVal.isNegative())
+ EltVal = ~EltVal;
+ MinSignBits = std::min(MinSignBits, EltVal.countLeadingZeros());
+ }
+ return MinSignBits;
+}
/// Return the number of times the sign bit of the register is replicated into
/// the other bits. We know that at least 1 bit is always equal to the sign bit
/// (itself), but other cases can give us information. For example, immediately
/// after an "ashr X, 2", we know that the top 3 bits are all equal to each
-/// other, so we return 3.
-///
-/// 'Op' must have a scalar integer type.
-///
+/// other, so we return 3. For vectors, return the number of sign bits for the
+/// vector element with the mininum number of known sign bits.
unsigned ComputeNumSignBits(Value *V, unsigned Depth, const Query &Q) {
unsigned TyBits = Q.DL.getTypeSizeInBits(V->getType()->getScalarType());
unsigned Tmp, Tmp2;
@@ -2123,6 +2146,12 @@ unsigned ComputeNumSignBits(Value *V, unsigned Depth, const Query &Q) {
// Finally, if we can prove that the top bits of the result are 0's or 1's,
// use this information.
+
+ // If we can examine all elements of a vector constant successfully, we're
+ // done (we can't do any better than that). If not, keep trying.
+ if (unsigned VecSignBits = computeNumSignBitsVectorConstant(V, TyBits))
+ return VecSignBits;
+
APInt KnownZero(TyBits, 0), KnownOne(TyBits, 0);
APInt Mask;
computeKnownBits(V, KnownZero, KnownOne, Depth, Q);