From efa1f7f367415bf954168d579d59ba339f597e25 Mon Sep 17 00:00:00 2001 From: Sanjay Patel Date: Wed, 22 Jun 2016 19:20:59 +0000 Subject: [PATCH] [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 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@273459 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/Analysis/ValueTracking.h | 6 +++--- lib/Analysis/ValueTracking.cpp | 37 +++++++++++++++++++++++++++++---- test/Transforms/InstSimplify/shr-nop.ll | 3 +-- 3 files changed, 37 insertions(+), 9 deletions(-) diff --git a/include/llvm/Analysis/ValueTracking.h b/include/llvm/Analysis/ValueTracking.h index 47803857072..0eaad3bf634 100644 --- a/include/llvm/Analysis/ValueTracking.h +++ b/include/llvm/Analysis/ValueTracking.h @@ -138,9 +138,9 @@ template class ArrayRef; /// 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. + /// equal to each 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 *Op, const DataLayout &DL, unsigned Depth = 0, AssumptionCache *AC = nullptr, const Instruction *CxtI = nullptr, diff --git a/lib/Analysis/ValueTracking.cpp b/lib/Analysis/ValueTracking.cpp index 7109ff84b8e..97b36923495 100644 --- a/lib/Analysis/ValueTracking.cpp +++ b/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(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(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); diff --git a/test/Transforms/InstSimplify/shr-nop.ll b/test/Transforms/InstSimplify/shr-nop.ll index 00fc328d2c8..9b0f4e9fe50 100644 --- a/test/Transforms/InstSimplify/shr-nop.ll +++ b/test/Transforms/InstSimplify/shr-nop.ll @@ -423,8 +423,7 @@ define <2 x i64> @ashr_minus1_vec(<2 x i64> %shiftval) { define <2 x i4> @ashr_zero_minus1_vec(<2 x i4> %shiftval) { ; CHECK-LABEL: @ashr_zero_minus1_vec( -; CHECK-NEXT: [[SHR:%.*]] = ashr <2 x i4> , %shiftval -; CHECK-NEXT: ret <2 x i4> [[SHR]] +; CHECK-NEXT: ret <2 x i4> ; %shr = ashr <2 x i4> , %shiftval ret <2 x i4> %shr -- 2.11.0