diff options
-rw-r--r-- | llvm/include/llvm/ADT/APInt.h | 11 | ||||
-rw-r--r-- | llvm/lib/Support/APInt.cpp | 8 | ||||
-rw-r--r-- | llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp | 2 | ||||
-rw-r--r-- | llvm/unittests/ADT/APIntTest.cpp | 29 |
4 files changed, 49 insertions, 1 deletions
diff --git a/llvm/include/llvm/ADT/APInt.h b/llvm/include/llvm/ADT/APInt.h index 785a9afd4d8..30326fd43ff 100644 --- a/llvm/include/llvm/ADT/APInt.h +++ b/llvm/include/llvm/ADT/APInt.h @@ -212,6 +212,9 @@ private: /// 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 @@ public: 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 /// @{ diff --git a/llvm/lib/Support/APInt.cpp b/llvm/lib/Support/APInt.cpp index 54ffc3c0274..2d049a1cff8 100644 --- a/llvm/lib/Support/APInt.cpp +++ b/llvm/lib/Support/APInt.cpp @@ -730,6 +730,14 @@ bool APInt::intersectsSlowCase(const APInt &RHS) const { 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) diff --git a/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp b/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp index c5328c77abb..0cee474320b 100644 --- a/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp @@ -38,7 +38,7 @@ static bool ShrinkDemandedConstant(Instruction *I, unsigned OpNo, // 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. diff --git a/llvm/unittests/ADT/APIntTest.cpp b/llvm/unittests/ADT/APIntTest.cpp index 7d451836ad9..5d3afe9a159 100644 --- a/llvm/unittests/ADT/APIntTest.cpp +++ b/llvm/unittests/ADT/APIntTest.cpp @@ -2057,4 +2057,33 @@ TEST(APIntTest, LeftShift) { 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 |