mirror of
https://github.com/RPCS3/llvm.git
synced 2025-04-14 03:50:48 +00:00

BitVector had methods for searching for the first and next set bits, but it did not have analagous methods for finding the first and next unset bits. This is useful when your ones and zeros are grouped together and you want to iterate over ranges of ones and zeros. Differential Revision: https://reviews.llvm.org/D31802 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@299857 91177308-0d34-0410-b5e6-96231b3b80d8
506 lines
11 KiB
C++
506 lines
11 KiB
C++
//===- llvm/unittest/ADT/BitVectorTest.cpp - BitVector tests --------------===//
|
|
//
|
|
// The LLVM Compiler Infrastructure
|
|
//
|
|
// This file is distributed under the University of Illinois Open Source
|
|
// License. See LICENSE.TXT for details.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// Some of these tests fail on PowerPC for unknown reasons.
|
|
#ifndef __ppc__
|
|
|
|
#include "llvm/ADT/BitVector.h"
|
|
#include "llvm/ADT/SmallBitVector.h"
|
|
#include "gtest/gtest.h"
|
|
|
|
using namespace llvm;
|
|
|
|
namespace {
|
|
|
|
// Test fixture
|
|
template <typename T>
|
|
class BitVectorTest : public ::testing::Test { };
|
|
|
|
// Test both BitVector and SmallBitVector with the same suite of tests.
|
|
typedef ::testing::Types<BitVector, SmallBitVector> 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());
|
|
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());
|
|
|
|
TypeParam Inv = Vec;
|
|
Inv.flip();
|
|
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.flip();
|
|
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);
|
|
|
|
TypeParam Copy = Vec;
|
|
TypeParam 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());
|
|
|
|
Vec.flip();
|
|
EXPECT_EQ(130U, Vec.count());
|
|
EXPECT_EQ(130U, Vec.size());
|
|
EXPECT_TRUE(Vec.any());
|
|
EXPECT_TRUE(Vec.all());
|
|
EXPECT_FALSE(Vec.none());
|
|
EXPECT_FALSE(Vec.empty());
|
|
|
|
Vec.resize(64);
|
|
EXPECT_EQ(64U, Vec.count());
|
|
EXPECT_EQ(64U, Vec.size());
|
|
EXPECT_TRUE(Vec.any());
|
|
EXPECT_TRUE(Vec.all());
|
|
EXPECT_FALSE(Vec.none());
|
|
EXPECT_FALSE(Vec.empty());
|
|
|
|
Vec.flip();
|
|
EXPECT_EQ(0U, Vec.count());
|
|
EXPECT_EQ(64U, Vec.size());
|
|
EXPECT_FALSE(Vec.any());
|
|
EXPECT_FALSE(Vec.all());
|
|
EXPECT_TRUE(Vec.none());
|
|
EXPECT_FALSE(Vec.empty());
|
|
|
|
Inv = TypeParam().flip();
|
|
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());
|
|
}
|
|
|
|
TYPED_TEST(BitVectorTest, FindOperations) {
|
|
// Test finding in an empty BitVector.
|
|
TypeParam A;
|
|
EXPECT_EQ(-1, A.find_first());
|
|
EXPECT_EQ(-1, A.find_first_unset());
|
|
EXPECT_EQ(-1, A.find_next(0));
|
|
EXPECT_EQ(-1, A.find_next_unset(0));
|
|
|
|
// Test finding next set and unset bits in a BitVector with multiple words
|
|
A.resize(100);
|
|
A.set(12);
|
|
A.set(13);
|
|
A.set(75);
|
|
|
|
EXPECT_EQ(12, A.find_first());
|
|
EXPECT_EQ(13, A.find_next(12));
|
|
EXPECT_EQ(75, A.find_next(13));
|
|
EXPECT_EQ(-1, A.find_next(75));
|
|
|
|
EXPECT_EQ(0, A.find_first_unset());
|
|
EXPECT_EQ(14, A.find_next_unset(11));
|
|
EXPECT_EQ(14, A.find_next_unset(12));
|
|
EXPECT_EQ(14, A.find_next_unset(13));
|
|
EXPECT_EQ(16, A.find_next_unset(15));
|
|
EXPECT_EQ(76, A.find_next_unset(74));
|
|
EXPECT_EQ(76, A.find_next_unset(75));
|
|
EXPECT_EQ(-1, A.find_next_unset(99));
|
|
|
|
A.set(0, 100);
|
|
EXPECT_EQ(100, A.count());
|
|
EXPECT_EQ(0, A.find_first());
|
|
EXPECT_EQ(-1, A.find_first_unset());
|
|
|
|
A.reset(0, 100);
|
|
EXPECT_EQ(0, A.count());
|
|
EXPECT_EQ(-1, A.find_first());
|
|
EXPECT_EQ(0, A.find_first_unset());
|
|
}
|
|
|
|
TYPED_TEST(BitVectorTest, CompoundAssignment) {
|
|
TypeParam A;
|
|
A.resize(10);
|
|
A.set(4);
|
|
A.set(7);
|
|
|
|
TypeParam 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());
|
|
}
|
|
|
|
TYPED_TEST(BitVectorTest, ProxyIndex) {
|
|
TypeParam 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());
|
|
}
|
|
|
|
TYPED_TEST(BitVectorTest, PortableBitMask) {
|
|
TypeParam A;
|
|
const uint32_t Mask1[] = { 0x80000000, 6, 5 };
|
|
|
|
A.resize(10);
|
|
A.setBitsInMask(Mask1, 1);
|
|
EXPECT_EQ(10u, A.size());
|
|
EXPECT_FALSE(A.test(0));
|
|
|
|
A.resize(32);
|
|
A.setBitsInMask(Mask1, 1);
|
|
EXPECT_FALSE(A.test(0));
|
|
EXPECT_TRUE(A.test(31));
|
|
EXPECT_EQ(1u, A.count());
|
|
|
|
A.resize(33);
|
|
A.setBitsInMask(Mask1, 1);
|
|
EXPECT_EQ(1u, A.count());
|
|
A.setBitsInMask(Mask1, 2);
|
|
EXPECT_EQ(1u, A.count());
|
|
|
|
A.resize(34);
|
|
A.setBitsInMask(Mask1, 2);
|
|
EXPECT_EQ(2u, A.count());
|
|
|
|
A.resize(65);
|
|
A.setBitsInMask(Mask1, 3);
|
|
EXPECT_EQ(4u, A.count());
|
|
|
|
A.setBitsNotInMask(Mask1, 1);
|
|
EXPECT_EQ(32u+3u, A.count());
|
|
|
|
A.setBitsNotInMask(Mask1, 3);
|
|
EXPECT_EQ(65u, A.count());
|
|
|
|
A.resize(96);
|
|
EXPECT_EQ(65u, A.count());
|
|
|
|
A.clear();
|
|
A.resize(128);
|
|
A.setBitsNotInMask(Mask1, 3);
|
|
EXPECT_EQ(96u-5u, A.count());
|
|
|
|
A.clearBitsNotInMask(Mask1, 1);
|
|
EXPECT_EQ(64-4u, A.count());
|
|
}
|
|
|
|
TYPED_TEST(BitVectorTest, BinOps) {
|
|
TypeParam A;
|
|
TypeParam B;
|
|
|
|
A.resize(65);
|
|
EXPECT_FALSE(A.anyCommon(B));
|
|
EXPECT_FALSE(B.anyCommon(B));
|
|
|
|
B.resize(64);
|
|
A.set(64);
|
|
EXPECT_FALSE(A.anyCommon(B));
|
|
EXPECT_FALSE(B.anyCommon(A));
|
|
|
|
B.set(63);
|
|
EXPECT_FALSE(A.anyCommon(B));
|
|
EXPECT_FALSE(B.anyCommon(A));
|
|
|
|
A.set(63);
|
|
EXPECT_TRUE(A.anyCommon(B));
|
|
EXPECT_TRUE(B.anyCommon(A));
|
|
|
|
B.resize(70);
|
|
B.set(64);
|
|
B.reset(63);
|
|
A.resize(64);
|
|
EXPECT_FALSE(A.anyCommon(B));
|
|
EXPECT_FALSE(B.anyCommon(A));
|
|
}
|
|
|
|
TYPED_TEST(BitVectorTest, RangeOps) {
|
|
TypeParam A;
|
|
A.resize(256);
|
|
A.reset();
|
|
A.set(1, 255);
|
|
|
|
EXPECT_FALSE(A.test(0));
|
|
EXPECT_TRUE( A.test(1));
|
|
EXPECT_TRUE( A.test(23));
|
|
EXPECT_TRUE( A.test(254));
|
|
EXPECT_FALSE(A.test(255));
|
|
|
|
TypeParam B;
|
|
B.resize(256);
|
|
B.set();
|
|
B.reset(1, 255);
|
|
|
|
EXPECT_TRUE( B.test(0));
|
|
EXPECT_FALSE(B.test(1));
|
|
EXPECT_FALSE(B.test(23));
|
|
EXPECT_FALSE(B.test(254));
|
|
EXPECT_TRUE( B.test(255));
|
|
|
|
TypeParam C;
|
|
C.resize(3);
|
|
C.reset();
|
|
C.set(0, 1);
|
|
|
|
EXPECT_TRUE(C.test(0));
|
|
EXPECT_FALSE( C.test(1));
|
|
EXPECT_FALSE( C.test(2));
|
|
|
|
TypeParam D;
|
|
D.resize(3);
|
|
D.set();
|
|
D.reset(0, 1);
|
|
|
|
EXPECT_FALSE(D.test(0));
|
|
EXPECT_TRUE( D.test(1));
|
|
EXPECT_TRUE( D.test(2));
|
|
|
|
TypeParam E;
|
|
E.resize(128);
|
|
E.reset();
|
|
E.set(1, 33);
|
|
|
|
EXPECT_FALSE(E.test(0));
|
|
EXPECT_TRUE( E.test(1));
|
|
EXPECT_TRUE( E.test(32));
|
|
EXPECT_FALSE(E.test(33));
|
|
|
|
TypeParam BufferOverrun;
|
|
unsigned size = sizeof(unsigned long) * 8;
|
|
BufferOverrun.resize(size);
|
|
BufferOverrun.reset(0, size);
|
|
BufferOverrun.set(0, size);
|
|
}
|
|
|
|
TYPED_TEST(BitVectorTest, CompoundTestReset) {
|
|
TypeParam A(50, true);
|
|
TypeParam B(50, false);
|
|
|
|
TypeParam C(100, true);
|
|
TypeParam D(100, false);
|
|
|
|
EXPECT_FALSE(A.test(A));
|
|
EXPECT_TRUE(A.test(B));
|
|
EXPECT_FALSE(A.test(C));
|
|
EXPECT_TRUE(A.test(D));
|
|
EXPECT_FALSE(B.test(A));
|
|
EXPECT_FALSE(B.test(B));
|
|
EXPECT_FALSE(B.test(C));
|
|
EXPECT_FALSE(B.test(D));
|
|
EXPECT_TRUE(C.test(A));
|
|
EXPECT_TRUE(C.test(B));
|
|
EXPECT_FALSE(C.test(C));
|
|
EXPECT_TRUE(C.test(D));
|
|
|
|
A.reset(B);
|
|
A.reset(D);
|
|
EXPECT_TRUE(A.all());
|
|
A.reset(A);
|
|
EXPECT_TRUE(A.none());
|
|
A.set();
|
|
A.reset(C);
|
|
EXPECT_TRUE(A.none());
|
|
A.set();
|
|
|
|
C.reset(A);
|
|
EXPECT_EQ(50, C.find_first());
|
|
C.reset(C);
|
|
EXPECT_TRUE(C.none());
|
|
}
|
|
|
|
TYPED_TEST(BitVectorTest, MoveConstructor) {
|
|
TypeParam A(10, true);
|
|
TypeParam B(std::move(A));
|
|
// Check that the move ctor leaves the moved-from object in a valid state.
|
|
// The following line used to crash.
|
|
A = B;
|
|
|
|
TypeParam C(10, true);
|
|
EXPECT_EQ(C, A);
|
|
EXPECT_EQ(C, B);
|
|
}
|
|
|
|
TYPED_TEST(BitVectorTest, MoveAssignment) {
|
|
TypeParam A(10, true);
|
|
TypeParam B;
|
|
B = std::move(A);
|
|
// Check that move assignment leaves the moved-from object in a valid state.
|
|
// The following line used to crash.
|
|
A = B;
|
|
|
|
TypeParam C(10, true);
|
|
EXPECT_EQ(C, A);
|
|
EXPECT_EQ(C, B);
|
|
}
|
|
|
|
template<class TypeParam>
|
|
static void testEmpty(const TypeParam &A) {
|
|
EXPECT_TRUE(A.empty());
|
|
EXPECT_EQ((size_t)0, A.size());
|
|
EXPECT_EQ((size_t)0, A.count());
|
|
EXPECT_FALSE(A.any());
|
|
EXPECT_TRUE(A.all());
|
|
EXPECT_TRUE(A.none());
|
|
EXPECT_EQ(-1, A.find_first());
|
|
EXPECT_EQ(A, TypeParam());
|
|
}
|
|
|
|
/// Tests whether BitVector behaves well with Bits==nullptr, Capacity==0
|
|
TYPED_TEST(BitVectorTest, EmptyVector) {
|
|
TypeParam A;
|
|
testEmpty(A);
|
|
|
|
TypeParam B;
|
|
B.reset();
|
|
testEmpty(B);
|
|
|
|
TypeParam C;
|
|
C.clear();
|
|
testEmpty(C);
|
|
|
|
TypeParam D(A);
|
|
testEmpty(D);
|
|
|
|
TypeParam E;
|
|
E = A;
|
|
testEmpty(E);
|
|
|
|
TypeParam F;
|
|
E.reset(A);
|
|
testEmpty(E);
|
|
}
|
|
|
|
}
|
|
#endif
|