summaryrefslogtreecommitdiff
path: root/include/llvm/ADT/BitVector.h
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2017-05-17 20:22:39 +0000
committerDimitry Andric <dim@FreeBSD.org>2017-05-17 20:22:39 +0000
commit7af96fb3afd6725a2824a0a5ca5dad34e5e0b056 (patch)
tree6661ffbabf869009597684462f5a3df3beccc952 /include/llvm/ADT/BitVector.h
parent6b3f41ed88e8e440e11a4fbf20b6600529f80049 (diff)
Diffstat (limited to 'include/llvm/ADT/BitVector.h')
-rw-r--r--include/llvm/ADT/BitVector.h273
1 files changed, 178 insertions, 95 deletions
diff --git a/include/llvm/ADT/BitVector.h b/include/llvm/ADT/BitVector.h
index 4a2af7cd68a6d..e68ef5f53d106 100644
--- a/include/llvm/ADT/BitVector.h
+++ b/include/llvm/ADT/BitVector.h
@@ -15,6 +15,7 @@
#define LLVM_ADT_BITVECTOR_H
#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/iterator_range.h"
#include "llvm/Support/MathExtras.h"
#include <algorithm>
#include <cassert>
@@ -26,6 +27,50 @@
namespace llvm {
+/// ForwardIterator for the bits that are set.
+/// Iterators get invalidated when resize / reserve is called.
+template <typename BitVectorT> class const_set_bits_iterator_impl {
+ const BitVectorT &Parent;
+ int Current = 0;
+
+ void advance() {
+ assert(Current != -1 && "Trying to advance past end.");
+ Current = Parent.find_next(Current);
+ }
+
+public:
+ const_set_bits_iterator_impl(const BitVectorT &Parent, int Current)
+ : Parent(Parent), Current(Current) {}
+ explicit const_set_bits_iterator_impl(const BitVectorT &Parent)
+ : const_set_bits_iterator_impl(Parent, Parent.find_first()) {}
+ const_set_bits_iterator_impl(const const_set_bits_iterator_impl &) = default;
+
+ const_set_bits_iterator_impl operator++(int) {
+ auto Prev = *this;
+ advance();
+ return Prev;
+ }
+
+ const_set_bits_iterator_impl &operator++() {
+ advance();
+ return *this;
+ }
+
+ unsigned operator*() const { return Current; }
+
+ bool operator==(const const_set_bits_iterator_impl &Other) const {
+ assert(&Parent == &Other.Parent &&
+ "Comparing iterators from different BitVectors");
+ return Current == Other.Current;
+ }
+
+ bool operator!=(const const_set_bits_iterator_impl &Other) const {
+ assert(&Parent == &Other.Parent &&
+ "Comparing iterators from different BitVectors");
+ return Current != Other.Current;
+ }
+};
+
class BitVector {
typedef unsigned long BitWord;
@@ -73,6 +118,18 @@ public:
}
};
+ typedef const_set_bits_iterator_impl<BitVector> const_set_bits_iterator;
+ typedef const_set_bits_iterator set_iterator;
+
+ const_set_bits_iterator set_bits_begin() const {
+ return const_set_bits_iterator(*this);
+ }
+ const_set_bits_iterator set_bits_end() const {
+ return const_set_bits_iterator(*this, -1);
+ }
+ iterator_range<const_set_bits_iterator> set_bits() const {
+ return make_range(set_bits_begin(), set_bits_end());
+ }
/// BitVector default ctor - Creates an empty bitvector.
BitVector() : Size(0) {}
@@ -146,138 +203,164 @@ public:
return !any();
}
- /// find_first - Returns the index of the first set bit, -1 if none
- /// of the bits are set.
- int find_first() const {
- for (unsigned i = 0; i < NumBitWords(size()); ++i)
- if (Bits[i] != 0)
- return i * BITWORD_SIZE + countTrailingZeros(Bits[i]);
- return -1;
- }
-
- /// find_last - Returns the index of the last set bit, -1 if none of the bits
- /// are set.
- int find_last() const {
- if (Size == 0)
+ /// find_first_in - Returns the index of the first set bit in the range
+ /// [Begin, End). Returns -1 if all bits in the range are unset.
+ int find_first_in(unsigned Begin, unsigned End) const {
+ assert(Begin <= End && End <= Size);
+ if (Begin == End)
return -1;
- unsigned N = NumBitWords(size());
- assert(N > 0);
+ unsigned FirstWord = Begin / BITWORD_SIZE;
+ unsigned LastWord = (End - 1) / BITWORD_SIZE;
- unsigned i = N - 1;
- while (i > 0 && Bits[i] == BitWord(0))
- --i;
+ // Check subsequent words.
+ for (unsigned i = FirstWord; i <= LastWord; ++i) {
+ BitWord Copy = Bits[i];
- return int((i + 1) * BITWORD_SIZE - countLeadingZeros(Bits[i])) - 1;
- }
+ if (i == FirstWord) {
+ unsigned FirstBit = Begin % BITWORD_SIZE;
+ Copy &= maskTrailingZeros<BitWord>(FirstBit);
+ }
- /// find_first_unset - Returns the index of the first unset bit, -1 if all
- /// of the bits are set.
- int find_first_unset() const {
- for (unsigned i = 0; i < NumBitWords(size()); ++i)
- if (Bits[i] != ~0UL) {
- unsigned Result = i * BITWORD_SIZE + countTrailingOnes(Bits[i]);
- return Result < size() ? Result : -1;
+ if (i == LastWord) {
+ unsigned LastBit = (End - 1) % BITWORD_SIZE;
+ Copy &= maskTrailingOnes<BitWord>(LastBit + 1);
}
+ if (Copy != 0)
+ return i * BITWORD_SIZE + countTrailingZeros(Copy);
+ }
return -1;
}
- /// find_last_unset - Returns the index of the last unset bit, -1 if all of
- /// the bits are set.
- int find_last_unset() const {
- if (Size == 0)
+ /// find_last_in - Returns the index of the last set bit in the range
+ /// [Begin, End). Returns -1 if all bits in the range are unset.
+ int find_last_in(unsigned Begin, unsigned End) const {
+ assert(Begin <= End && End <= Size);
+ if (Begin == End)
return -1;
- const unsigned N = NumBitWords(size());
- assert(N > 0);
+ unsigned LastWord = (End - 1) / BITWORD_SIZE;
+ unsigned FirstWord = Begin / BITWORD_SIZE;
- unsigned i = N - 1;
- BitWord W = Bits[i];
+ for (unsigned i = LastWord + 1; i >= FirstWord + 1; --i) {
+ unsigned CurrentWord = i - 1;
- // The last word in the BitVector has some unused bits, so we need to set
- // them all to 1 first. Set them all to 1 so they don't get treated as
- // valid unset bits.
- unsigned UnusedCount = BITWORD_SIZE - size() % BITWORD_SIZE;
- W |= maskLeadingOnes<BitWord>(UnusedCount);
+ BitWord Copy = Bits[CurrentWord];
+ if (CurrentWord == LastWord) {
+ unsigned LastBit = (End - 1) % BITWORD_SIZE;
+ Copy &= maskTrailingOnes<BitWord>(LastBit + 1);
+ }
- while (W == ~BitWord(0) && --i > 0)
- W = Bits[i];
+ if (CurrentWord == FirstWord) {
+ unsigned FirstBit = Begin % BITWORD_SIZE;
+ Copy &= maskTrailingZeros<BitWord>(FirstBit);
+ }
+
+ if (Copy != 0)
+ return (CurrentWord + 1) * BITWORD_SIZE - countLeadingZeros(Copy) - 1;
+ }
- return int((i + 1) * BITWORD_SIZE - countLeadingOnes(W)) - 1;
+ return -1;
}
- /// find_next - Returns the index of the next set bit following the
- /// "Prev" bit. Returns -1 if the next set bit is not found.
- int find_next(unsigned Prev) const {
- ++Prev;
- if (Prev >= Size)
+ /// find_first_unset_in - Returns the index of the first unset bit in the
+ /// range [Begin, End). Returns -1 if all bits in the range are set.
+ int find_first_unset_in(unsigned Begin, unsigned End) const {
+ assert(Begin <= End && End <= Size);
+ if (Begin == End)
return -1;
- unsigned WordPos = Prev / BITWORD_SIZE;
- unsigned BitPos = Prev % BITWORD_SIZE;
- BitWord Copy = Bits[WordPos];
- // Mask off previous bits.
- Copy &= maskTrailingZeros<BitWord>(BitPos);
-
- if (Copy != 0)
- return WordPos * BITWORD_SIZE + countTrailingZeros(Copy);
+ unsigned FirstWord = Begin / BITWORD_SIZE;
+ unsigned LastWord = (End - 1) / BITWORD_SIZE;
// Check subsequent words.
- for (unsigned i = WordPos+1; i < NumBitWords(size()); ++i)
- if (Bits[i] != 0)
- return i * BITWORD_SIZE + countTrailingZeros(Bits[i]);
+ for (unsigned i = FirstWord; i <= LastWord; ++i) {
+ BitWord Copy = Bits[i];
+
+ if (i == FirstWord) {
+ unsigned FirstBit = Begin % BITWORD_SIZE;
+ Copy |= maskTrailingOnes<BitWord>(FirstBit);
+ }
+
+ if (i == LastWord) {
+ unsigned LastBit = (End - 1) % BITWORD_SIZE;
+ Copy |= maskTrailingZeros<BitWord>(LastBit + 1);
+ }
+ if (Copy != ~0UL) {
+ unsigned Result = i * BITWORD_SIZE + countTrailingOnes(Copy);
+ return Result < size() ? Result : -1;
+ }
+ }
return -1;
}
- /// find_next_unset - Returns the index of the next unset bit following the
- /// "Prev" bit. Returns -1 if all remaining bits are set.
- int find_next_unset(unsigned Prev) const {
- ++Prev;
- if (Prev >= Size)
+ /// find_last_unset_in - Returns the index of the last unset bit in the
+ /// range [Begin, End). Returns -1 if all bits in the range are set.
+ int find_last_unset_in(unsigned Begin, unsigned End) const {
+ assert(Begin <= End && End <= Size);
+ if (Begin == End)
return -1;
- unsigned WordPos = Prev / BITWORD_SIZE;
- unsigned BitPos = Prev % BITWORD_SIZE;
- BitWord Copy = Bits[WordPos];
- // Mask in previous bits.
- BitWord Mask = (1 << BitPos) - 1;
- Copy |= Mask;
+ unsigned LastWord = (End - 1) / BITWORD_SIZE;
+ unsigned FirstWord = Begin / BITWORD_SIZE;
- if (Copy != ~0UL)
- return next_unset_in_word(WordPos, Copy);
+ for (unsigned i = LastWord + 1; i >= FirstWord + 1; --i) {
+ unsigned CurrentWord = i - 1;
- // Check subsequent words.
- for (unsigned i = WordPos + 1; i < NumBitWords(size()); ++i)
- if (Bits[i] != ~0UL)
- return next_unset_in_word(i, Bits[i]);
+ BitWord Copy = Bits[CurrentWord];
+ if (CurrentWord == LastWord) {
+ unsigned LastBit = (End - 1) % BITWORD_SIZE;
+ Copy |= maskTrailingZeros<BitWord>(LastBit + 1);
+ }
+
+ if (CurrentWord == FirstWord) {
+ unsigned FirstBit = Begin % BITWORD_SIZE;
+ Copy |= maskTrailingOnes<BitWord>(FirstBit);
+ }
+
+ if (Copy != ~0UL) {
+ unsigned Result =
+ (CurrentWord + 1) * BITWORD_SIZE - countLeadingOnes(Copy) - 1;
+ return Result < Size ? Result : -1;
+ }
+ }
return -1;
}
+ /// find_first - Returns the index of the first set bit, -1 if none
+ /// of the bits are set.
+ int find_first() const { return find_first_in(0, Size); }
+
+ /// find_last - Returns the index of the last set bit, -1 if none of the bits
+ /// are set.
+ int find_last() const { return find_last_in(0, Size); }
+
+ /// find_next - Returns the index of the next set bit following the
+ /// "Prev" bit. Returns -1 if the next set bit is not found.
+ int find_next(unsigned Prev) const { return find_first_in(Prev + 1, Size); }
+
/// 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 (PriorTo == 0)
- return -1;
+ int find_prev(unsigned PriorTo) const { return find_last_in(0, PriorTo); }
- --PriorTo;
+ /// find_first_unset - Returns the index of the first unset bit, -1 if all
+ /// of the bits are set.
+ int find_first_unset() const { return find_first_unset_in(0, Size); }
- unsigned WordPos = PriorTo / BITWORD_SIZE;
- unsigned BitPos = PriorTo % BITWORD_SIZE;
- BitWord Copy = Bits[WordPos];
- // Mask off next bits.
- Copy &= maskTrailingOnes<BitWord>(BitPos + 1);
+ /// find_next_unset - Returns the index of the next unset bit following the
+ /// "Prev" bit. Returns -1 if all remaining bits are set.
+ int find_next_unset(unsigned Prev) const {
+ return find_first_unset_in(Prev + 1, Size);
+ }
- if (Copy != 0)
- return (WordPos + 1) * BITWORD_SIZE - countLeadingZeros(Copy) - 1;
+ /// find_last_unset - Returns the index of the last unset bit, -1 if all of
+ /// the bits are set.
+ int find_last_unset() const { return find_last_unset_in(0, Size); }
- // 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;
+ /// find_prev_unset - Returns the index of the first unset bit that precedes
+ /// the bit at \p PriorTo. Returns -1 if all previous bits are set.
+ int find_prev_unset(unsigned PriorTo) {
+ return find_last_unset_in(0, PriorTo);
}
/// clear - Removes all bits from the bitvector. Does not change capacity.