X-Git-Url: http://demsky.eecs.uci.edu/git/?a=blobdiff_plain;f=include%2Fllvm%2FADT%2FSparseBitVector.h;h=306e92832f0b0fd43b64e4f2dd6bdf83c3f483d4;hb=ac39a035351a20928e087617e412aa6ce510181f;hp=2064a4a177c21d8a8916a494d9d82dc6012779ff;hpb=1b6998e8d6807d3e0b6d4904111f43738ceae5e6;p=oota-llvm.git diff --git a/include/llvm/ADT/SparseBitVector.h b/include/llvm/ADT/SparseBitVector.h index 2064a4a177c..306e92832f0 100644 --- a/include/llvm/ADT/SparseBitVector.h +++ b/include/llvm/ADT/SparseBitVector.h @@ -2,8 +2,8 @@ // // The LLVM Compiler Infrastructure // -// This file was developed by Daniel Berlin and is distributed under -// the University of Illinois Open Source License. See LICENSE.TXT for details. +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// // @@ -15,13 +15,14 @@ #ifndef LLVM_ADT_SPARSEBITVECTOR_H #define LLVM_ADT_SPARSEBITVECTOR_H -#include -#include -#include -#include +#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/Support/raw_ostream.h" +#include +#include namespace llvm { @@ -40,34 +41,33 @@ namespace llvm { template -struct SparseBitVectorElement { +struct SparseBitVectorElement + : public ilist_node > { public: typedef unsigned long BitWord; 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 }; + private: // Index of Element in terms of where first bit starts. unsigned ElementIndex; BitWord Bits[BITWORDS_PER_ELEMENT]; - SparseBitVectorElement(); + // Needed for sentinels + friend struct ilist_sentinel_traits; + SparseBitVectorElement() { + ElementIndex = ~0U; + memset(&Bits[0], 0, sizeof (BitWord) * BITWORDS_PER_ELEMENT); + } + 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) @@ -105,9 +105,11 @@ public: bool test_and_set (unsigned Idx) { bool old = test(Idx); - if (!old) + if (!old) { set(Idx); - return !old; + return true; + } + return false; } void reset(unsigned Idx) { @@ -126,7 +128,7 @@ public: else if (sizeof(BitWord) == 8) NumBits += CountPopulation_64(Bits[i]); else - assert(0 && "Unsupported!"); + llvm_unreachable("Unsupported!"); return NumBits; } @@ -136,37 +138,34 @@ public: if (Bits[i] != 0) { if (sizeof(BitWord) == 4) return i * BITWORD_SIZE + CountTrailingZeros_32(Bits[i]); - else if (sizeof(BitWord) == 8) + if (sizeof(BitWord) == 8) return i * BITWORD_SIZE + CountTrailingZeros_64(Bits[i]); - else - assert(0 && "Unsupported!"); + llvm_unreachable("Unsupported!"); } - assert(0 && "Illegal empty element"); + llvm_unreachable("Illegal empty element"); } - /// 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 >= BITS_PER_ELEMENT) + /// 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; - unsigned WordPos = Prev / BITWORD_SIZE; - unsigned BitPos = Prev % BITWORD_SIZE; + 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 &= ~0L << BitPos; + Copy &= ~0UL << BitPos; if (Copy != 0) { if (sizeof(BitWord) == 4) return WordPos * BITWORD_SIZE + CountTrailingZeros_32(Copy); - else if (sizeof(BitWord) == 8) + if (sizeof(BitWord) == 8) return WordPos * BITWORD_SIZE + CountTrailingZeros_64(Copy); - else - assert(0 && "Unsupported!"); + llvm_unreachable("Unsupported!"); } // Check subsequent words. @@ -174,10 +173,9 @@ public: if (Bits[i] != 0) { if (sizeof(BitWord) == 4) return i * BITWORD_SIZE + CountTrailingZeros_32(Bits[i]); - else if (sizeof(BitWord) == 8) + if (sizeof(BitWord) == 8) return i * BITWORD_SIZE + CountTrailingZeros_64(Bits[i]); - else - assert(0 && "Unsupported!"); + llvm_unreachable("Unsupported!"); } return -1; } @@ -189,7 +187,7 @@ public: BitWord old = changed ? 0 : Bits[i]; Bits[i] |= RHS.Bits[i]; - if (old != Bits[i]) + if (!changed && old != Bits[i]) changed = true; } return changed; @@ -199,11 +197,11 @@ public: bool intersects(const SparseBitVectorElement &RHS) const { for (unsigned i = 0; i < BITWORDS_PER_ELEMENT; ++i) { if (RHS.Bits[i] & Bits[i]) - return true; + return true; } return false; } - + // Intersect this Element with RHS and return true if this one changed. // BecameZero is set to true if this element became all-zero bits. bool intersectWith(const SparseBitVectorElement &RHS, @@ -219,17 +217,17 @@ public: if (Bits[i] != 0) allzero = false; - if (old != Bits[i]) + if (!changed && old != Bits[i]) changed = true; } - BecameZero = !allzero; + 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. bool intersectWithComplement(const SparseBitVectorElement &RHS, - bool &BecameZero) { + bool &BecameZero) { bool changed = false; bool allzero = true; @@ -241,17 +239,48 @@ public: if (Bits[i] != 0) allzero = false; - if (old != Bits[i]) + if (!changed && old != Bits[i]) changed = true; } - BecameZero = !allzero; + BecameZero = allzero; return changed; } + // Three argument version of intersectWithComplement that intersects + // RHS1 & ~RHS2 into this element + void intersectWithComplement(const SparseBitVectorElement &RHS1, + const SparseBitVectorElement &RHS2, + bool &BecameZero) { + bool allzero = true; + + BecameZero = false; + for (unsigned i = 0; i < BITWORDS_PER_ELEMENT; ++i) { + Bits[i] = RHS1.Bits[i] & ~RHS2.Bits[i]; + if (Bits[i] != 0) + allzero = false; + } + BecameZero = allzero; + } +}; + +template +struct ilist_traits > + : public ilist_default_traits > { + typedef SparseBitVectorElement Element; + + Element *createSentinel() const { return static_cast(&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 Sentinel; }; template class SparseBitVector { - typedef std::list *> ElementList; + typedef ilist > ElementList; typedef typename ElementList::iterator ElementListIter; typedef typename ElementList::const_iterator ElementListConstIter; enum { @@ -278,17 +307,16 @@ class SparseBitVector { // Search from our current iterator, either backwards or forwards, // depending on what element we are looking for. ElementListIter ElementIter = CurrElementIter; - if ((*CurrElementIter)->index() == ElementIndex) { + if (CurrElementIter->index() == ElementIndex) { return ElementIter; - } else if ((*CurrElementIter)->index() > ElementIndex) { + } else if (CurrElementIter->index() > ElementIndex) { while (ElementIter != Elements.begin() - && (*ElementIter)->index() > ElementIndex) + && ElementIter->index() > ElementIndex) --ElementIter; } else { while (ElementIter != Elements.end() && - (*ElementIter)->index() <= ElementIndex) + ElementIter->index() < ElementIndex) ++ElementIter; - --ElementIter; } CurrElementIter = ElementIter; return ElementIter; @@ -323,11 +351,11 @@ class SparseBitVector { return; } Iter = BitVector->Elements.begin(); - BitNumber = (*Iter)->index() * ElementSize; - unsigned BitPos = (*Iter)->find_first(); + BitNumber = Iter->index() * ElementSize; + unsigned BitPos = Iter->find_first(); BitNumber += BitPos; WordNumber = (BitNumber % ElementSize) / BITWORD_SIZE; - Bits = (*Iter)->word(WordNumber); + Bits = Iter->word(WordNumber); Bits >>= BitPos % BITWORD_SIZE; } @@ -343,10 +371,10 @@ class SparseBitVector { // See if we ran out of Bits in this word. if (!Bits) { - int NextSetBitNumber = (*Iter)->find_next(BitNumber % ElementSize) ; + 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++; + ++Iter; WordNumber = 0; // We may run out of elements in the bitmap. @@ -355,23 +383,25 @@ class SparseBitVector { return; } // Set up for next non zero word in bitmap. - BitNumber = (*Iter)->index() * ElementSize; - NextSetBitNumber = (*Iter)->find_first(); + BitNumber = Iter->index() * ElementSize; + NextSetBitNumber = Iter->find_first(); BitNumber += NextSetBitNumber; WordNumber = (BitNumber % ElementSize) / BITWORD_SIZE; - Bits = (*Iter)->word(WordNumber); + Bits = Iter->word(WordNumber); Bits >>= NextSetBitNumber % BITWORD_SIZE; } else { WordNumber = (NextSetBitNumber % ElementSize) / BITWORD_SIZE; - Bits = (*Iter)->word(WordNumber); + Bits = Iter->word(WordNumber); Bits >>= NextSetBitNumber % BITWORD_SIZE; + BitNumber = Iter->index() * ElementSize; + BitNumber += NextSetBitNumber; } } } public: // Preincrement. inline SparseBitVectorIterator& operator++() { - BitNumber++; + ++BitNumber; Bits >>= 1; AdvanceToNextNonZero(); return *this; @@ -391,7 +421,7 @@ class SparseBitVector { bool operator==(const SparseBitVectorIterator &RHS) const { // If they are both at the end, ignore the rest of the fields. - if (AtEnd == RHS.AtEnd) + if (AtEnd && RHS.AtEnd) return true; // Otherwise they are the same if they have the same bit number and // bitmap. @@ -400,10 +430,10 @@ class SparseBitVector { bool operator!=(const SparseBitVectorIterator &RHS) const { return !(*this == RHS); } - SparseBitVectorIterator(): BitVector(NULL) { + SparseBitVectorIterator(): BitVector(NULL) { } - - + + SparseBitVectorIterator(const SparseBitVector *RHS, bool end = false):BitVector(RHS) { Iter = BitVector->Elements.begin(); @@ -422,22 +452,39 @@ public: } ~SparseBitVector() { - for_each(Elements.begin(), Elements.end(), - deleter >); } // SparseBitVector copy ctor. SparseBitVector(const SparseBitVector &RHS) { ElementListConstIter ElementIter = RHS.Elements.begin(); while (ElementIter != RHS.Elements.end()) { - SparseBitVectorElement *ElementCopy; - ElementCopy = new SparseBitVectorElement(*(*ElementIter)); - Elements.push_back(ElementCopy); + Elements.push_back(SparseBitVectorElement(*ElementIter)); + ++ElementIter; } CurrElementIter = Elements.begin (); } + // Clear. + void clear() { + Elements.clear(); + } + + // Assignment + SparseBitVector& operator=(const SparseBitVector& RHS) { + Elements.clear(); + + ElementListConstIter ElementIter = RHS.Elements.begin(); + while (ElementIter != RHS.Elements.end()) { + Elements.push_back(SparseBitVectorElement(*ElementIter)); + ++ElementIter; + } + + CurrElementIter = Elements.begin (); + + return *this; + } + // Test, Reset, and Set a bit in the bitmap. bool test(unsigned Idx) { if (Elements.empty()) @@ -449,9 +496,9 @@ public: // If we can't find an element that is supposed to contain this bit, there // is nothing more to do. if (ElementIter == Elements.end() || - (*ElementIter)->index() != ElementIndex) + ElementIter->index() != ElementIndex) return false; - return (*ElementIter)->test(Idx % ElementSize); + return ElementIter->test(Idx % ElementSize); } void reset(unsigned Idx) { @@ -464,45 +511,69 @@ public: // If we can't find an element that is supposed to contain this bit, there // is nothing more to do. if (ElementIter == Elements.end() || - (*ElementIter)->index() != ElementIndex) + ElementIter->index() != ElementIndex) return; - (*ElementIter)->reset(Idx % ElementSize); + ElementIter->reset(Idx % ElementSize); // When the element is zeroed out, delete it. - if ((*ElementIter)->empty()) { - delete (*ElementIter); + if (ElementIter->empty()) { ++CurrElementIter; Elements.erase(ElementIter); } } void set(unsigned Idx) { - SparseBitVectorElement *Element; unsigned ElementIndex = Idx / ElementSize; - + SparseBitVectorElement *Element; + ElementListIter ElementIter; if (Elements.empty()) { Element = new SparseBitVectorElement(ElementIndex); - Elements.push_back(Element); + ElementIter = Elements.insert(Elements.end(), Element); + } else { - ElementListIter ElementIter = FindLowerBound(ElementIndex); + ElementIter = FindLowerBound(ElementIndex); - if (ElementIter != Elements.end() && - (*ElementIter)->index() == ElementIndex) - Element = *ElementIter; - else { + if (ElementIter == Elements.end() || + ElementIter->index() != ElementIndex) { Element = new SparseBitVectorElement(ElementIndex); - // Insert does insert before, and lower bound gives the one before. - Elements.insert(++ElementIter, Element); + // We may have hit the beginning of our SparseBitVector, in which case, + // we may need to insert right after this element, which requires moving + // the current iterator forward one, because insert does insert before. + if (ElementIter != Elements.end() && + ElementIter->index() < ElementIndex) + ElementIter = Elements.insert(++ElementIter, Element); + else + ElementIter = Elements.insert(ElementIter, Element); } } - Element->set(Idx % ElementSize); + CurrElementIter = ElementIter; + + ElementIter->set(Idx % ElementSize); } - + bool test_and_set (unsigned Idx) { bool old = test(Idx); - if (!old) + if (!old) { set(Idx); - return !old; + return true; + } + return false; + } + + bool operator!=(const SparseBitVector &RHS) const { + return !(*this == RHS); + } + + bool operator==(const SparseBitVector &RHS) const { + ElementListConstIter Iter1 = Elements.begin(); + ElementListConstIter Iter2 = RHS.Elements.begin(); + + for (; Iter1 != Elements.end() && Iter2 != RHS.Elements.end(); + ++Iter1, ++Iter2) { + if (*Iter1 != *Iter2) + return false; + } + return Iter1 == Elements.end() && Iter2 == RHS.Elements.end(); } // Union our bitmap with the RHS and return true if we changed. @@ -511,30 +582,22 @@ public: ElementListIter Iter1 = Elements.begin(); ElementListConstIter Iter2 = RHS.Elements.begin(); - // IE They may both be end - if (Iter1 == Iter2) + // If RHS is empty, we are done + if (RHS.Elements.empty()) return false; - // See if the first bitmap element is the same in both. This is only - // possible if they are the same bitmap. - if (Iter1 != Elements.end() && Iter2 != RHS.Elements.end()) - if (*Iter1 == *Iter2) - return false; - while (Iter2 != RHS.Elements.end()) { - if (Iter1 == Elements.end() || (*Iter1)->index() > (*Iter2)->index()) { - SparseBitVectorElement *NewElem; - - NewElem = new SparseBitVectorElement(*(*Iter2)); - Elements.insert(Iter1, NewElem); - Iter2++; + if (Iter1 == Elements.end() || Iter1->index() > Iter2->index()) { + Elements.insert(Iter1, + new SparseBitVectorElement(*Iter2)); + ++Iter2; changed = true; - } else if ((*Iter1)->index() == (*Iter2)->index()) { - changed |= (*Iter1)->unionWith(*(*Iter2)); - Iter1++; - Iter2++; + } else if (Iter1->index() == Iter2->index()) { + changed |= Iter1->unionWith(*Iter2); + ++Iter1; + ++Iter2; } else { - Iter1++; + ++Iter1; } } CurrElementIter = Elements.begin(); @@ -547,89 +610,74 @@ public: ElementListIter Iter1 = Elements.begin(); ElementListConstIter Iter2 = RHS.Elements.begin(); - // IE They may both be end. - if (Iter1 == Iter2) + // Check if both bitmaps are empty. + if (Elements.empty() && RHS.Elements.empty()) return false; - // See if the first bitmap element is the same in both. This is only - // possible if they are the same bitmap. - if (Iter1 != Elements.end() && Iter2 != RHS.Elements.end()) - if (*Iter1 == *Iter2) - return false; - // Loop through, intersecting as we go, erasing elements when necessary. while (Iter2 != RHS.Elements.end()) { - if (Iter1 == Elements.end()) + if (Iter1 == Elements.end()) { + CurrElementIter = Elements.begin(); return changed; + } - if ((*Iter1)->index() > (*Iter2)->index()) { - Iter2++; - } else if ((*Iter1)->index() == (*Iter2)->index()) { + if (Iter1->index() > Iter2->index()) { + ++Iter2; + } else if (Iter1->index() == Iter2->index()) { bool BecameZero; - changed |= (*Iter1)->intersectWith(*(*Iter2), BecameZero); + changed |= Iter1->intersectWith(*Iter2, BecameZero); if (BecameZero) { ElementListIter IterTmp = Iter1; - delete *IterTmp; + ++Iter1; Elements.erase(IterTmp); - Iter1++; } else { - Iter1++; + ++Iter1; } - Iter2++; + ++Iter2; } else { ElementListIter IterTmp = Iter1; - Iter1++; - delete *IterTmp; + ++Iter1; Elements.erase(IterTmp); } } + Elements.erase(Iter1, Elements.end()); 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) { bool changed = false; ElementListIter Iter1 = Elements.begin(); ElementListConstIter Iter2 = RHS.Elements.begin(); - // IE They may both be end. - if (Iter1 == Iter2) + // If either our bitmap or RHS is empty, we are done + if (Elements.empty() || RHS.Elements.empty()) return false; - // See if the first bitmap element is the same in both. This is only - // possible if they are the same bitmap. - if (Iter1 != Elements.end() && Iter2 != RHS.Elements.end()) - if (*Iter1 == *Iter2) { - Elements.clear(); - return true; - } - // Loop through, intersecting as we go, erasing elements when necessary. while (Iter2 != RHS.Elements.end()) { - if (Iter1 == Elements.end()) + if (Iter1 == Elements.end()) { + CurrElementIter = Elements.begin(); return changed; + } - if ((*Iter1)->index() > (*Iter2)->index()) { - Iter2++; - } else if ((*Iter1)->index() == (*Iter2)->index()) { + if (Iter1->index() > Iter2->index()) { + ++Iter2; + } else if (Iter1->index() == Iter2->index()) { bool BecameZero; - changed |= (*Iter1)->intersectWithComplement(*(*Iter2), BecameZero); + changed |= Iter1->intersectWithComplement(*Iter2, BecameZero); if (BecameZero) { ElementListIter IterTmp = Iter1; - delete *IterTmp; + ++Iter1; Elements.erase(IterTmp); - Iter1++; } else { - Iter1++; + ++Iter1; } - Iter2++; + ++Iter2; } else { - ElementListIter IterTmp = Iter1; - Iter1++; - delete *IterTmp; - Elements.erase(IterTmp); + ++Iter1; } } CurrElementIter = Elements.begin(); @@ -639,67 +687,126 @@ public: bool intersectWithComplement(const SparseBitVector *RHS) const { return intersectWithComplement(*RHS); } - - + + + // Three argument version of intersectWithComplement. + // Result of RHS1 & ~RHS2 is stored into this bitmap. + void intersectWithComplement(const SparseBitVector &RHS1, + const SparseBitVector &RHS2) + { + Elements.clear(); + CurrElementIter = Elements.begin(); + ElementListConstIter Iter1 = RHS1.Elements.begin(); + ElementListConstIter Iter2 = RHS2.Elements.begin(); + + // If RHS1 is empty, we are done + // If RHS2 is empty, we still have to copy RHS1 + if (RHS1.Elements.empty()) + return; + + // Loop through, intersecting as we go, erasing elements when necessary. + while (Iter2 != RHS2.Elements.end()) { + if (Iter1 == RHS1.Elements.end()) + return; + + if (Iter1->index() > Iter2->index()) { + ++Iter2; + } else if (Iter1->index() == Iter2->index()) { + bool BecameZero = false; + SparseBitVectorElement *NewElement = + new SparseBitVectorElement(Iter1->index()); + NewElement->intersectWithComplement(*Iter1, *Iter2, BecameZero); + if (!BecameZero) { + Elements.push_back(NewElement); + } + else + delete NewElement; + ++Iter1; + ++Iter2; + } else { + SparseBitVectorElement *NewElement = + new SparseBitVectorElement(*Iter1); + Elements.push_back(NewElement); + ++Iter1; + } + } + + // copy the remaining elements + while (Iter1 != RHS1.Elements.end()) { + SparseBitVectorElement *NewElement = + new SparseBitVectorElement(*Iter1); + Elements.push_back(NewElement); + ++Iter1; + } + + return; + } + + void intersectWithComplement(const SparseBitVector *RHS1, + const SparseBitVector *RHS2) { + intersectWithComplement(*RHS1, *RHS2); + } + bool intersects(const SparseBitVector *RHS) const { return intersects(*RHS); } - + // Return true if we share any bits in common with RHS bool intersects(const SparseBitVector &RHS) const { ElementListConstIter Iter1 = Elements.begin(); ElementListConstIter Iter2 = RHS.Elements.begin(); - // IE They may both be end. - if (Iter1 == Iter2) + // Check if both bitmaps are empty. + if (Elements.empty() && RHS.Elements.empty()) return false; - // See if the first bitmap element is the same in both. This is only - // possible if they are the same bitmap. - if (Iter1 != Elements.end() && Iter2 != RHS.Elements.end()) - if (*Iter1 == *Iter2) { - return true; - } - // Loop through, intersecting stopping when we hit bits in common. while (Iter2 != RHS.Elements.end()) { if (Iter1 == Elements.end()) return false; - if ((*Iter1)->index() > (*Iter2)->index()) { - Iter2++; - } else if ((*Iter1)->index() == (*Iter2)->index()) { - if ((*Iter1)->intersects(*(*Iter2))) + if (Iter1->index() > Iter2->index()) { + ++Iter2; + } else if (Iter1->index() == Iter2->index()) { + if (Iter1->intersects(*Iter2)) return true; - Iter1++; - Iter2++; + ++Iter1; + ++Iter2; } else { - Iter1++; + ++Iter1; } } return false; } - + + // Return true iff all bits set in this SparseBitVector are + // also set in RHS. + bool contains(const SparseBitVector &RHS) const { + SparseBitVector 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()) return -1; - const SparseBitVectorElement *First = *(Elements.begin()); - return (First->index() * ElementSize) + First->find_first(); + const SparseBitVectorElement &First = *(Elements.begin()); + return (First.index() * ElementSize) + First.find_first(); } // Return true if the SparseBitVector is empty bool empty() const { return Elements.empty(); } - + unsigned count() const { unsigned BitCount = 0; for (ElementListConstIter Iter = Elements.begin(); Iter != Elements.end(); ++Iter) - BitCount += (*Iter)->count(); - + BitCount += Iter->count(); + return BitCount; } iterator begin() const { @@ -707,36 +814,84 @@ public: } iterator end() const { - return iterator(this, ~0); + return iterator(this, true); } }; // Convenience functions to allow Or and And without dereferencing in the user -// code. +// code. + template -inline void operator |=(SparseBitVector *LHS, - const SparseBitVector &RHS) { - LHS->operator|=(RHS); +inline bool operator |=(SparseBitVector &LHS, + const SparseBitVector *RHS) { + return LHS |= *RHS; } template -inline void operator |=(SparseBitVector *LHS, - const SparseBitVector *RHS) { - LHS->operator|=(RHS); +inline bool operator |=(SparseBitVector *LHS, + const SparseBitVector &RHS) { + return LHS->operator|=(RHS); } template -inline void operator &=(SparseBitVector *LHS, +inline bool operator &=(SparseBitVector *LHS, const SparseBitVector &RHS) { - LHS->operator&=(RHS); + return LHS->operator&=(RHS); } template -inline void operator &=(SparseBitVector *LHS, +inline bool operator &=(SparseBitVector &LHS, const SparseBitVector *RHS) { - LHS->operator&=(RHS); + return LHS &= *RHS; } - + +// Convenience functions for infix union, intersection, difference operators. + +template +inline SparseBitVector +operator|(const SparseBitVector &LHS, + const SparseBitVector &RHS) { + SparseBitVector Result(LHS); + Result |= RHS; + return Result; +} + +template +inline SparseBitVector +operator&(const SparseBitVector &LHS, + const SparseBitVector &RHS) { + SparseBitVector Result(LHS); + Result &= RHS; + return Result; +} + +template +inline SparseBitVector +operator-(const SparseBitVector &LHS, + const SparseBitVector &RHS) { + SparseBitVector Result; + Result.intersectWithComplement(LHS, RHS); + return Result; +} + + + + +// Dump a SparseBitVector to a stream +template +void dump(const SparseBitVector &LHS, raw_ostream &out) { + out << "["; + + typename SparseBitVector::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