llvm.org GIT mirror llvm / a360984
[Support] Add support for finding unset bits in a BitVector. BitVector had methods for searching for the first and next set bits, but it did not have analagous methods for finding the first and next unset bits. This is useful when your ones and zeros are grouped together and you want to iterate over ranges of ones and zeros. Differential Revision: https://reviews.llvm.org/D31802 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@299857 91177308-0d34-0410-b5e6-96231b3b80d8 Zachary Turner 2 years ago
3 changed file(s) with 108 addition(s) and 0 deletion(s). Raw diff Collapse all Expand all
160160 return -1;
161161 }
162162
163 /// find_first_unset - Returns the index of the first unset bit, -1 if all
164 /// of the bits are set.
165 int find_first_unset() const {
166 for (unsigned i = 0; i < NumBitWords(size()); ++i)
167 if (Bits[i] != ~0UL) {
168 unsigned Result = i * BITWORD_SIZE + countTrailingOnes(Bits[i]);
169 return Result < size() ? Result : -1;
170 }
171 return -1;
172 }
173
163174 /// find_next - Returns the index of the next set bit following the
164175 /// "Prev" bit. Returns -1 if the next set bit is not found.
165176 int find_next(unsigned Prev) const {
180191 for (unsigned i = WordPos+1; i < NumBitWords(size()); ++i)
181192 if (Bits[i] != 0)
182193 return i * BITWORD_SIZE + countTrailingZeros(Bits[i]);
194 return -1;
195 }
196
197 /// find_next_unset - Returns the index of the next usnet bit following the
198 /// "Prev" bit. Returns -1 if all remaining bits are set.
199 int find_next_unset(unsigned Prev) const {
200 ++Prev;
201 if (Prev >= Size)
202 return -1;
203
204 unsigned WordPos = Prev / BITWORD_SIZE;
205 unsigned BitPos = Prev % BITWORD_SIZE;
206 BitWord Copy = Bits[WordPos];
207 // Mask in previous bits.
208 BitWord Mask = (1 << BitPos) - 1;
209 Copy |= Mask;
210
211 if (Copy != ~0UL)
212 return next_unset_in_word(WordPos, Copy);
213
214 // Check subsequent words.
215 for (unsigned i = WordPos + 1; i < NumBitWords(size()); ++i)
216 if (Bits[i] != ~0UL)
217 return next_unset_in_word(i, Bits[i]);
183218 return -1;
184219 }
185220
502537 }
503538
504539 private:
540 int next_unset_in_word(int WordIndex, BitWord Word) const {
541 unsigned Result = WordIndex * BITWORD_SIZE + countTrailingOnes(Word);
542 return Result < size() ? Result : -1;
543 }
544
505545 unsigned NumBitWords(unsigned S) const {
506546 return (S + BITWORD_SIZE-1) / BITWORD_SIZE;
507547 }
215215 return getPointer()->find_first();
216216 }
217217
218 /// Returns the index of the first unset bit, -1 if all of the bits are set.
219 int find_first_unset() const {
220 if (isSmall()) {
221 if (count() == getSmallSize())
222 return -1;
223
224 uintptr_t Bits = getSmallBits();
225 return countTrailingOnes(Bits);
226 }
227 return getPointer()->find_first_unset();
228 }
229
218230 /// Returns the index of the next set bit following the "Prev" bit.
219231 /// Returns -1 if the next set bit is not found.
220232 int find_next(unsigned Prev) const {
227239 return countTrailingZeros(Bits);
228240 }
229241 return getPointer()->find_next(Prev);
242 }
243
244 /// Returns the index of the next unset bit following the "Prev" bit.
245 /// Returns -1 if the next unset bit is not found.
246 int find_next_unset(unsigned Prev) const {
247 if (isSmall()) {
248 ++Prev;
249 uintptr_t Bits = getSmallBits();
250 // Mask in previous bits.
251 uintptr_t Mask = (1 << Prev) - 1;
252 Bits |= Mask;
253
254 if (Bits == ~uintptr_t(0) || Prev + 1 >= getSmallSize())
255 return -1;
256 return countTrailingOnes(Bits);
257 }
258 return getPointer()->find_next_unset(Prev);
230259 }
231260
232261 /// Clear all bits.
181181 EXPECT_TRUE(Vec.empty());
182182 }
183183
184 TYPED_TEST(BitVectorTest, FindOperations) {
185 // Test finding in an empty BitVector.
186 TypeParam A;
187 EXPECT_EQ(-1, A.find_first());
188 EXPECT_EQ(-1, A.find_first_unset());
189 EXPECT_EQ(-1, A.find_next(0));
190 EXPECT_EQ(-1, A.find_next_unset(0));
191
192 // Test finding next set and unset bits in a BitVector with multiple words
193 A.resize(100);
194 A.set(12);
195 A.set(13);
196 A.set(75);
197
198 EXPECT_EQ(12, A.find_first());
199 EXPECT_EQ(13, A.find_next(12));
200 EXPECT_EQ(75, A.find_next(13));
201 EXPECT_EQ(-1, A.find_next(75));
202
203 EXPECT_EQ(0, A.find_first_unset());
204 EXPECT_EQ(14, A.find_next_unset(11));
205 EXPECT_EQ(14, A.find_next_unset(12));
206 EXPECT_EQ(14, A.find_next_unset(13));
207 EXPECT_EQ(16, A.find_next_unset(15));
208 EXPECT_EQ(76, A.find_next_unset(74));
209 EXPECT_EQ(76, A.find_next_unset(75));
210 EXPECT_EQ(-1, A.find_next_unset(99));
211
212 A.set(0, 100);
213 EXPECT_EQ(100, A.count());
214 EXPECT_EQ(0, A.find_first());
215 EXPECT_EQ(-1, A.find_first_unset());
216
217 A.reset(0, 100);
218 EXPECT_EQ(0, A.count());
219 EXPECT_EQ(-1, A.find_first());
220 EXPECT_EQ(0, A.find_first_unset());
221 }
222
184223 TYPED_TEST(BitVectorTest, CompoundAssignment) {
185224 TypeParam A;
186225 A.resize(10);