[llvm] r233195 - [APInt] Add an isSplat helper and use it in some places.

Benjamin Kramer benny.kra at googlemail.com
Wed Mar 25 09:49:59 PDT 2015


Author: d0k
Date: Wed Mar 25 11:49:59 2015
New Revision: 233195

URL: http://llvm.org/viewvc/llvm-project?rev=233195&view=rev
Log:
[APInt] Add an isSplat helper and use it in some places.

To complement getSplat. This is more general than the binary
decomposition method as it also handles non-pow2 splat sizes.

Modified:
    llvm/trunk/include/llvm/ADT/APInt.h
    llvm/trunk/lib/Analysis/ValueTracking.cpp
    llvm/trunk/lib/Support/APInt.cpp
    llvm/trunk/lib/Target/PowerPC/PPCISelLowering.cpp
    llvm/trunk/unittests/ADT/APIntTest.cpp

Modified: llvm/trunk/include/llvm/ADT/APInt.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/ADT/APInt.h?rev=233195&r1=233194&r2=233195&view=diff
==============================================================================
--- llvm/trunk/include/llvm/ADT/APInt.h (original)
+++ llvm/trunk/include/llvm/ADT/APInt.h Wed Mar 25 11:49:59 2015
@@ -407,6 +407,13 @@ public:
                                                             : getZExtValue();
   }
 
+  /// \brief Check if the APInt consists of a repeated bit pattern.
+  ///
+  /// e.g. 0x01010101 satisfies isSplat(8).
+  /// \param SplatSizeInBits The size of the pattern in bits. Must divide bit
+  /// width without remainder.
+  bool isSplat(unsigned SplatSizeInBits) const;
+
   /// @}
   /// \name Value Generators
   /// @{

