summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorCraig Topper <craig.topper@gmail.com>2017-04-20 16:17:13 +0000
committerCraig Topper <craig.topper@gmail.com>2017-04-20 16:17:13 +0000
commita8129a11222249d5072c132927dbf9d402b5f9da (patch)
tree5a449591a98fa76421c1dd0297c2a5a074f94091
parentb7701bc9af13662f9658cf6a9db50daad3affd90 (diff)
downloadbcm5719-llvm-a8129a11222249d5072c132927dbf9d402b5f9da.tar.gz
bcm5719-llvm-a8129a11222249d5072c132927dbf9d402b5f9da.zip
[APInt] Add isSubsetOf method that can check if one APInt is a subset of another without creating temporary APInts
This question comes up in many places in SimplifyDemandedBits. This makes it easy to ask without allocating additional temporary APInts. The BitVector class provides a similar functionality through its (IMHO badly named) test(const BitVector&) method. Though its output polarity is reversed. I've provided one example use case in this patch. I plan to do more as a follow up. Differential Revision: https://reviews.llvm.org/D32258 llvm-svn: 300851
-rw-r--r--llvm/include/llvm/ADT/APInt.h11
-rw-r--r--llvm/lib/Support/APInt.cpp8
-rw-r--r--llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp2
-rw-r--r--llvm/unittests/ADT/APIntTest.cpp29
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
OpenPOWER on IntegriCloud