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 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 54 SmallBitVector() { reset(); } 55 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; 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 99 int find_first() const { return find_first<0>(); } 100 101 int find_next(unsigned Prev) const { return find_next<0>(Prev); } 102 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 112 SizeT size() const { return Size; } 113 114 void resize(SizeT Size) { 115 assert(Size <= MaxBits); 116 this->Size = Size; 117 } 118 119 void reserve(SizeT Size) { 120 assert(Size <= MaxBits); 121 (void)Size; 122 } 123 124 void set(unsigned Idx) { (*this)[Idx] = true; } 125 126 void set() { 127 for (SizeT ii = 0; ii < size(); ++ii) { 128 (*this)[ii] = true; 129 } 130 } 131 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 173 void reset() { memset(Bits, 0, sizeof(Bits)); } 174 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> 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 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> 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 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: 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()) 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. 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 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 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. 349 bool empty() const { return Size == 0; } 350 351 /// size - Returns the number of bits in this bitvector. 352 size_type size() const { return Size; } 353 354 /// count - Returns the number of bits which are set. 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. 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. 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. 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. 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. 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. 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 442 void reserve(unsigned N) { 443 if (N > Capacity * BITWORD_SIZE) 444 grow(N); 445 } 446 447 // Set, reset, flip 448 BitVectorTmpl &set() { 449 init_words(Bits, Capacity, true); 450 clear_unused_bits(); 451 return *this; 452 } 453 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) 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 490 BitVectorTmpl &reset() { 491 init_words(Bits, Capacity, false); 492 return *this; 493 } 494 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) 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 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 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 554 bool test(unsigned Idx) const { return (*this)[Idx]; } 555 556 /// Test if any common bits are set. 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. 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(). 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 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: 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. 764 void clear_unused_bits() { set_unused_bits(false); } 765 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 std::memcpy(Bits, NewBits, OldCapacity * sizeof(BitWord)); 772 Alloc.deallocate(Bits, OldCapacity); 773 Bits = NewBits; 774 775 clear_unused_bits(); 776 } 777 778 void init_words(BitWord *B, unsigned NumWords, bool t) { 779 memset(B, 0 - (int)t, NumWords * sizeof(BitWord)); 780 } 781 782 template <bool AddBits, bool InvertMask> 783 void applyMask(const uint32_t *Mask, unsigned MaskWords) { 784 static_assert(BITWORD_SIZE % 32 == 0, "Unsupported BitWord size."); 785 MaskWords = std::min(MaskWords, (size() + 31) / 32); 786 const unsigned Scale = BITWORD_SIZE / 32; 787 unsigned i; 788 for (i = 0; MaskWords >= Scale; ++i, MaskWords -= Scale) { 789 BitWord BW = Bits[i]; 790 // This inner loop should unroll completely when BITWORD_SIZE > 32. 791 for (unsigned b = 0; b != BITWORD_SIZE; b += 32) { 792 uint32_t M = *Mask++; 793 if (InvertMask) 794 M = ~M; 795 if (AddBits) 796 BW |= BitWord(M) << b; 797 else 798 BW &= ~(BitWord(M) << b); 799 } 800 Bits[i] = BW; 801 } 802 for (unsigned b = 0; MaskWords; b += 32, --MaskWords) { 803 uint32_t M = *Mask++; 804 if (InvertMask) 805 M = ~M; 806 if (AddBits) 807 Bits[i] |= BitWord(M) << b; 808 else 809 Bits[i] &= ~(BitWord(M) << b); 810 } 811 if (AddBits) 812 clear_unused_bits(); 813 } 814 }; 815 816 using BitVector = BitVectorTmpl<CfgLocalAllocator>; 817 818 } // end of namespace Ice 819 820 namespace std { 821 /// Implement std::swap in terms of BitVectorTmpl swap. 822 template <template <typename> class AT> 823 inline void swap(Ice::BitVectorTmpl<AT> &LHS, Ice::BitVectorTmpl<AT> &RHS) { 824 LHS.swap(RHS); 825 } 826 } 827 828 #endif // SUBZERO_SRC_ICEBITVECTOR_H 829