1 //===- llvm/ADT/SmallBitVector.h - 'Normally small' bit vectors -*- C++ -*-===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 // 10 // This file implements the SmallBitVector class. 11 // 12 //===----------------------------------------------------------------------===// 13 14 #ifndef LLVM_ADT_SMALLBITVECTOR_H 15 #define LLVM_ADT_SMALLBITVECTOR_H 16 17 #include "llvm/ADT/BitVector.h" 18 #include "llvm/Support/MathExtras.h" 19 #include <cassert> 20 21 namespace llvm { 22 23 /// SmallBitVector - This is a 'bitvector' (really, a variable-sized bit array), 24 /// optimized for the case when the array is small. It contains one 25 /// pointer-sized field, which is directly used as a plain collection of bits 26 /// when possible, or as a pointer to a larger heap-allocated array when 27 /// necessary. This allows normal "small" cases to be fast without losing 28 /// generality for large inputs. 29 /// 30 class SmallBitVector { 31 // TODO: In "large" mode, a pointer to a BitVector is used, leading to an 32 // unnecessary level of indirection. It would be more efficient to use a 33 // pointer to memory containing size, allocation size, and the array of bits. 34 uintptr_t X; 35 36 enum { 37 // The number of bits in this class. 38 NumBaseBits = sizeof(uintptr_t) * CHAR_BIT, 39 40 // One bit is used to discriminate between small and large mode. The 41 // remaining bits are used for the small-mode representation. 42 SmallNumRawBits = NumBaseBits - 1, 43 44 // A few more bits are used to store the size of the bit set in small mode. 45 // Theoretically this is a ceil-log2. These bits are encoded in the most 46 // significant bits of the raw bits. 47 SmallNumSizeBits = (NumBaseBits == 32 ? 5 : 48 NumBaseBits == 64 ? 6 : 49 SmallNumRawBits), 50 51 // The remaining bits are used to store the actual set in small mode. 52 SmallNumDataBits = SmallNumRawBits - SmallNumSizeBits 53 }; 54 55 public: 56 // Encapsulation of a single bit. 57 class reference { 58 SmallBitVector &TheVector; 59 unsigned BitPos; 60 61 public: 62 reference(SmallBitVector &b, unsigned Idx) : TheVector(b), BitPos(Idx) {} 63 64 reference& operator=(reference t) { 65 *this = bool(t); 66 return *this; 67 } 68 69 reference& operator=(bool t) { 70 if (t) 71 TheVector.set(BitPos); 72 else 73 TheVector.reset(BitPos); 74 return *this; 75 } 76 77 operator bool() const { 78 return const_cast<const SmallBitVector &>(TheVector).operator[](BitPos); 79 } 80 }; 81 82 private: 83 bool isSmall() const { 84 return X & uintptr_t(1); 85 } 86 87 BitVector *getPointer() const { 88 assert(!isSmall()); 89 return reinterpret_cast<BitVector *>(X); 90 } 91 92 void switchToSmall(uintptr_t NewSmallBits, size_t NewSize) { 93 X = 1; 94 setSmallSize(NewSize); 95 setSmallBits(NewSmallBits); 96 } 97 98 void switchToLarge(BitVector *BV) { 99 X = reinterpret_cast<uintptr_t>(BV); 100 assert(!isSmall() && "Tried to use an unaligned pointer"); 101 } 102 103 // Return all the bits used for the "small" representation; this includes 104 // bits for the size as well as the element bits. 105 uintptr_t getSmallRawBits() const { 106 assert(isSmall()); 107 return X >> 1; 108 } 109 110 void setSmallRawBits(uintptr_t NewRawBits) { 111 assert(isSmall()); 112 X = (NewRawBits << 1) | uintptr_t(1); 113 } 114 115 // Return the size. 116 size_t getSmallSize() const { 117 return getSmallRawBits() >> SmallNumDataBits; 118 } 119 120 void setSmallSize(size_t Size) { 121 setSmallRawBits(getSmallBits() | (Size << SmallNumDataBits)); 122 } 123 124 // Return the element bits. 125 uintptr_t getSmallBits() const { 126 return getSmallRawBits() & ~(~uintptr_t(0) << getSmallSize()); 127 } 128 129 void setSmallBits(uintptr_t NewBits) { 130 setSmallRawBits((NewBits & ~(~uintptr_t(0) << getSmallSize())) | 131 (getSmallSize() << SmallNumDataBits)); 132 } 133 134 public: 135 /// SmallBitVector default ctor - Creates an empty bitvector. 136 SmallBitVector() : X(1) {} 137 138 /// SmallBitVector ctor - Creates a bitvector of specified number of bits. All 139 /// bits are initialized to the specified value. 140 explicit SmallBitVector(unsigned s, bool t = false) { 141 if (s <= SmallNumDataBits) 142 switchToSmall(t ? ~uintptr_t(0) : 0, s); 143 else 144 switchToLarge(new BitVector(s, t)); 145 } 146 147 /// SmallBitVector copy ctor. 148 SmallBitVector(const SmallBitVector &RHS) { 149 if (RHS.isSmall()) 150 X = RHS.X; 151 else 152 switchToLarge(new BitVector(*RHS.getPointer())); 153 } 154 155 ~SmallBitVector() { 156 if (!isSmall()) 157 delete getPointer(); 158 } 159 160 /// empty - Tests whether there are no bits in this bitvector. 161 bool empty() const { 162 return isSmall() ? getSmallSize() == 0 : getPointer()->empty(); 163 } 164 165 /// size - Returns the number of bits in this bitvector. 166 size_t size() const { 167 return isSmall() ? getSmallSize() : getPointer()->size(); 168 } 169 170 /// count - Returns the number of bits which are set. 171 unsigned count() const { 172 if (isSmall()) { 173 uintptr_t Bits = getSmallBits(); 174 if (sizeof(uintptr_t) * CHAR_BIT == 32) 175 return CountPopulation_32(Bits); 176 if (sizeof(uintptr_t) * CHAR_BIT == 64) 177 return CountPopulation_64(Bits); 178 assert(0 && "Unsupported!"); 179 } 180 return getPointer()->count(); 181 } 182 183 /// any - Returns true if any bit is set. 184 bool any() const { 185 if (isSmall()) 186 return getSmallBits() != 0; 187 return getPointer()->any(); 188 } 189 190 /// all - Returns true if all bits are set. 191 bool all() const { 192 if (isSmall()) 193 return getSmallBits() == (uintptr_t(1) << getSmallSize()) - 1; 194 return getPointer()->all(); 195 } 196 197 /// none - Returns true if none of the bits are set. 198 bool none() const { 199 if (isSmall()) 200 return getSmallBits() == 0; 201 return getPointer()->none(); 202 } 203 204 /// find_first - Returns the index of the first set bit, -1 if none 205 /// of the bits are set. 206 int find_first() const { 207 if (isSmall()) { 208 uintptr_t Bits = getSmallBits(); 209 if (Bits == 0) 210 return -1; 211 if (sizeof(uintptr_t) * CHAR_BIT == 32) 212 return CountTrailingZeros_32(Bits); 213 if (sizeof(uintptr_t) * CHAR_BIT == 64) 214 return CountTrailingZeros_64(Bits); 215 assert(0 && "Unsupported!"); 216 } 217 return getPointer()->find_first(); 218 } 219 220 /// find_next - Returns the index of the next set bit following the 221 /// "Prev" bit. Returns -1 if the next set bit is not found. 222 int find_next(unsigned Prev) const { 223 if (isSmall()) { 224 uintptr_t Bits = getSmallBits(); 225 // Mask off previous bits. 226 Bits &= ~uintptr_t(0) << (Prev + 1); 227 if (Bits == 0 || Prev + 1 >= getSmallSize()) 228 return -1; 229 if (sizeof(uintptr_t) * CHAR_BIT == 32) 230 return CountTrailingZeros_32(Bits); 231 if (sizeof(uintptr_t) * CHAR_BIT == 64) 232 return CountTrailingZeros_64(Bits); 233 assert(0 && "Unsupported!"); 234 } 235 return getPointer()->find_next(Prev); 236 } 237 238 /// clear - Clear all bits. 239 void clear() { 240 if (!isSmall()) 241 delete getPointer(); 242 switchToSmall(0, 0); 243 } 244 245 /// resize - Grow or shrink the bitvector. 246 void resize(unsigned N, bool t = false) { 247 if (!isSmall()) { 248 getPointer()->resize(N, t); 249 } else if (SmallNumDataBits >= N) { 250 uintptr_t NewBits = t ? ~uintptr_t(0) << getSmallSize() : 0; 251 setSmallSize(N); 252 setSmallBits(NewBits | getSmallBits()); 253 } else { 254 BitVector *BV = new BitVector(N, t); 255 uintptr_t OldBits = getSmallBits(); 256 for (size_t i = 0, e = getSmallSize(); i != e; ++i) 257 (*BV)[i] = (OldBits >> i) & 1; 258 switchToLarge(BV); 259 } 260 } 261 262 void reserve(unsigned N) { 263 if (isSmall()) { 264 if (N > SmallNumDataBits) { 265 uintptr_t OldBits = getSmallRawBits(); 266 size_t SmallSize = getSmallSize(); 267 BitVector *BV = new BitVector(SmallSize); 268 for (size_t i = 0; i < SmallSize; ++i) 269 if ((OldBits >> i) & 1) 270 BV->set(i); 271 BV->reserve(N); 272 switchToLarge(BV); 273 } 274 } else { 275 getPointer()->reserve(N); 276 } 277 } 278 279 // Set, reset, flip 280 SmallBitVector &set() { 281 if (isSmall()) 282 setSmallBits(~uintptr_t(0)); 283 else 284 getPointer()->set(); 285 return *this; 286 } 287 288 SmallBitVector &set(unsigned Idx) { 289 if (isSmall()) 290 setSmallBits(getSmallBits() | (uintptr_t(1) << Idx)); 291 else 292 getPointer()->set(Idx); 293 return *this; 294 } 295 296 SmallBitVector &reset() { 297 if (isSmall()) 298 setSmallBits(0); 299 else 300 getPointer()->reset(); 301 return *this; 302 } 303 304 SmallBitVector &reset(unsigned Idx) { 305 if (isSmall()) 306 setSmallBits(getSmallBits() & ~(uintptr_t(1) << Idx)); 307 else 308 getPointer()->reset(Idx); 309 return *this; 310 } 311 312 SmallBitVector &flip() { 313 if (isSmall()) 314 setSmallBits(~getSmallBits()); 315 else 316 getPointer()->flip(); 317 return *this; 318 } 319 320 SmallBitVector &flip(unsigned Idx) { 321 if (isSmall()) 322 setSmallBits(getSmallBits() ^ (uintptr_t(1) << Idx)); 323 else 324 getPointer()->flip(Idx); 325 return *this; 326 } 327 328 // No argument flip. 329 SmallBitVector operator~() const { 330 return SmallBitVector(*this).flip(); 331 } 332 333 // Indexing. 334 reference operator[](unsigned Idx) { 335 assert(Idx < size() && "Out-of-bounds Bit access."); 336 return reference(*this, Idx); 337 } 338 339 bool operator[](unsigned Idx) const { 340 assert(Idx < size() && "Out-of-bounds Bit access."); 341 if (isSmall()) 342 return ((getSmallBits() >> Idx) & 1) != 0; 343 return getPointer()->operator[](Idx); 344 } 345 346 bool test(unsigned Idx) const { 347 return (*this)[Idx]; 348 } 349 350 // Comparison operators. 351 bool operator==(const SmallBitVector &RHS) const { 352 if (size() != RHS.size()) 353 return false; 354 if (isSmall()) 355 return getSmallBits() == RHS.getSmallBits(); 356 else 357 return *getPointer() == *RHS.getPointer(); 358 } 359 360 bool operator!=(const SmallBitVector &RHS) const { 361 return !(*this == RHS); 362 } 363 364 // Intersection, union, disjoint union. 365 SmallBitVector &operator&=(const SmallBitVector &RHS) { 366 resize(std::max(size(), RHS.size())); 367 if (isSmall()) 368 setSmallBits(getSmallBits() & RHS.getSmallBits()); 369 else if (!RHS.isSmall()) 370 getPointer()->operator&=(*RHS.getPointer()); 371 else { 372 SmallBitVector Copy = RHS; 373 Copy.resize(size()); 374 getPointer()->operator&=(*Copy.getPointer()); 375 } 376 return *this; 377 } 378 379 SmallBitVector &operator|=(const SmallBitVector &RHS) { 380 resize(std::max(size(), RHS.size())); 381 if (isSmall()) 382 setSmallBits(getSmallBits() | RHS.getSmallBits()); 383 else if (!RHS.isSmall()) 384 getPointer()->operator|=(*RHS.getPointer()); 385 else { 386 SmallBitVector Copy = RHS; 387 Copy.resize(size()); 388 getPointer()->operator|=(*Copy.getPointer()); 389 } 390 return *this; 391 } 392 393 SmallBitVector &operator^=(const SmallBitVector &RHS) { 394 resize(std::max(size(), RHS.size())); 395 if (isSmall()) 396 setSmallBits(getSmallBits() ^ RHS.getSmallBits()); 397 else if (!RHS.isSmall()) 398 getPointer()->operator^=(*RHS.getPointer()); 399 else { 400 SmallBitVector Copy = RHS; 401 Copy.resize(size()); 402 getPointer()->operator^=(*Copy.getPointer()); 403 } 404 return *this; 405 } 406 407 // Assignment operator. 408 const SmallBitVector &operator=(const SmallBitVector &RHS) { 409 if (isSmall()) { 410 if (RHS.isSmall()) 411 X = RHS.X; 412 else 413 switchToLarge(new BitVector(*RHS.getPointer())); 414 } else { 415 if (!RHS.isSmall()) 416 *getPointer() = *RHS.getPointer(); 417 else { 418 delete getPointer(); 419 X = RHS.X; 420 } 421 } 422 return *this; 423 } 424 425 void swap(SmallBitVector &RHS) { 426 std::swap(X, RHS.X); 427 } 428 }; 429 430 inline SmallBitVector 431 operator&(const SmallBitVector &LHS, const SmallBitVector &RHS) { 432 SmallBitVector Result(LHS); 433 Result &= RHS; 434 return Result; 435 } 436 437 inline SmallBitVector 438 operator|(const SmallBitVector &LHS, const SmallBitVector &RHS) { 439 SmallBitVector Result(LHS); 440 Result |= RHS; 441 return Result; 442 } 443 444 inline SmallBitVector 445 operator^(const SmallBitVector &LHS, const SmallBitVector &RHS) { 446 SmallBitVector Result(LHS); 447 Result ^= RHS; 448 return Result; 449 } 450 451 } // End llvm namespace 452 453 namespace std { 454 /// Implement std::swap in terms of BitVector swap. 455 inline void 456 swap(llvm::SmallBitVector &LHS, llvm::SmallBitVector &RHS) { 457 LHS.swap(RHS); 458 } 459 } 460 461 #endif 462