Static Value-Flow Analysis
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 
32 namespace SVF
33 {
34 
37 {
43  ZB_Width
44 };
45 
46 template <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)
74 template <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;
85  _BitScanForward(&Index, Val);
86  return Index;
87 #endif
88  }
89 };
90 
91 #if !defined(_MSC_VER) || defined(_M_X64)
92 template <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;
103  _BitScanForward64(&Index, Val);
104  return Index;
105 #endif
106  }
107 };
108 #endif
109 #endif
110 
118 template <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 
127 template <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__)
134  return __builtin_popcount(Value);
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 
144 template <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)
166 template <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;
177  _BitScanReverse(&Index, Val);
178  return Index ^ 31;
179 #endif
180  }
181 };
182 
183 #if !defined(_MSC_VER) || defined(_M_X64)
184 template <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;
195  _BitScanReverse64(&Index, Val);
196  return Index ^ 63;
197 #endif
198  }
199 };
200 #endif
201 #endif
202 
210 template <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 
219 template <typename T> struct PopulationCounter<T, 8>
220 {
221  static unsigned count(T Value)
222  {
223 #if defined(__GNUC__)
224  return __builtin_popcountll(Value);
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 
238 template <typename T>
239 inline 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 
259 template <unsigned ElementSize = 128> struct SparseBitVectorElement
260 {
261  friend class SVFIRWriter;
262  friend class SVFIRReader;
263 
264 public:
265  using BitWord = unsigned long;
266  using size_type = unsigned;
267  enum
268  {
269  BITWORD_SIZE = sizeof(BitWord) * CHAR_BIT,
270  // N.B. (+ BITWORD_SIZE - 1) is to round up, to ensure we can have
271  // sufficient bits to represent *at least* ElementSize bits.
273  BITS_PER_ELEMENT = ElementSize
274  };
275 
276 private:
277  // Index of Element in terms of where first bit starts.
278  unsigned ElementIndex = 0;
280 
282 
283 public:
284  explicit SparseBitVectorElement(unsigned Idx) : ElementIndex(Idx) {}
285 
286  // Comparison.
287  bool operator==(const SparseBitVectorElement &RHS) const
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 
297  bool operator!=(const SparseBitVectorElement &RHS) const
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  {
305  assert(Idx < BITWORDS_PER_ELEMENT);
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 
348  size_type count() const
349  {
350  unsigned NumBits = 0;
351  for (unsigned i = 0; i < BITWORDS_PER_ELEMENT; ++i)
352  NumBits += countPopulation(Bits[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)
361  return i * BITWORD_SIZE + countTrailingZeros(Bits[i]);
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 -
374  countLeadingZeros(Bits[Idx]) - 1;
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];
390  assert(WordPos <= BITWORDS_PER_ELEMENT
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)
402  return i * BITWORD_SIZE + countTrailingZeros(Bits[i]);
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
422  bool intersects(const SparseBitVectorElement &RHS) const
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  }
452  BecameZero = allzero;
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  }
477  BecameZero = allzero;
478  return changed;
479  }
480 
481  // Three argument version of intersectWithComplement that intersects
482  // RHS1 & ~RHS2 into this element
484  const SparseBitVectorElement &RHS2,
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  }
496  BecameZero = allzero;
497  }
498 };
499 
500 template <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.
530  ElementListIter Begin =
531  const_cast<SparseBitVector<ElementSize> *>(this)->Elements.begin();
532  ElementListIter End =
533  const_cast<SparseBitVector<ElementSize> *>(this)->Elements.end();
534 
535  if (Elements.empty())
536  {
537  CurrElementIter = Begin;
538  return CurrElementIter;
539  }
540 
541  // Make sure our current iterator is valid.
542  if (CurrElementIter == End)
543  --CurrElementIter;
544 
545  // Search from our current iterator, either backwards or forwards,
546  // depending on what element we are looking for.
547  ElementListIter ElementIter = CurrElementIter;
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  }
564  CurrElementIter = ElementIter;
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;
611  WordNumber = (BitNumber % ElementSize) / BITWORD_SIZE;
612  Bits = Iter->word(WordNumber);
613  Bits >>= BitPos % BITWORD_SIZE;
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  {
631  int NextSetBitNumber = Iter->find_next(BitNumber % ElementSize) ;
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();
647  BitNumber += NextSetBitNumber;
648  WordNumber = (BitNumber % ElementSize) / BITWORD_SIZE;
649  Bits = Iter->word(WordNumber);
650  Bits >>= NextSetBitNumber % BITWORD_SIZE;
651  }
652  else
653  {
654  WordNumber = (NextSetBitNumber % ElementSize) / BITWORD_SIZE;
655  Bits = Iter->word(WordNumber);
656  Bits >>= NextSetBitNumber % BITWORD_SIZE;
657  BitNumber = Iter->index() * ElementSize;
658  BitNumber += NextSetBitNumber;
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  {
689  SparseBitVectorIterator tmp = *this;
690  ++*this;
691  return tmp;
692  }
693 
694  // Return the current set bit number.
695  unsigned operator*() const
696  {
697  return BitNumber;
698  }
699 
700  bool operator==(const SparseBitVectorIterator &RHS) const
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 
710  bool operator!=(const SparseBitVectorIterator &RHS) const
711  {
712  return !(*this == RHS);
713  }
714  };
715 
716 public:
718 
720 
724  noexcept : Elements(std::move(RHS.Elements)), CurrElementIter(Elements.begin()) {}
725 
726  // Clear.
727  void clear()
728  {
729  Elements.clear();
730  }
731 
732  // Assignment
734  {
735  if (this == &RHS)
736  return *this;
737 
738  Elements = RHS.Elements;
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;
756  ElementListConstIter ElementIter = FindLowerBoundConst(ElementIndex);
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;
772  ElementListIter ElementIter = FindLowerBound(ElementIndex);
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  {
784  ++CurrElementIter;
785  Elements.erase(ElementIter);
786  }
787  }
788 
789  void set(unsigned Idx)
790  {
791  unsigned ElementIndex = Idx / ElementSize;
792  ElementListIter ElementIter;
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  }
813  CurrElementIter = ElementIter;
814 
815  ElementIter->set(Idx % ElementSize);
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  {
836  ElementListConstIter Iter1 = Elements.begin();
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.
849  bool operator|=(const SparseBitVector &RHS)
850  {
851  if (this == &RHS)
852  return false;
853 
854  bool changed = false;
855  ElementListIter Iter1 = Elements.begin();
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.
886  bool operator&=(const SparseBitVector &RHS)
887  {
888  if (this == &RHS)
889  return false;
890 
891  bool changed = false;
892  ElementListIter Iter1 = Elements.begin();
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  {
918  ElementListIter IterTmp = Iter1;
919  ++Iter1;
920  Elements.erase(IterTmp);
921  }
922  else
923  {
924  ++Iter1;
925  }
926  ++Iter2;
927  }
928  else
929  {
930  ElementListIter IterTmp = Iter1;
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;
960  ElementListIter Iter1 = Elements.begin();
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  {
986  ElementListIter IterTmp = Iter1;
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 
1006  {
1007  return intersectWithComplement(*RHS);
1008  }
1009 
1010  // Three argument version of intersectWithComplement.
1011  // Result of RHS1 & ~RHS2 is stored into this bitmap.
1013  const SparseBitVector<ElementSize> &RHS2)
1014  {
1015  if (this == &RHS1)
1016  {
1018  return;
1019  }
1020  else if (this == &RHS2)
1021  {
1022  SparseBitVector RHS2Copy(RHS2);
1023  intersectWithComplement(RHS1, RHS2Copy);
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 
1068  const SparseBitVector<ElementSize> *RHS2)
1069  {
1070  intersectWithComplement(*RHS1, *RHS2);
1071  }
1072 
1074  {
1075  return intersects(*RHS);
1076  }
1077 
1078  // Return true if we share any bits in common with RHS
1080  {
1081  ElementListConstIter Iter1 = Elements.begin();
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  {
1117  SparseBitVector<ElementSize> Result(*this);
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;
1127  const SparseBitVectorElement<ElementSize> &First = *(Elements.begin());
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;
1136  const SparseBitVectorElement<ElementSize> &Last = *(Elements.rbegin());
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 
1157  iterator begin() const
1158  {
1159  return iterator(this);
1160  }
1161 
1162  iterator end() const
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 
1171 template <unsigned ElementSize>
1173  const SparseBitVector<ElementSize> *RHS)
1174 {
1175  return LHS |= *RHS;
1176 }
1177 
1178 template <unsigned ElementSize>
1180  const SparseBitVector<ElementSize> &RHS)
1181 {
1182  return LHS->operator|=(RHS);
1183 }
1184 
1185 template <unsigned ElementSize>
1187  const SparseBitVector<ElementSize> &RHS)
1188 {
1189  return LHS->operator&=(RHS);
1190 }
1191 
1192 template <unsigned ElementSize>
1194  const SparseBitVector<ElementSize> *RHS)
1195 {
1196  return LHS &= *RHS;
1197 }
1198 
1199 // Convenience functions for infix union, intersection, difference operators.
1200 
1201 template <unsigned ElementSize>
1202 inline SparseBitVector<ElementSize>
1204  const SparseBitVector<ElementSize> &RHS)
1205 {
1206  SparseBitVector<ElementSize> Result(LHS);
1207  Result |= RHS;
1208  return Result;
1209 }
1210 
1211 template <unsigned ElementSize>
1212 inline SparseBitVector<ElementSize>
1214  const SparseBitVector<ElementSize> &RHS)
1215 {
1216  SparseBitVector<ElementSize> Result(LHS);
1217  Result &= RHS;
1218  return Result;
1219 }
1220 
1221 template <unsigned ElementSize>
1222 inline SparseBitVector<ElementSize>
1224  const SparseBitVector<ElementSize> &RHS)
1225 {
1227  Result.intersectWithComplement(LHS, RHS);
1228  return Result;
1229 }
1230 
1231 // Dump a SparseBitVector to a stream
1232 template <unsigned ElementSize>
1233 void dump(const SparseBitVector<ElementSize> &LHS, std::ostream &out)
1234 {
1235  out << "[";
1236 
1237  typename SparseBitVector<ElementSize>::iterator bi = LHS.begin(),
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
copy
Definition: cJSON.cpp:414
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
bool test(unsigned Idx) const
bool operator&=(const SparseBitVector &RHS)
bool intersects(const SparseBitVector< ElementSize > *RHS) const
iterator end() 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
SparseBitVector & operator=(SparseBitVector &&RHS)
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
ElementListIter CurrElementIter
SparseBitVector & operator=(const SparseBitVector &RHS)
void intersectWithComplement(const SparseBitVector< ElementSize > &RHS1, const SparseBitVector< ElementSize > &RHS2)
constexpr std::remove_reference< T >::type && move(T &&t) noexcept
Definition: SVFUtil.h:447
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
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)
SparseBitVectorElement(unsigned Idx)
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)