LLVM 24.0.0git
SparseBitVector.h
Go to the documentation of this file.
1//===- llvm/ADT/SparseBitVector.h - Efficient Sparse BitVector --*- C++ -*-===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8///
9/// \file
10/// This file defines the SparseBitVector class. See the doxygen comment for
11/// SparseBitVector for more details on the algorithm used.
12///
13//===----------------------------------------------------------------------===//
14
15#ifndef LLVM_ADT_SPARSEBITVECTOR_H
16#define LLVM_ADT_SPARSEBITVECTOR_H
17
18#include "llvm/ADT/bit.h"
22#include <cassert>
23#include <climits>
24#include <cstring>
25#include <iterator>
26#include <list>
27
28namespace llvm {
29
30/// SparseBitVector is an implementation of a bitvector that is sparse by only
31/// storing the elements that have non-zero bits set. In order to make this
32/// fast for the most common cases, SparseBitVector is implemented as a linked
33/// list of SparseBitVectorElements. We maintain a pointer to the last
34/// SparseBitVectorElement accessed (in the form of a list iterator), in order
35/// to make multiple in-order test/set constant time after the first one is
36/// executed. Note that using vectors to store SparseBitVectorElement's does
37/// not work out very well because it causes insertion in the middle to take
38/// enormous amounts of time with a large amount of bits. Other structures that
39/// have better worst cases for insertion in the middle (various balanced trees,
40/// etc) do not perform as well in practice as a linked list with this iterator
41/// kept up to date. They are also significantly more memory intensive.
42
43template <unsigned ElementSize = 128> struct SparseBitVectorElement {
44public:
45 using BitWord = unsigned long;
47 enum {
48 BITWORD_SIZE = sizeof(BitWord) * CHAR_BIT,
50 BITS_PER_ELEMENT = ElementSize
51 };
52
53private:
54 // Index of Element in terms of where first bit starts.
55 unsigned ElementIndex;
57
59 ElementIndex = ~0U;
60 memset(&Bits[0], 0, sizeof (BitWord) * BITWORDS_PER_ELEMENT);
61 }
62
63public:
64 explicit SparseBitVectorElement(unsigned Idx) {
65 ElementIndex = Idx;
66 memset(&Bits[0], 0, sizeof (BitWord) * BITWORDS_PER_ELEMENT);
67 }
68
69 // Comparison.
70 bool operator==(const SparseBitVectorElement &RHS) const {
71 if (ElementIndex != RHS.ElementIndex)
72 return false;
73 for (unsigned i = 0; i < BITWORDS_PER_ELEMENT; ++i)
74 if (Bits[i] != RHS.Bits[i])
75 return false;
76 return true;
77 }
78
79 bool operator!=(const SparseBitVectorElement &RHS) const {
80 return !(*this == RHS);
81 }
82
83 // Return the bits that make up word Idx in our element.
84 BitWord word(unsigned Idx) const {
86 return Bits[Idx];
87 }
88
89 unsigned index() const {
90 return ElementIndex;
91 }
92
93 bool empty() const {
94 for (unsigned i = 0; i < BITWORDS_PER_ELEMENT; ++i)
95 if (Bits[i])
96 return false;
97 return true;
98 }
99
100 void set(unsigned Idx) {
101 Bits[Idx / BITWORD_SIZE] |= 1L << (Idx % BITWORD_SIZE);
102 }
103
104 bool test_and_set(unsigned Idx) {
105 bool old = test(Idx);
106 if (!old) {
107 set(Idx);
108 return true;
109 }
110 return false;
111 }
112
113 void reset(unsigned Idx) {
114 Bits[Idx / BITWORD_SIZE] &= ~(1L << (Idx % BITWORD_SIZE));
115 }
116
117 bool test(unsigned Idx) const {
118 return Bits[Idx / BITWORD_SIZE] & (1L << (Idx % BITWORD_SIZE));
119 }
120
121 size_type count() const {
122 unsigned NumBits = 0;
123 for (BitWord Bit : Bits)
124 NumBits += llvm::popcount(Bit);
125 return NumBits;
126 }
127
128 /// find_first - Returns the index of the first set bit.
129 int find_first() const {
130 for (unsigned i = 0; i < BITWORDS_PER_ELEMENT; ++i)
131 if (Bits[i] != 0)
132 return i * BITWORD_SIZE + llvm::countr_zero(Bits[i]);
133 llvm_unreachable("Illegal empty element");
134 }
135
136 /// find_last - Returns the index of the last set bit.
137 int find_last() const {
138 for (unsigned I = 0; I < BITWORDS_PER_ELEMENT; ++I) {
139 unsigned Idx = BITWORDS_PER_ELEMENT - I - 1;
140 if (Bits[Idx] != 0)
141 return Idx * BITWORD_SIZE + BITWORD_SIZE -
142 llvm::countl_zero(Bits[Idx]) - 1;
143 }
144 llvm_unreachable("Illegal empty element");
145 }
146
147 /// find_next - Returns the index of the next set bit starting from the
148 /// "Curr" bit. Returns -1 if the next set bit is not found.
149 int find_next(unsigned Curr) const {
150 if (Curr >= BITS_PER_ELEMENT)
151 return -1;
152
153 unsigned WordPos = Curr / BITWORD_SIZE;
154 unsigned BitPos = Curr % BITWORD_SIZE;
155 BitWord Copy = Bits[WordPos];
157 && "Word Position outside of element");
158
159 // Mask off previous bits.
160 Copy &= ~0UL << BitPos;
161
162 if (Copy != 0)
163 return WordPos * BITWORD_SIZE + llvm::countr_zero(Copy);
164
165 // Check subsequent words.
166 for (unsigned i = WordPos+1; i < BITWORDS_PER_ELEMENT; ++i)
167 if (Bits[i] != 0)
168 return i * BITWORD_SIZE + llvm::countr_zero(Bits[i]);
169 return -1;
170 }
171
172 // Union this element with RHS and return true if this one changed.
173 bool unionWith(const SparseBitVectorElement &RHS) {
174 bool changed = false;
175 for (unsigned i = 0; i < BITWORDS_PER_ELEMENT; ++i) {
176 BitWord old = changed ? 0 : Bits[i];
177
178 Bits[i] |= RHS.Bits[i];
179 if (!changed && old != Bits[i])
180 changed = true;
181 }
182 return changed;
183 }
184
185 // Return true if we have any bits in common with RHS
186 bool intersects(const SparseBitVectorElement &RHS) const {
187 for (unsigned i = 0; i < BITWORDS_PER_ELEMENT; ++i) {
188 if (RHS.Bits[i] & Bits[i])
189 return true;
190 }
191 return false;
192 }
193
194 // Intersect this Element with RHS and return true if this one changed.
195 // BecameZero is set to true if this element became all-zero bits.
196 bool intersectWith(const SparseBitVectorElement &RHS,
197 bool &BecameZero) {
198 bool changed = false;
199 bool allzero = true;
200
201 BecameZero = false;
202 for (unsigned i = 0; i < BITWORDS_PER_ELEMENT; ++i) {
203 BitWord old = changed ? 0 : Bits[i];
204
205 Bits[i] &= RHS.Bits[i];
206 if (Bits[i] != 0)
207 allzero = false;
208
209 if (!changed && old != Bits[i])
210 changed = true;
211 }
212 BecameZero = allzero;
213 return changed;
214 }
215
216 // Intersect this Element with the complement of RHS and return true if this
217 // one changed. BecameZero is set to true if this element became all-zero
218 // bits.
219 bool intersectWithComplement(const SparseBitVectorElement &RHS,
220 bool &BecameZero) {
221 bool changed = false;
222 bool allzero = true;
223
224 BecameZero = false;
225 for (unsigned i = 0; i < BITWORDS_PER_ELEMENT; ++i) {
226 BitWord old = changed ? 0 : Bits[i];
227
228 Bits[i] &= ~RHS.Bits[i];
229 if (Bits[i] != 0)
230 allzero = false;
231
232 if (!changed && old != Bits[i])
233 changed = true;
234 }
235 BecameZero = allzero;
236 return changed;
237 }
238
239 // Three argument version of intersectWithComplement that intersects
240 // RHS1 & ~RHS2 into this element
241 void intersectWithComplement(const SparseBitVectorElement &RHS1,
242 const SparseBitVectorElement &RHS2,
243 bool &BecameZero) {
244 bool allzero = true;
245
246 BecameZero = false;
247 for (unsigned i = 0; i < BITWORDS_PER_ELEMENT; ++i) {
248 Bits[i] = RHS1.Bits[i] & ~RHS2.Bits[i];
249 if (Bits[i] != 0)
250 allzero = false;
251 }
252 BecameZero = allzero;
253 }
254};
255
256template <unsigned ElementSize = 128>
258 using ElementList = std::list<SparseBitVectorElement<ElementSize>>;
259 using ElementListIter = typename ElementList::iterator;
260 using ElementListConstIter = typename ElementList::const_iterator;
261 enum {
263 };
264
265 ElementList Elements;
266 // Pointer to our current Element. This has no visible effect on the external
267 // state of a SparseBitVector, it's just used to improve performance in the
268 // common case of testing/modifying bits with similar indices.
269 mutable ElementListIter CurrElementIter;
270
271 // This is like std::lower_bound, except we do linear searching from the
272 // current position.
273 ElementListIter FindLowerBoundImpl(unsigned ElementIndex) const {
274
275 // We cache a non-const iterator so we're forced to resort to const_cast to
276 // get the begin/end in the case where 'this' is const. To avoid duplication
277 // of code with the only difference being whether the const cast is present
278 // 'this' is always const in this particular function and we sort out the
279 // difference in FindLowerBound and FindLowerBoundConst.
280 ElementListIter Begin =
281 const_cast<SparseBitVector<ElementSize> *>(this)->Elements.begin();
282 ElementListIter End =
283 const_cast<SparseBitVector<ElementSize> *>(this)->Elements.end();
284
285 if (Elements.empty()) {
286 CurrElementIter = Begin;
287 return CurrElementIter;
288 }
289
290 // Make sure our current iterator is valid.
291 if (CurrElementIter == End)
292 --CurrElementIter;
293
294 // Search from our current iterator, either backwards or forwards,
295 // depending on what element we are looking for.
296 ElementListIter ElementIter = CurrElementIter;
297 if (CurrElementIter->index() == ElementIndex) {
298 return ElementIter;
299 } else if (CurrElementIter->index() > ElementIndex) {
300 while (ElementIter != Begin
301 && ElementIter->index() > ElementIndex)
302 --ElementIter;
303 } else {
304 while (ElementIter != End &&
305 ElementIter->index() < ElementIndex)
306 ++ElementIter;
307 }
308 CurrElementIter = ElementIter;
309 return ElementIter;
310 }
311 ElementListConstIter FindLowerBoundConst(unsigned ElementIndex) const {
312 return FindLowerBoundImpl(ElementIndex);
313 }
314 ElementListIter FindLowerBound(unsigned ElementIndex) {
315 return FindLowerBoundImpl(ElementIndex);
316 }
317
318 // Iterator to walk set bits in the bitmap. This iterator is a lot uglier
319 // than it would be, in order to be efficient.
320 class SparseBitVectorIterator {
321 private:
322 bool AtEnd;
323
325
326 // Current element inside of bitmap.
327 ElementListConstIter Iter;
328
329 // Current bit number inside of our bitmap.
330 unsigned BitNumber;
331
332 // Current word number inside of our element.
333 unsigned WordNumber;
334
335 // Current bits from the element.
337
338 // Move our iterator to the first non-zero bit in the bitmap.
339 void AdvanceToFirstNonZero() {
340 if (AtEnd)
341 return;
342 if (BitVector->Elements.empty()) {
343 AtEnd = true;
344 return;
345 }
346 Iter = BitVector->Elements.begin();
347 BitNumber = Iter->index() * ElementSize;
348 unsigned BitPos = Iter->find_first();
349 BitNumber += BitPos;
350 WordNumber = (BitNumber % ElementSize) / BITWORD_SIZE;
351 Bits = Iter->word(WordNumber);
352 Bits >>= BitPos % BITWORD_SIZE;
353 }
354
355 // Move our iterator to the next non-zero bit.
356 void AdvanceToNextNonZero() {
357 if (AtEnd)
358 return;
359
360 while (Bits && !(Bits & 1)) {
361 Bits >>= 1;
362 BitNumber += 1;
363 }
364
365 // See if we ran out of Bits in this word.
366 if (!Bits) {
367 int NextSetBitNumber = Iter->find_next(BitNumber % ElementSize) ;
368 // If we ran out of set bits in this element, move to next element.
369 if (NextSetBitNumber == -1 || (BitNumber % ElementSize == 0)) {
370 ++Iter;
371 WordNumber = 0;
372
373 // We may run out of elements in the bitmap.
374 if (Iter == BitVector->Elements.end()) {
375 AtEnd = true;
376 return;
377 }
378 // Set up for next non-zero word in bitmap.
379 BitNumber = Iter->index() * ElementSize;
380 NextSetBitNumber = Iter->find_first();
381 BitNumber += NextSetBitNumber;
382 WordNumber = (BitNumber % ElementSize) / BITWORD_SIZE;
383 Bits = Iter->word(WordNumber);
384 Bits >>= NextSetBitNumber % BITWORD_SIZE;
385 } else {
386 WordNumber = (NextSetBitNumber % ElementSize) / BITWORD_SIZE;
387 Bits = Iter->word(WordNumber);
388 Bits >>= NextSetBitNumber % BITWORD_SIZE;
389 BitNumber = Iter->index() * ElementSize;
390 BitNumber += NextSetBitNumber;
391 }
392 }
393 }
394
395 public:
396 SparseBitVectorIterator() = default;
397
398 SparseBitVectorIterator(const SparseBitVector<ElementSize> *RHS,
399 bool end = false):BitVector(RHS) {
400 Iter = BitVector->Elements.begin();
401 BitNumber = 0;
402 Bits = 0;
403 WordNumber = ~0;
404 AtEnd = end;
405 AdvanceToFirstNonZero();
406 }
407
408 // Preincrement.
409 inline SparseBitVectorIterator& operator++() {
410 ++BitNumber;
411 Bits >>= 1;
412 AdvanceToNextNonZero();
413 return *this;
414 }
415
416 // Postincrement.
417 inline SparseBitVectorIterator operator++(int) {
418 SparseBitVectorIterator tmp = *this;
419 ++*this;
420 return tmp;
421 }
422
423 // Return the current set bit number.
424 unsigned operator*() const {
425 return BitNumber;
426 }
427
428 bool operator==(const SparseBitVectorIterator &RHS) const {
429 // If they are both at the end, ignore the rest of the fields.
430 if (AtEnd && RHS.AtEnd)
431 return true;
432 // Otherwise they are the same if they have the same bit number and
433 // bitmap.
434 return AtEnd == RHS.AtEnd && RHS.BitNumber == BitNumber;
435 }
436
437 bool operator!=(const SparseBitVectorIterator &RHS) const {
438 return !(*this == RHS);
439 }
440 };
441
442public:
443 using iterator = SparseBitVectorIterator;
444
445 SparseBitVector() : Elements(), CurrElementIter(Elements.begin()) {}
446
448 : Elements(RHS.Elements), CurrElementIter(Elements.begin()) {}
450 : Elements(std::move(RHS.Elements)), CurrElementIter(Elements.begin()) {}
451
452 // Clear.
453 void clear() {
454 Elements.clear();
455 }
456
457 // Assignment
459 if (this == &RHS)
460 return *this;
461
462 Elements = RHS.Elements;
463 CurrElementIter = Elements.begin();
464 return *this;
465 }
467 Elements = std::move(RHS.Elements);
468 CurrElementIter = Elements.begin();
469 return *this;
470 }
471
472 // Test, Reset, and Set a bit in the bitmap.
473 bool test(unsigned Idx) const {
474 if (Elements.empty())
475 return false;
476
477 unsigned ElementIndex = Idx / ElementSize;
478 ElementListConstIter ElementIter = FindLowerBoundConst(ElementIndex);
479
480 // If we can't find an element that is supposed to contain this bit, there
481 // is nothing more to do.
482 if (ElementIter == Elements.end() ||
483 ElementIter->index() != ElementIndex)
484 return false;
485 return ElementIter->test(Idx % ElementSize);
486 }
487
488 void reset(unsigned Idx) {
489 if (Elements.empty())
490 return;
491
492 unsigned ElementIndex = Idx / ElementSize;
493 ElementListIter ElementIter = FindLowerBound(ElementIndex);
494
495 // If we can't find an element that is supposed to contain this bit, there
496 // is nothing more to do.
497 if (ElementIter == Elements.end() ||
498 ElementIter->index() != ElementIndex)
499 return;
500 ElementIter->reset(Idx % ElementSize);
501
502 // When the element is zeroed out, delete it.
503 if (ElementIter->empty()) {
504 ++CurrElementIter;
505 Elements.erase(ElementIter);
506 }
507 }
508
509 void set(unsigned Idx) {
510 unsigned ElementIndex = Idx / ElementSize;
511 ElementListIter ElementIter;
512 if (Elements.empty()) {
513 ElementIter = Elements.emplace(Elements.end(), ElementIndex);
514 } else {
515 ElementIter = FindLowerBound(ElementIndex);
516
517 if (ElementIter == Elements.end() ||
518 ElementIter->index() != ElementIndex) {
519 // We may have hit the beginning of our SparseBitVector, in which case,
520 // we may need to insert right after this element, which requires moving
521 // the current iterator forward one, because insert does insert before.
522 if (ElementIter != Elements.end() &&
523 ElementIter->index() < ElementIndex)
524 ++ElementIter;
525 ElementIter = Elements.emplace(ElementIter, ElementIndex);
526 }
527 }
528 CurrElementIter = ElementIter;
529
530 ElementIter->set(Idx % ElementSize);
531 }
532
533 bool test_and_set(unsigned Idx) {
534 bool old = test(Idx);
535 if (!old) {
536 set(Idx);
537 return true;
538 }
539 return false;
540 }
541
542 bool operator!=(const SparseBitVector &RHS) const {
543 return !(*this == RHS);
544 }
545
546 bool operator==(const SparseBitVector &RHS) const {
547 ElementListConstIter Iter1 = Elements.begin();
548 ElementListConstIter Iter2 = RHS.Elements.begin();
549
550 for (; Iter1 != Elements.end() && Iter2 != RHS.Elements.end();
551 ++Iter1, ++Iter2) {
552 if (*Iter1 != *Iter2)
553 return false;
554 }
555 return Iter1 == Elements.end() && Iter2 == RHS.Elements.end();
556 }
557
558 // Union our bitmap with the RHS and return true if we changed.
560 if (this == &RHS)
561 return false;
562
563 bool changed = false;
564 ElementListIter Iter1 = Elements.begin();
565 ElementListConstIter Iter2 = RHS.Elements.begin();
566
567 // If RHS is empty, we are done
568 if (RHS.Elements.empty())
569 return false;
570
571 while (Iter2 != RHS.Elements.end()) {
572 if (Iter1 == Elements.end() || Iter1->index() > Iter2->index()) {
573 Elements.insert(Iter1, *Iter2);
574 ++Iter2;
575 changed = true;
576 } else if (Iter1->index() == Iter2->index()) {
577 changed |= Iter1->unionWith(*Iter2);
578 ++Iter1;
579 ++Iter2;
580 } else {
581 ++Iter1;
582 }
583 }
584 CurrElementIter = Elements.begin();
585 return changed;
586 }
587
588 // Intersect our bitmap with the RHS and return true if ours changed.
590 if (this == &RHS)
591 return false;
592
593 bool changed = false;
594 ElementListIter Iter1 = Elements.begin();
595 ElementListConstIter Iter2 = RHS.Elements.begin();
596
597 // Check if both bitmaps are empty.
598 if (Elements.empty() && RHS.Elements.empty())
599 return false;
600
601 // Loop through, intersecting as we go, erasing elements when necessary.
602 while (Iter2 != RHS.Elements.end()) {
603 if (Iter1 == Elements.end()) {
604 CurrElementIter = Elements.begin();
605 return changed;
606 }
607
608 if (Iter1->index() > Iter2->index()) {
609 ++Iter2;
610 } else if (Iter1->index() == Iter2->index()) {
611 bool BecameZero;
612 changed |= Iter1->intersectWith(*Iter2, BecameZero);
613 if (BecameZero) {
614 ElementListIter IterTmp = Iter1;
615 ++Iter1;
616 Elements.erase(IterTmp);
617 } else {
618 ++Iter1;
619 }
620 ++Iter2;
621 } else {
622 ElementListIter IterTmp = Iter1;
623 ++Iter1;
624 Elements.erase(IterTmp);
625 changed = true;
626 }
627 }
628 if (Iter1 != Elements.end()) {
629 Elements.erase(Iter1, Elements.end());
630 changed = true;
631 }
632 CurrElementIter = Elements.begin();
633 return changed;
634 }
635
636 // Intersect our bitmap with the complement of the RHS and return true
637 // if ours changed.
639 if (this == &RHS) {
640 if (!empty()) {
641 clear();
642 return true;
643 }
644 return false;
645 }
646
647 bool changed = false;
648 ElementListIter Iter1 = Elements.begin();
649 ElementListConstIter Iter2 = RHS.Elements.begin();
650
651 // If either our bitmap or RHS is empty, we are done
652 if (Elements.empty() || RHS.Elements.empty())
653 return false;
654
655 // Loop through, intersecting as we go, erasing elements when necessary.
656 while (Iter2 != RHS.Elements.end()) {
657 if (Iter1 == Elements.end()) {
658 CurrElementIter = Elements.begin();
659 return changed;
660 }
661
662 if (Iter1->index() > Iter2->index()) {
663 ++Iter2;
664 } else if (Iter1->index() == Iter2->index()) {
665 bool BecameZero;
666 changed |= Iter1->intersectWithComplement(*Iter2, BecameZero);
667 if (BecameZero) {
668 ElementListIter IterTmp = Iter1;
669 ++Iter1;
670 Elements.erase(IterTmp);
671 } else {
672 ++Iter1;
673 }
674 ++Iter2;
675 } else {
676 ++Iter1;
677 }
678 }
679 CurrElementIter = Elements.begin();
680 return changed;
681 }
682
686
687 // Three argument version of intersectWithComplement.
688 // Result of RHS1 & ~RHS2 is stored into this bitmap.
691 {
692 if (this == &RHS1) {
694 return;
695 } else if (this == &RHS2) {
696 SparseBitVector RHS2Copy(RHS2);
697 intersectWithComplement(RHS1, RHS2Copy);
698 return;
699 }
700
701 Elements.clear();
702 CurrElementIter = Elements.begin();
703 ElementListConstIter Iter1 = RHS1.Elements.begin();
704 ElementListConstIter Iter2 = RHS2.Elements.begin();
705
706 // If RHS1 is empty, we are done
707 // If RHS2 is empty, we still have to copy RHS1
708 if (RHS1.Elements.empty())
709 return;
710
711 // Loop through, intersecting as we go, erasing elements when necessary.
712 while (Iter2 != RHS2.Elements.end()) {
713 if (Iter1 == RHS1.Elements.end())
714 return;
715
716 if (Iter1->index() > Iter2->index()) {
717 ++Iter2;
718 } else if (Iter1->index() == Iter2->index()) {
719 bool BecameZero = false;
720 Elements.emplace_back(Iter1->index());
721 Elements.back().intersectWithComplement(*Iter1, *Iter2, BecameZero);
722 if (BecameZero)
723 Elements.pop_back();
724 ++Iter1;
725 ++Iter2;
726 } else {
727 Elements.push_back(*Iter1++);
728 }
729 }
730
731 // copy the remaining elements
732 std::copy(Iter1, RHS1.Elements.end(), std::back_inserter(Elements));
733 }
734
739
741 return intersects(*RHS);
742 }
743
744 // Return true if we share any bits in common with RHS
746 ElementListConstIter Iter1 = Elements.begin();
747 ElementListConstIter Iter2 = RHS.Elements.begin();
748
749 // Check if both bitmaps are empty.
750 if (Elements.empty() && RHS.Elements.empty())
751 return false;
752
753 // Loop through, intersecting stopping when we hit bits in common.
754 while (Iter2 != RHS.Elements.end()) {
755 if (Iter1 == Elements.end())
756 return false;
757
758 if (Iter1->index() > Iter2->index()) {
759 ++Iter2;
760 } else if (Iter1->index() == Iter2->index()) {
761 if (Iter1->intersects(*Iter2))
762 return true;
763 ++Iter1;
764 ++Iter2;
765 } else {
766 ++Iter1;
767 }
768 }
769 return false;
770 }
771
772 // Return true iff all bits set in this SparseBitVector are
773 // also set in RHS.
775 SparseBitVector<ElementSize> Result(*this);
776 Result &= RHS;
777 return (Result == RHS);
778 }
779
780 // Return the first set bit in the bitmap. Return -1 if no bits are set.
781 int find_first() const {
782 if (Elements.empty())
783 return -1;
784 const SparseBitVectorElement<ElementSize> &First = *(Elements.begin());
785 return (First.index() * ElementSize) + First.find_first();
786 }
787
788 // Return the last set bit in the bitmap. Return -1 if no bits are set.
789 int find_last() const {
790 if (Elements.empty())
791 return -1;
792 const SparseBitVectorElement<ElementSize> &Last = *(Elements.rbegin());
793 return (Last.index() * ElementSize) + Last.find_last();
794 }
795
796 // Return true if the SparseBitVector is empty
797 bool empty() const {
798 return Elements.empty();
799 }
800
801 unsigned count() const {
802 unsigned BitCount = 0;
803 for (const SparseBitVectorElement<ElementSize> &Elem : Elements)
804 BitCount += Elem.count();
805 return BitCount;
806 }
807
808 iterator begin() const {
809 return iterator(this);
810 }
811
812 iterator end() const {
813 return iterator(this, true);
814 }
815};
816
817// Convenience functions to allow Or and And without dereferencing in the user
818// code.
819
820template <unsigned ElementSize>
823 return LHS |= *RHS;
824}
825
826template <unsigned ElementSize>
829 return LHS->operator|=(RHS);
830}
831
832template <unsigned ElementSize>
835 return LHS->operator&=(RHS);
836}
837
838template <unsigned ElementSize>
841 return LHS &= *RHS;
842}
843
844// Convenience functions for infix union, intersection, difference operators.
845
846template <unsigned ElementSize>
847inline SparseBitVector<ElementSize>
851 Result |= RHS;
852 return Result;
853}
854
855template <unsigned ElementSize>
856inline SparseBitVector<ElementSize>
860 Result &= RHS;
861 return Result;
862}
863
864template <unsigned ElementSize>
865inline SparseBitVector<ElementSize>
869 Result.intersectWithComplement(LHS, RHS);
870 return Result;
871}
872
873// Dump a SparseBitVector to a stream
874template <unsigned ElementSize>
876 out << "[";
877
878 typename SparseBitVector<ElementSize>::iterator bi = LHS.begin(),
879 be = LHS.end();
880 if (bi != be) {
881 out << *bi;
882 for (++bi; bi != be; ++bi) {
883 out << " " << *bi;
884 }
885 }
886 out << "]\n";
887}
888
889} // end namespace llvm
890
891#endif // LLVM_ADT_SPARSEBITVECTOR_H
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
#define LLVM_ATTRIBUTE_WARN_UNUSED
Definition Compiler.h:240
static std::optional< ArrayRef< InsnRange >::iterator > intersects(const MachineInstr *StartMI, const MachineInstr *EndMI, ArrayRef< InsnRange > Ranges, const InstructionOrdering &Ordering)
Check if the instruction range [StartMI, EndMI] intersects any instruction range in Ranges.
#define I(x, y, z)
Definition MD5.cpp:57
bool operator==(const MergedFunctionsInfo &LHS, const MergedFunctionsInfo &RHS)
modulo schedule test
Value * RHS
Value * LHS
This file implements the C++20 <bit> header.
bool empty() const
Returns whether there are no bits in this bitvector.
Definition BitVector.h:175
bool operator!=(const SparseBitVector &RHS) const
bool intersects(const SparseBitVector< ElementSize > &RHS) const
bool operator==(const SparseBitVector &RHS) const
SparseBitVector & operator=(const SparseBitVector &RHS)
void set(unsigned Idx)
unsigned count() const
bool test_and_set(unsigned Idx)
void intersectWithComplement(const SparseBitVector< ElementSize > *RHS1, const SparseBitVector< ElementSize > *RHS2)
bool contains(const SparseBitVector< ElementSize > &RHS) const
void intersectWithComplement(const SparseBitVector< ElementSize > &RHS1, const SparseBitVector< ElementSize > &RHS2)
SparseBitVector(const SparseBitVector &RHS)
bool operator|=(const SparseBitVector &RHS)
bool test(unsigned Idx) const
void reset(unsigned Idx)
bool operator&=(const SparseBitVector &RHS)
SparseBitVector & operator=(SparseBitVector &&RHS)
bool intersectWithComplement(const SparseBitVector< ElementSize > *RHS) const
bool intersectWithComplement(const SparseBitVector &RHS)
bool intersects(const SparseBitVector< ElementSize > *RHS) const
SparseBitVectorIterator iterator
SparseBitVector(SparseBitVector &&RHS)
This class implements an extremely fast bulk output stream that can only output to a stream.
Definition raw_ostream.h:53
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
This is an optimization pass for GlobalISel generic memory operations.
void dump(const SparseBitVector< ElementSize > &LHS, raw_ostream &out)
APInt operator&(APInt a, const APInt &b)
Definition APInt.h:2149
APInt operator*(APInt a, uint64_t RHS)
Definition APInt.h:2261
constexpr int popcount(T Value) noexcept
Count the number of set bits in a value.
Definition bit.h:156
int countr_zero(T Val)
Count number of 0's from the least significant bit to the most stopping at the first 1.
Definition bit.h:204
int countl_zero(T Val)
Count number of 0's from the most significant bit to the least stopping at the first 1.
Definition bit.h:263
@ First
Helpers to iterate all locations in the MemoryEffectsBase class.
Definition ModRef.h:74
bool operator&=(SparseBitVector< ElementSize > *LHS, const SparseBitVector< ElementSize > &RHS)
OutputIt move(R &&Range, OutputIt Out)
Provide wrappers to std::move which take ranges instead of having to pass begin/end explicitly.
Definition STLExtras.h:1933
APInt operator-(APInt)
Definition APInt.h:2214
bool operator|=(SparseBitVector< ElementSize > &LHS, const SparseBitVector< ElementSize > *RHS)
APInt operator|(APInt a, const APInt &b)
Definition APInt.h:2169
@ End
Run the machine verifier once, at the end of the pipeline.
Definition CodeGen.h:320
Implement std::hash so that hash_code can be used in STL containers.
Definition BitVector.h:878
SparseBitVector is an implementation of a bitvector that is sparse by only storing the elements that ...
bool operator==(const SparseBitVectorElement &RHS) const
int find_next(unsigned Curr) const
find_next - Returns the index of the next set bit starting from the "Curr" bit.
bool unionWith(const SparseBitVectorElement &RHS)
int find_last() const
find_last - Returns the index of the last set bit.
void intersectWithComplement(const SparseBitVectorElement &RHS1, const SparseBitVectorElement &RHS2, bool &BecameZero)
bool intersectWith(const SparseBitVectorElement &RHS, bool &BecameZero)
bool operator!=(const SparseBitVectorElement &RHS) const
bool test_and_set(unsigned Idx)
BitWord word(unsigned Idx) const
bool test(unsigned Idx) const
bool intersectWithComplement(const SparseBitVectorElement &RHS, bool &BecameZero)
int find_first() const
find_first - Returns the index of the first set bit.
bool intersects(const SparseBitVectorElement &RHS) const