Skip to content

[ADT] Simplify SparseBitVectorIterator. NFCI. #143885

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 3 commits into
base: main
Choose a base branch
from
Open
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
128 changes: 24 additions & 104 deletions llvm/include/llvm/ADT/SparseBitVector.h
Original file line number Diff line number Diff line change
Expand Up @@ -145,19 +145,14 @@ template <unsigned ElementSize = 128> struct SparseBitVectorElement {

/// find_next - Returns the index of the next set bit starting from the
/// "Curr" bit. Returns -1 if the next set bit is not found.
int find_next(unsigned Curr) const {
if (Curr >= BITS_PER_ELEMENT)
return -1;
int find_next(int Curr) const {
assert(Curr >= 0 && Curr < BITS_PER_ELEMENT);

unsigned WordPos = Curr / BITWORD_SIZE;
unsigned BitPos = Curr % BITWORD_SIZE;
BitWord Copy = Bits[WordPos];
assert(WordPos <= BITWORDS_PER_ELEMENT
&& "Word Position outside of element");

// Mask off previous bits.
Copy &= ~0UL << BitPos;

BitWord Copy = Bits[WordPos] & ~1UL << BitPos;
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Using ~1UL instead of ~0UL is a bug fix. Previously this whole find_next method was unused.

if (Copy != 0)
return WordPos * BITWORD_SIZE + llvm::countr_zero(Copy);

Expand Down Expand Up @@ -314,101 +309,34 @@ class SparseBitVector {
return FindLowerBoundImpl(ElementIndex);
}

// Iterator to walk set bits in the bitmap. This iterator is a lot uglier
// than it would be, in order to be efficient.
// Iterator to walk set bits in the bitvector.
class SparseBitVectorIterator {
private:
bool AtEnd;

const SparseBitVector<ElementSize> *BitVector = nullptr;
// Current bit number within the current element, or -1 if we are at the
// end.
int BitPos = -1;

// Current element inside of bitmap.
// Iterators to the current element and the end of the bitvector. These are
// only valid when BitPos >= 0.
ElementListConstIter Iter;

// Current bit number inside of our bitmap.
unsigned BitNumber;

// Current word number inside of our element.
unsigned WordNumber;

// Current bits from the element.
typename SparseBitVectorElement<ElementSize>::BitWord Bits;

// Move our iterator to the first non-zero bit in the bitmap.
void AdvanceToFirstNonZero() {
if (AtEnd)
return;
if (BitVector->Elements.empty()) {
AtEnd = true;
return;
}
Iter = BitVector->Elements.begin();
BitNumber = Iter->index() * ElementSize;
unsigned BitPos = Iter->find_first();
BitNumber += BitPos;
WordNumber = (BitNumber % ElementSize) / BITWORD_SIZE;
Bits = Iter->word(WordNumber);
Bits >>= BitPos % BITWORD_SIZE;
}

// Move our iterator to the next non-zero bit.
void AdvanceToNextNonZero() {
if (AtEnd)
return;

while (Bits && !(Bits & 1)) {
Bits >>= 1;
BitNumber += 1;
}

// See if we ran out of Bits in this word.
if (!Bits) {
int NextSetBitNumber = Iter->find_next(BitNumber % ElementSize) ;
// If we ran out of set bits in this element, move to next element.
if (NextSetBitNumber == -1 || (BitNumber % ElementSize == 0)) {
++Iter;
WordNumber = 0;

// We may run out of elements in the bitmap.
if (Iter == BitVector->Elements.end()) {
AtEnd = true;
return;
}
// Set up for next non-zero word in bitmap.
BitNumber = Iter->index() * ElementSize;
NextSetBitNumber = Iter->find_first();
BitNumber += NextSetBitNumber;
WordNumber = (BitNumber % ElementSize) / BITWORD_SIZE;
Bits = Iter->word(WordNumber);
Bits >>= NextSetBitNumber % BITWORD_SIZE;
} else {
WordNumber = (NextSetBitNumber % ElementSize) / BITWORD_SIZE;
Bits = Iter->word(WordNumber);
Bits >>= NextSetBitNumber % BITWORD_SIZE;
BitNumber = Iter->index() * ElementSize;
BitNumber += NextSetBitNumber;
}
}
}
ElementListConstIter End;

public:
SparseBitVectorIterator() = default;

SparseBitVectorIterator(const SparseBitVector<ElementSize> *RHS,
bool end = false):BitVector(RHS) {
Iter = BitVector->Elements.begin();
BitNumber = 0;
Bits = 0;
WordNumber = ~0;
AtEnd = end;
AdvanceToFirstNonZero();
SparseBitVectorIterator(const ElementList &Elements) {
if (Elements.empty())
return;
Iter = Elements.begin();
End = Elements.end();
BitPos = Iter->find_first();
}

// Preincrement.
inline SparseBitVectorIterator& operator++() {
++BitNumber;
Bits >>= 1;
AdvanceToNextNonZero();
BitPos = Iter->find_next(BitPos);
if (BitPos < 0 && ++Iter != End)
BitPos = Iter->find_first();
return *this;
}

Expand All @@ -421,16 +349,12 @@ class SparseBitVector {

// Return the current set bit number.
unsigned operator*() const {
return BitNumber;
assert(BitPos >= 0);
return Iter->index() * ElementSize + BitPos;
}

bool operator==(const SparseBitVectorIterator &RHS) const {
// If they are both at the end, ignore the rest of the fields.
if (AtEnd && RHS.AtEnd)
return true;
// Otherwise they are the same if they have the same bit number and
// bitmap.
return AtEnd == RHS.AtEnd && RHS.BitNumber == BitNumber;
return BitPos == RHS.BitPos;
}

bool operator!=(const SparseBitVectorIterator &RHS) const {
Expand Down Expand Up @@ -807,13 +731,9 @@ class SparseBitVector {
return BitCount;
}

iterator begin() const {
return iterator(this);
}
iterator begin() const { return iterator(Elements); }

iterator end() const {
return iterator(this, true);
}
iterator end() const { return iterator(); }
};

// Convenience functions to allow Or and And without dereferencing in the user
Expand Down
Loading