Index: llvm/trunk/include/llvm/ADT/APInt.h =================================================================== --- llvm/trunk/include/llvm/ADT/APInt.h +++ llvm/trunk/include/llvm/ADT/APInt.h @@ -212,6 +212,9 @@ /// out-of-line slow case for intersects. bool intersectsSlowCase(const APInt &RHS) const LLVM_READONLY; + /// out-of-line slow case for isSubsetOf. + bool isSubsetOfSlowCase(const APInt &RHS) const LLVM_READONLY; + /// out-of-line slow case for setBits. void setBitsSlowCase(unsigned loBit, unsigned hiBit); @@ -1219,6 +1222,14 @@ return intersectsSlowCase(RHS); } + /// This operation checks that all bits set in this APInt are also set in RHS. + bool isSubsetOf(const APInt &RHS) const { + assert(BitWidth == RHS.BitWidth && "Bit widths must be the same"); + if (isSingleWord()) + return (VAL & ~RHS.VAL) == 0; + return isSubsetOfSlowCase(RHS); + } + /// @} /// \name Resizing Operators /// @{ Index: llvm/trunk/lib/Support/APInt.cpp =================================================================== --- llvm/trunk/lib/Support/APInt.cpp +++ llvm/trunk/lib/Support/APInt.cpp @@ -730,6 +730,14 @@ return false; } +bool APInt::isSubsetOfSlowCase(const APInt &RHS) const { + for (unsigned i = 0, e = getNumWords(); i != e; ++i) + if ((pVal[i] & ~RHS.pVal[i]) != 0) + return false; + + return true; +} + APInt APInt::byteSwap() const { assert(BitWidth >= 16 && BitWidth % 16 == 0 && "Cannot byteswap!"); if (BitWidth == 16) Index: llvm/trunk/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp =================================================================== --- llvm/trunk/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp +++ llvm/trunk/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp @@ -38,7 +38,7 @@ // If there are no bits set that aren't demanded, nothing to do. Demanded = Demanded.zextOrTrunc(C->getBitWidth()); - if ((~Demanded & *C) == 0) + if (C->isSubsetOf(Demanded)) return false; // This instruction is producing bits that are not demanded. Shrink the RHS. Index: llvm/trunk/unittests/ADT/APIntTest.cpp =================================================================== --- llvm/trunk/unittests/ADT/APIntTest.cpp +++ llvm/trunk/unittests/ADT/APIntTest.cpp @@ -2057,4 +2057,33 @@ EXPECT_EQ(0, neg_one.shl(128)); } +TEST(APIntTest, isSubsetOf) { + APInt i32_1(32, 1); + APInt i32_2(32, 2); + APInt i32_3(32, 3); + EXPECT_FALSE(i32_3.isSubsetOf(i32_1)); + EXPECT_TRUE(i32_1.isSubsetOf(i32_3)); + EXPECT_FALSE(i32_2.isSubsetOf(i32_1)); + EXPECT_FALSE(i32_1.isSubsetOf(i32_2)); + EXPECT_TRUE(i32_3.isSubsetOf(i32_3)); + + APInt i128_1(128, 1); + APInt i128_2(128, 2); + APInt i128_3(128, 3); + EXPECT_FALSE(i128_3.isSubsetOf(i128_1)); + EXPECT_TRUE(i128_1.isSubsetOf(i128_3)); + EXPECT_FALSE(i128_2.isSubsetOf(i128_1)); + EXPECT_FALSE(i128_1.isSubsetOf(i128_2)); + EXPECT_TRUE(i128_3.isSubsetOf(i128_3)); + + i128_1 <<= 64; + i128_2 <<= 64; + i128_3 <<= 64; + EXPECT_FALSE(i128_3.isSubsetOf(i128_1)); + EXPECT_TRUE(i128_1.isSubsetOf(i128_3)); + EXPECT_FALSE(i128_2.isSubsetOf(i128_1)); + EXPECT_FALSE(i128_1.isSubsetOf(i128_2)); + EXPECT_TRUE(i128_3.isSubsetOf(i128_3)); +} + } // end anonymous namespace