llvm.org GIT mirror llvm / 3a50d5b
[ADT] Fix bugs in SmallBitVector. Fixes: * find_last/find_last_unset - off-by-one error * Compound assignment ops and operator== when mixing big/small modes Patch by Brad Moody Differential Revision: https://reviews.llvm.org/D54933 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@349173 91177308-0d34-0410-b5e6-96231b3b80d8 Zachary Turner 1 year, 10 months ago
2 changed file(s) with 293 addition(s) and 31 deletion(s). Raw diff Collapse all Expand all
9191 };
9292
9393 private:
94 bool isSmall() const {
95 return X & uintptr_t(1);
96 }
97
9894 BitVector *getPointer() const {
9995 assert(!isSmall());
10096 return reinterpret_cast(X);
185181 return make_range(set_bits_begin(), set_bits_end());
186182 }
187183
184 bool isSmall() const { return X & uintptr_t(1); }
185
188186 /// Tests whether there are no bits in this bitvector.
189187 bool empty() const {
190188 return isSmall() ? getSmallSize() == 0 : getPointer()->empty();
241239 uintptr_t Bits = getSmallBits();
242240 if (Bits == 0)
243241 return -1;
244 return NumBaseBits - countLeadingZeros(Bits);
242 return NumBaseBits - countLeadingZeros(Bits) - 1;
245243 }
246244 return getPointer()->find_last();
247245 }
264262 return -1;
265263
266264 uintptr_t Bits = getSmallBits();
267 return NumBaseBits - countLeadingOnes(Bits);
265 // Set unused bits.
266 Bits |= ~uintptr_t(0) << getSmallSize();
267 return NumBaseBits - countLeadingOnes(Bits) - 1;
268268 }
269269 return getPointer()->find_last_unset();
270270 }
486486 bool operator==(const SmallBitVector &RHS) const {
487487 if (size() != RHS.size())
488488 return false;
489 if (isSmall())
489 if (isSmall() && RHS.isSmall())
490490 return getSmallBits() == RHS.getSmallBits();
491 else
491 else if (!isSmall() && !RHS.isSmall())
492492 return *getPointer() == *RHS.getPointer();
493 else {
494 for (size_t i = 0, e = size(); i != e; ++i) {
495 if ((*this)[i] != RHS[i])
496 return false;
497 }
498 return true;
499 }
493500 }
494501
495502 bool operator!=(const SmallBitVector &RHS) const {
497504 }
498505
499506 // Intersection, union, disjoint union.
507 // FIXME BitVector::operator&= does not resize the LHS but this does
500508 SmallBitVector &operator&=(const SmallBitVector &RHS) {
501509 resize(std::max(size(), RHS.size()));
502 if (isSmall())
510 if (isSmall() && RHS.isSmall())
503511 setSmallBits(getSmallBits() & RHS.getSmallBits());
504 else if (!RHS.isSmall())
512 else if (!isSmall() && !RHS.isSmall())
505513 getPointer()->operator&=(*RHS.getPointer());
506514 else {
507 SmallBitVector Copy = RHS;
508 Copy.resize(size());
509 getPointer()->operator&=(*Copy.getPointer());
515 size_t i, e;
516 for (i = 0, e = std::min(size(), RHS.size()); i != e; ++i)
517 (*this)[i] = test(i) && RHS.test(i);
518 for (e = size(); i != e; ++i)
519 reset(i);
510520 }
511521 return *this;
512522 }
546556
547557 SmallBitVector &operator|=(const SmallBitVector &RHS) {
548558 resize(std::max(size(), RHS.size()));
549 if (isSmall())
559 if (isSmall() && RHS.isSmall())
550560 setSmallBits(getSmallBits() | RHS.getSmallBits());
551 else if (!RHS.isSmall())
561 else if (!isSmall() && !RHS.isSmall())
552562 getPointer()->operator|=(*RHS.getPointer());
553563 else {
554 SmallBitVector Copy = RHS;
555 Copy.resize(size());
556 getPointer()->operator|=(*Copy.getPointer());
564 for (size_t i = 0, e = RHS.size(); i != e; ++i)
565 (*this)[i] = test(i) || RHS.test(i);
557566 }
558567 return *this;
559568 }
560569
561570 SmallBitVector &operator^=(const SmallBitVector &RHS) {
562571 resize(std::max(size(), RHS.size()));
563 if (isSmall())
572 if (isSmall() && RHS.isSmall())
564573 setSmallBits(getSmallBits() ^ RHS.getSmallBits());
565 else if (!RHS.isSmall())
574 else if (!isSmall() && !RHS.isSmall())
566575 getPointer()->operator^=(*RHS.getPointer());
567576 else {
568 SmallBitVector Copy = RHS;
569 Copy.resize(size());
570 getPointer()->operator^=(*Copy.getPointer());
577 for (size_t i = 0, e = RHS.size(); i != e; ++i)
578 (*this)[i] = test(i) != RHS.test(i);
571579 }
572580 return *this;
573581 }
181181 EXPECT_TRUE(Vec.empty());
182182 }
183183
184 TYPED_TEST(BitVectorTest, SimpleFindOps) {
185 // Test finding in an empty BitVector.
184 TYPED_TEST(BitVectorTest, SimpleFindOpsMultiWord) {
186185 TypeParam A;
187 EXPECT_EQ(-1, A.find_first());
188 EXPECT_EQ(-1, A.find_last());
189 EXPECT_EQ(-1, A.find_first_unset());
190 EXPECT_EQ(-1, A.find_last_unset());
191186
192187 // Test finding next set and unset bits in a BitVector with multiple words
193188 A.resize(100);
231226 EXPECT_EQ(0, A.find_first_unset());
232227 EXPECT_EQ(99, A.find_last_unset());
233228 EXPECT_EQ(99, A.find_next_unset(98));
234
235 // Also test with a vector that is small enough to fit in 1 word.
229 }
230
231 // Check if a SmallBitVector is in small mode. This check is used in tests
232 // that run for both SmallBitVector and BitVector. This check doesn't apply
233 // to BitVector so we provide an overload that returns true to get the tests
234 // to compile.
235 static bool SmallBitVectorIsSmallMode(const SmallBitVector &bv) {
236 return bv.isSmall();
237 }
238 static bool SmallBitVectorIsSmallMode(const BitVector &) { return true; }
239
240 // These tests are intended to exercise the single-word case of BitVector
241 // and the small-mode case of SmallBitVector.
242 TYPED_TEST(BitVectorTest, SimpleFindOpsSingleWord) {
243 // Test finding in an empty BitVector.
244 TypeParam A;
245 ASSERT_TRUE(SmallBitVectorIsSmallMode(A));
246 EXPECT_EQ(-1, A.find_first());
247 EXPECT_EQ(-1, A.find_last());
248 EXPECT_EQ(-1, A.find_first_unset());
249 EXPECT_EQ(-1, A.find_last_unset());
250
236251 A.resize(20);
237252 A.set(3);
238253 A.set(4);
239254 A.set(16);
255 ASSERT_TRUE(SmallBitVectorIsSmallMode(A));
240256 EXPECT_EQ(16, A.find_last());
241257 EXPECT_EQ(3, A.find_first());
242258 EXPECT_EQ(3, A.find_next(1));
430446 A &= B;
431447 EXPECT_FALSE(A.test(2));
432448 EXPECT_FALSE(A.test(7));
449 EXPECT_TRUE(A.test(4));
450 EXPECT_TRUE(A.test(5));
433451 EXPECT_EQ(2U, A.count());
434452 EXPECT_EQ(50U, A.size());
435453
441459 EXPECT_TRUE(A.test(7));
442460 EXPECT_EQ(98U, A.count());
443461 EXPECT_EQ(100U, A.size());
462 }
463
464 // Test SmallBitVector operations with mixed big/small representations
465 TYPED_TEST(BitVectorTest, MixedBigSmall) {
466 {
467 TypeParam Big;
468 TypeParam Small;
469
470 Big.reserve(100);
471 Big.resize(20);
472 Small.resize(10);
473
474 Small.set(0);
475 Small.set(1);
476 Big.set(0);
477 Big.set(2);
478 Big.set(16);
479
480 Small &= Big;
481 EXPECT_TRUE(Small.test(0));
482 EXPECT_EQ(1u, Small.count());
483 // FIXME BitVector and SmallBitVector behave differently here.
484 // SmallBitVector resizes the LHS to max(LHS.size(), RHS.size())
485 // but BitVector does not.
486 // EXPECT_EQ(20u, Small.size());
487 }
488
489 {
490 TypeParam Big;
491 TypeParam Small;
492
493 Big.reserve(100);
494 Big.resize(20);
495 Small.resize(10);
496
497 Small.set(0);
498 Small.set(1);
499 Big.set(0);
500 Big.set(2);
501 Big.set(16);
502
503 Big &= Small;
504 EXPECT_TRUE(Big.test(0));
505 EXPECT_EQ(1u, Big.count());
506 // FIXME BitVector and SmallBitVector behave differently here.
507 // SmallBitVector resizes the LHS to max(LHS.size(), RHS.size())
508 // but BitVector does not.
509 // EXPECT_EQ(20u, Big.size());
510 }
511
512 {
513 TypeParam Big;
514 TypeParam Small;
515
516 Big.reserve(100);
517 Big.resize(20);
518 Small.resize(10);
519
520 Small.set(0);
521 Small.set(1);
522 Big.set(0);
523 Big.set(2);
524 Big.set(16);
525
526 Small |= Big;
527 EXPECT_TRUE(Small.test(0));
528 EXPECT_TRUE(Small.test(1));
529 EXPECT_TRUE(Small.test(2));
530 EXPECT_TRUE(Small.test(16));
531 EXPECT_EQ(4u, Small.count());
532 EXPECT_EQ(20u, Small.size());
533 }
534
535 {
536 TypeParam Big;
537 TypeParam Small;
538
539 Big.reserve(100);
540 Big.resize(20);
541 Small.resize(10);
542
543 Small.set(0);
544 Small.set(1);
545 Big.set(0);
546 Big.set(2);
547 Big.set(16);
548
549 Big |= Small;
550 EXPECT_TRUE(Big.test(0));
551 EXPECT_TRUE(Big.test(1));
552 EXPECT_TRUE(Big.test(2));
553 EXPECT_TRUE(Big.test(16));
554 EXPECT_EQ(4u, Big.count());
555 EXPECT_EQ(20u, Big.size());
556 }
557
558 {
559 TypeParam Big;
560 TypeParam Small;
561
562 Big.reserve(100);
563 Big.resize(20);
564 Small.resize(10);
565
566 Small.set(0);
567 Small.set(1);
568 Big.set(0);
569 Big.set(2);
570 Big.set(16);
571
572 Small ^= Big;
573 EXPECT_TRUE(Small.test(1));
574 EXPECT_TRUE(Small.test(2));
575 EXPECT_TRUE(Small.test(16));
576 EXPECT_EQ(3u, Small.count());
577 EXPECT_EQ(20u, Small.size());
578 }
579
580 {
581 TypeParam Big;
582 TypeParam Small;
583
584 Big.reserve(100);
585 Big.resize(20);
586 Small.resize(10);
587
588 Small.set(0);
589 Small.set(1);
590 Big.set(0);
591 Big.set(2);
592 Big.set(16);
593
594 Big ^= Small;
595 EXPECT_TRUE(Big.test(1));
596 EXPECT_TRUE(Big.test(2));
597 EXPECT_TRUE(Big.test(16));
598 EXPECT_EQ(3u, Big.count());
599 EXPECT_EQ(20u, Big.size());
600 }
601
602 {
603 TypeParam Big;
604 TypeParam Small;
605
606 Big.reserve(100);
607 Big.resize(20);
608 Small.resize(10);
609
610 Small.set(0);
611 Small.set(1);
612 Big.set(0);
613 Big.set(2);
614 Big.set(16);
615
616 Small.reset(Big);
617 EXPECT_TRUE(Small.test(1));
618 EXPECT_EQ(1u, Small.count());
619 EXPECT_EQ(10u, Small.size());
620 }
621
622 {
623 TypeParam Big;
624 TypeParam Small;
625
626 Big.reserve(100);
627 Big.resize(20);
628 Small.resize(10);
629
630 Small.set(0);
631 Small.set(1);
632 Big.set(0);
633 Big.set(2);
634 Big.set(16);
635
636 Big.reset(Small);
637 EXPECT_TRUE(Big.test(2));
638 EXPECT_TRUE(Big.test(16));
639 EXPECT_EQ(2u, Big.count());
640 EXPECT_EQ(20u, Big.size());
641 }
642
643 {
644 TypeParam Big;
645 TypeParam Small;
646
647 Big.reserve(100);
648 Big.resize(10);
649 Small.resize(10);
650
651 Small.set(0);
652 Small.set(1);
653 Big.set(0);
654
655 EXPECT_FALSE(Big == Small);
656 EXPECT_FALSE(Small == Big);
657 Big.set(1);
658 EXPECT_TRUE(Big == Small);
659 EXPECT_TRUE(Small == Big);
660 }
661
662 {
663 TypeParam Big;
664 TypeParam Small;
665
666 Big.reserve(100);
667 Big.resize(20);
668 Small.resize(10);
669
670 Small.set(0);
671 Big.set(1);
672
673 EXPECT_FALSE(Small.anyCommon(Big));
674 EXPECT_FALSE(Big.anyCommon(Small));
675 Big.set(0);
676 EXPECT_TRUE(Small.anyCommon(Big));
677 EXPECT_TRUE(Big.anyCommon(Small));
678 }
679
680 {
681 TypeParam Big;
682 TypeParam Small;
683
684 Big.reserve(100);
685 Big.resize(10);
686 Small.resize(10);
687
688 Small.set(0);
689 Small.set(1);
690 Big.set(0);
691
692 EXPECT_TRUE(Small.test(Big));
693 EXPECT_FALSE(Big.test(Small));
694 Big.set(1);
695 EXPECT_FALSE(Small.test(Big));
696 EXPECT_FALSE(Big.test(Small));
697 }
444698 }
445699
446700 TYPED_TEST(BitVectorTest, ProxyIndex) {