• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //===- subzero/src/IceBitVector.h - Inline bit vector. ----------*- C++ -*-===//
2 //
3 //                        The Subzero Code Generator
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 ///
10 /// \file
11 /// \brief Defines and implements a bit vector classes.
12 ///
13 /// SmallBitVector is a drop in replacement for llvm::SmallBitVector. It uses
14 /// inline storage, at the expense of limited, static size.
15 ///
16 /// BitVector is a allocator aware version of llvm::BitVector. Its
17 /// implementation was copied ipsis literis from llvm.
18 ///
19 //===----------------------------------------------------------------------===//
20 
21 #ifndef SUBZERO_SRC_ICEBITVECTOR_H
22 #define SUBZERO_SRC_ICEBITVECTOR_H
23 
24 #include "IceMemory.h"
25 #include "IceOperand.h"
26 
27 #include "llvm/Support/MathExtras.h"
28 
29 #include <algorithm>
30 #include <cassert>
31 #include <climits>
32 #include <memory>
33 #include <type_traits>
34 #include <utility>
35 
36 namespace Ice {
37 class SmallBitVector {
38 public:
39   using ElementType = uint64_t;
40   static constexpr SizeT BitIndexSize = 6; // log2(NumBitsPerPos);
41   static constexpr SizeT NumBitsPerPos = sizeof(ElementType) * CHAR_BIT;
42   static_assert(1 << BitIndexSize == NumBitsPerPos, "Invalid BitIndexSize.");
43 
SmallBitVector(const SmallBitVector & BV)44   SmallBitVector(const SmallBitVector &BV) { *this = BV; }
45 
46   SmallBitVector &operator=(const SmallBitVector &BV) {
47     if (&BV != this) {
48       resize(BV.size());
49       memcpy(Bits, BV.Bits, sizeof(Bits));
50     }
51     return *this;
52   }
53 
SmallBitVector()54   SmallBitVector() { reset(); }
55 
SmallBitVector(SizeT S)56   explicit SmallBitVector(SizeT S) : SmallBitVector() {
57     assert(S <= MaxBits);
58     resize(S);
59   }
60 
61   class Reference {
62     Reference() = delete;
63 
64   public:
65     Reference(const Reference &) = default;
66     Reference &operator=(const Reference &Rhs) { return *this = (bool)Rhs; }
67     Reference &operator=(bool t) {
68       if (t) {
69         *Data |= _1 << Bit;
70       } else {
71         *Data &= ~(_1 << Bit);
72       }
73       return *this;
74     }
75     operator bool() const { return (*Data & (_1 << Bit)) != 0; }
76 
77   private:
78     friend class SmallBitVector;
Reference(ElementType * D,SizeT B)79     Reference(ElementType *D, SizeT B) : Data(D), Bit(B) {
80       assert(B < NumBitsPerPos);
81     }
82 
83     ElementType *const Data;
84     const SizeT Bit;
85   };
86 
87   Reference operator[](unsigned Idx) {
88     assert(Idx < size());
89     return Reference(Bits + (Idx >> BitIndexSize),
90                      Idx & ((_1 << BitIndexSize) - 1));
91   }
92 
93   bool operator[](unsigned Idx) const {
94     assert(Idx < size());
95     return Bits[Idx >> BitIndexSize] &
96            (_1 << (Idx & ((_1 << BitIndexSize) - 1)));
97   }
98 
find_first()99   int find_first() const { return find_first<0>(); }
100 
find_next(unsigned Prev)101   int find_next(unsigned Prev) const { return find_next<0>(Prev); }
102 
any()103   bool any() const {
104     for (SizeT i = 0; i < BitsElements; ++i) {
105       if (Bits[i]) {
106         return true;
107       }
108     }
109     return false;
110   }
111 
size()112   SizeT size() const { return Size; }
113 
resize(SizeT Size)114   void resize(SizeT Size) {
115     assert(Size <= MaxBits);
116     this->Size = Size;
117   }
118 
reserve(SizeT Size)119   void reserve(SizeT Size) {
120     assert(Size <= MaxBits);
121     (void)Size;
122   }
123 
set(unsigned Idx)124   void set(unsigned Idx) { (*this)[Idx] = true; }
125 
set()126   void set() {
127     for (SizeT ii = 0; ii < size(); ++ii) {
128       (*this)[ii] = true;
129     }
130   }
131 
count()132   SizeT count() const {
133     SizeT Count = 0;
134     for (SizeT i = 0; i < BitsElements; ++i) {
135       Count += llvm::countPopulation(Bits[i]);
136     }
137     return Count;
138   }
139 
140   SmallBitVector operator&(const SmallBitVector &Rhs) const {
141     assert(size() == Rhs.size());
142     SmallBitVector Ret(std::max(size(), Rhs.size()));
143     for (SizeT i = 0; i < BitsElements; ++i) {
144       Ret.Bits[i] = Bits[i] & Rhs.Bits[i];
145     }
146     return Ret;
147   }
148 
149   SmallBitVector operator~() const {
150     SmallBitVector Ret = *this;
151     Ret.invert<0>();
152     return Ret;
153   }
154 
155   SmallBitVector &operator|=(const SmallBitVector &Rhs) {
156     assert(size() == Rhs.size());
157     resize(std::max(size(), Rhs.size()));
158     for (SizeT i = 0; i < BitsElements; ++i) {
159       Bits[i] |= Rhs.Bits[i];
160     }
161     return *this;
162   }
163 
164   SmallBitVector operator|(const SmallBitVector &Rhs) const {
165     assert(size() == Rhs.size());
166     SmallBitVector Ret(std::max(size(), Rhs.size()));
167     for (SizeT i = 0; i < BitsElements; ++i) {
168       Ret.Bits[i] = Bits[i] | Rhs.Bits[i];
169     }
170     return Ret;
171   }
172 
reset()173   void reset() { memset(Bits, 0, sizeof(Bits)); }
174 
reset(const SmallBitVector & Mask)175   void reset(const SmallBitVector &Mask) {
176     for (const auto V : RegNumBVIter(Mask)) {
177       (*this)[unsigned(V)] = false;
178     }
179   }
180 
181 private:
182   // _1 is the constant 1 of type ElementType.
183   static constexpr ElementType _1 = ElementType(1);
184 
185   static constexpr SizeT BitsElements = 2;
186   ElementType Bits[BitsElements];
187 
188   // MaxBits is defined here because it needs Bits to be defined.
189   static constexpr SizeT MaxBits = sizeof(SmallBitVector::Bits) * CHAR_BIT;
190   static_assert(sizeof(SmallBitVector::Bits) == 16,
191                 "Bits must be 16 bytes wide.");
192   SizeT Size = 0;
193 
194   template <SizeT Pos>
find_first()195   typename std::enable_if<Pos == BitsElements, int>::type find_first() const {
196     return -1;
197   }
198 
199   template <SizeT Pos>
200       typename std::enable_if <
201       Pos<BitsElements, int>::type find_first() const {
202     if (Bits[Pos] != 0) {
203       return NumBitsPerPos * Pos + llvm::countTrailingZeros(Bits[Pos]);
204     }
205     return find_first<Pos + 1>();
206   }
207 
208   template <SizeT Pos>
209   typename std::enable_if<Pos == BitsElements, int>::type
find_next(unsigned)210   find_next(unsigned) const {
211     return -1;
212   }
213 
214   template <SizeT Pos>
215       typename std::enable_if <
216       Pos<BitsElements, int>::type find_next(unsigned Prev) const {
217     if (Prev + 1 < (Pos + 1) * NumBitsPerPos) {
218       const ElementType Mask =
219           (ElementType(1) << ((Prev + 1) - Pos * NumBitsPerPos)) - 1;
220       const ElementType B = Bits[Pos] & ~Mask;
221       if (B != 0) {
222         return NumBitsPerPos * Pos + llvm::countTrailingZeros(B);
223       }
224       Prev = (1 + Pos) * NumBitsPerPos - 1;
225     }
226     return find_next<Pos + 1>(Prev);
227   }
228 
229   template <SizeT Pos>
invert()230   typename std::enable_if<Pos == BitsElements, void>::type invert() {}
231 
232   template <SizeT Pos>
233       typename std::enable_if < Pos<BitsElements, void>::type invert() {
234     if (size() < Pos * NumBitsPerPos) {
235       Bits[Pos] = 0;
236     } else if ((Pos + 1) * NumBitsPerPos < size()) {
237       Bits[Pos] ^= ~ElementType(0);
238     } else {
239       const ElementType Mask =
240           (ElementType(1) << (size() - (Pos * NumBitsPerPos))) - 1;
241       Bits[Pos] ^= Mask;
242     }
243     invert<Pos + 1>();
244   }
245 };
246 
247 template <template <typename> class AT> class BitVectorTmpl {
248   typedef unsigned long BitWord;
249   using Allocator = AT<BitWord>;
250 
251   enum { BITWORD_SIZE = (unsigned)sizeof(BitWord) * CHAR_BIT };
252 
253   static_assert(BITWORD_SIZE == 64 || BITWORD_SIZE == 32,
254                 "Unsupported word size");
255 
256   BitWord *Bits;     // Actual bits.
257   unsigned Size;     // Size of bitvector in bits.
258   unsigned Capacity; // Size of allocated memory in BitWord.
259   Allocator Alloc;
260 
alignTo(uint64_t Value,uint64_t Align)261   uint64_t alignTo(uint64_t Value, uint64_t Align) {
262 #ifdef PNACL_LLVM
263     return llvm::RoundUpToAlignment(Value, Align);
264 #else  // !PNACL_LLVM
265     return llvm::alignTo(Value, Align);
266 #endif // !PNACL_LLVM
267   }
268 
269 public:
270   typedef unsigned size_type;
271   // Encapsulation of a single bit.
272   class reference {
273     friend class BitVectorTmpl;
274 
275     BitWord *WordRef;
276     unsigned BitPos;
277 
278     reference(); // Undefined
279 
280   public:
reference(BitVectorTmpl & b,unsigned Idx)281     reference(BitVectorTmpl &b, unsigned Idx) {
282       WordRef = &b.Bits[Idx / BITWORD_SIZE];
283       BitPos = Idx % BITWORD_SIZE;
284     }
285 
286     reference(const reference &) = default;
287 
288     reference &operator=(reference t) {
289       *this = bool(t);
290       return *this;
291     }
292 
293     reference &operator=(bool t) {
294       if (t)
295         *WordRef |= BitWord(1) << BitPos;
296       else
297         *WordRef &= ~(BitWord(1) << BitPos);
298       return *this;
299     }
300 
301     operator bool() const {
302       return ((*WordRef) & (BitWord(1) << BitPos)) ? true : false;
303     }
304   };
305 
306   /// BitVectorTmpl default ctor - Creates an empty bitvector.
307   BitVectorTmpl(Allocator A = Allocator())
308       : Size(0), Capacity(0), Alloc(std::move(A)) {
309     Bits = nullptr;
310   }
311 
312   /// BitVectorTmpl ctor - Creates a bitvector of specified number of bits. All
313   /// bits are initialized to the specified value.
314   explicit BitVectorTmpl(unsigned s, bool t = false, Allocator A = Allocator())
Size(s)315       : Size(s), Alloc(std::move(A)) {
316     Capacity = NumBitWords(s);
317     Bits = Alloc.allocate(Capacity);
318     init_words(Bits, Capacity, t);
319     if (t)
320       clear_unused_bits();
321   }
322 
323   /// BitVectorTmpl copy ctor.
BitVectorTmpl(const BitVectorTmpl & RHS)324   BitVectorTmpl(const BitVectorTmpl &RHS) : Size(RHS.size()), Alloc(RHS.Alloc) {
325     if (Size == 0) {
326       Bits = nullptr;
327       Capacity = 0;
328       return;
329     }
330 
331     Capacity = NumBitWords(RHS.size());
332     Bits = Alloc.allocate(Capacity);
333     std::memcpy(Bits, RHS.Bits, Capacity * sizeof(BitWord));
334   }
335 
BitVectorTmpl(BitVectorTmpl && RHS)336   BitVectorTmpl(BitVectorTmpl &&RHS)
337       : Bits(RHS.Bits), Size(RHS.Size), Capacity(RHS.Capacity),
338         Alloc(std::move(RHS.Alloc)) {
339     RHS.Bits = nullptr;
340   }
341 
~BitVectorTmpl()342   ~BitVectorTmpl() {
343     if (Bits != nullptr) {
344       Alloc.deallocate(Bits, Capacity);
345     }
346   }
347 
348   /// empty - Tests whether there are no bits in this bitvector.
empty()349   bool empty() const { return Size == 0; }
350 
351   /// size - Returns the number of bits in this bitvector.
size()352   size_type size() const { return Size; }
353 
354   /// count - Returns the number of bits which are set.
count()355   size_type count() const {
356     unsigned NumBits = 0;
357     for (unsigned i = 0; i < NumBitWords(size()); ++i)
358       NumBits += llvm::countPopulation(Bits[i]);
359     return NumBits;
360   }
361 
362   /// any - Returns true if any bit is set.
any()363   bool any() const {
364     for (unsigned i = 0; i < NumBitWords(size()); ++i)
365       if (Bits[i] != 0)
366         return true;
367     return false;
368   }
369 
370   /// all - Returns true if all bits are set.
all()371   bool all() const {
372     for (unsigned i = 0; i < Size / BITWORD_SIZE; ++i)
373       if (Bits[i] != ~0UL)
374         return false;
375 
376     // If bits remain check that they are ones. The unused bits are always zero.
377     if (unsigned Remainder = Size % BITWORD_SIZE)
378       return Bits[Size / BITWORD_SIZE] == (1UL << Remainder) - 1;
379 
380     return true;
381   }
382 
383   /// none - Returns true if none of the bits are set.
none()384   bool none() const { return !any(); }
385 
386   /// find_first - Returns the index of the first set bit, -1 if none
387   /// of the bits are set.
find_first()388   int find_first() const {
389     for (unsigned i = 0; i < NumBitWords(size()); ++i)
390       if (Bits[i] != 0)
391         return i * BITWORD_SIZE + llvm::countTrailingZeros(Bits[i]);
392     return -1;
393   }
394 
395   /// find_next - Returns the index of the next set bit following the
396   /// "Prev" bit. Returns -1 if the next set bit is not found.
find_next(unsigned Prev)397   int find_next(unsigned Prev) const {
398     ++Prev;
399     if (Prev >= Size)
400       return -1;
401 
402     unsigned WordPos = Prev / BITWORD_SIZE;
403     unsigned BitPos = Prev % BITWORD_SIZE;
404     BitWord Copy = Bits[WordPos];
405     // Mask off previous bits.
406     Copy &= ~0UL << BitPos;
407 
408     if (Copy != 0)
409       return WordPos * BITWORD_SIZE + llvm::countTrailingZeros(Copy);
410 
411     // Check subsequent words.
412     for (unsigned i = WordPos + 1; i < NumBitWords(size()); ++i)
413       if (Bits[i] != 0)
414         return i * BITWORD_SIZE + llvm::countTrailingZeros(Bits[i]);
415     return -1;
416   }
417 
418   /// clear - Clear all bits.
clear()419   void clear() { Size = 0; }
420 
421   /// resize - Grow or shrink the bitvector.
422   void resize(unsigned N, bool t = false) {
423     if (N > Capacity * BITWORD_SIZE) {
424       unsigned OldCapacity = Capacity;
425       grow(N);
426       init_words(&Bits[OldCapacity], (Capacity - OldCapacity), t);
427     }
428 
429     // Set any old unused bits that are now included in the BitVectorTmpl. This
430     // may set bits that are not included in the new vector, but we will clear
431     // them back out below.
432     if (N > Size)
433       set_unused_bits(t);
434 
435     // Update the size, and clear out any bits that are now unused
436     unsigned OldSize = Size;
437     Size = N;
438     if (t || N < OldSize)
439       clear_unused_bits();
440   }
441 
reserve(unsigned N)442   void reserve(unsigned N) {
443     if (N > Capacity * BITWORD_SIZE)
444       grow(N);
445   }
446 
447   // Set, reset, flip
set()448   BitVectorTmpl &set() {
449     init_words(Bits, Capacity, true);
450     clear_unused_bits();
451     return *this;
452   }
453 
set(unsigned Idx)454   BitVectorTmpl &set(unsigned Idx) {
455     assert(Bits && "Bits never allocated");
456     Bits[Idx / BITWORD_SIZE] |= BitWord(1) << (Idx % BITWORD_SIZE);
457     return *this;
458   }
459 
460   /// set - Efficiently set a range of bits in [I, E)
set(unsigned I,unsigned E)461   BitVectorTmpl &set(unsigned I, unsigned E) {
462     assert(I <= E && "Attempted to set backwards range!");
463     assert(E <= size() && "Attempted to set out-of-bounds range!");
464 
465     if (I == E)
466       return *this;
467 
468     if (I / BITWORD_SIZE == E / BITWORD_SIZE) {
469       BitWord EMask = 1UL << (E % BITWORD_SIZE);
470       BitWord IMask = 1UL << (I % BITWORD_SIZE);
471       BitWord Mask = EMask - IMask;
472       Bits[I / BITWORD_SIZE] |= Mask;
473       return *this;
474     }
475 
476     BitWord PrefixMask = ~0UL << (I % BITWORD_SIZE);
477     Bits[I / BITWORD_SIZE] |= PrefixMask;
478     I = alignTo(I, BITWORD_SIZE);
479 
480     for (; I + BITWORD_SIZE <= E; I += BITWORD_SIZE)
481       Bits[I / BITWORD_SIZE] = ~0UL;
482 
483     BitWord PostfixMask = (1UL << (E % BITWORD_SIZE)) - 1;
484     if (I < E)
485       Bits[I / BITWORD_SIZE] |= PostfixMask;
486 
487     return *this;
488   }
489 
reset()490   BitVectorTmpl &reset() {
491     init_words(Bits, Capacity, false);
492     return *this;
493   }
494 
reset(unsigned Idx)495   BitVectorTmpl &reset(unsigned Idx) {
496     Bits[Idx / BITWORD_SIZE] &= ~(BitWord(1) << (Idx % BITWORD_SIZE));
497     return *this;
498   }
499 
500   /// reset - Efficiently reset a range of bits in [I, E)
reset(unsigned I,unsigned E)501   BitVectorTmpl &reset(unsigned I, unsigned E) {
502     assert(I <= E && "Attempted to reset backwards range!");
503     assert(E <= size() && "Attempted to reset out-of-bounds range!");
504 
505     if (I == E)
506       return *this;
507 
508     if (I / BITWORD_SIZE == E / BITWORD_SIZE) {
509       BitWord EMask = 1UL << (E % BITWORD_SIZE);
510       BitWord IMask = 1UL << (I % BITWORD_SIZE);
511       BitWord Mask = EMask - IMask;
512       Bits[I / BITWORD_SIZE] &= ~Mask;
513       return *this;
514     }
515 
516     BitWord PrefixMask = ~0UL << (I % BITWORD_SIZE);
517     Bits[I / BITWORD_SIZE] &= ~PrefixMask;
518     I = alignTo(I, BITWORD_SIZE);
519 
520     for (; I + BITWORD_SIZE <= E; I += BITWORD_SIZE)
521       Bits[I / BITWORD_SIZE] = 0UL;
522 
523     BitWord PostfixMask = (1UL << (E % BITWORD_SIZE)) - 1;
524     if (I < E)
525       Bits[I / BITWORD_SIZE] &= ~PostfixMask;
526 
527     return *this;
528   }
529 
flip()530   BitVectorTmpl &flip() {
531     for (unsigned i = 0; i < NumBitWords(size()); ++i)
532       Bits[i] = ~Bits[i];
533     clear_unused_bits();
534     return *this;
535   }
536 
flip(unsigned Idx)537   BitVectorTmpl &flip(unsigned Idx) {
538     Bits[Idx / BITWORD_SIZE] ^= BitWord(1) << (Idx % BITWORD_SIZE);
539     return *this;
540   }
541 
542   // Indexing.
543   reference operator[](unsigned Idx) {
544     assert(Idx < Size && "Out-of-bounds Bit access.");
545     return reference(*this, Idx);
546   }
547 
548   bool operator[](unsigned Idx) const {
549     assert(Idx < Size && "Out-of-bounds Bit access.");
550     BitWord Mask = BitWord(1) << (Idx % BITWORD_SIZE);
551     return (Bits[Idx / BITWORD_SIZE] & Mask) != 0;
552   }
553 
test(unsigned Idx)554   bool test(unsigned Idx) const { return (*this)[Idx]; }
555 
556   /// Test if any common bits are set.
anyCommon(const BitVectorTmpl & RHS)557   bool anyCommon(const BitVectorTmpl &RHS) const {
558     unsigned ThisWords = NumBitWords(size());
559     unsigned RHSWords = NumBitWords(RHS.size());
560     for (unsigned i = 0, e = std::min(ThisWords, RHSWords); i != e; ++i)
561       if (Bits[i] & RHS.Bits[i])
562         return true;
563     return false;
564   }
565 
566   // Comparison operators.
567   bool operator==(const BitVectorTmpl &RHS) const {
568     unsigned ThisWords = NumBitWords(size());
569     unsigned RHSWords = NumBitWords(RHS.size());
570     unsigned i;
571     for (i = 0; i != std::min(ThisWords, RHSWords); ++i)
572       if (Bits[i] != RHS.Bits[i])
573         return false;
574 
575     // Verify that any extra words are all zeros.
576     if (i != ThisWords) {
577       for (; i != ThisWords; ++i)
578         if (Bits[i])
579           return false;
580     } else if (i != RHSWords) {
581       for (; i != RHSWords; ++i)
582         if (RHS.Bits[i])
583           return false;
584     }
585     return true;
586   }
587 
588   bool operator!=(const BitVectorTmpl &RHS) const { return !(*this == RHS); }
589 
590   /// Intersection, union, disjoint union.
591   BitVectorTmpl &operator&=(const BitVectorTmpl &RHS) {
592     unsigned ThisWords = NumBitWords(size());
593     unsigned RHSWords = NumBitWords(RHS.size());
594     unsigned i;
595     for (i = 0; i != std::min(ThisWords, RHSWords); ++i)
596       Bits[i] &= RHS.Bits[i];
597 
598     // Any bits that are just in this bitvector become zero, because they aren't
599     // in the RHS bit vector.  Any words only in RHS are ignored because they
600     // are already zero in the LHS.
601     for (; i != ThisWords; ++i)
602       Bits[i] = 0;
603 
604     return *this;
605   }
606 
607   /// reset - Reset bits that are set in RHS. Same as *this &= ~RHS.
reset(const BitVectorTmpl & RHS)608   BitVectorTmpl &reset(const BitVectorTmpl &RHS) {
609     unsigned ThisWords = NumBitWords(size());
610     unsigned RHSWords = NumBitWords(RHS.size());
611     unsigned i;
612     for (i = 0; i != std::min(ThisWords, RHSWords); ++i)
613       Bits[i] &= ~RHS.Bits[i];
614     return *this;
615   }
616 
617   /// test - Check if (This - RHS) is zero.
618   /// This is the same as reset(RHS) and any().
test(const BitVectorTmpl & RHS)619   bool test(const BitVectorTmpl &RHS) const {
620     unsigned ThisWords = NumBitWords(size());
621     unsigned RHSWords = NumBitWords(RHS.size());
622     unsigned i;
623     for (i = 0; i != std::min(ThisWords, RHSWords); ++i)
624       if ((Bits[i] & ~RHS.Bits[i]) != 0)
625         return true;
626 
627     for (; i != ThisWords; ++i)
628       if (Bits[i] != 0)
629         return true;
630 
631     return false;
632   }
633 
634   BitVectorTmpl &operator|=(const BitVectorTmpl &RHS) {
635     if (size() < RHS.size())
636       resize(RHS.size());
637     for (size_t i = 0, e = NumBitWords(RHS.size()); i != e; ++i)
638       Bits[i] |= RHS.Bits[i];
639     return *this;
640   }
641 
642   BitVectorTmpl &operator^=(const BitVectorTmpl &RHS) {
643     if (size() < RHS.size())
644       resize(RHS.size());
645     for (size_t i = 0, e = NumBitWords(RHS.size()); i != e; ++i)
646       Bits[i] ^= RHS.Bits[i];
647     return *this;
648   }
649 
650   // Assignment operator.
651   const BitVectorTmpl &operator=(const BitVectorTmpl &RHS) {
652     if (this == &RHS)
653       return *this;
654 
655     Size = RHS.size();
656     unsigned RHSWords = NumBitWords(Size);
657     if (Size <= Capacity * BITWORD_SIZE) {
658       if (Size)
659         std::memcpy(Bits, RHS.Bits, RHSWords * sizeof(BitWord));
660       clear_unused_bits();
661       return *this;
662     }
663 
664     // Currently, BitVectorTmpl is only used by liveness analysis.  With the
665     // following assert, we make sure BitVectorTmpls grow in a single step from
666     // 0 to their final capacity, rather than growing slowly and "leaking"
667     // memory in the process.
668     assert(Capacity == 0);
669 
670     // Grow the bitvector to have enough elements.
671     const auto OldCapacity = Capacity;
672     Capacity = RHSWords;
673     assert(Capacity > 0 && "negative capacity?");
674     BitWord *NewBits = Alloc.allocate(Capacity);
675     std::memcpy(NewBits, RHS.Bits, Capacity * sizeof(BitWord));
676 
677     // Destroy the old bits.
678     Alloc.deallocate(Bits, OldCapacity);
679     Bits = NewBits;
680 
681     return *this;
682   }
683 
684   const BitVectorTmpl &operator=(BitVectorTmpl &&RHS) {
685     if (this == &RHS)
686       return *this;
687 
688     Alloc.deallocate(Bits, Capacity);
689     Bits = RHS.Bits;
690     Size = RHS.Size;
691     Capacity = RHS.Capacity;
692 
693     RHS.Bits = nullptr;
694 
695     return *this;
696   }
697 
swap(BitVectorTmpl & RHS)698   void swap(BitVectorTmpl &RHS) {
699     std::swap(Bits, RHS.Bits);
700     std::swap(Size, RHS.Size);
701     std::swap(Capacity, RHS.Capacity);
702   }
703 
704   //===--------------------------------------------------------------------===//
705   // Portable bit mask operations.
706   //===--------------------------------------------------------------------===//
707   //
708   // These methods all operate on arrays of uint32_t, each holding 32 bits. The
709   // fixed word size makes it easier to work with literal bit vector constants
710   // in portable code.
711   //
712   // The LSB in each word is the lowest numbered bit.  The size of a portable
713   // bit mask is always a whole multiple of 32 bits.  If no bit mask size is
714   // given, the bit mask is assumed to cover the entire BitVectorTmpl.
715 
716   /// setBitsInMask - Add '1' bits from Mask to this vector. Don't resize.
717   /// This computes "*this |= Mask".
718   void setBitsInMask(const uint32_t *Mask, unsigned MaskWords = ~0u) {
719     applyMask<true, false>(Mask, MaskWords);
720   }
721 
722   /// clearBitsInMask - Clear any bits in this vector that are set in Mask.
723   /// Don't resize. This computes "*this &= ~Mask".
724   void clearBitsInMask(const uint32_t *Mask, unsigned MaskWords = ~0u) {
725     applyMask<false, false>(Mask, MaskWords);
726   }
727 
728   /// setBitsNotInMask - Add a bit to this vector for every '0' bit in Mask.
729   /// Don't resize.  This computes "*this |= ~Mask".
730   void setBitsNotInMask(const uint32_t *Mask, unsigned MaskWords = ~0u) {
731     applyMask<true, true>(Mask, MaskWords);
732   }
733 
734   /// clearBitsNotInMask - Clear a bit in this vector for every '0' bit in Mask.
735   /// Don't resize.  This computes "*this &= Mask".
736   void clearBitsNotInMask(const uint32_t *Mask, unsigned MaskWords = ~0u) {
737     applyMask<false, true>(Mask, MaskWords);
738   }
739 
740 private:
NumBitWords(unsigned S)741   unsigned NumBitWords(unsigned S) const {
742     return (S + BITWORD_SIZE - 1) / BITWORD_SIZE;
743   }
744 
745   // Set the unused bits in the high words.
746   void set_unused_bits(bool t = true) {
747     //  Set high words first.
748     unsigned UsedWords = NumBitWords(Size);
749     if (Capacity > UsedWords)
750       init_words(&Bits[UsedWords], (Capacity - UsedWords), t);
751 
752     //  Then set any stray high bits of the last used word.
753     unsigned ExtraBits = Size % BITWORD_SIZE;
754     if (ExtraBits) {
755       BitWord ExtraBitMask = ~0UL << ExtraBits;
756       if (t)
757         Bits[UsedWords - 1] |= ExtraBitMask;
758       else
759         Bits[UsedWords - 1] &= ~ExtraBitMask;
760     }
761   }
762 
763   // Clear the unused bits in the high words.
clear_unused_bits()764   void clear_unused_bits() { set_unused_bits(false); }
765 
grow(unsigned NewSize)766   void grow(unsigned NewSize) {
767     const auto OldCapacity = Capacity;
768     Capacity = std::max(NumBitWords(NewSize), Capacity * 2);
769     assert(Capacity > 0 && "realloc-ing zero space");
770     auto *NewBits = Alloc.allocate(Capacity);
771     if (Bits) {
772       std::memcpy(NewBits, Bits, OldCapacity * sizeof(BitWord));
773       Alloc.deallocate(Bits, OldCapacity);
774     }
775     Bits = NewBits;
776 
777     clear_unused_bits();
778   }
779 
init_words(BitWord * B,unsigned NumWords,bool t)780   void init_words(BitWord *B, unsigned NumWords, bool t) {
781     memset(B, 0 - (int)t, NumWords * sizeof(BitWord));
782   }
783 
784   template <bool AddBits, bool InvertMask>
applyMask(const uint32_t * Mask,unsigned MaskWords)785   void applyMask(const uint32_t *Mask, unsigned MaskWords) {
786     static_assert(BITWORD_SIZE % 32 == 0, "Unsupported BitWord size.");
787     MaskWords = std::min(MaskWords, (size() + 31) / 32);
788     const unsigned Scale = BITWORD_SIZE / 32;
789     unsigned i;
790     for (i = 0; MaskWords >= Scale; ++i, MaskWords -= Scale) {
791       BitWord BW = Bits[i];
792       // This inner loop should unroll completely when BITWORD_SIZE > 32.
793       for (unsigned b = 0; b != BITWORD_SIZE; b += 32) {
794         uint32_t M = *Mask++;
795         if (InvertMask)
796           M = ~M;
797         if (AddBits)
798           BW |= BitWord(M) << b;
799         else
800           BW &= ~(BitWord(M) << b);
801       }
802       Bits[i] = BW;
803     }
804     for (unsigned b = 0; MaskWords; b += 32, --MaskWords) {
805       uint32_t M = *Mask++;
806       if (InvertMask)
807         M = ~M;
808       if (AddBits)
809         Bits[i] |= BitWord(M) << b;
810       else
811         Bits[i] &= ~(BitWord(M) << b);
812     }
813     if (AddBits)
814       clear_unused_bits();
815   }
816 };
817 
818 using BitVector = BitVectorTmpl<CfgLocalAllocator>;
819 
820 } // end of namespace Ice
821 
822 namespace std {
823 /// Implement std::swap in terms of BitVectorTmpl swap.
824 template <template <typename> class AT>
swap(Ice::BitVectorTmpl<AT> & LHS,Ice::BitVectorTmpl<AT> & RHS)825 inline void swap(Ice::BitVectorTmpl<AT> &LHS, Ice::BitVectorTmpl<AT> &RHS) {
826   LHS.swap(RHS);
827 }
828 } // namespace std
829 
830 #endif // SUBZERO_SRC_ICEBITVECTOR_H
831