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 friend class SVFIRWriter;
262 friend class SVFIRReader;
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 friend class SVFIRWriter;
504 friend class SVFIRReader;
505
506 using ElementList = std::list<SparseBitVectorElement<ElementSize>>;
507 using ElementListIter = typename ElementList::iterator;
508 using ElementListConstIter = typename ElementList::const_iterator;
509 enum
510 {
512 };
513
515 // Pointer to our current Element. This has no visible effect on the external
516 // state of a SparseBitVector, it's just used to improve performance in the
517 // common case of testing/modifying bits with similar indices.
519
520 // This is like std::lower_bound, except we do linear searching from the
521 // current position.
522 ElementListIter FindLowerBoundImpl(unsigned ElementIndex) const
523 {
524
525 // We cache a non-const iterator so we're forced to resort to const_cast to
526 // get the begin/end in the case where 'this' is const. To avoid duplication
527 // of code with the only difference being whether the const cast is present
528 // 'this' is always const in this particular function and we sort out the
529 // difference in FindLowerBound and FindLowerBoundConst.
531 const_cast<SparseBitVector<ElementSize> *>(this)->Elements.begin();
533 const_cast<SparseBitVector<ElementSize> *>(this)->Elements.end();
534
535 if (Elements.empty())
536 {
538 return CurrElementIter;
539 }
540
541 // Make sure our current iterator is valid.
542 if (CurrElementIter == End)
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 return false;
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: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)