Skip to content

Commit

Permalink
[ADT] Add BitVector::find_prev.
Browse files Browse the repository at this point in the history
This almost completes the matrix of all possible find
functions.

*EXISTING*
----------
find_first
find_first_unset
find_next
find_next_unset
find_last
find_last_unset

*NEW*
----
find_prev

*STILL MISSING*
---------------
find_prev_unset

Differential Revision: https://reviews.llvm.org/D32885

llvm-svn: 302254
  • Loading branch information
Zachary Turner committed May 5, 2017
1 parent 9c5c2bf commit 25597b2
Show file tree
Hide file tree
Showing 3 changed files with 55 additions and 0 deletions.
27 changes: 27 additions & 0 deletions llvm/include/llvm/ADT/BitVector.h
Expand Up @@ -253,6 +253,33 @@ class BitVector {
return -1;
}

/// find_prev - Returns the index of the first set bit that precedes the
/// the bit at \p PriorTo. Returns -1 if all previous bits are unset.
int find_prev(unsigned PriorTo) {
if (PriorTo == 0)
return -1;

--PriorTo;

unsigned WordPos = PriorTo / BITWORD_SIZE;
unsigned BitPos = PriorTo % BITWORD_SIZE;
BitWord Copy = Bits[WordPos];
// Mask off next bits.
Copy &= maskTrailingOnes<BitWord>(BitPos + 1);

if (Copy != 0)
return (WordPos + 1) * BITWORD_SIZE - countLeadingZeros(Copy) - 1;

// Check previous words.
for (unsigned i = 1; i <= WordPos; ++i) {
unsigned Index = WordPos - i;
if (Bits[Index] == 0)
continue;
return (Index + 1) * BITWORD_SIZE - countLeadingZeros(Bits[Index]) - 1;
}
return -1;
}

/// clear - Clear all bits.
void clear() {
Size = 0;
Expand Down
18 changes: 18 additions & 0 deletions llvm/include/llvm/ADT/SmallBitVector.h
Expand Up @@ -278,6 +278,24 @@ class SmallBitVector {
return getPointer()->find_next_unset(Prev);
}

/// find_prev - Returns the index of the first set bit that precedes the
/// the bit at \p PriorTo. Returns -1 if all previous bits are unset.
int find_prev(unsigned PriorTo) const {
if (isSmall()) {
if (PriorTo == 0)
return -1;

--PriorTo;
uintptr_t Bits = getSmallBits();
Bits &= maskTrailingOnes<uintptr_t>(PriorTo + 1);
if (Bits == 0)
return -1;

return NumBaseBits - countLeadingZeros(Bits) - 1;
}
return getPointer()->find_prev(PriorTo);
}

/// Clear all bits.
void clear() {
if (!isSmall())
Expand Down
10 changes: 10 additions & 0 deletions llvm/unittests/ADT/BitVectorTest.cpp
Expand Up @@ -204,6 +204,11 @@ TYPED_TEST(BitVectorTest, FindOperations) {
EXPECT_EQ(75, A.find_next(13));
EXPECT_EQ(-1, A.find_next(75));

EXPECT_EQ(-1, A.find_prev(12));
EXPECT_EQ(12, A.find_prev(13));
EXPECT_EQ(13, A.find_prev(75));
EXPECT_EQ(75, A.find_prev(90));

EXPECT_EQ(0, A.find_first_unset());
EXPECT_EQ(99, A.find_last_unset());
EXPECT_EQ(14, A.find_next_unset(11));
Expand Down Expand Up @@ -240,6 +245,11 @@ TYPED_TEST(BitVectorTest, FindOperations) {
EXPECT_EQ(16, A.find_next(4));
EXPECT_EQ(-1, A.find_next(16));

EXPECT_EQ(-1, A.find_prev(3));
EXPECT_EQ(3, A.find_prev(4));
EXPECT_EQ(4, A.find_prev(16));
EXPECT_EQ(16, A.find_prev(18));

EXPECT_EQ(0, A.find_first_unset());
EXPECT_EQ(19, A.find_last_unset());
EXPECT_EQ(5, A.find_next_unset(3));
Expand Down

0 comments on commit 25597b2

Please sign in to comment.