diff --git a/include/llvm/ADT/SmallBitVector.h b/include/llvm/ADT/SmallBitVector.h index d43c7afb104..7a645e0c724 100644 --- a/include/llvm/ADT/SmallBitVector.h +++ b/include/llvm/ADT/SmallBitVector.h @@ -354,6 +354,19 @@ public: return (*this)[Idx]; } + /// Test if any common bits are set. + bool anyCommon(const SmallBitVector &RHS) const { + if (isSmall() && RHS.isSmall()) + return (getSmallBits() & RHS.getSmallBits()) != 0; + if (!isSmall() && !RHS.isSmall()) + return getPointer()->anyCommon(*RHS.getPointer()); + + for (unsigned i = 0, e = std::min(size(), RHS.size()); i != e; ++i) + if (test(i) && RHS.test(i)) + return true; + return false; + } + // Comparison operators. bool operator==(const SmallBitVector &RHS) const { if (size() != RHS.size()) @@ -442,6 +455,59 @@ public: void swap(SmallBitVector &RHS) { std::swap(X, RHS.X); } + + /// setBitsInMask - Add '1' bits from Mask to this vector. Don't resize. + /// This computes "*this |= Mask". + void setBitsInMask(const uint32_t *Mask, unsigned MaskWords = ~0u) { + if (isSmall()) + applyMask(Mask, MaskWords); + else + getPointer()->setBitsInMask(Mask, MaskWords); + } + + /// clearBitsInMask - Clear any bits in this vector that are set in Mask. + /// Don't resize. This computes "*this &= ~Mask". + void clearBitsInMask(const uint32_t *Mask, unsigned MaskWords = ~0u) { + if (isSmall()) + applyMask(Mask, MaskWords); + else + getPointer()->clearBitsInMask(Mask, MaskWords); + } + + /// setBitsNotInMask - Add a bit to this vector for every '0' bit in Mask. + /// Don't resize. This computes "*this |= ~Mask". + void setBitsNotInMask(const uint32_t *Mask, unsigned MaskWords = ~0u) { + if (isSmall()) + applyMask(Mask, MaskWords); + else + getPointer()->setBitsNotInMask(Mask, MaskWords); + } + + /// clearBitsNotInMask - Clear a bit in this vector for every '0' bit in Mask. + /// Don't resize. This computes "*this &= Mask". + void clearBitsNotInMask(const uint32_t *Mask, unsigned MaskWords = ~0u) { + if (isSmall()) + applyMask(Mask, MaskWords); + else + getPointer()->clearBitsNotInMask(Mask, MaskWords); + } + +private: + template + void applyMask(const uint32_t *Mask, unsigned MaskWords) { + assert((NumBaseBits == 64 || NumBaseBits == 32) && "Unsupported word size"); + if (NumBaseBits == 64 && MaskWords >= 2) { + uint64_t M = Mask[0] | (uint64_t(Mask[1]) << 32); + if (InvertMask) M = ~M; + if (AddBits) setSmallBits(getSmallBits() | M); + else setSmallBits(getSmallBits() & ~M); + } else { + uint32_t M = Mask[0]; + if (InvertMask) M = ~M; + if (AddBits) setSmallBits(getSmallBits() | M); + else setSmallBits(getSmallBits() & ~M); + } + } }; inline SmallBitVector diff --git a/unittests/ADT/BitVectorTest.cpp b/unittests/ADT/BitVectorTest.cpp index 62aadf6f0e7..d836036aeae 100644 --- a/unittests/ADT/BitVectorTest.cpp +++ b/unittests/ADT/BitVectorTest.cpp @@ -11,14 +11,23 @@ #ifndef __ppc__ #include "llvm/ADT/BitVector.h" +#include "llvm/ADT/SmallBitVector.h" #include "gtest/gtest.h" using namespace llvm; namespace { -TEST(BitVectorTest, TrivialOperation) { - BitVector Vec; +// Test fixture +template +class BitVectorTest : public ::testing::Test { }; + +// Test both BitVector and SmallBitVector with the same suite of tests. +typedef ::testing::Types BitVectorTestTypes; +TYPED_TEST_CASE(BitVectorTest, BitVectorTestTypes); + +TYPED_TEST(BitVectorTest, TrivialOperation) { + TypeParam Vec; EXPECT_EQ(0U, Vec.count()); EXPECT_EQ(0U, Vec.size()); EXPECT_FALSE(Vec.any()); @@ -42,7 +51,7 @@ TEST(BitVectorTest, TrivialOperation) { EXPECT_FALSE(Vec.none()); EXPECT_FALSE(Vec.empty()); - BitVector Inv = Vec; + TypeParam Inv = Vec; Inv.flip(); EXPECT_EQ(6U, Inv.count()); EXPECT_EQ(11U, Inv.size()); @@ -77,8 +86,8 @@ TEST(BitVectorTest, TrivialOperation) { EXPECT_FALSE(Vec[56]); Vec.resize(61, false); - BitVector Copy = Vec; - BitVector Alt(3, false); + TypeParam Copy = Vec; + TypeParam Alt(3, false); Alt.resize(6, true); std::swap(Alt, Vec); EXPECT_TRUE(Copy == Alt); @@ -132,7 +141,7 @@ TEST(BitVectorTest, TrivialOperation) { EXPECT_TRUE(Vec.none()); EXPECT_FALSE(Vec.empty()); - Inv = BitVector().flip(); + Inv = TypeParam().flip(); EXPECT_EQ(0U, Inv.count()); EXPECT_EQ(0U, Inv.size()); EXPECT_FALSE(Inv.any()); @@ -149,13 +158,13 @@ TEST(BitVectorTest, TrivialOperation) { EXPECT_TRUE(Vec.empty()); } -TEST(BitVectorTest, CompoundAssignment) { - BitVector A; +TYPED_TEST(BitVectorTest, CompoundAssignment) { + TypeParam A; A.resize(10); A.set(4); A.set(7); - BitVector B; + TypeParam B; B.resize(50); B.set(5); B.set(18); @@ -188,8 +197,8 @@ TEST(BitVectorTest, CompoundAssignment) { EXPECT_EQ(100U, A.size()); } -TEST(BitVectorTest, ProxyIndex) { - BitVector Vec(3); +TYPED_TEST(BitVectorTest, ProxyIndex) { + TypeParam Vec(3); EXPECT_TRUE(Vec.none()); Vec[0] = Vec[1] = Vec[2] = true; EXPECT_EQ(Vec.size(), Vec.count()); @@ -197,8 +206,8 @@ TEST(BitVectorTest, ProxyIndex) { EXPECT_TRUE(Vec.none()); } -TEST(BitVectorTest, PortableBitMask) { - BitVector A; +TYPED_TEST(BitVectorTest, PortableBitMask) { + TypeParam A; const uint32_t Mask1[] = { 0x80000000, 6, 5 }; A.resize(10); @@ -244,9 +253,9 @@ TEST(BitVectorTest, PortableBitMask) { EXPECT_EQ(64-4u, A.count()); } -TEST(BitVectorTest, BinOps) { - BitVector A; - BitVector B; +TYPED_TEST(BitVectorTest, BinOps) { + TypeParam A; + TypeParam B; A.resize(65); EXPECT_FALSE(A.anyCommon(B)); diff --git a/unittests/ADT/SmallBitVectorTest.cpp b/unittests/ADT/SmallBitVectorTest.cpp deleted file mode 100644 index c4dda9e88d4..00000000000 --- a/unittests/ADT/SmallBitVectorTest.cpp +++ /dev/null @@ -1,196 +0,0 @@ -//===- llvm/unittest/ADT/SmallBitVectorTest.cpp - SmallBitVector tests ----===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#include "llvm/ADT/SmallBitVector.h" -#include "gtest/gtest.h" - -using namespace llvm; - -namespace { - -TEST(SmallBitVectorTest, TrivialOperation) { - SmallBitVector Vec; - EXPECT_EQ(0U, Vec.count()); - EXPECT_EQ(0U, Vec.size()); - EXPECT_FALSE(Vec.any()); - EXPECT_TRUE(Vec.all()); - EXPECT_TRUE(Vec.none()); - EXPECT_TRUE(Vec.empty()); - - Vec.resize(5, true); - EXPECT_EQ(5U, Vec.count()); - EXPECT_EQ(5U, Vec.size()); - EXPECT_TRUE(Vec.any()); - EXPECT_TRUE(Vec.all()); - EXPECT_FALSE(Vec.none()); - EXPECT_FALSE(Vec.empty()); - - Vec.resize(11); - EXPECT_EQ(5U, Vec.count()); - EXPECT_EQ(11U, Vec.size()); - EXPECT_TRUE(Vec.any()); - EXPECT_FALSE(Vec.all()); - EXPECT_FALSE(Vec.none()); - EXPECT_FALSE(Vec.empty()); - - SmallBitVector Inv = ~Vec; - EXPECT_EQ(6U, Inv.count()); - EXPECT_EQ(11U, Inv.size()); - EXPECT_TRUE(Inv.any()); - EXPECT_FALSE(Inv.all()); - EXPECT_FALSE(Inv.none()); - EXPECT_FALSE(Inv.empty()); - - EXPECT_FALSE(Inv == Vec); - EXPECT_TRUE(Inv != Vec); - Vec = ~Vec; - EXPECT_TRUE(Inv == Vec); - EXPECT_FALSE(Inv != Vec); - - // Add some "interesting" data to Vec. - Vec.resize(23, true); - Vec.resize(25, false); - Vec.resize(26, true); - Vec.resize(29, false); - Vec.resize(33, true); - Vec.resize(57, false); - unsigned Count = 0; - for (unsigned i = Vec.find_first(); i != -1u; i = Vec.find_next(i)) { - ++Count; - EXPECT_TRUE(Vec[i]); - EXPECT_TRUE(Vec.test(i)); - } - EXPECT_EQ(Count, Vec.count()); - EXPECT_EQ(Count, 23u); - EXPECT_FALSE(Vec[0]); - EXPECT_TRUE(Vec[32]); - EXPECT_FALSE(Vec[56]); - Vec.resize(61, false); - - SmallBitVector Copy = Vec; - SmallBitVector Alt(3, false); - Alt.resize(6, true); - std::swap(Alt, Vec); - EXPECT_TRUE(Copy == Alt); - EXPECT_TRUE(Vec.size() == 6); - EXPECT_TRUE(Vec.count() == 3); - EXPECT_TRUE(Vec.find_first() == 3); - std::swap(Copy, Vec); - - // Add some more "interesting" data. - Vec.resize(68, true); - Vec.resize(78, false); - Vec.resize(89, true); - Vec.resize(90, false); - Vec.resize(91, true); - Vec.resize(130, false); - Count = 0; - for (unsigned i = Vec.find_first(); i != -1u; i = Vec.find_next(i)) { - ++Count; - EXPECT_TRUE(Vec[i]); - EXPECT_TRUE(Vec.test(i)); - } - EXPECT_EQ(Count, Vec.count()); - EXPECT_EQ(Count, 42u); - EXPECT_FALSE(Vec[0]); - EXPECT_TRUE(Vec[32]); - EXPECT_FALSE(Vec[60]); - EXPECT_FALSE(Vec[129]); - - Vec.flip(60); - EXPECT_TRUE(Vec[60]); - EXPECT_EQ(Count + 1, Vec.count()); - Vec.flip(60); - EXPECT_FALSE(Vec[60]); - EXPECT_EQ(Count, Vec.count()); - - Vec.reset(32); - EXPECT_FALSE(Vec[32]); - EXPECT_EQ(Count - 1, Vec.count()); - Vec.set(32); - EXPECT_TRUE(Vec[32]); - EXPECT_EQ(Count, Vec.count()); - - Vec.flip(); - EXPECT_EQ(Vec.size() - Count, Vec.count()); - - Vec.reset(); - EXPECT_EQ(0U, Vec.count()); - EXPECT_EQ(130U, Vec.size()); - EXPECT_FALSE(Vec.any()); - EXPECT_FALSE(Vec.all()); - EXPECT_TRUE(Vec.none()); - EXPECT_FALSE(Vec.empty()); - - Inv = ~SmallBitVector(); - EXPECT_EQ(0U, Inv.count()); - EXPECT_EQ(0U, Inv.size()); - EXPECT_FALSE(Inv.any()); - EXPECT_TRUE(Inv.all()); - EXPECT_TRUE(Inv.none()); - EXPECT_TRUE(Inv.empty()); - - Vec.clear(); - EXPECT_EQ(0U, Vec.count()); - EXPECT_EQ(0U, Vec.size()); - EXPECT_FALSE(Vec.any()); - EXPECT_TRUE(Vec.all()); - EXPECT_TRUE(Vec.none()); - EXPECT_TRUE(Vec.empty()); -} - -TEST(SmallBitVectorTest, CompoundAssignment) { - SmallBitVector A; - A.resize(10); - A.set(4); - A.set(7); - - SmallBitVector B; - B.resize(50); - B.set(5); - B.set(18); - - A |= B; - EXPECT_TRUE(A.test(4)); - EXPECT_TRUE(A.test(5)); - EXPECT_TRUE(A.test(7)); - EXPECT_TRUE(A.test(18)); - EXPECT_EQ(4U, A.count()); - EXPECT_EQ(50U, A.size()); - - B.resize(10); - B.set(); - B.reset(2); - B.reset(7); - A &= B; - EXPECT_FALSE(A.test(2)); - EXPECT_FALSE(A.test(7)); - EXPECT_EQ(2U, A.count()); - EXPECT_EQ(50U, A.size()); - - B.resize(100); - B.set(); - - A ^= B; - EXPECT_TRUE(A.test(2)); - EXPECT_TRUE(A.test(7)); - EXPECT_EQ(98U, A.count()); - EXPECT_EQ(100U, A.size()); -} - -TEST(SmallBitVectorTest, ProxyIndex) { - SmallBitVector Vec(3); - EXPECT_TRUE(Vec.none()); - Vec[0] = Vec[1] = Vec[2] = true; - EXPECT_EQ(Vec.size(), Vec.count()); - Vec[2] = Vec[1] = Vec[0] = false; - EXPECT_TRUE(Vec.none()); -} - -}