#ifndef LLVM_ADT_SPARSEBITVECTOR_H
#define LLVM_ADT_SPARSEBITVECTOR_H
-#include <cassert>
-#include <cstring>
-#include <algorithm>
+#include "llvm/ADT/ilist.h"
+#include "llvm/ADT/ilist_node.h"
#include "llvm/Support/DataTypes.h"
-#include "llvm/ADT/STLExtras.h"
+#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/MathExtras.h"
-#include "llvm/ADT/ilist"
+#include "llvm/Support/raw_ostream.h"
+#include <cassert>
+#include <climits>
+
namespace llvm {
/// SparseBitVector is an implementation of a bitvector that is sparse by only
/// etc) do not perform as well in practice as a linked list with this iterator
/// kept up to date. They are also significantly more memory intensive.
-
template <unsigned ElementSize = 128>
-struct SparseBitVectorElement {
+struct SparseBitVectorElement
+ : public ilist_node<SparseBitVectorElement<ElementSize> > {
public:
typedef unsigned long BitWord;
+ typedef unsigned size_type;
enum {
- BITWORD_SIZE = sizeof(BitWord) * 8,
+ BITWORD_SIZE = sizeof(BitWord) * CHAR_BIT,
BITWORDS_PER_ELEMENT = (ElementSize + BITWORD_SIZE - 1) / BITWORD_SIZE,
BITS_PER_ELEMENT = ElementSize
};
- SparseBitVectorElement<ElementSize> *getNext() const {
- return Next;
- }
- SparseBitVectorElement<ElementSize> *getPrev() const {
- return Prev;
- }
-
- void setNext(SparseBitVectorElement<ElementSize> *RHS) {
- Next = RHS;
- }
- void setPrev(SparseBitVectorElement<ElementSize> *RHS) {
- Prev = RHS;
- }
-
private:
- SparseBitVectorElement<ElementSize> *Next;
- SparseBitVectorElement<ElementSize> *Prev;
// Index of Element in terms of where first bit starts.
unsigned ElementIndex;
BitWord Bits[BITWORDS_PER_ELEMENT];
// Needed for sentinels
+ friend struct ilist_sentinel_traits<SparseBitVectorElement>;
SparseBitVectorElement() {
- ElementIndex = ~0UL;
+ ElementIndex = ~0U;
memset(&Bits[0], 0, sizeof (BitWord) * BITWORDS_PER_ELEMENT);
}
- friend struct ilist_traits<SparseBitVectorElement<ElementSize> >;
public:
explicit SparseBitVectorElement(unsigned Idx) {
ElementIndex = Idx;
memset(&Bits[0], 0, sizeof (BitWord) * BITWORDS_PER_ELEMENT);
}
- ~SparseBitVectorElement() {
- }
-
- // Copy ctor.
- SparseBitVectorElement(const SparseBitVectorElement &RHS) {
- ElementIndex = RHS.ElementIndex;
- std::copy(&RHS.Bits[0], &RHS.Bits[BITWORDS_PER_ELEMENT], Bits);
- }
-
// Comparison.
bool operator==(const SparseBitVectorElement &RHS) const {
if (ElementIndex != RHS.ElementIndex)
return Bits[Idx / BITWORD_SIZE] & (1L << (Idx % BITWORD_SIZE));
}
- unsigned count() const {
+ size_type count() const {
unsigned NumBits = 0;
for (unsigned i = 0; i < BITWORDS_PER_ELEMENT; ++i)
- if (sizeof(BitWord) == 4)
- NumBits += CountPopulation_32(Bits[i]);
- else if (sizeof(BitWord) == 8)
- NumBits += CountPopulation_64(Bits[i]);
- else
- assert(0 && "Unsupported!");
+ NumBits += countPopulation(Bits[i]);
return NumBits;
}
/// find_first - Returns the index of the first set bit.
int find_first() const {
for (unsigned i = 0; i < BITWORDS_PER_ELEMENT; ++i)
- if (Bits[i] != 0) {
- if (sizeof(BitWord) == 4)
- return i * BITWORD_SIZE + CountTrailingZeros_32(Bits[i]);
- else if (sizeof(BitWord) == 8)
- return i * BITWORD_SIZE + CountTrailingZeros_64(Bits[i]);
- else
- assert(0 && "Unsupported!");
- }
- assert(0 && "Illegal empty element");
+ if (Bits[i] != 0)
+ return i * BITWORD_SIZE + countTrailingZeros(Bits[i]);
+ llvm_unreachable("Illegal empty element");
}
/// find_next - Returns the index of the next set bit starting from the
&& "Word Position outside of element");
// Mask off previous bits.
- Copy &= ~0L << BitPos;
+ Copy &= ~0UL << BitPos;
- if (Copy != 0) {
- if (sizeof(BitWord) == 4)
- return WordPos * BITWORD_SIZE + CountTrailingZeros_32(Copy);
- else if (sizeof(BitWord) == 8)
- return WordPos * BITWORD_SIZE + CountTrailingZeros_64(Copy);
- else
- assert(0 && "Unsupported!");
- }
+ if (Copy != 0)
+ return WordPos * BITWORD_SIZE + countTrailingZeros(Copy);
// Check subsequent words.
for (unsigned i = WordPos+1; i < BITWORDS_PER_ELEMENT; ++i)
- if (Bits[i] != 0) {
- if (sizeof(BitWord) == 4)
- return i * BITWORD_SIZE + CountTrailingZeros_32(Bits[i]);
- else if (sizeof(BitWord) == 8)
- return i * BITWORD_SIZE + CountTrailingZeros_64(Bits[i]);
- else
- assert(0 && "Unsupported!");
- }
+ if (Bits[i] != 0)
+ return i * BITWORD_SIZE + countTrailingZeros(Bits[i]);
return -1;
}
BecameZero = allzero;
return changed;
}
+
// Intersect this Element with the complement of RHS and return true if this
// one changed. BecameZero is set to true if this element became all-zero
// bits.
BecameZero = allzero;
return changed;
}
+
// Three argument version of intersectWithComplement that intersects
// RHS1 & ~RHS2 into this element
void intersectWithComplement(const SparseBitVectorElement &RHS1,
}
BecameZero = allzero;
}
+};
- // Get a hash value for this element;
- uint64_t getHashValue() const {
- uint64_t HashVal = 0;
- for (unsigned i = 0; i < BITWORDS_PER_ELEMENT; ++i) {
- HashVal ^= Bits[i];
- }
- return HashVal;
- }
+template <unsigned ElementSize>
+struct ilist_traits<SparseBitVectorElement<ElementSize> >
+ : public ilist_default_traits<SparseBitVectorElement<ElementSize> > {
+ typedef SparseBitVectorElement<ElementSize> Element;
+
+ Element *createSentinel() const { return static_cast<Element *>(&Sentinel); }
+ static void destroySentinel(Element *) {}
+
+ Element *provideInitialHead() const { return createSentinel(); }
+ Element *ensureHead(Element *) const { return createSentinel(); }
+ static void noteHead(Element *, Element *) {}
+
+private:
+ mutable ilist_half_node<Element> Sentinel;
};
template <unsigned ElementSize = 128>
AtEnd = true;
return;
}
- // Set up for next non zero word in bitmap.
+ // Set up for next non-zero word in bitmap.
BitNumber = Iter->index() * ElementSize;
NextSetBitNumber = Iter->find_first();
BitNumber += NextSetBitNumber;
// bitmap.
return AtEnd == RHS.AtEnd && RHS.BitNumber == BitNumber;
}
+
bool operator!=(const SparseBitVectorIterator &RHS) const {
return !(*this == RHS);
}
- SparseBitVectorIterator(): BitVector(NULL) {
- }
+ SparseBitVectorIterator(): BitVector(nullptr) {
+ }
SparseBitVectorIterator(const SparseBitVector<ElementSize> *RHS,
bool end = false):BitVector(RHS) {
CurrElementIter = Elements.begin ();
}
+ // Clear.
+ void clear() {
+ Elements.clear();
+ }
+
+ // Assignment
+ SparseBitVector& operator=(const SparseBitVector& RHS) {
+ if (this == &RHS)
+ return *this;
+
+ Elements.clear();
+
+ ElementListConstIter ElementIter = RHS.Elements.begin();
+ while (ElementIter != RHS.Elements.end()) {
+ Elements.push_back(SparseBitVectorElement<ElementSize>(*ElementIter));
+ ++ElementIter;
+ }
+
+ CurrElementIter = Elements.begin ();
+
+ return *this;
+ }
+
// Test, Reset, and Set a bit in the bitmap.
bool test(unsigned Idx) {
if (Elements.empty())
// Union our bitmap with the RHS and return true if we changed.
bool operator|=(const SparseBitVector &RHS) {
+ if (this == &RHS)
+ return false;
+
bool changed = false;
ElementListIter Iter1 = Elements.begin();
ElementListConstIter Iter2 = RHS.Elements.begin();
// Intersect our bitmap with the RHS and return true if ours changed.
bool operator&=(const SparseBitVector &RHS) {
+ if (this == &RHS)
+ return false;
+
bool changed = false;
ElementListIter Iter1 = Elements.begin();
ElementListConstIter Iter2 = RHS.Elements.begin();
ElementListIter IterTmp = Iter1;
++Iter1;
Elements.erase(IterTmp);
+ changed = true;
}
}
- Elements.erase(Iter1, Elements.end());
+ if (Iter1 != Elements.end()) {
+ Elements.erase(Iter1, Elements.end());
+ changed = true;
+ }
CurrElementIter = Elements.begin();
return changed;
}
- // Intersect our bitmap with the complement of the RHS and return true if ours
- // changed.
+ // Intersect our bitmap with the complement of the RHS and return true
+ // if ours changed.
bool intersectWithComplement(const SparseBitVector &RHS) {
+ if (this == &RHS) {
+ if (!empty()) {
+ clear();
+ return true;
+ }
+ return false;
+ }
+
bool changed = false;
ElementListIter Iter1 = Elements.begin();
ElementListConstIter Iter2 = RHS.Elements.begin();
return intersectWithComplement(*RHS);
}
-
- // Three argument version of intersectWithComplement. Result of RHS1 & ~RHS2
- // is stored into this bitmap.
+ // Three argument version of intersectWithComplement.
+ // Result of RHS1 & ~RHS2 is stored into this bitmap.
void intersectWithComplement(const SparseBitVector<ElementSize> &RHS1,
const SparseBitVector<ElementSize> &RHS2)
{
+ if (this == &RHS1) {
+ intersectWithComplement(RHS2);
+ return;
+ } else if (this == &RHS2) {
+ SparseBitVector RHS2Copy(RHS2);
+ intersectWithComplement(RHS1, RHS2Copy);
+ return;
+ }
+
Elements.clear();
CurrElementIter = Elements.begin();
ElementListConstIter Iter1 = RHS1.Elements.begin();
Elements.push_back(NewElement);
++Iter1;
}
-
- return;
}
void intersectWithComplement(const SparseBitVector<ElementSize> *RHS1,
return false;
}
+ // Return true iff all bits set in this SparseBitVector are
+ // also set in RHS.
+ bool contains(const SparseBitVector<ElementSize> &RHS) const {
+ SparseBitVector<ElementSize> Result(*this);
+ Result &= RHS;
+ return (Result == RHS);
+ }
+
// Return the first set bit in the bitmap. Return -1 if no bits are set.
int find_first() const {
if (Elements.empty())
iterator end() const {
return iterator(this, true);
}
-
- // Get a hash value for this bitmap.
- uint64_t getHashValue() const {
- uint64_t HashVal = 0;
- for (ElementListConstIter Iter = Elements.begin();
- Iter != Elements.end();
- ++Iter) {
- HashVal ^= Iter->index();
- HashVal ^= Iter->getHashValue();
- }
- return HashVal;
- }
};
// Convenience functions to allow Or and And without dereferencing in the user
template <unsigned ElementSize>
inline bool operator &=(SparseBitVector<ElementSize> &LHS,
const SparseBitVector<ElementSize> *RHS) {
- return LHS &= (*RHS);
+ return LHS &= *RHS;
}
+// Convenience functions for infix union, intersection, difference operators.
-// Dump a SparseBitVector to a stream
template <unsigned ElementSize>
-void dump(const SparseBitVector<ElementSize> &LHS, llvm::OStream &out) {
- out << "[ ";
-
- typename SparseBitVector<ElementSize>::iterator bi;
- for (bi = LHS.begin(); bi != LHS.end(); ++bi) {
- out << *bi << " ";
- }
- out << " ]\n";
+inline SparseBitVector<ElementSize>
+operator|(const SparseBitVector<ElementSize> &LHS,
+ const SparseBitVector<ElementSize> &RHS) {
+ SparseBitVector<ElementSize> Result(LHS);
+ Result |= RHS;
+ return Result;
}
+
+template <unsigned ElementSize>
+inline SparseBitVector<ElementSize>
+operator&(const SparseBitVector<ElementSize> &LHS,
+ const SparseBitVector<ElementSize> &RHS) {
+ SparseBitVector<ElementSize> Result(LHS);
+ Result &= RHS;
+ return Result;
}
+template <unsigned ElementSize>
+inline SparseBitVector<ElementSize>
+operator-(const SparseBitVector<ElementSize> &LHS,
+ const SparseBitVector<ElementSize> &RHS) {
+ SparseBitVector<ElementSize> Result;
+ Result.intersectWithComplement(LHS, RHS);
+ return Result;
+}
+// Dump a SparseBitVector to a stream
+template <unsigned ElementSize>
+void dump(const SparseBitVector<ElementSize> &LHS, raw_ostream &out) {
+ out << "[";
+
+ typename SparseBitVector<ElementSize>::iterator bi = LHS.begin(),
+ be = LHS.end();
+ if (bi != be) {
+ out << *bi;
+ for (++bi; bi != be; ++bi) {
+ out << " " << *bi;
+ }
+ }
+ out << "]\n";
+}
+} // end namespace llvm
-#endif
+#endif // LLVM_ADT_SPARSEBITVECTOR_H