Skip to content

Commit 1eb3aae

Browse files
author
Zachary Turner
committed
[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 llvm-svn: 349173
1 parent cd3306c commit 1eb3aae

File tree

2 files changed

+292
-30
lines changed

2 files changed

+292
-30
lines changed

llvm/include/llvm/ADT/SmallBitVector.h

Lines changed: 31 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -92,10 +92,6 @@ class SmallBitVector {
9292
};
9393

9494
private:
95-
bool isSmall() const {
96-
return X & uintptr_t(1);
97-
}
98-
9995
BitVector *getPointer() const {
10096
assert(!isSmall());
10197
return reinterpret_cast<BitVector *>(X);
@@ -186,6 +182,8 @@ class SmallBitVector {
186182
return make_range(set_bits_begin(), set_bits_end());
187183
}
188184

185+
bool isSmall() const { return X & uintptr_t(1); }
186+
189187
/// Tests whether there are no bits in this bitvector.
190188
bool empty() const {
191189
return isSmall() ? getSmallSize() == 0 : getPointer()->empty();
@@ -242,7 +240,7 @@ class SmallBitVector {
242240
uintptr_t Bits = getSmallBits();
243241
if (Bits == 0)
244242
return -1;
245-
return NumBaseBits - countLeadingZeros(Bits);
243+
return NumBaseBits - countLeadingZeros(Bits) - 1;
246244
}
247245
return getPointer()->find_last();
248246
}
@@ -265,7 +263,9 @@ class SmallBitVector {
265263
return -1;
266264

267265
uintptr_t Bits = getSmallBits();
268-
return NumBaseBits - countLeadingOnes(Bits);
266+
// Set unused bits.
267+
Bits |= ~uintptr_t(0) << getSmallSize();
268+
return NumBaseBits - countLeadingOnes(Bits) - 1;
269269
}
270270
return getPointer()->find_last_unset();
271271
}
@@ -487,27 +487,37 @@ class SmallBitVector {
487487
bool operator==(const SmallBitVector &RHS) const {
488488
if (size() != RHS.size())
489489
return false;
490-
if (isSmall())
490+
if (isSmall() && RHS.isSmall())
491491
return getSmallBits() == RHS.getSmallBits();
492-
else
492+
else if (!isSmall() && !RHS.isSmall())
493493
return *getPointer() == *RHS.getPointer();
494+
else {
495+
for (size_t i = 0, e = size(); i != e; ++i) {
496+
if ((*this)[i] != RHS[i])
497+
return false;
498+
}
499+
return true;
500+
}
494501
}
495502

496503
bool operator!=(const SmallBitVector &RHS) const {
497504
return !(*this == RHS);
498505
}
499506

500507
// Intersection, union, disjoint union.
508+
// FIXME BitVector::operator&= does not resize the LHS but this does
501509
SmallBitVector &operator&=(const SmallBitVector &RHS) {
502510
resize(std::max(size(), RHS.size()));
503-
if (isSmall())
511+
if (isSmall() && RHS.isSmall())
504512
setSmallBits(getSmallBits() & RHS.getSmallBits());
505-
else if (!RHS.isSmall())
513+
else if (!isSmall() && !RHS.isSmall())
506514
getPointer()->operator&=(*RHS.getPointer());
507515
else {
508-
SmallBitVector Copy = RHS;
509-
Copy.resize(size());
510-
getPointer()->operator&=(*Copy.getPointer());
516+
size_t i, e;
517+
for (i = 0, e = std::min(size(), RHS.size()); i != e; ++i)
518+
(*this)[i] = test(i) && RHS.test(i);
519+
for (e = size(); i != e; ++i)
520+
reset(i);
511521
}
512522
return *this;
513523
}
@@ -547,28 +557,26 @@ class SmallBitVector {
547557

548558
SmallBitVector &operator|=(const SmallBitVector &RHS) {
549559
resize(std::max(size(), RHS.size()));
550-
if (isSmall())
560+
if (isSmall() && RHS.isSmall())
551561
setSmallBits(getSmallBits() | RHS.getSmallBits());
552-
else if (!RHS.isSmall())
562+
else if (!isSmall() && !RHS.isSmall())
553563
getPointer()->operator|=(*RHS.getPointer());
554564
else {
555-
SmallBitVector Copy = RHS;
556-
Copy.resize(size());
557-
getPointer()->operator|=(*Copy.getPointer());
565+
for (size_t i = 0, e = RHS.size(); i != e; ++i)
566+
(*this)[i] = test(i) || RHS.test(i);
558567
}
559568
return *this;
560569
}
561570

562571
SmallBitVector &operator^=(const SmallBitVector &RHS) {
563572
resize(std::max(size(), RHS.size()));
564-
if (isSmall())
573+
if (isSmall() && RHS.isSmall())
565574
setSmallBits(getSmallBits() ^ RHS.getSmallBits());
566-
else if (!RHS.isSmall())
575+
else if (!isSmall() && !RHS.isSmall())
567576
getPointer()->operator^=(*RHS.getPointer());
568577
else {
569-
SmallBitVector Copy = RHS;
570-
Copy.resize(size());
571-
getPointer()->operator^=(*Copy.getPointer());
578+
for (size_t i = 0, e = RHS.size(); i != e; ++i)
579+
(*this)[i] = test(i) != RHS.test(i);
572580
}
573581
return *this;
574582
}

0 commit comments

Comments
 (0)