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#include "Util/Hash.h"
20
21// Appease GCC?
22#ifdef __has_builtin
23# define HAS_CLZ __has_builtin(__builtin_clz)
24# define HAS_CLZLL __has_builtin(__builtin_clzll)
25# define HAS_CTZ __has_builtin(__builtin_ctz)
26# define HAS_CTZLL __has_builtin(__builtin_ctzll)
27#else
28# define HAS_CLZ 0
29# define HAS_CLZLL 0
30# define HAS_CLZ 0
31# define HAS_CLZLL 0
32#endif
33
34namespace SVF
35{
36
47
48template <typename T, std::size_t SizeOfT> struct TrailingZerosCounter
49{
50 static unsigned count(T Val, ZeroBehavior)
51 {
52 if (!Val)
53 return std::numeric_limits<T>::digits;
54 if (Val & 0x1)
55 return 0;
56
57 // Bisection method.
58 unsigned ZeroBits = 0;
59 T Shift = std::numeric_limits<T>::digits >> 1;
60 T Mask = std::numeric_limits<T>::max() >> Shift;
61 while (Shift)
62 {
63 if ((Val & Mask) == 0)
64 {
65 Val >>= Shift;
66 ZeroBits |= Shift;
67 }
68 Shift >>= 1;
69 Mask >>= Shift;
70 }
71 return ZeroBits;
72 }
73};
74
75#if defined(__GNUC__) || defined(_MSC_VER)
76template <typename T> struct TrailingZerosCounter<T, 4>
77{
78 static unsigned count(T Val, ZeroBehavior)
79 {
80 if (Val == 0)
81 return 32;
82
83#if HAS_CTZ || defined(__GNUC__)
84 return __builtin_ctz(Val);
85#elif defined(_MSC_VER)
86 unsigned long Index;
88 return Index;
89#endif
90 }
91};
92
93#if !defined(_MSC_VER) || defined(_M_X64)
94template <typename T> struct TrailingZerosCounter<T, 8>
95{
96 static unsigned count(T Val, ZeroBehavior)
97 {
98 if (Val == 0)
99 return 64;
100
101#if HAS_CTZLL || defined(__GNUC__)
102 return __builtin_ctzll(Val);
103#elif defined(_MSC_VER)
104 unsigned long Index;
106 return Index;
107#endif
108 }
109};
110#endif
111#endif
112
120template <typename T>
122{
123 static_assert(std::numeric_limits<T>::is_integer &&
124 !std::numeric_limits<T>::is_signed,
125 "Only unsigned integral types are allowed.");
126 return TrailingZerosCounter<T, sizeof(T)>::count(Val, ZB);
127}
128
129template <typename T, std::size_t SizeOfT> struct PopulationCounter
130{
131 static unsigned count(T Value)
132 {
133 // Generic version, forward to 32 bits.
134 static_assert(SizeOfT <= 4, "Not implemented!");
135#if defined(__GNUC__)
137#else
138 uint32_t v = Value;
139 v = v - ((v >> 1) & 0x55555555);
140 v = (v & 0x33333333) + ((v >> 2) & 0x33333333);
141 return ((v + (v >> 4) & 0xF0F0F0F) * 0x1010101) >> 24;
142#endif
143 }
144};
145
146template <typename T, std::size_t SizeOfT> struct LeadingZerosCounter
147{
148 static unsigned count(T Val, ZeroBehavior)
149 {
150 if (!Val)
151 return std::numeric_limits<T>::digits;
152
153 // Bisection method.
154 unsigned ZeroBits = 0;
155 for (T Shift = std::numeric_limits<T>::digits >> 1; Shift; Shift >>= 1)
156 {
157 T Tmp = Val >> Shift;
158 if (Tmp)
159 Val = Tmp;
160 else
161 ZeroBits |= Shift;
162 }
163 return ZeroBits;
164 }
165};
166
167#if defined(__GNUC__) || defined(_MSC_VER)
168template <typename T> struct LeadingZerosCounter<T, 4>
169{
170 static unsigned count(T Val, ZeroBehavior ZB)
171 {
172 if (ZB != ZB_Undefined && Val == 0)
173 return 32;
174
175#if defined(__GNUC__) || HAS_CLZ
176 return __builtin_clz(Val);
177#elif defined(_MSC_VER)
178 unsigned long Index;
180 return Index ^ 31;
181#endif
182 }
183};
184
185#if !defined(_MSC_VER) || defined(_M_X64)
186template <typename T> struct LeadingZerosCounter<T, 8>
187{
188 static unsigned count(T Val, ZeroBehavior ZB)
189 {
190 if (ZB != ZB_Undefined && Val == 0)
191 return 64;
192
193#if defined(__GNUC__) || HAS_CLZLL
194 return __builtin_clzll(Val);
195#elif defined(_MSC_VER)
196 unsigned long Index;
198 return Index ^ 63;
199#endif
200 }
201};
202#endif
203#endif
204
212template <typename T>
214{
215 static_assert(std::numeric_limits<T>::is_integer &&
216 !std::numeric_limits<T>::is_signed,
217 "Only unsigned integral types are allowed.");
218 return LeadingZerosCounter<T, sizeof(T)>::count(Val, ZB);
219}
220
221template <typename T> struct PopulationCounter<T, 8>
222{
223 static unsigned count(T Value)
224 {
225#if defined(__GNUC__)
227#else
228 uint64_t v = Value;
229 v = v - ((v >> 1) & 0x5555555555555555ULL);
230 v = (v & 0x3333333333333333ULL) + ((v >> 2) & 0x3333333333333333ULL);
231 v = (v + (v >> 4)) & 0x0F0F0F0F0F0F0F0FULL;
232 return unsigned((uint64_t)(v * 0x0101010101010101ULL) >> 56);
233#endif
234 }
235};
236
240template <typename T>
241inline unsigned countPopulation(T Value)
242{
243 static_assert(std::numeric_limits<T>::is_integer &&
244 !std::numeric_limits<T>::is_signed,
245 "Only unsigned integral types are allowed.");
246 return PopulationCounter<T, sizeof(T)>::count(Value);
247}
248
261template <unsigned ElementSize = 128> struct SparseBitVectorElement
262{
263
264public:
265 using BitWord = unsigned long;
267 enum
268 {
270 // N.B. (+ BITWORD_SIZE - 1) is to round up, to ensure we can have
271 // sufficient bits to represent *at least* ElementSize bits.
274 };
275
276private:
277 // Index of Element in terms of where first bit starts.
278 unsigned ElementIndex = 0;
280
282
283public:
285
286 // Comparison.
288 {
289 if (ElementIndex != RHS.ElementIndex)
290 return false;
291 for (unsigned i = 0; i < BITWORDS_PER_ELEMENT; ++i)
292 if (Bits[i] != RHS.Bits[i])
293 return false;
294 return true;
295 }
296
298 {
299 return !(*this == RHS);
300 }
301
302 // Return the bits that make up word Idx in our element.
303 BitWord word(unsigned Idx) const
304 {
306 return Bits[Idx];
307 }
308
309 unsigned index() const
310 {
311 return ElementIndex;
312 }
313
314 bool empty() const
315 {
316 for (unsigned i = 0; i < BITWORDS_PER_ELEMENT; ++i)
317 if (Bits[i])
318 return false;
319 return true;
320 }
321
322 void set(unsigned Idx)
323 {
324 Bits[Idx / BITWORD_SIZE] |= 1L << (Idx % BITWORD_SIZE);
325 }
326
327 bool test_and_set(unsigned Idx)
328 {
329 bool old = test(Idx);
330 if (!old)
331 {
332 set(Idx);
333 return true;
334 }
335 return false;
336 }
337
338 void reset(unsigned Idx)
339 {
340 Bits[Idx / BITWORD_SIZE] &= ~(1L << (Idx % BITWORD_SIZE));
341 }
342
343 bool test(unsigned Idx) const
344 {
345 return Bits[Idx / BITWORD_SIZE] & (1L << (Idx % BITWORD_SIZE));
346 }
347
349 {
350 unsigned NumBits = 0;
351 for (unsigned i = 0; i < BITWORDS_PER_ELEMENT; ++i)
353 return NumBits;
354 }
355
357 int find_first() const
358 {
359 for (unsigned i = 0; i < BITWORDS_PER_ELEMENT; ++i)
360 if (Bits[i] != 0)
362 assert(false && "SBV: find_first: SBV cannot be empty");
363 abort();
364 }
365
367 int find_last() const
368 {
369 for (unsigned I = 0; I < BITWORDS_PER_ELEMENT; ++I)
370 {
371 unsigned Idx = BITWORDS_PER_ELEMENT - I - 1;
372 if (Bits[Idx] != 0)
373 return Idx * BITWORD_SIZE + BITWORD_SIZE -
375 }
376 assert(false && "SBV: find_last: SBV cannot be empty");
377 abort();
378 }
379
382 int find_next(unsigned Curr) const
383 {
384 if (Curr >= BITS_PER_ELEMENT)
385 return -1;
386
387 unsigned WordPos = Curr / BITWORD_SIZE;
388 unsigned BitPos = Curr % BITWORD_SIZE;
389 BitWord Copy = Bits[WordPos];
391 && "Word Position outside of element");
392
393 // Mask off previous bits.
394 Copy &= ~0UL << BitPos;
395
396 if (Copy != 0)
397 return WordPos * BITWORD_SIZE + countTrailingZeros(Copy);
398
399 // Check subsequent words.
400 for (unsigned i = WordPos+1; i < BITWORDS_PER_ELEMENT; ++i)
401 if (Bits[i] != 0)
403 return -1;
404 }
405
406 // Union this element with RHS and return true if this one changed.
408 {
409 bool changed = false;
410 for (unsigned i = 0; i < BITWORDS_PER_ELEMENT; ++i)
411 {
412 BitWord old = changed ? 0 : Bits[i];
413
414 Bits[i] |= RHS.Bits[i];
415 if (!changed && old != Bits[i])
416 changed = true;
417 }
418 return changed;
419 }
420
421 // Return true if we have any bits in common with RHS
423 {
424 for (unsigned i = 0; i < BITWORDS_PER_ELEMENT; ++i)
425 {
426 if (RHS.Bits[i] & Bits[i])
427 return true;
428 }
429 return false;
430 }
431
432 // Intersect this Element with RHS and return true if this one changed.
433 // BecameZero is set to true if this element became all-zero bits.
435 bool &BecameZero)
436 {
437 bool changed = false;
438 bool allzero = true;
439
440 BecameZero = false;
441 for (unsigned i = 0; i < BITWORDS_PER_ELEMENT; ++i)
442 {
443 BitWord old = changed ? 0 : Bits[i];
444
445 Bits[i] &= RHS.Bits[i];
446 if (Bits[i] != 0)
447 allzero = false;
448
449 if (!changed && old != Bits[i])
450 changed = true;
451 }
453 return changed;
454 }
455
456 // Intersect this Element with the complement of RHS and return true if this
457 // one changed. BecameZero is set to true if this element became all-zero
458 // bits.
460 bool &BecameZero)
461 {
462 bool changed = false;
463 bool allzero = true;
464
465 BecameZero = false;
466 for (unsigned i = 0; i < BITWORDS_PER_ELEMENT; ++i)
467 {
468 BitWord old = changed ? 0 : Bits[i];
469
470 Bits[i] &= ~RHS.Bits[i];
471 if (Bits[i] != 0)
472 allzero = false;
473
474 if (!changed && old != Bits[i])
475 changed = true;
476 }
478 return changed;
479 }
480
481 // Three argument version of intersectWithComplement that intersects
482 // RHS1 & ~RHS2 into this element
485 bool &BecameZero)
486 {
487 bool allzero = true;
488
489 BecameZero = false;
490 for (unsigned i = 0; i < BITWORDS_PER_ELEMENT; ++i)
491 {
492 Bits[i] = RHS1.Bits[i] & ~RHS2.Bits[i];
493 if (Bits[i] != 0)
494 allzero = false;
495 }
497 }
498};
499
500template <unsigned ElementSize = 128>
502{
503
504 using ElementList = std::list<SparseBitVectorElement<ElementSize>>;
505 using ElementListIter = typename ElementList::iterator;
506 using ElementListConstIter = typename ElementList::const_iterator;
507 enum
508 {
510 };
511
513 // Pointer to our current Element. This has no visible effect on the external
514 // state of a SparseBitVector, it's just used to improve performance in the
515 // common case of testing/modifying bits with similar indices.
517
518 // This is like std::lower_bound, except we do linear searching from the
519 // current position.
520 ElementListIter FindLowerBoundImpl(unsigned ElementIndex) const
521 {
522
523 // We cache a non-const iterator so we're forced to resort to const_cast to
524 // get the begin/end in the case where 'this' is const. To avoid duplication
525 // of code with the only difference being whether the const cast is present
526 // 'this' is always const in this particular function and we sort out the
527 // difference in FindLowerBound and FindLowerBoundConst.
529 const_cast<SparseBitVector<ElementSize> *>(this)->Elements.begin();
531 const_cast<SparseBitVector<ElementSize> *>(this)->Elements.end();
532
533 if (Elements.empty())
534 {
536 return CurrElementIter;
537 }
538
539 // Make sure our current iterator is valid.
540 if (CurrElementIter == End)
541 {
543 }
544
545 // Search from our current iterator, either backwards or forwards,
546 // depending on what element we are looking for.
548 if (CurrElementIter->index() == ElementIndex)
549 {
550 return ElementIter;
551 }
552 else if (CurrElementIter->index() > ElementIndex)
553 {
554 while (ElementIter != Begin
555 && ElementIter->index() > ElementIndex)
556 --ElementIter;
557 }
558 else
559 {
560 while (ElementIter != End &&
561 ElementIter->index() < ElementIndex)
562 ++ElementIter;
563 }
565 return ElementIter;
566 }
567 ElementListConstIter FindLowerBoundConst(unsigned ElementIndex) const
568 {
569 return FindLowerBoundImpl(ElementIndex);
570 }
571 ElementListIter FindLowerBound(unsigned ElementIndex)
572 {
573 return FindLowerBoundImpl(ElementIndex);
574 }
575
576 // Iterator to walk set bits in the bitmap. This iterator is a lot uglier
577 // than it would be, in order to be efficient.
579 {
580 private:
581 bool AtEnd;
582
584
585 // Current element inside of bitmap.
587
588 // Current bit number inside of our bitmap.
589 unsigned BitNumber;
590
591 // Current word number inside of our element.
592 unsigned WordNumber;
593
594 // Current bits from the element.
596
597 // Move our iterator to the first non-zero bit in the bitmap.
599 {
600 if (AtEnd)
601 return;
602 if (BitVector->Elements.empty())
603 {
604 AtEnd = true;
605 return;
606 }
607 Iter = BitVector->Elements.begin();
608 BitNumber = Iter->index() * ElementSize;
609 unsigned BitPos = Iter->find_first();
610 BitNumber += BitPos;
614 }
615
616 // Move our iterator to the next non-zero bit.
618 {
619 if (AtEnd)
620 return;
621
622 while (Bits && !(Bits & 1))
623 {
624 Bits >>= 1;
625 BitNumber += 1;
626 }
627
628 // See if we ran out of Bits in this word.
629 if (!Bits)
630 {
632 // If we ran out of set bits in this element, move to next element.
633 if (NextSetBitNumber == -1 || (BitNumber % ElementSize == 0))
634 {
635 ++Iter;
636 WordNumber = 0;
637
638 // We may run out of elements in the bitmap.
639 if (Iter == BitVector->Elements.end())
640 {
641 AtEnd = true;
642 return;
643 }
644 // Set up for next non-zero word in bitmap.
645 BitNumber = Iter->index() * ElementSize;
646 NextSetBitNumber = Iter->find_first();
651 }
652 else
653 {
659 }
660 }
661 }
662
663 public:
665
667 bool end = false):BitVector(RHS)
668 {
669 Iter = BitVector->Elements.begin();
670 BitNumber = 0;
671 Bits = 0;
672 WordNumber = ~0;
673 AtEnd = end;
675 }
676
677 // Preincrement.
679 {
680 ++BitNumber;
681 Bits >>= 1;
683 return *this;
684 }
685
686 // Postincrement.
688 {
690 ++*this;
691 return tmp;
692 }
693
694 // Return the current set bit number.
695 unsigned operator*() const
696 {
697 return BitNumber;
698 }
699
701 {
702 // If they are both at the end, ignore the rest of the fields.
703 if (AtEnd && RHS.AtEnd)
704 return true;
705 // Otherwise they are the same if they have the same bit number and
706 // bitmap.
707 return AtEnd == RHS.AtEnd && RHS.BitNumber == BitNumber;
708 }
709
711 {
712 return !(*this == RHS);
713 }
714 };
715
716public:
718
720
725
726 // Clear.
727 void clear()
728 {
729 Elements.clear();
730 }
731
732 // Assignment
734 {
735 if (this == &RHS)
736 return *this;
737
739 CurrElementIter = Elements.begin();
740 return *this;
741 }
743 {
744 Elements = std::move(RHS.Elements);
745 CurrElementIter = Elements.begin();
746 return *this;
747 }
748
749 // Test, Reset, and Set a bit in the bitmap.
750 bool test(unsigned Idx) const
751 {
752 if (Elements.empty())
753 return false;
754
755 unsigned ElementIndex = Idx / ElementSize;
757
758 // If we can't find an element that is supposed to contain this bit, there
759 // is nothing more to do.
760 if (ElementIter == Elements.end() ||
761 ElementIter->index() != ElementIndex)
762 {
763 return false;
764 }
765 return ElementIter->test(Idx % ElementSize);
766 }
767
768 void reset(unsigned Idx)
769 {
770 if (Elements.empty())
771 return;
772
773 unsigned ElementIndex = Idx / ElementSize;
775
776 // If we can't find an element that is supposed to contain this bit, there
777 // is nothing more to do.
778 if (ElementIter == Elements.end() ||
779 ElementIter->index() != ElementIndex)
780 return;
781 ElementIter->reset(Idx % ElementSize);
782
783 // When the element is zeroed out, delete it.
784 if (ElementIter->empty())
785 {
787 Elements.erase(ElementIter);
788 }
789 }
790
791 void set(unsigned Idx)
792 {
793 unsigned ElementIndex = Idx / ElementSize;
795 if (Elements.empty())
796 {
797 ElementIter = Elements.emplace(Elements.end(), ElementIndex);
798 }
799 else
800 {
801 ElementIter = FindLowerBound(ElementIndex);
802
803 if (ElementIter == Elements.end() ||
804 ElementIter->index() != ElementIndex)
805 {
806 // We may have hit the beginning of our SparseBitVector, in which case,
807 // we may need to insert right after this element, which requires moving
808 // the current iterator forward one, because insert does insert before.
809 if (ElementIter != Elements.end() &&
810 ElementIter->index() < ElementIndex)
811 ++ElementIter;
812 ElementIter = Elements.emplace(ElementIter, ElementIndex);
813 }
814 }
816
818 }
819
820 bool test_and_set(unsigned Idx)
821 {
822 bool old = test(Idx);
823 if (!old)
824 {
825 set(Idx);
826 return true;
827 }
828 return false;
829 }
830
831 bool operator!=(const SparseBitVector &RHS) const
832 {
833 return !(*this == RHS);
834 }
835
836 bool operator==(const SparseBitVector &RHS) const
837 {
839 ElementListConstIter Iter2 = RHS.Elements.begin();
840
841 for (; Iter1 != Elements.end() && Iter2 != RHS.Elements.end();
842 ++Iter1, ++Iter2)
843 {
844 if (*Iter1 != *Iter2)
845 return false;
846 }
847 return Iter1 == Elements.end() && Iter2 == RHS.Elements.end();
848 }
849
850 // Union our bitmap with the RHS and return true if we changed.
852 {
853 if (this == &RHS)
854 return false;
855
856 bool changed = false;
858 ElementListConstIter Iter2 = RHS.Elements.begin();
859
860 // If RHS is empty, we are done
861 if (RHS.Elements.empty())
862 return false;
863
864 while (Iter2 != RHS.Elements.end())
865 {
866 if (Iter1 == Elements.end() || Iter1->index() > Iter2->index())
867 {
868 Elements.insert(Iter1, *Iter2);
869 ++Iter2;
870 changed = true;
871 }
872 else if (Iter1->index() == Iter2->index())
873 {
874 changed |= Iter1->unionWith(*Iter2);
875 ++Iter1;
876 ++Iter2;
877 }
878 else
879 {
880 ++Iter1;
881 }
882 }
883 CurrElementIter = Elements.begin();
884 return changed;
885 }
886
887 // Intersect our bitmap with the RHS and return true if ours changed.
889 {
890 if (this == &RHS)
891 return false;
892
893 bool changed = false;
895 ElementListConstIter Iter2 = RHS.Elements.begin();
896
897 // Check if both bitmaps are empty.
898 if (Elements.empty() && RHS.Elements.empty())
899 return false;
900
901 // Loop through, intersecting as we go, erasing elements when necessary.
902 while (Iter2 != RHS.Elements.end())
903 {
904 if (Iter1 == Elements.end())
905 {
906 CurrElementIter = Elements.begin();
907 return changed;
908 }
909
910 if (Iter1->index() > Iter2->index())
911 {
912 ++Iter2;
913 }
914 else if (Iter1->index() == Iter2->index())
915 {
916 bool BecameZero;
917 changed |= Iter1->intersectWith(*Iter2, BecameZero);
918 if (BecameZero)
919 {
921 ++Iter1;
922 Elements.erase(IterTmp);
923 }
924 else
925 {
926 ++Iter1;
927 }
928 ++Iter2;
929 }
930 else
931 {
933 ++Iter1;
934 Elements.erase(IterTmp);
935 changed = true;
936 }
937 }
938 if (Iter1 != Elements.end())
939 {
940 Elements.erase(Iter1, Elements.end());
941 changed = true;
942 }
943 CurrElementIter = Elements.begin();
944 return changed;
945 }
946
947 // Intersect our bitmap with the complement of the RHS and return true
948 // if ours changed.
950 {
951 if (this == &RHS)
952 {
953 if (!empty())
954 {
955 clear();
956 return true;
957 }
958 return false;
959 }
960
961 bool changed = false;
963 ElementListConstIter Iter2 = RHS.Elements.begin();
964
965 // If either our bitmap or RHS is empty, we are done
966 if (Elements.empty() || RHS.Elements.empty())
967 return false;
968
969 // Loop through, intersecting as we go, erasing elements when necessary.
970 while (Iter2 != RHS.Elements.end())
971 {
972 if (Iter1 == Elements.end())
973 {
974 CurrElementIter = Elements.begin();
975 return changed;
976 }
977
978 if (Iter1->index() > Iter2->index())
979 {
980 ++Iter2;
981 }
982 else if (Iter1->index() == Iter2->index())
983 {
984 bool BecameZero;
985 changed |= Iter1->intersectWithComplement(*Iter2, BecameZero);
986 if (BecameZero)
987 {
989 ++Iter1;
990 Elements.erase(IterTmp);
991 }
992 else
993 {
994 ++Iter1;
995 }
996 ++Iter2;
997 }
998 else
999 {
1000 ++Iter1;
1001 }
1002 }
1003 CurrElementIter = Elements.begin();
1004 return changed;
1005 }
1006
1011
1012 // Three argument version of intersectWithComplement.
1013 // Result of RHS1 & ~RHS2 is stored into this bitmap.
1016 {
1017 if (this == &RHS1)
1018 {
1020 return;
1021 }
1022 else if (this == &RHS2)
1023 {
1026 return;
1027 }
1028
1029 Elements.clear();
1030 CurrElementIter = Elements.begin();
1031 ElementListConstIter Iter1 = RHS1.Elements.begin();
1032 ElementListConstIter Iter2 = RHS2.Elements.begin();
1033
1034 // If RHS1 is empty, we are done
1035 // If RHS2 is empty, we still have to copy RHS1
1036 if (RHS1.Elements.empty())
1037 return;
1038
1039 // Loop through, intersecting as we go, erasing elements when necessary.
1040 while (Iter2 != RHS2.Elements.end())
1041 {
1042 if (Iter1 == RHS1.Elements.end())
1043 return;
1044
1045 if (Iter1->index() > Iter2->index())
1046 {
1047 ++Iter2;
1048 }
1049 else if (Iter1->index() == Iter2->index())
1050 {
1051 bool BecameZero = false;
1052 Elements.emplace_back(Iter1->index());
1053 Elements.back().intersectWithComplement(*Iter1, *Iter2, BecameZero);
1054 if (BecameZero)
1055 Elements.pop_back();
1056 ++Iter1;
1057 ++Iter2;
1058 }
1059 else
1060 {
1061 Elements.push_back(*Iter1++);
1062 }
1063 }
1064
1065 // copy the remaining elements
1066 std::copy(Iter1, RHS1.Elements.end(), std::back_inserter(Elements));
1067 }
1068
1074
1076 {
1077 return intersects(*RHS);
1078 }
1079
1080 // Return true if we share any bits in common with RHS
1082 {
1084 ElementListConstIter Iter2 = RHS.Elements.begin();
1085
1086 // Check if both bitmaps are empty.
1087 if (Elements.empty() && RHS.Elements.empty())
1088 return false;
1089
1090 // Loop through, intersecting stopping when we hit bits in common.
1091 while (Iter2 != RHS.Elements.end())
1092 {
1093 if (Iter1 == Elements.end())
1094 return false;
1095
1096 if (Iter1->index() > Iter2->index())
1097 {
1098 ++Iter2;
1099 }
1100 else if (Iter1->index() == Iter2->index())
1101 {
1102 if (Iter1->intersects(*Iter2))
1103 return true;
1104 ++Iter1;
1105 ++Iter2;
1106 }
1107 else
1108 {
1109 ++Iter1;
1110 }
1111 }
1112 return false;
1113 }
1114
1115 // Return true iff all bits set in this SparseBitVector are
1116 // also set in RHS.
1118 {
1120 Result &= RHS;
1121 return (Result == RHS);
1122 }
1123
1124 // Return the first set bit in the bitmap. Return -1 if no bits are set.
1125 int find_first() const
1126 {
1127 if (Elements.empty())
1128 return -1;
1130 return (First.index() * ElementSize) + First.find_first();
1131 }
1132
1133 // Return the last set bit in the bitmap. Return -1 if no bits are set.
1134 int find_last() const
1135 {
1136 if (Elements.empty())
1137 return -1;
1139 return (Last.index() * ElementSize) + Last.find_last();
1140 }
1141
1142 // Return true if the SparseBitVector is empty
1143 bool empty() const
1144 {
1145 return Elements.empty();
1146 }
1147
1148 unsigned count() const
1149 {
1150 unsigned BitCount = 0;
1151 for (ElementListConstIter Iter = Elements.begin();
1152 Iter != Elements.end();
1153 ++Iter)
1154 BitCount += Iter->count();
1155
1156 return BitCount;
1157 }
1158
1160 {
1161 return iterator(this);
1162 }
1163
1165 {
1166 return iterator(this, true);
1167 }
1168};
1169
1170// Convenience functions to allow Or and And without dereferencing in the user
1171// code.
1172
1173template <unsigned ElementSize>
1176{
1177 return LHS |= *RHS;
1178}
1179
1180template <unsigned ElementSize>
1183{
1184 return LHS->operator|=(RHS);
1185}
1186
1187template <unsigned ElementSize>
1190{
1191 return LHS->operator&=(RHS);
1192}
1193
1194template <unsigned ElementSize>
1197{
1198 return LHS &= *RHS;
1199}
1200
1201// Convenience functions for infix union, intersection, difference operators.
1202
1203template <unsigned ElementSize>
1204inline SparseBitVector<ElementSize>
1212
1213template <unsigned ElementSize>
1214inline SparseBitVector<ElementSize>
1222
1223template <unsigned ElementSize>
1224inline SparseBitVector<ElementSize>
1227{
1229 Result.intersectWithComplement(LHS, RHS);
1230 return Result;
1231}
1232
1233// Dump a SparseBitVector to a stream
1234template <unsigned ElementSize>
1235void dump(const SparseBitVector<ElementSize> &LHS, std::ostream &out)
1236{
1237 out << "[";
1238
1240 be = LHS.end();
1241 if (bi != be)
1242 {
1243 out << *bi;
1244 for (++bi; bi != be; ++bi)
1245 {
1246 out << " " << *bi;
1247 }
1248 }
1249 out << "]\n";
1250}
1251
1252} // End namespace SVF
1253
1255template <unsigned N> struct std::hash<SVF::SparseBitVector<N>>
1256{
1257 size_t operator()(const SVF::SparseBitVector<N>& sbv) const
1258 {
1260 return h(std::make_pair(std::make_pair(sbv.count(), sbv.find_first()),
1261 sbv.find_last()));
1262 }
1263};
1264
1265#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)
size_t operator()(const SVF::SparseBitVector< N > &sbv) const