Static Value-Flow Analysis
Loading...
Searching...
No Matches
SparseBitVector.h
Go to the documentation of this file.
1//===- SparseBitVector.h - Efficient Sparse BitVector --*- C++ -*-===//
2//
3// From the LLVM Project with some modifications, under the Apache License v2.0
4// with LLVM Exceptions. See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7
8#ifndef SPARSEBITVECTOR_H
9#define SPARSEBITVECTOR_H
10
11#include <ostream>
12#include <cassert>
13#include <cstring>
14#include <climits>
15#include <limits>
16#include <iterator>
17#include <list>
18
19// Appease GCC?
20#ifdef __has_builtin
21# define HAS_CLZ __has_builtin(__builtin_clz)
22# define HAS_CLZLL __has_builtin(__builtin_clzll)
23# define HAS_CTZ __has_builtin(__builtin_ctz)
24# define HAS_CTZLL __has_builtin(__builtin_ctzll)
25#else
26# define HAS_CLZ 0
27# define HAS_CLZLL 0
28# define HAS_CLZ 0
29# define HAS_CLZLL 0
30#endif
31
32namespace SVF
33{
34
45
46template <typename T, std::size_t SizeOfT> struct TrailingZerosCounter
47{
48 static unsigned count(T Val, ZeroBehavior)
49 {
50 if (!Val)
51 return std::numeric_limits<T>::digits;
52 if (Val & 0x1)
53 return 0;
54
55 // Bisection method.
56 unsigned ZeroBits = 0;
57 T Shift = std::numeric_limits<T>::digits >> 1;
58 T Mask = std::numeric_limits<T>::max() >> Shift;
59 while (Shift)
60 {
61 if ((Val & Mask) == 0)
62 {
63 Val >>= Shift;
64 ZeroBits |= Shift;
65 }
66 Shift >>= 1;
67 Mask >>= Shift;
68 }
69 return ZeroBits;
70 }
71};
72
73#if defined(__GNUC__) || defined(_MSC_VER)
74template <typename T> struct TrailingZerosCounter<T, 4>
75{
76 static unsigned count(T Val, ZeroBehavior)
77 {
78 if (Val == 0)
79 return 32;
80
81#if HAS_CTZ || defined(__GNUC__)
82 return __builtin_ctz(Val);
83#elif defined(_MSC_VER)
84 unsigned long Index;
86 return Index;
87#endif
88 }
89};
90
91#if !defined(_MSC_VER) || defined(_M_X64)
92template <typename T> struct TrailingZerosCounter<T, 8>
93{
94 static unsigned count(T Val, ZeroBehavior)
95 {
96 if (Val == 0)
97 return 64;
98
99#if HAS_CTZLL || defined(__GNUC__)
100 return __builtin_ctzll(Val);
101#elif defined(_MSC_VER)
102 unsigned long Index;
104 return Index;
105#endif
106 }
107};
108#endif
109#endif
110
118template <typename T>
120{
121 static_assert(std::numeric_limits<T>::is_integer &&
122 !std::numeric_limits<T>::is_signed,
123 "Only unsigned integral types are allowed.");
124 return TrailingZerosCounter<T, sizeof(T)>::count(Val, ZB);
125}
126
127template <typename T, std::size_t SizeOfT> struct PopulationCounter
128{
129 static unsigned count(T Value)
130 {
131 // Generic version, forward to 32 bits.
132 static_assert(SizeOfT <= 4, "Not implemented!");
133#if defined(__GNUC__)
135#else
136 uint32_t v = Value;
137 v = v - ((v >> 1) & 0x55555555);
138 v = (v & 0x33333333) + ((v >> 2) & 0x33333333);
139 return ((v + (v >> 4) & 0xF0F0F0F) * 0x1010101) >> 24;
140#endif
141 }
142};
143
144template <typename T, std::size_t SizeOfT> struct LeadingZerosCounter
145{
146 static unsigned count(T Val, ZeroBehavior)
147 {
148 if (!Val)
149 return std::numeric_limits<T>::digits;
150
151 // Bisection method.
152 unsigned ZeroBits = 0;
153 for (T Shift = std::numeric_limits<T>::digits >> 1; Shift; Shift >>= 1)
154 {
155 T Tmp = Val >> Shift;
156 if (Tmp)
157 Val = Tmp;
158 else
159 ZeroBits |= Shift;
160 }
161 return ZeroBits;
162 }
163};
164
165#if defined(__GNUC__) || defined(_MSC_VER)
166template <typename T> struct LeadingZerosCounter<T, 4>
167{
168 static unsigned count(T Val, ZeroBehavior ZB)
169 {
170 if (ZB != ZB_Undefined && Val == 0)
171 return 32;
172
173#if defined(__GNUC__) || HAS_CLZ
174 return __builtin_clz(Val);
175#elif defined(_MSC_VER)
176 unsigned long Index;
178 return Index ^ 31;
179#endif
180 }
181};
182
183#if !defined(_MSC_VER) || defined(_M_X64)
184template <typename T> struct LeadingZerosCounter<T, 8>
185{
186 static unsigned count(T Val, ZeroBehavior ZB)
187 {
188 if (ZB != ZB_Undefined && Val == 0)
189 return 64;
190
191#if defined(__GNUC__) || HAS_CLZLL
192 return __builtin_clzll(Val);
193#elif defined(_MSC_VER)
194 unsigned long Index;
196 return Index ^ 63;
197#endif
198 }
199};
200#endif
201#endif
202
210template <typename T>
212{
213 static_assert(std::numeric_limits<T>::is_integer &&
214 !std::numeric_limits<T>::is_signed,
215 "Only unsigned integral types are allowed.");
216 return LeadingZerosCounter<T, sizeof(T)>::count(Val, ZB);
217}
218
219template <typename T> struct PopulationCounter<T, 8>
220{
221 static unsigned count(T Value)
222 {
223#if defined(__GNUC__)
225#else
226 uint64_t v = Value;
227 v = v - ((v >> 1) & 0x5555555555555555ULL);
228 v = (v & 0x3333333333333333ULL) + ((v >> 2) & 0x3333333333333333ULL);
229 v = (v + (v >> 4)) & 0x0F0F0F0F0F0F0F0FULL;
230 return unsigned((uint64_t)(v * 0x0101010101010101ULL) >> 56);
231#endif
232 }
233};
234
238template <typename T>
239inline unsigned countPopulation(T Value)
240{
241 static_assert(std::numeric_limits<T>::is_integer &&
242 !std::numeric_limits<T>::is_signed,
243 "Only unsigned integral types are allowed.");
244 return PopulationCounter<T, sizeof(T)>::count(Value);
245}
246
259template <unsigned ElementSize = 128> struct SparseBitVectorElement
260{
261
262public:
263 using BitWord = unsigned long;
265 enum
266 {
268 // N.B. (+ BITWORD_SIZE - 1) is to round up, to ensure we can have
269 // sufficient bits to represent *at least* ElementSize bits.
272 };
273
274private:
275 // Index of Element in terms of where first bit starts.
276 unsigned ElementIndex = 0;
278
280
281public:
283
284 // Comparison.
286 {
287 if (ElementIndex != RHS.ElementIndex)
288 return false;
289 for (unsigned i = 0; i < BITWORDS_PER_ELEMENT; ++i)
290 if (Bits[i] != RHS.Bits[i])
291 return false;
292 return true;
293 }
294
296 {
297 return !(*this == RHS);
298 }
299
300 // Return the bits that make up word Idx in our element.
301 BitWord word(unsigned Idx) const
302 {
304 return Bits[Idx];
305 }
306
307 unsigned index() const
308 {
309 return ElementIndex;
310 }
311
312 bool empty() const
313 {
314 for (unsigned i = 0; i < BITWORDS_PER_ELEMENT; ++i)
315 if (Bits[i])
316 return false;
317 return true;
318 }
319
320 void set(unsigned Idx)
321 {
322 Bits[Idx / BITWORD_SIZE] |= 1L << (Idx % BITWORD_SIZE);
323 }
324
325 bool test_and_set(unsigned Idx)
326 {
327 bool old = test(Idx);
328 if (!old)
329 {
330 set(Idx);
331 return true;
332 }
333 return false;
334 }
335
336 void reset(unsigned Idx)
337 {
338 Bits[Idx / BITWORD_SIZE] &= ~(1L << (Idx % BITWORD_SIZE));
339 }
340
341 bool test(unsigned Idx) const
342 {
343 return Bits[Idx / BITWORD_SIZE] & (1L << (Idx % BITWORD_SIZE));
344 }
345
347 {
348 unsigned NumBits = 0;
349 for (unsigned i = 0; i < BITWORDS_PER_ELEMENT; ++i)
351 return NumBits;
352 }
353
355 int find_first() const
356 {
357 for (unsigned i = 0; i < BITWORDS_PER_ELEMENT; ++i)
358 if (Bits[i] != 0)
360 assert(false && "SBV: find_first: SBV cannot be empty");
361 abort();
362 }
363
365 int find_last() const
366 {
367 for (unsigned I = 0; I < BITWORDS_PER_ELEMENT; ++I)
368 {
369 unsigned Idx = BITWORDS_PER_ELEMENT - I - 1;
370 if (Bits[Idx] != 0)
371 return Idx * BITWORD_SIZE + BITWORD_SIZE -
373 }
374 assert(false && "SBV: find_last: SBV cannot be empty");
375 abort();
376 }
377
380 int find_next(unsigned Curr) const
381 {
382 if (Curr >= BITS_PER_ELEMENT)
383 return -1;
384
385 unsigned WordPos = Curr / BITWORD_SIZE;
386 unsigned BitPos = Curr % BITWORD_SIZE;
387 BitWord Copy = Bits[WordPos];
389 && "Word Position outside of element");
390
391 // Mask off previous bits.
392 Copy &= ~0UL << BitPos;
393
394 if (Copy != 0)
395 return WordPos * BITWORD_SIZE + countTrailingZeros(Copy);
396
397 // Check subsequent words.
398 for (unsigned i = WordPos+1; i < BITWORDS_PER_ELEMENT; ++i)
399 if (Bits[i] != 0)
401 return -1;
402 }
403
404 // Union this element with RHS and return true if this one changed.
406 {
407 bool changed = false;
408 for (unsigned i = 0; i < BITWORDS_PER_ELEMENT; ++i)
409 {
410 BitWord old = changed ? 0 : Bits[i];
411
412 Bits[i] |= RHS.Bits[i];
413 if (!changed && old != Bits[i])
414 changed = true;
415 }
416 return changed;
417 }
418
419 // Return true if we have any bits in common with RHS
421 {
422 for (unsigned i = 0; i < BITWORDS_PER_ELEMENT; ++i)
423 {
424 if (RHS.Bits[i] & Bits[i])
425 return true;
426 }
427 return false;
428 }
429
430 // Intersect this Element with RHS and return true if this one changed.
431 // BecameZero is set to true if this element became all-zero bits.
433 bool &BecameZero)
434 {
435 bool changed = false;
436 bool allzero = true;
437
438 BecameZero = false;
439 for (unsigned i = 0; i < BITWORDS_PER_ELEMENT; ++i)
440 {
441 BitWord old = changed ? 0 : Bits[i];
442
443 Bits[i] &= RHS.Bits[i];
444 if (Bits[i] != 0)
445 allzero = false;
446
447 if (!changed && old != Bits[i])
448 changed = true;
449 }
451 return changed;
452 }
453
454 // Intersect this Element with the complement of RHS and return true if this
455 // one changed. BecameZero is set to true if this element became all-zero
456 // bits.
458 bool &BecameZero)
459 {
460 bool changed = false;
461 bool allzero = true;
462
463 BecameZero = false;
464 for (unsigned i = 0; i < BITWORDS_PER_ELEMENT; ++i)
465 {
466 BitWord old = changed ? 0 : Bits[i];
467
468 Bits[i] &= ~RHS.Bits[i];
469 if (Bits[i] != 0)
470 allzero = false;
471
472 if (!changed && old != Bits[i])
473 changed = true;
474 }
476 return changed;
477 }
478
479 // Three argument version of intersectWithComplement that intersects
480 // RHS1 & ~RHS2 into this element
483 bool &BecameZero)
484 {
485 bool allzero = true;
486
487 BecameZero = false;
488 for (unsigned i = 0; i < BITWORDS_PER_ELEMENT; ++i)
489 {
490 Bits[i] = RHS1.Bits[i] & ~RHS2.Bits[i];
491 if (Bits[i] != 0)
492 allzero = false;
493 }
495 }
496};
497
498template <unsigned ElementSize = 128>
500{
501
502 using ElementList = std::list<SparseBitVectorElement<ElementSize>>;
503 using ElementListIter = typename ElementList::iterator;
504 using ElementListConstIter = typename ElementList::const_iterator;
505 enum
506 {
508 };
509
511 // Pointer to our current Element. This has no visible effect on the external
512 // state of a SparseBitVector, it's just used to improve performance in the
513 // common case of testing/modifying bits with similar indices.
515
516 // This is like std::lower_bound, except we do linear searching from the
517 // current position.
518 ElementListIter FindLowerBoundImpl(unsigned ElementIndex) const
519 {
520
521 // We cache a non-const iterator so we're forced to resort to const_cast to
522 // get the begin/end in the case where 'this' is const. To avoid duplication
523 // of code with the only difference being whether the const cast is present
524 // 'this' is always const in this particular function and we sort out the
525 // difference in FindLowerBound and FindLowerBoundConst.
527 const_cast<SparseBitVector<ElementSize> *>(this)->Elements.begin();
529 const_cast<SparseBitVector<ElementSize> *>(this)->Elements.end();
530
531 if (Elements.empty())
532 {
534 return CurrElementIter;
535 }
536
537 // Make sure our current iterator is valid.
538 if (CurrElementIter == End)
540
541 // Search from our current iterator, either backwards or forwards,
542 // depending on what element we are looking for.
544 if (CurrElementIter->index() == ElementIndex)
545 {
546 return ElementIter;
547 }
548 else if (CurrElementIter->index() > ElementIndex)
549 {
550 while (ElementIter != Begin
551 && ElementIter->index() > ElementIndex)
552 --ElementIter;
553 }
554 else
555 {
556 while (ElementIter != End &&
557 ElementIter->index() < ElementIndex)
558 ++ElementIter;
559 }
561 return ElementIter;
562 }
563 ElementListConstIter FindLowerBoundConst(unsigned ElementIndex) const
564 {
565 return FindLowerBoundImpl(ElementIndex);
566 }
567 ElementListIter FindLowerBound(unsigned ElementIndex)
568 {
569 return FindLowerBoundImpl(ElementIndex);
570 }
571
572 // Iterator to walk set bits in the bitmap. This iterator is a lot uglier
573 // than it would be, in order to be efficient.
575 {
576 private:
577 bool AtEnd;
578
580
581 // Current element inside of bitmap.
583
584 // Current bit number inside of our bitmap.
585 unsigned BitNumber;
586
587 // Current word number inside of our element.
588 unsigned WordNumber;
589
590 // Current bits from the element.
592
593 // Move our iterator to the first non-zero bit in the bitmap.
595 {
596 if (AtEnd)
597 return;
598 if (BitVector->Elements.empty())
599 {
600 AtEnd = true;
601 return;
602 }
603 Iter = BitVector->Elements.begin();
604 BitNumber = Iter->index() * ElementSize;
605 unsigned BitPos = Iter->find_first();
606 BitNumber += BitPos;
610 }
611
612 // Move our iterator to the next non-zero bit.
614 {
615 if (AtEnd)
616 return;
617
618 while (Bits && !(Bits & 1))
619 {
620 Bits >>= 1;
621 BitNumber += 1;
622 }
623
624 // See if we ran out of Bits in this word.
625 if (!Bits)
626 {
628 // If we ran out of set bits in this element, move to next element.
629 if (NextSetBitNumber == -1 || (BitNumber % ElementSize == 0))
630 {
631 ++Iter;
632 WordNumber = 0;
633
634 // We may run out of elements in the bitmap.
635 if (Iter == BitVector->Elements.end())
636 {
637 AtEnd = true;
638 return;
639 }
640 // Set up for next non-zero word in bitmap.
641 BitNumber = Iter->index() * ElementSize;
642 NextSetBitNumber = Iter->find_first();
647 }
648 else
649 {
655 }
656 }
657 }
658
659 public:
661
663 bool end = false):BitVector(RHS)
664 {
665 Iter = BitVector->Elements.begin();
666 BitNumber = 0;
667 Bits = 0;
668 WordNumber = ~0;
669 AtEnd = end;
671 }
672
673 // Preincrement.
675 {
676 ++BitNumber;
677 Bits >>= 1;
679 return *this;
680 }
681
682 // Postincrement.
684 {
686 ++*this;
687 return tmp;
688 }
689
690 // Return the current set bit number.
691 unsigned operator*() const
692 {
693 return BitNumber;
694 }
695
697 {
698 // If they are both at the end, ignore the rest of the fields.
699 if (AtEnd && RHS.AtEnd)
700 return true;
701 // Otherwise they are the same if they have the same bit number and
702 // bitmap.
703 return AtEnd == RHS.AtEnd && RHS.BitNumber == BitNumber;
704 }
705
707 {
708 return !(*this == RHS);
709 }
710 };
711
712public:
714
716
721
722 // Clear.
723 void clear()
724 {
725 Elements.clear();
726 }
727
728 // Assignment
730 {
731 if (this == &RHS)
732 return *this;
733
735 CurrElementIter = Elements.begin();
736 return *this;
737 }
739 {
740 Elements = std::move(RHS.Elements);
741 CurrElementIter = Elements.begin();
742 return *this;
743 }
744
745 // Test, Reset, and Set a bit in the bitmap.
746 bool test(unsigned Idx) const
747 {
748 if (Elements.empty())
749 return false;
750
751 unsigned ElementIndex = Idx / ElementSize;
753
754 // If we can't find an element that is supposed to contain this bit, there
755 // is nothing more to do.
756 if (ElementIter == Elements.end() ||
757 ElementIter->index() != ElementIndex)
758 return false;
759 return ElementIter->test(Idx % ElementSize);
760 }
761
762 void reset(unsigned Idx)
763 {
764 if (Elements.empty())
765 return;
766
767 unsigned ElementIndex = Idx / ElementSize;
769
770 // If we can't find an element that is supposed to contain this bit, there
771 // is nothing more to do.
772 if (ElementIter == Elements.end() ||
773 ElementIter->index() != ElementIndex)
774 return;
775 ElementIter->reset(Idx % ElementSize);
776
777 // When the element is zeroed out, delete it.
778 if (ElementIter->empty())
779 {
781 Elements.erase(ElementIter);
782 }
783 }
784
785 void set(unsigned Idx)
786 {
787 unsigned ElementIndex = Idx / ElementSize;
789 if (Elements.empty())
790 {
791 ElementIter = Elements.emplace(Elements.end(), ElementIndex);
792 }
793 else
794 {
795 ElementIter = FindLowerBound(ElementIndex);
796
797 if (ElementIter == Elements.end() ||
798 ElementIter->index() != ElementIndex)
799 {
800 // We may have hit the beginning of our SparseBitVector, in which case,
801 // we may need to insert right after this element, which requires moving
802 // the current iterator forward one, because insert does insert before.
803 if (ElementIter != Elements.end() &&
804 ElementIter->index() < ElementIndex)
805 ++ElementIter;
806 ElementIter = Elements.emplace(ElementIter, ElementIndex);
807 }
808 }
810
812 }
813
814 bool test_and_set(unsigned Idx)
815 {
816 bool old = test(Idx);
817 if (!old)
818 {
819 set(Idx);
820 return true;
821 }
822 return false;
823 }
824
825 bool operator!=(const SparseBitVector &RHS) const
826 {
827 return !(*this == RHS);
828 }
829
830 bool operator==(const SparseBitVector &RHS) const
831 {
833 ElementListConstIter Iter2 = RHS.Elements.begin();
834
835 for (; Iter1 != Elements.end() && Iter2 != RHS.Elements.end();
836 ++Iter1, ++Iter2)
837 {
838 if (*Iter1 != *Iter2)
839 return false;
840 }
841 return Iter1 == Elements.end() && Iter2 == RHS.Elements.end();
842 }
843
844 // Union our bitmap with the RHS and return true if we changed.
846 {
847 if (this == &RHS)
848 return false;
849
850 bool changed = false;
852 ElementListConstIter Iter2 = RHS.Elements.begin();
853
854 // If RHS is empty, we are done
855 if (RHS.Elements.empty())
856 return false;
857
858 while (Iter2 != RHS.Elements.end())
859 {
860 if (Iter1 == Elements.end() || Iter1->index() > Iter2->index())
861 {
862 Elements.insert(Iter1, *Iter2);
863 ++Iter2;
864 changed = true;
865 }
866 else if (Iter1->index() == Iter2->index())
867 {
868 changed |= Iter1->unionWith(*Iter2);
869 ++Iter1;
870 ++Iter2;
871 }
872 else
873 {
874 ++Iter1;
875 }
876 }
877 CurrElementIter = Elements.begin();
878 return changed;
879 }
880
881 // Intersect our bitmap with the RHS and return true if ours changed.
883 {
884 if (this == &RHS)
885 return false;
886
887 bool changed = false;
889 ElementListConstIter Iter2 = RHS.Elements.begin();
890
891 // Check if both bitmaps are empty.
892 if (Elements.empty() && RHS.Elements.empty())
893 return false;
894
895 // Loop through, intersecting as we go, erasing elements when necessary.
896 while (Iter2 != RHS.Elements.end())
897 {
898 if (Iter1 == Elements.end())
899 {
900 CurrElementIter = Elements.begin();
901 return changed;
902 }
903
904 if (Iter1->index() > Iter2->index())
905 {
906 ++Iter2;
907 }
908 else if (Iter1->index() == Iter2->index())
909 {
910 bool BecameZero;
911 changed |= Iter1->intersectWith(*Iter2, BecameZero);
912 if (BecameZero)
913 {
915 ++Iter1;
916 Elements.erase(IterTmp);
917 }
918 else
919 {
920 ++Iter1;
921 }
922 ++Iter2;
923 }
924 else
925 {
927 ++Iter1;
928 Elements.erase(IterTmp);
929 changed = true;
930 }
931 }
932 if (Iter1 != Elements.end())
933 {
934 Elements.erase(Iter1, Elements.end());
935 changed = true;
936 }
937 CurrElementIter = Elements.begin();
938 return changed;
939 }
940
941 // Intersect our bitmap with the complement of the RHS and return true
942 // if ours changed.
944 {
945 if (this == &RHS)
946 {
947 if (!empty())
948 {
949 clear();
950 return true;
951 }
952 return false;
953 }
954
955 bool changed = false;
957 ElementListConstIter Iter2 = RHS.Elements.begin();
958
959 // If either our bitmap or RHS is empty, we are done
960 if (Elements.empty() || RHS.Elements.empty())
961 return false;
962
963 // Loop through, intersecting as we go, erasing elements when necessary.
964 while (Iter2 != RHS.Elements.end())
965 {
966 if (Iter1 == Elements.end())
967 {
968 CurrElementIter = Elements.begin();
969 return changed;
970 }
971
972 if (Iter1->index() > Iter2->index())
973 {
974 ++Iter2;
975 }
976 else if (Iter1->index() == Iter2->index())
977 {
978 bool BecameZero;
979 changed |= Iter1->intersectWithComplement(*Iter2, BecameZero);
980 if (BecameZero)
981 {
983 ++Iter1;
984 Elements.erase(IterTmp);
985 }
986 else
987 {
988 ++Iter1;
989 }
990 ++Iter2;
991 }
992 else
993 {
994 ++Iter1;
995 }
996 }
997 CurrElementIter = Elements.begin();
998 return changed;
999 }
1000
1005
1006 // Three argument version of intersectWithComplement.
1007 // Result of RHS1 & ~RHS2 is stored into this bitmap.
1010 {
1011 if (this == &RHS1)
1012 {
1014 return;
1015 }
1016 else if (this == &RHS2)
1017 {
1020 return;
1021 }
1022
1023 Elements.clear();
1024 CurrElementIter = Elements.begin();
1025 ElementListConstIter Iter1 = RHS1.Elements.begin();
1026 ElementListConstIter Iter2 = RHS2.Elements.begin();
1027
1028 // If RHS1 is empty, we are done
1029 // If RHS2 is empty, we still have to copy RHS1
1030 if (RHS1.Elements.empty())
1031 return;
1032
1033 // Loop through, intersecting as we go, erasing elements when necessary.
1034 while (Iter2 != RHS2.Elements.end())
1035 {
1036 if (Iter1 == RHS1.Elements.end())
1037 return;
1038
1039 if (Iter1->index() > Iter2->index())
1040 {
1041 ++Iter2;
1042 }
1043 else if (Iter1->index() == Iter2->index())
1044 {
1045 bool BecameZero = false;
1046 Elements.emplace_back(Iter1->index());
1047 Elements.back().intersectWithComplement(*Iter1, *Iter2, BecameZero);
1048 if (BecameZero)
1049 Elements.pop_back();
1050 ++Iter1;
1051 ++Iter2;
1052 }
1053 else
1054 {
1055 Elements.push_back(*Iter1++);
1056 }
1057 }
1058
1059 // copy the remaining elements
1060 std::copy(Iter1, RHS1.Elements.end(), std::back_inserter(Elements));
1061 }
1062
1068
1070 {
1071 return intersects(*RHS);
1072 }
1073
1074 // Return true if we share any bits in common with RHS
1076 {
1078 ElementListConstIter Iter2 = RHS.Elements.begin();
1079
1080 // Check if both bitmaps are empty.
1081 if (Elements.empty() && RHS.Elements.empty())
1082 return false;
1083
1084 // Loop through, intersecting stopping when we hit bits in common.
1085 while (Iter2 != RHS.Elements.end())
1086 {
1087 if (Iter1 == Elements.end())
1088 return false;
1089
1090 if (Iter1->index() > Iter2->index())
1091 {
1092 ++Iter2;
1093 }
1094 else if (Iter1->index() == Iter2->index())
1095 {
1096 if (Iter1->intersects(*Iter2))
1097 return true;
1098 ++Iter1;
1099 ++Iter2;
1100 }
1101 else
1102 {
1103 ++Iter1;
1104 }
1105 }
1106 return false;
1107 }
1108
1109 // Return true iff all bits set in this SparseBitVector are
1110 // also set in RHS.
1112 {
1114 Result &= RHS;
1115 return (Result == RHS);
1116 }
1117
1118 // Return the first set bit in the bitmap. Return -1 if no bits are set.
1119 int find_first() const
1120 {
1121 if (Elements.empty())
1122 return -1;
1124 return (First.index() * ElementSize) + First.find_first();
1125 }
1126
1127 // Return the last set bit in the bitmap. Return -1 if no bits are set.
1128 int find_last() const
1129 {
1130 if (Elements.empty())
1131 return -1;
1133 return (Last.index() * ElementSize) + Last.find_last();
1134 }
1135
1136 // Return true if the SparseBitVector is empty
1137 bool empty() const
1138 {
1139 return Elements.empty();
1140 }
1141
1142 unsigned count() const
1143 {
1144 unsigned BitCount = 0;
1145 for (ElementListConstIter Iter = Elements.begin();
1146 Iter != Elements.end();
1147 ++Iter)
1148 BitCount += Iter->count();
1149
1150 return BitCount;
1151 }
1152
1154 {
1155 return iterator(this);
1156 }
1157
1159 {
1160 return iterator(this, true);
1161 }
1162};
1163
1164// Convenience functions to allow Or and And without dereferencing in the user
1165// code.
1166
1167template <unsigned ElementSize>
1170{
1171 return LHS |= *RHS;
1172}
1173
1174template <unsigned ElementSize>
1177{
1178 return LHS->operator|=(RHS);
1179}
1180
1181template <unsigned ElementSize>
1184{
1185 return LHS->operator&=(RHS);
1186}
1187
1188template <unsigned ElementSize>
1191{
1192 return LHS &= *RHS;
1193}
1194
1195// Convenience functions for infix union, intersection, difference operators.
1196
1197template <unsigned ElementSize>
1198inline SparseBitVector<ElementSize>
1206
1207template <unsigned ElementSize>
1208inline SparseBitVector<ElementSize>
1216
1217template <unsigned ElementSize>
1218inline SparseBitVector<ElementSize>
1221{
1223 Result.intersectWithComplement(LHS, RHS);
1224 return Result;
1225}
1226
1227// Dump a SparseBitVector to a stream
1228template <unsigned ElementSize>
1229void dump(const SparseBitVector<ElementSize> &LHS, std::ostream &out)
1230{
1231 out << "[";
1232
1234 be = LHS.end();
1235 if (bi != be)
1236 {
1237 out << *bi;
1238 for (++bi; bi != be; ++bi)
1239 {
1240 out << " " << *bi;
1241 }
1242 }
1243 out << "]\n";
1244}
1245
1246} // End namespace SVF
1247
1248#endif // SPARSEBITVECTOR_H
int count
Definition cJSON.h:216
const_iterator begin(void) const
const_iterator end(void) const
bool empty(void) const
Returns true if no bits are set.
bool operator!=(const SparseBitVectorIterator &RHS) const
SparseBitVectorIterator(const SparseBitVector< ElementSize > *RHS, bool end=false)
bool operator==(const SparseBitVectorIterator &RHS) const
SparseBitVectorElement< ElementSize >::BitWord Bits
SparseBitVectorIterator iterator
SparseBitVector & operator=(SparseBitVector &&RHS)
bool test(unsigned Idx) const
bool operator&=(const SparseBitVector &RHS)
bool intersects(const SparseBitVector< ElementSize > *RHS) const
void intersectWithComplement(const SparseBitVector< ElementSize > *RHS1, const SparseBitVector< ElementSize > *RHS2)
bool test_and_set(unsigned Idx)
typename ElementList::iterator ElementListIter
bool operator|=(const SparseBitVector &RHS)
void set(unsigned Idx)
bool intersects(const SparseBitVector< ElementSize > &RHS) const
std::list< SparseBitVectorElement< ElementSize > > ElementList
bool operator==(const SparseBitVector &RHS) const
bool intersectWithComplement(const SparseBitVector &RHS)
SparseBitVector(SparseBitVector &&RHS) noexcept
SparseBitVector(const SparseBitVector &RHS)
unsigned count() const
bool intersectWithComplement(const SparseBitVector< ElementSize > *RHS) const
ElementListIter FindLowerBound(unsigned ElementIndex)
ElementListConstIter FindLowerBoundConst(unsigned ElementIndex) const
bool contains(const SparseBitVector< ElementSize > &RHS) const
iterator begin() const
bool operator!=(const SparseBitVector &RHS) const
typename ElementList::const_iterator ElementListConstIter
void reset(unsigned Idx)
ElementListIter FindLowerBoundImpl(unsigned ElementIndex) const
SparseBitVector & operator=(const SparseBitVector &RHS)
ElementListIter CurrElementIter
void intersectWithComplement(const SparseBitVector< ElementSize > &RHS1, const SparseBitVector< ElementSize > &RHS2)
for isBitcode
Definition BasicTypes.h:68
IntervalValue operator-(const IntervalValue &lhs, const IntervalValue &rhs)
Subtract IntervalValues.
unsigned countTrailingZeros(T Val, ZeroBehavior ZB=ZB_Width)
bool operator&=(SparseBitVector< ElementSize > *LHS, const SparseBitVector< ElementSize > &RHS)
IntervalValue operator&(const IntervalValue &lhs, const IntervalValue &rhs)
Bitwise AND of IntervalValues.
llvm::Value Value
LLVM Basic classes.
Definition BasicTypes.h:82
llvm::IRBuilder IRBuilder
Definition BasicTypes.h:74
bool operator|=(SparseBitVector< ElementSize > &LHS, const SparseBitVector< ElementSize > *RHS)
void dump(const SparseBitVector< ElementSize > &LHS, std::ostream &out)
IntervalValue operator|(const IntervalValue &lhs, const IntervalValue &rhs)
Bitwise OR of IntervalValues.
unsigned countPopulation(T Value)
ZeroBehavior
The behavior an operation has on an input of 0.
@ ZB_Undefined
The returned value is undefined.
@ ZB_Max
The returned value is numeric_limits<T>::max()
@ ZB_Width
The returned value is numeric_limits<T>::digits.
unsigned countLeadingZeros(T Val, ZeroBehavior ZB=ZB_Width)
static unsigned count(T Val, ZeroBehavior)
static unsigned count(T Value)
static unsigned count(T Value)
int find_last() const
find_last - Returns the index of the last set bit.
int find_first() const
find_first - Returns the index of the first set bit.
bool intersects(const SparseBitVectorElement &RHS) const
bool intersectWith(const SparseBitVectorElement &RHS, bool &BecameZero)
bool unionWith(const SparseBitVectorElement &RHS)
bool test(unsigned Idx) const
BitWord Bits[BITWORDS_PER_ELEMENT]
BitWord word(unsigned Idx) const
int find_next(unsigned Curr) const
void intersectWithComplement(const SparseBitVectorElement &RHS1, const SparseBitVectorElement &RHS2, bool &BecameZero)
bool test_and_set(unsigned Idx)
bool operator==(const SparseBitVectorElement &RHS) const
bool operator!=(const SparseBitVectorElement &RHS) const
bool intersectWithComplement(const SparseBitVectorElement &RHS, bool &BecameZero)
static unsigned count(T Val, ZeroBehavior)