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