[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.

llvm-svn: 233195
This commit is contained in:
Benjamin Kramer 2015-03-25 16:49:59 +00:00
parent 2ed53cd9d5
commit 3deba1d2df
5 changed files with 60 additions and 14 deletions

View File

@ -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
/// @{

View File

@ -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));
}

View File

@ -672,6 +672,14 @@ hash_code llvm::hash_value(const APInt &Arg) {
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);

View File

@ -1403,17 +1403,10 @@ SDValue PPC::get_VSPLTI_elt(SDNode *N, unsigned ByteSize, SelectionDAG &DAG) {
// 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);

View File

@ -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