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)
539 {
541 }
542
543 // Search from our current iterator, either backwards or forwards,
544 // depending on what element we are looking for.
546 if (CurrElementIter->index() == ElementIndex)
547 {
548 return ElementIter;
549 }
550 else if (CurrElementIter->index() > ElementIndex)
551 {
552 while (ElementIter != Begin
553 && ElementIter->index() > ElementIndex)
554 --ElementIter;
555 }
556 else
557 {
558 while (ElementIter != End &&
559 ElementIter->index() < ElementIndex)
560 ++ElementIter;
561 }
563 return ElementIter;
564 }
565 ElementListConstIter FindLowerBoundConst(unsigned ElementIndex) const
566 {
567 return FindLowerBoundImpl(ElementIndex);
568 }
569 ElementListIter FindLowerBound(unsigned ElementIndex)
570 {
571 return FindLowerBoundImpl(ElementIndex);
572 }
573
574 // Iterator to walk set bits in the bitmap. This iterator is a lot uglier
575 // than it would be, in order to be efficient.
577 {
578 private:
579 bool AtEnd;
580
582
583 // Current element inside of bitmap.
585
586 // Current bit number inside of our bitmap.
587 unsigned BitNumber;
588
589 // Current word number inside of our element.
590 unsigned WordNumber;
591
592 // Current bits from the element.
594
595 // Move our iterator to the first non-zero bit in the bitmap.
597 {
598 if (AtEnd)
599 return;
600 if (BitVector->Elements.empty())
601 {
602 AtEnd = true;
603 return;
604 }
605 Iter = BitVector->Elements.begin();
606 BitNumber = Iter->index() * ElementSize;
607 unsigned BitPos = Iter->find_first();
608 BitNumber += BitPos;
612 }
613
614 // Move our iterator to the next non-zero bit.
616 {
617 if (AtEnd)
618 return;
619
620 while (Bits && !(Bits & 1))
621 {
622 Bits >>= 1;
623 BitNumber += 1;
624 }
625
626 // See if we ran out of Bits in this word.
627 if (!Bits)
628 {
630 // If we ran out of set bits in this element, move to next element.
631 if (NextSetBitNumber == -1 || (BitNumber % ElementSize == 0))
632 {
633 ++Iter;
634 WordNumber = 0;
635
636 // We may run out of elements in the bitmap.
637 if (Iter == BitVector->Elements.end())
638 {
639 AtEnd = true;
640 return;
641 }
642 // Set up for next non-zero word in bitmap.
643 BitNumber = Iter->index() * ElementSize;
644 NextSetBitNumber = Iter->find_first();
649 }
650 else
651 {
657 }
658 }
659 }
660
661 public:
663
665 bool end = false):BitVector(RHS)
666 {
667 Iter = BitVector->Elements.begin();
668 BitNumber = 0;
669 Bits = 0;
670 WordNumber = ~0;
671 AtEnd = end;
673 }
674
675 // Preincrement.
677 {
678 ++BitNumber;
679 Bits >>= 1;
681 return *this;
682 }
683
684 // Postincrement.
686 {
688 ++*this;
689 return tmp;
690 }
691
692 // Return the current set bit number.
693 unsigned operator*() const
694 {
695 return BitNumber;
696 }
697
699 {
700 // If they are both at the end, ignore the rest of the fields.
701 if (AtEnd && RHS.AtEnd)
702 return true;
703 // Otherwise they are the same if they have the same bit number and
704 // bitmap.
705 return AtEnd == RHS.AtEnd && RHS.BitNumber == BitNumber;
706 }
707
709 {
710 return !(*this == RHS);
711 }
712 };
713
714public:
716
718
723
724 // Clear.
725 void clear()
726 {
727 Elements.clear();
728 }
729
730 // Assignment
732 {
733 if (this == &RHS)
734 return *this;
735
737 CurrElementIter = Elements.begin();
738 return *this;
739 }
741 {
742 Elements = std::move(RHS.Elements);
743 CurrElementIter = Elements.begin();
744 return *this;
745 }
746
747 // Test, Reset, and Set a bit in the bitmap.
748 bool test(unsigned Idx) const
749 {
750 if (Elements.empty())
751 return false;
752
753 unsigned ElementIndex = Idx / ElementSize;
755
756 // If we can't find an element that is supposed to contain this bit, there
757 // is nothing more to do.
758 if (ElementIter == Elements.end() ||
759 ElementIter->index() != ElementIndex)
760 {
761 return false;
762 }
763 return ElementIter->test(Idx % ElementSize);
764 }
765
766 void reset(unsigned Idx)
767 {
768 if (Elements.empty())
769 return;
770
771 unsigned ElementIndex = Idx / ElementSize;
773
774 // If we can't find an element that is supposed to contain this bit, there
775 // is nothing more to do.
776 if (ElementIter == Elements.end() ||
777 ElementIter->index() != ElementIndex)
778 return;
779 ElementIter->reset(Idx % ElementSize);
780
781 // When the element is zeroed out, delete it.
782 if (ElementIter->empty())
783 {
785 Elements.erase(ElementIter);
786 }
787 }
788
789 void set(unsigned Idx)
790 {
791 unsigned ElementIndex = Idx / ElementSize;
793 if (Elements.empty())
794 {
795 ElementIter = Elements.emplace(Elements.end(), ElementIndex);
796 }
797 else
798 {
799 ElementIter = FindLowerBound(ElementIndex);
800
801 if (ElementIter == Elements.end() ||
802 ElementIter->index() != ElementIndex)
803 {
804 // We may have hit the beginning of our SparseBitVector, in which case,
805 // we may need to insert right after this element, which requires moving
806 // the current iterator forward one, because insert does insert before.
807 if (ElementIter != Elements.end() &&
808 ElementIter->index() < ElementIndex)
809 ++ElementIter;
810 ElementIter = Elements.emplace(ElementIter, ElementIndex);
811 }
812 }
814
816 }
817
818 bool test_and_set(unsigned Idx)
819 {
820 bool old = test(Idx);
821 if (!old)
822 {
823 set(Idx);
824 return true;
825 }
826 return false;
827 }
828
829 bool operator!=(const SparseBitVector &RHS) const
830 {
831 return !(*this == RHS);
832 }
833
834 bool operator==(const SparseBitVector &RHS) const
835 {
837 ElementListConstIter Iter2 = RHS.Elements.begin();
838
839 for (; Iter1 != Elements.end() && Iter2 != RHS.Elements.end();
840 ++Iter1, ++Iter2)
841 {
842 if (*Iter1 != *Iter2)
843 return false;
844 }
845 return Iter1 == Elements.end() && Iter2 == RHS.Elements.end();
846 }
847
848 // Union our bitmap with the RHS and return true if we changed.
850 {
851 if (this == &RHS)
852 return false;
853
854 bool changed = false;
856 ElementListConstIter Iter2 = RHS.Elements.begin();
857
858 // If RHS is empty, we are done
859 if (RHS.Elements.empty())
860 return false;
861
862 while (Iter2 != RHS.Elements.end())
863 {
864 if (Iter1 == Elements.end() || Iter1->index() > Iter2->index())
865 {
866 Elements.insert(Iter1, *Iter2);
867 ++Iter2;
868 changed = true;
869 }
870 else if (Iter1->index() == Iter2->index())
871 {
872 changed |= Iter1->unionWith(*Iter2);
873 ++Iter1;
874 ++Iter2;
875 }
876 else
877 {
878 ++Iter1;
879 }
880 }
881 CurrElementIter = Elements.begin();
882 return changed;
883 }
884
885 // Intersect our bitmap with the RHS and return true if ours changed.
887 {
888 if (this == &RHS)
889 return false;
890
891 bool changed = false;
893 ElementListConstIter Iter2 = RHS.Elements.begin();
894
895 // Check if both bitmaps are empty.
896 if (Elements.empty() && RHS.Elements.empty())
897 return false;
898
899 // Loop through, intersecting as we go, erasing elements when necessary.
900 while (Iter2 != RHS.Elements.end())
901 {
902 if (Iter1 == Elements.end())
903 {
904 CurrElementIter = Elements.begin();
905 return changed;
906 }
907
908 if (Iter1->index() > Iter2->index())
909 {
910 ++Iter2;
911 }
912 else if (Iter1->index() == Iter2->index())
913 {
914 bool BecameZero;
915 changed |= Iter1->intersectWith(*Iter2, BecameZero);
916 if (BecameZero)
917 {
919 ++Iter1;
920 Elements.erase(IterTmp);
921 }
922 else
923 {
924 ++Iter1;
925 }
926 ++Iter2;
927 }
928 else
929 {
931 ++Iter1;
932 Elements.erase(IterTmp);
933 changed = true;
934 }
935 }
936 if (Iter1 != Elements.end())
937 {
938 Elements.erase(Iter1, Elements.end());
939 changed = true;
940 }
941 CurrElementIter = Elements.begin();
942 return changed;
943 }
944
945 // Intersect our bitmap with the complement of the RHS and return true
946 // if ours changed.
948 {
949 if (this == &RHS)
950 {
951 if (!empty())
952 {
953 clear();
954 return true;
955 }
956 return false;
957 }
958
959 bool changed = false;
961 ElementListConstIter Iter2 = RHS.Elements.begin();
962
963 // If either our bitmap or RHS is empty, we are done
964 if (Elements.empty() || RHS.Elements.empty())
965 return false;
966
967 // Loop through, intersecting as we go, erasing elements when necessary.
968 while (Iter2 != RHS.Elements.end())
969 {
970 if (Iter1 == Elements.end())
971 {
972 CurrElementIter = Elements.begin();
973 return changed;
974 }
975
976 if (Iter1->index() > Iter2->index())
977 {
978 ++Iter2;
979 }
980 else if (Iter1->index() == Iter2->index())
981 {
982 bool BecameZero;
983 changed |= Iter1->intersectWithComplement(*Iter2, BecameZero);
984 if (BecameZero)
985 {
987 ++Iter1;
988 Elements.erase(IterTmp);
989 }
990 else
991 {
992 ++Iter1;
993 }
994 ++Iter2;
995 }
996 else
997 {
998 ++Iter1;
999 }
1000 }
1001 CurrElementIter = Elements.begin();
1002 return changed;
1003 }
1004
1009
1010 // Three argument version of intersectWithComplement.
1011 // Result of RHS1 & ~RHS2 is stored into this bitmap.
1014 {
1015 if (this == &RHS1)
1016 {
1018 return;
1019 }
1020 else if (this == &RHS2)
1021 {
1024 return;
1025 }
1026
1027 Elements.clear();
1028 CurrElementIter = Elements.begin();
1029 ElementListConstIter Iter1 = RHS1.Elements.begin();
1030 ElementListConstIter Iter2 = RHS2.Elements.begin();
1031
1032 // If RHS1 is empty, we are done
1033 // If RHS2 is empty, we still have to copy RHS1
1034 if (RHS1.Elements.empty())
1035 return;
1036
1037 // Loop through, intersecting as we go, erasing elements when necessary.
1038 while (Iter2 != RHS2.Elements.end())
1039 {
1040 if (Iter1 == RHS1.Elements.end())
1041 return;
1042
1043 if (Iter1->index() > Iter2->index())
1044 {
1045 ++Iter2;
1046 }
1047 else if (Iter1->index() == Iter2->index())
1048 {
1049 bool BecameZero = false;
1050 Elements.emplace_back(Iter1->index());
1051 Elements.back().intersectWithComplement(*Iter1, *Iter2, BecameZero);
1052 if (BecameZero)
1053 Elements.pop_back();
1054 ++Iter1;
1055 ++Iter2;
1056 }
1057 else
1058 {
1059 Elements.push_back(*Iter1++);
1060 }
1061 }
1062
1063 // copy the remaining elements
1064 std::copy(Iter1, RHS1.Elements.end(), std::back_inserter(Elements));
1065 }
1066
1072
1074 {
1075 return intersects(*RHS);
1076 }
1077
1078 // Return true if we share any bits in common with RHS
1080 {
1082 ElementListConstIter Iter2 = RHS.Elements.begin();
1083
1084 // Check if both bitmaps are empty.
1085 if (Elements.empty() && RHS.Elements.empty())
1086 return false;
1087
1088 // Loop through, intersecting stopping when we hit bits in common.
1089 while (Iter2 != RHS.Elements.end())
1090 {
1091 if (Iter1 == Elements.end())
1092 return false;
1093
1094 if (Iter1->index() > Iter2->index())
1095 {
1096 ++Iter2;
1097 }
1098 else if (Iter1->index() == Iter2->index())
1099 {
1100 if (Iter1->intersects(*Iter2))
1101 return true;
1102 ++Iter1;
1103 ++Iter2;
1104 }
1105 else
1106 {
1107 ++Iter1;
1108 }
1109 }
1110 return false;
1111 }
1112
1113 // Return true iff all bits set in this SparseBitVector are
1114 // also set in RHS.
1116 {
1118 Result &= RHS;
1119 return (Result == RHS);
1120 }
1121
1122 // Return the first set bit in the bitmap. Return -1 if no bits are set.
1123 int find_first() const
1124 {
1125 if (Elements.empty())
1126 return -1;
1128 return (First.index() * ElementSize) + First.find_first();
1129 }
1130
1131 // Return the last set bit in the bitmap. Return -1 if no bits are set.
1132 int find_last() const
1133 {
1134 if (Elements.empty())
1135 return -1;
1137 return (Last.index() * ElementSize) + Last.find_last();
1138 }
1139
1140 // Return true if the SparseBitVector is empty
1141 bool empty() const
1142 {
1143 return Elements.empty();
1144 }
1145
1146 unsigned count() const
1147 {
1148 unsigned BitCount = 0;
1149 for (ElementListConstIter Iter = Elements.begin();
1150 Iter != Elements.end();
1151 ++Iter)
1152 BitCount += Iter->count();
1153
1154 return BitCount;
1155 }
1156
1158 {
1159 return iterator(this);
1160 }
1161
1163 {
1164 return iterator(this, true);
1165 }
1166};
1167
1168// Convenience functions to allow Or and And without dereferencing in the user
1169// code.
1170
1171template <unsigned ElementSize>
1174{
1175 return LHS |= *RHS;
1176}
1177
1178template <unsigned ElementSize>
1181{
1182 return LHS->operator|=(RHS);
1183}
1184
1185template <unsigned ElementSize>
1188{
1189 return LHS->operator&=(RHS);
1190}
1191
1192template <unsigned ElementSize>
1195{
1196 return LHS &= *RHS;
1197}
1198
1199// Convenience functions for infix union, intersection, difference operators.
1200
1201template <unsigned ElementSize>
1202inline SparseBitVector<ElementSize>
1210
1211template <unsigned ElementSize>
1212inline SparseBitVector<ElementSize>
1220
1221template <unsigned ElementSize>
1222inline SparseBitVector<ElementSize>
1225{
1227 Result.intersectWithComplement(LHS, RHS);
1228 return Result;
1229}
1230
1231// Dump a SparseBitVector to a stream
1232template <unsigned ElementSize>
1233void dump(const SparseBitVector<ElementSize> &LHS, std::ostream &out)
1234{
1235 out << "[";
1236
1238 be = LHS.end();
1239 if (bi != be)
1240 {
1241 out << *bi;
1242 for (++bi; bi != be; ++bi)
1243 {
1244 out << " " << *bi;
1245 }
1246 }
1247 out << "]\n";
1248}
1249
1250} // End namespace SVF
1251
1252#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:70
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:86
llvm::IRBuilder IRBuilder
Definition BasicTypes.h:76
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)