llvm.org GIT mirror llvm / ff5bad0
Add portable bit mask operations to BitVector. BitVector uses the native word size for its internal representation. That doesn't work well for literal bit masks in source code. This patch adds BitVector operations to efficiently apply literal bit masks specified as arrays of uint32_t. Since each array entry always holds exactly 32 bits, these portable bit masks can be source code literals, probably produced by TableGen. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@148272 91177308-0d34-0410-b5e6-96231b3b80d8 Jakob Stoklund Olesen 7 years ago
2 changed file(s) with 109 addition(s) and 0 deletion(s). Raw diff Collapse all Expand all
364364 std::swap(Capacity, RHS.Capacity);
365365 }
366366
367 //===--------------------------------------------------------------------===//
368 // Portable bit mask operations.
369 //===--------------------------------------------------------------------===//
370 //
371 // These methods all operate on arrays of uint32_t, each holding 32 bits. The
372 // fixed word size makes it easier to work with literal bit vector constants
373 // in portable code.
374 //
375 // The LSB in each word is the lowest numbered bit. The size of a portable
376 // bit mask is always a whole multiple of 32 bits. If no bit mask size is
377 // given, the bit mask is assumed to cover the entire BitVector.
378
379 /// setBitsInMask - Add '1' bits from Mask to this vector. Don't resize.
380 /// This computes "*this |= Mask".
381 void setBitsInMask(const uint32_t *Mask, unsigned MaskWords = ~0u) {
382 applyMask(Mask, MaskWords);
383 }
384
385 /// clearBitsInMask - Clear any bits in this vector that are set in Mask.
386 /// Don't resize. This computes "*this &= ~Mask".
387 void clearBitsInMask(const uint32_t *Mask, unsigned MaskWords = ~0u) {
388 applyMask(Mask, MaskWords);
389 }
390
391 /// setBitsNotInMask - Add a bit to this vector for every '0' bit in Mask.
392 /// Don't resize. This computes "*this |= ~Mask".
393 void setBitsNotInMask(const uint32_t *Mask, unsigned MaskWords = ~0u) {
394 applyMask(Mask, MaskWords);
395 }
396
397 /// clearBitsNotInMask - Clear a bit in this vector for every '0' bit in Mask.
398 /// Don't resize. This computes "*this &= Mask".
399 void clearBitsNotInMask(const uint32_t *Mask, unsigned MaskWords = ~0u) {
400 applyMask(Mask, MaskWords);
401 }
402
367403 private:
368404 unsigned NumBitWords(unsigned S) const {
369405 return (S + BITWORD_SIZE-1) / BITWORD_SIZE;
399435 void init_words(BitWord *B, unsigned NumWords, bool t) {
400436 memset(B, 0 - (int)t, NumWords*sizeof(BitWord));
401437 }
438
439 template
440 void applyMask(const uint32_t *Mask, unsigned MaskWords) {
441 assert(BITWORD_SIZE % 32 == 0 && "Unsupported BitWord size.");
442 MaskWords = std::min(MaskWords, (size() + 31) / 32);
443 const unsigned Scale = BITWORD_SIZE / 32;
444 unsigned i;
445 for (i = 0; MaskWords >= Scale; ++i, MaskWords -= Scale) {
446 BitWord BW = Bits[i];
447 // This inner loop should unroll completely when BITWORD_SIZE > 32.
448 for (unsigned b = 0; b != BITWORD_SIZE; b += 32) {
449 uint32_t M = *Mask++;
450 if (InvertMask) M = ~M;
451 if (AddBits) BW |= BitWord(M) << b;
452 else BW &= ~(BitWord(M) << b);
453 }
454 Bits[i] = BW;
455 }
456 for (unsigned b = 0; MaskWords; b += 32, --MaskWords) {
457 uint32_t M = *Mask++;
458 if (InvertMask) M = ~M;
459 if (AddBits) Bits[i] |= BitWord(M) << b;
460 else Bits[i] &= ~(BitWord(M) << b);
461 }
462 if (AddBits)
463 clear_unused_bits();
464 }
402465 };
403466
404467 inline BitVector operator&(const BitVector &LHS, const BitVector &RHS) {
195195 EXPECT_TRUE(Vec.none());
196196 }
197197
198 TEST(BitVectorTest, PortableBitMask) {
199 BitVector A;
200 const uint32_t Mask1[] = { 0x80000000, 6, 5 };
201
202 A.resize(10);
203 A.setBitsInMask(Mask1, 3);
204 EXPECT_EQ(10u, A.size());
205 EXPECT_FALSE(A.test(0));
206
207 A.resize(32);
208 A.setBitsInMask(Mask1, 3);
209 EXPECT_FALSE(A.test(0));
210 EXPECT_TRUE(A.test(31));
211 EXPECT_EQ(1u, A.count());
212
213 A.resize(33);
214 A.setBitsInMask(Mask1, 1);
215 EXPECT_EQ(1u, A.count());
216 A.setBitsInMask(Mask1, 2);
217 EXPECT_EQ(1u, A.count());
218
219 A.resize(34);
220 A.setBitsInMask(Mask1, 2);
221 EXPECT_EQ(2u, A.count());
222
223 A.resize(65);
224 A.setBitsInMask(Mask1, 3);
225 EXPECT_EQ(4u, A.count());
226
227 A.setBitsNotInMask(Mask1, 1);
228 EXPECT_EQ(32u+3u, A.count());
229
230 A.setBitsNotInMask(Mask1, 3);
231 EXPECT_EQ(65u, A.count());
232
233 A.resize(96);
234 EXPECT_EQ(65u, A.count());
235
236 A.clear();
237 A.resize(128);
238 A.setBitsNotInMask(Mask1, 3);
239 EXPECT_EQ(96u-5u, A.count());
240
241 A.clearBitsNotInMask(Mask1, 1);
242 EXPECT_EQ(64-4u, A.count());
243 }
198244 }
199245
200246 #endif