Index: llvm/include/llvm/ADT/BitVector.h =================================================================== --- llvm/include/llvm/ADT/BitVector.h +++ llvm/include/llvm/ADT/BitVector.h @@ -163,6 +163,19 @@ return -1; } + /// find_last - Returns the index of the last set bit, -1 if none of the bits + /// are set. + int find_last() const { + ArrayRef Words(Bits, NumBitWords(size())); + for (auto Word : enumerate(reverse(Words))) { + if (Word.value() == BitWord(0)) + continue; + unsigned Idx = NumBitWords(size()) - Word.index(); + return Idx * BITWORD_SIZE - countLeadingZeros(Word.value()) - 1; + } + return -1; + } + /// find_first_unset - Returns the index of the first unset bit, -1 if all /// of the bits are set. int find_first_unset() const { @@ -174,6 +187,31 @@ return -1; } + /// find_last_unset - Returns the index of the last unset bit, -1 if all of + /// the bits are set. + int find_last_unset() const { + ArrayRef Words(Bits, NumBitWords(size())); + for (auto Word : enumerate(reverse(Words))) { + BitWord Val = Word.value(); + if (Word.index() == 0) { + // If this is the last word in the BitVector, it has some unused bits. + // Set them all to 1 so that the countLeadingOnes check works. + unsigned UnusedCount = BITWORD_SIZE - size() % BITWORD_SIZE; + BitWord Mask = maskLeadingOnes(UnusedCount); + Val |= Mask; + } + + if (Val == ~BitWord(0)) + continue; + + unsigned Idx = NumBitWords(size()) - Word.index() - 1; + unsigned Result = (Idx + 1) * BITWORD_SIZE - countLeadingOnes(Val) - 1; + assert(Result < size()); + return Result; + } + return -1; + } + /// find_next - Returns the index of the next set bit following the /// "Prev" bit. Returns -1 if the next set bit is not found. int find_next(unsigned Prev) const { Index: llvm/include/llvm/ADT/SmallBitVector.h =================================================================== --- llvm/include/llvm/ADT/SmallBitVector.h +++ llvm/include/llvm/ADT/SmallBitVector.h @@ -117,9 +117,7 @@ } // Return the size. - size_t getSmallSize() const { - return getSmallRawBits() >> SmallNumDataBits; - } + size_t getSmallSize() const { return getSmallRawBits() >> SmallNumDataBits; } void setSmallSize(size_t Size) { setSmallRawBits(getSmallBits() | (Size << SmallNumDataBits)); @@ -216,6 +214,16 @@ return getPointer()->find_first(); } + int find_last() const { + if (isSmall()) { + uintptr_t Bits = getSmallBits(); + if (Bits == 0) + return -1; + return NumBaseBits - countLeadingZeros(Bits); + } + return getPointer()->find_last(); + } + /// Returns the index of the first unset bit, -1 if all of the bits are set. int find_first_unset() const { if (isSmall()) { @@ -228,6 +236,17 @@ return getPointer()->find_first_unset(); } + int find_last_unset() const { + if (isSmall()) { + if (count() == getSmallSize()) + return -1; + + uintptr_t Bits = getSmallBits(); + return NumBaseBits - countLeadingOnes(Bits); + } + return getPointer()->find_last_unset(); + } + /// Returns the index of the next set bit following the "Prev" bit. /// Returns -1 if the next set bit is not found. int find_next(unsigned Prev) const { Index: llvm/unittests/ADT/BitVectorTest.cpp =================================================================== --- llvm/unittests/ADT/BitVectorTest.cpp +++ llvm/unittests/ADT/BitVectorTest.cpp @@ -186,7 +186,9 @@ // Test finding in an empty BitVector. TypeParam A; EXPECT_EQ(-1, A.find_first()); + EXPECT_EQ(-1, A.find_last()); EXPECT_EQ(-1, A.find_first_unset()); + EXPECT_EQ(-1, A.find_last_unset()); EXPECT_EQ(-1, A.find_next(0)); EXPECT_EQ(-1, A.find_next_unset(0)); @@ -196,12 +198,14 @@ A.set(13); A.set(75); + EXPECT_EQ(75, A.find_last()); EXPECT_EQ(12, A.find_first()); EXPECT_EQ(13, A.find_next(12)); EXPECT_EQ(75, A.find_next(13)); EXPECT_EQ(-1, A.find_next(75)); EXPECT_EQ(0, A.find_first_unset()); + EXPECT_EQ(99, A.find_last_unset()); EXPECT_EQ(14, A.find_next_unset(11)); EXPECT_EQ(14, A.find_next_unset(12)); EXPECT_EQ(14, A.find_next_unset(13)); @@ -213,12 +217,16 @@ A.set(0, 100); EXPECT_EQ(100U, A.count()); EXPECT_EQ(0, A.find_first()); + EXPECT_EQ(99, A.find_last()); EXPECT_EQ(-1, A.find_first_unset()); + EXPECT_EQ(-1, A.find_last_unset()); A.reset(0, 100); EXPECT_EQ(0U, A.count()); EXPECT_EQ(-1, A.find_first()); + EXPECT_EQ(-1, A.find_last()); EXPECT_EQ(0, A.find_first_unset()); + EXPECT_EQ(99, A.find_last_unset()); } TYPED_TEST(BitVectorTest, CompoundAssignment) {