[llvm] r273459 - [ValueTracking] improve ComputeNumSignBits for vector constants

Sanjay Patel via llvm-commits llvm-commits at lists.llvm.org
Wed Jun 22 12:20:59 PDT 2016


Author: spatel
Date: Wed Jun 22 14:20:59 2016
New Revision: 273459

URL: http://llvm.org/viewvc/llvm-project?rev=273459&view=rev
Log:
[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


Modified:
    llvm/trunk/include/llvm/Analysis/ValueTracking.h
    llvm/trunk/lib/Analysis/ValueTracking.cpp
    llvm/trunk/test/Transforms/InstSimplify/shr-nop.ll

Modified: llvm/trunk/include/llvm/Analysis/ValueTracking.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Analysis/ValueTracking.h?rev=273459&r1=273458&r2=273459&view=diff
==============================================================================
--- llvm/trunk/include/llvm/Analysis/ValueTracking.h (original)
+++ llvm/trunk/include/llvm/Analysis/ValueTracking.h Wed Jun 22 14:20:59 2016
@@ -138,9 +138,9 @@ template <typename T> 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,

Modified: llvm/trunk/lib/Analysis/ValueTracking.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Analysis/ValueTracking.cpp?rev=273459&r1=273458&r2=273459&view=diff
==============================================================================
--- llvm/trunk/lib/Analysis/ValueTracking.cpp (original)
+++ llvm/trunk/lib/Analysis/ValueTracking.cpp Wed Jun 22 14:20:59 2016
@@ -1918,16 +1918,39 @@ bool MaskedValueIsZero(Value *V, const A
   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, un
 
   // 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);

Modified: llvm/trunk/test/Transforms/InstSimplify/shr-nop.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/InstSimplify/shr-nop.ll?rev=273459&r1=273458&r2=273459&view=diff
==============================================================================
--- llvm/trunk/test/Transforms/InstSimplify/shr-nop.ll (original)
+++ llvm/trunk/test/Transforms/InstSimplify/shr-nop.ll Wed Jun 22 14:20:59 2016
@@ -423,8 +423,7 @@ define <2 x i64> @ashr_minus1_vec(<2 x i
 
 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> <i4 0, i4 -1>, %shiftval
-; CHECK-NEXT:    ret <2 x i4> [[SHR]]
+; CHECK-NEXT:    ret <2 x i4> <i4 0, i4 -1>
 ;
   %shr = ashr <2 x i4> <i4 0, i4 -1>, %shiftval
   ret <2 x i4> %shr




More information about the llvm-commits mailing list