Modified: llvm/trunk/lib/Analysis/ValueTracking.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Analysis/ValueTracking.cpp?rev=233195&r1=233194&r2=233195&view=diff
==============================================================================
--- llvm/trunk/lib/Analysis/ValueTracking.cpp (original)
+++ llvm/trunk/lib/Analysis/ValueTracking.cpp Wed Mar 25 11:49:59 2015
@@ -2348,9 +2348,7 @@ Value *llvm::isBytewiseValue(Value *V) {
     if (CI->getBitWidth() % 8 == 0) {
       assert(CI->getBitWidth() > 8 && "8 bits should be handled above!");
 
-      // We can check that all bytes of an integer are equal by making use of a
-      // little trick: rotate by 8 and check if it's still the same value.
-      if (CI->getValue() != CI->getValue().rotl(8))
+      if (!CI->getValue().isSplat(8))
         return nullptr;
       return ConstantInt::get(V->getContext(), CI->getValue().trunc(8));
     }

Modified: llvm/trunk/lib/Support/APInt.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Support/APInt.cpp?rev=233195&r1=233194&r2=233195&view=diff
==============================================================================
--- llvm/trunk/lib/Support/APInt.cpp (original)
+++ llvm/trunk/lib/Support/APInt.cpp Wed Mar 25 11:49:59 2015
@@ -672,6 +672,14 @@ hash_code llvm::hash_value(const APInt &
   return hash_combine_range(Arg.pVal, Arg.pVal + Arg.getNumWords());
 }
 
+bool APInt::isSplat(unsigned SplatSizeInBits) const {
+  assert(getBitWidth() % SplatSizeInBits == 0 &&
+         "SplatSizeInBits must divide width!");
+  // We can check that all parts of an integer are equal by making use of a
+  // little trick: rotate and check if it's still the same value.
+  return *this == rotl(SplatSizeInBits);
+}
+
 /// HiBits - This function returns the high "numBits" bits of this APInt.
 APInt APInt::getHiBits(unsigned numBits) const {
   return APIntOps::lshr(*this, BitWidth - numBits);

Modified: llvm/trunk/lib/Target/PowerPC/PPCISelLowering.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/PowerPC/PPCISelLowering.cpp?rev=233195&r1=233194&r2=233195&view=diff
==============================================================================
--- llvm/trunk/lib/Target/PowerPC/PPCISelLowering.cpp (original)
+++ llvm/trunk/lib/Target/PowerPC/PPCISelLowering.cpp Wed Mar 25 11:49:59 2015
@@ -1403,17 +1403,10 @@ SDValue PPC::get_VSPLTI_elt(SDNode *N, u
   // immediate field for would be zero, and we prefer to use vxor for it.
   if (ValSizeInBytes < ByteSize) return SDValue();
 
-  // If the element value is larger than the splat value, cut it in half and
-  // check to see if the two halves are equal.  Continue doing this until we
-  // get to ByteSize.  This allows us to handle 0x01010101 as 0x01.
-  while (ValSizeInBytes > ByteSize) {
-    ValSizeInBytes >>= 1;
-
-    // If the top half equals the bottom half, we're still ok.
-    if (((Value >> (ValSizeInBytes*8)) & ((1 << (8*ValSizeInBytes))-1)) !=
-         (Value                        & ((1 << (8*ValSizeInBytes))-1)))
-      return SDValue();
-  }
+  // If the element value is larger than the splat value, check if it consists
+  // of a repeated bit pattern of size ByteSize.
+  if (!APInt(ValSizeInBytes * 8, Value).isSplat(ByteSize * 8))
+    return SDValue();
 
   // Properly sign extend the value.
   int MaskVal = SignExtend32(Value, ByteSize * 8);

Modified: llvm/trunk/unittests/ADT/APIntTest.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/unittests/ADT/APIntTest.cpp?rev=233195&r1=233194&r2=233195&view=diff
==============================================================================
--- llvm/trunk/unittests/ADT/APIntTest.cpp (original)
+++ llvm/trunk/unittests/ADT/APIntTest.cpp Wed Mar 25 11:49:59 2015
@@ -678,6 +678,46 @@ TEST(APIntTest, nearestLogBase2) {
   EXPECT_EQ(A9.nearestLogBase2(), UINT32_MAX);
 }
 
+TEST(APIntTest, IsSplat) {
+  APInt A(32, 0x01010101);
+  EXPECT_FALSE(A.isSplat(1));
+  EXPECT_FALSE(A.isSplat(2));
+  EXPECT_FALSE(A.isSplat(4));
+  EXPECT_TRUE(A.isSplat(8));
+  EXPECT_TRUE(A.isSplat(16));
+  EXPECT_TRUE(A.isSplat(32));
+
+  APInt B(24, 0xAAAAAA);
+  EXPECT_FALSE(B.isSplat(1));
+  EXPECT_TRUE(B.isSplat(2));
+  EXPECT_TRUE(B.isSplat(4));
+  EXPECT_TRUE(B.isSplat(8));
+  EXPECT_TRUE(B.isSplat(24));
+
+  APInt C(24, 0xABAAAB);
+  EXPECT_FALSE(C.isSplat(1));
+  EXPECT_FALSE(C.isSplat(2));
+  EXPECT_FALSE(C.isSplat(4));
+  EXPECT_FALSE(C.isSplat(8));
+  EXPECT_TRUE(C.isSplat(24));
+
+  APInt D(32, 0xABBAABBA);
+  EXPECT_FALSE(D.isSplat(1));
+  EXPECT_FALSE(D.isSplat(2));
+  EXPECT_FALSE(D.isSplat(4));
+  EXPECT_FALSE(D.isSplat(8));
+  EXPECT_TRUE(D.isSplat(16));
+  EXPECT_TRUE(D.isSplat(32));
+
+  APInt E(32, 0);
+  EXPECT_TRUE(E.isSplat(1));
+  EXPECT_TRUE(E.isSplat(2));
+  EXPECT_TRUE(E.isSplat(4));
+  EXPECT_TRUE(E.isSplat(8));
+  EXPECT_TRUE(E.isSplat(16));
+  EXPECT_TRUE(E.isSplat(32));
+}
+
 #if defined(__clang__)
 // Disable the pragma warning from versions of Clang without -Wself-move
 #pragma clang diagnostic push





More information about the llvm-commits mailing list