1 //=== CoalescingBitVectorTest.cpp - CoalescingBitVector unit tests --------===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
9 #include "llvm/ADT/CoalescingBitVector.h"
10 #include "gtest/gtest.h"
16 using UBitVec
= CoalescingBitVector
<unsigned>;
17 using U64BitVec
= CoalescingBitVector
<uint64_t>;
19 bool elementsMatch(const UBitVec
&BV
, std::initializer_list
<unsigned> List
) {
20 if (!std::equal(BV
.begin(), BV
.end(), List
.begin(), List
.end())) {
21 UBitVec::Allocator Alloc
;
22 UBitVec
Expected(Alloc
);
24 dbgs() << "elementsMatch:\n"
26 Expected
.print(dbgs());
34 bool rangesMatch(iterator_range
<UBitVec::const_iterator
> R
,
35 std::initializer_list
<unsigned> List
) {
36 return std::equal(R
.begin(), R
.end(), List
.begin(), List
.end());
39 TEST(CoalescingBitVectorTest
, Set
) {
40 UBitVec::Allocator Alloc
;
45 EXPECT_TRUE(BV1
.test(0));
46 EXPECT_FALSE(BV1
.test(1));
49 EXPECT_TRUE(BV2
.test(0));
52 TEST(CoalescingBitVectorTest
, Count
) {
53 UBitVec::Allocator Alloc
;
55 EXPECT_EQ(BV
.count(), 0u);
57 EXPECT_EQ(BV
.count(), 1u);
58 BV
.set({11, 12, 13, 14, 15});
59 EXPECT_EQ(BV
.count(), 6u);
62 TEST(CoalescingBitVectorTest
, ClearAndEmpty
) {
63 UBitVec::Allocator Alloc
;
65 EXPECT_TRUE(BV
.empty());
67 EXPECT_FALSE(BV
.empty());
69 EXPECT_TRUE(BV
.empty());
72 TEST(CoalescingBitVector
, Copy
) {
73 UBitVec::Allocator Alloc
;
77 EXPECT_TRUE(elementsMatch(BV1
, {0}));
78 EXPECT_TRUE(elementsMatch(BV2
, {0}));
81 EXPECT_TRUE(elementsMatch(BV1
, {0}));
82 EXPECT_TRUE(elementsMatch(BV2
, {0}));
85 TEST(CoalescingBitVectorTest
, Iterators
) {
86 UBitVec::Allocator Alloc
;
92 EXPECT_TRUE(It
== BV
.begin());
99 EXPECT_TRUE(It
== BV
.end());
100 EXPECT_TRUE(BV
.end() == BV
.end());
103 EXPECT_TRUE(It
== BV
.begin());
105 EXPECT_TRUE(ItCopy
== BV
.begin());
106 EXPECT_EQ(*ItCopy
, 0u);
109 EXPECT_TRUE(elementsMatch(BV
, {0, 1, 2}));
112 EXPECT_TRUE(elementsMatch(BV
, {0, 1, 2, 4, 5, 6}));
115 EXPECT_TRUE(elementsMatch(BV
, {0, 1, 2, 3, 4, 5, 6}));
118 EXPECT_TRUE(elementsMatch(BV
, {0, 1, 2, 3, 4, 5, 6, 10}));
120 // Should be able to reset unset bits.
124 BV
.set({1000, 1001, 1002});
125 EXPECT_TRUE(elementsMatch(BV
, {0, 1, 2, 4, 5, 6, 10, 1000, 1001, 1002}));
127 auto It1
= BV
.begin();
128 EXPECT_TRUE(It1
== BV
.begin());
129 EXPECT_TRUE(++It1
== ++BV
.begin());
130 EXPECT_TRUE(It1
!= BV
.begin());
131 EXPECT_TRUE(It1
!= BV
.end());
134 TEST(CoalescingBitVectorTest
, Reset
) {
135 UBitVec::Allocator Alloc
;
139 EXPECT_TRUE(BV
.test(0));
141 EXPECT_FALSE(BV
.test(0));
146 EXPECT_TRUE(elementsMatch(BV
, {2, 3}));
151 EXPECT_TRUE(elementsMatch(BV
, {1, 3}));
156 EXPECT_TRUE(elementsMatch(BV
, {1, 2}));
159 TEST(CoalescingBitVectorTest
, Comparison
) {
160 UBitVec::Allocator Alloc
;
168 EXPECT_FALSE(BV1
!= BV2
);
170 // Different number of intervals.
176 // Multiple intervals.
179 BV1
.set({1, 2, 11, 12});
180 BV2
.set({1, 2, 11, 12});
189 // A simple implementation of set union, used to double-check the human
190 // "expected" answer.
191 void simpleUnion(UBitVec
&Union
, const UBitVec
&LHS
,
192 const UBitVec
&RHS
) {
193 for (unsigned Bit
: LHS
)
194 Union
.test_and_set(Bit
);
195 for (unsigned Bit
: RHS
)
196 Union
.test_and_set(Bit
);
199 TEST(CoalescingBitVectorTest
, Union
) {
200 UBitVec::Allocator Alloc
;
202 // Check that after doing LHS |= RHS, LHS == Expected.
203 auto unionIs
= [&](std::initializer_list
<unsigned> LHS
,
204 std::initializer_list
<unsigned> RHS
,
205 std::initializer_list
<unsigned> Expected
) {
210 UBitVec
DoubleCheckedExpected(Alloc
);
211 simpleUnion(DoubleCheckedExpected
, BV1
, BV2
);
212 ASSERT_TRUE(elementsMatch(DoubleCheckedExpected
, Expected
));
214 ASSERT_TRUE(elementsMatch(BV1
, Expected
));
217 // Check that "LHS |= RHS" and "RHS |= LHS" both produce the expected result.
218 auto testUnionSymmetrically
= [&](std::initializer_list
<unsigned> LHS
,
219 std::initializer_list
<unsigned> RHS
,
220 std::initializer_list
<unsigned> Expected
) {
221 unionIs(LHS
, RHS
, Expected
);
222 unionIs(RHS
, LHS
, Expected
);
226 testUnionSymmetrically({}, {1, 2, 3}, {1, 2, 3});
229 testUnionSymmetrically({1, 2, 3}, {}, {1, 2, 3});
232 testUnionSymmetrically({1}, {1}, {1});
233 testUnionSymmetrically({1, 2, 11, 12}, {1, 2, 11, 12}, {1, 2, 11, 12});
235 // Sliding window: fix {2, 3, 4} as the LHS, and slide a window before/after
236 // it. Repeat this swapping LHS and RHS.
237 testUnionSymmetrically({2, 3, 4}, {1, 2, 3}, {1, 2, 3, 4});
238 testUnionSymmetrically({2, 3, 4}, {2, 3, 4}, {2, 3, 4});
239 testUnionSymmetrically({2, 3, 4}, {3, 4, 5}, {2, 3, 4, 5});
240 testUnionSymmetrically({1, 2, 3}, {2, 3, 4}, {1, 2, 3, 4});
241 testUnionSymmetrically({3, 4, 5}, {2, 3, 4}, {2, 3, 4, 5});
243 // Multiple overlaps, but at least one of the overlaps forces us to split an
244 // interval (and possibly both do). For ease of understanding, fix LHS to be
245 // {1, 2, 11, 12}, but vary RHS.
246 testUnionSymmetrically({1, 2, 11, 12}, {1}, {1, 2, 11, 12});
247 testUnionSymmetrically({1, 2, 11, 12}, {2}, {1, 2, 11, 12});
248 testUnionSymmetrically({1, 2, 11, 12}, {11}, {1, 2, 11, 12});
249 testUnionSymmetrically({1, 2, 11, 12}, {12}, {1, 2, 11, 12});
250 testUnionSymmetrically({1, 2, 11, 12}, {1, 11}, {1, 2, 11, 12});
251 testUnionSymmetrically({1, 2, 11, 12}, {1, 12}, {1, 2, 11, 12});
252 testUnionSymmetrically({1, 2, 11, 12}, {2, 11}, {1, 2, 11, 12});
253 testUnionSymmetrically({1, 2, 11, 12}, {2, 12}, {1, 2, 11, 12});
254 testUnionSymmetrically({1, 2, 11, 12}, {1, 2, 11}, {1, 2, 11, 12});
255 testUnionSymmetrically({1, 2, 11, 12}, {1, 2, 12}, {1, 2, 11, 12});
256 testUnionSymmetrically({1, 2, 11, 12}, {1, 11, 12}, {1, 2, 11, 12});
257 testUnionSymmetrically({1, 2, 11, 12}, {2, 11, 12}, {1, 2, 11, 12});
258 testUnionSymmetrically({1, 2, 11, 12}, {0, 11, 12}, {0, 1, 2, 11, 12});
259 testUnionSymmetrically({1, 2, 11, 12}, {3, 11, 12}, {1, 2, 3, 11, 12});
260 testUnionSymmetrically({1, 2, 11, 12}, {1, 11, 13}, {1, 2, 11, 12, 13});
261 testUnionSymmetrically({1, 2, 11, 12}, {1, 10, 11}, {1, 2, 10, 11, 12});
263 // Partial overlap, but the existing interval covers future overlaps.
264 testUnionSymmetrically({1, 2, 3, 4, 5, 6, 7, 8}, {2, 3, 4, 6, 7},
265 {1, 2, 3, 4, 5, 6, 7, 8});
266 testUnionSymmetrically({1, 2, 3, 4, 5, 6, 7, 8}, {2, 3, 7, 8, 9},
267 {1, 2, 3, 4, 5, 6, 7, 8, 9});
269 // More partial overlaps.
270 testUnionSymmetrically({1, 2, 3, 4, 5}, {0, 1, 2, 4, 5, 6},
271 {0, 1, 2, 3, 4, 5, 6});
272 testUnionSymmetrically({2, 3}, {1, 2, 3, 4}, {1, 2, 3, 4});
273 testUnionSymmetrically({3, 4}, {1, 2, 3, 4}, {1, 2, 3, 4});
274 testUnionSymmetrically({1, 2}, {1, 2, 3, 4}, {1, 2, 3, 4});
275 testUnionSymmetrically({0, 1}, {1, 2, 3, 4}, {0, 1, 2, 3, 4});
277 // Merge non-overlapping.
278 testUnionSymmetrically({0, 1}, {2, 3}, {0, 1, 2, 3});
279 testUnionSymmetrically({0, 3}, {1, 2}, {0, 1, 2, 3});
282 // A simple implementation of set intersection, used to double-check the
283 // human "expected" answer.
284 void simpleIntersection(UBitVec
&Intersection
, const UBitVec
&LHS
,
285 const UBitVec
&RHS
) {
286 for (unsigned Bit
: LHS
)
288 Intersection
.set(Bit
);
291 TEST(CoalescingBitVectorTest
, Intersection
) {
292 UBitVec::Allocator Alloc
;
294 // Check that after doing LHS &= RHS, LHS == Expected.
295 auto intersectionIs
= [&](std::initializer_list
<unsigned> LHS
,
296 std::initializer_list
<unsigned> RHS
,
297 std::initializer_list
<unsigned> Expected
) {
302 UBitVec
DoubleCheckedExpected(Alloc
);
303 simpleIntersection(DoubleCheckedExpected
, BV1
, BV2
);
304 ASSERT_TRUE(elementsMatch(DoubleCheckedExpected
, Expected
));
306 ASSERT_TRUE(elementsMatch(BV1
, Expected
));
309 // Check that "LHS &= RHS" and "RHS &= LHS" both produce the expected result.
310 auto testIntersectionSymmetrically
= [&](std::initializer_list
<unsigned> LHS
,
311 std::initializer_list
<unsigned> RHS
,
312 std::initializer_list
<unsigned> Expected
) {
313 intersectionIs(LHS
, RHS
, Expected
);
314 intersectionIs(RHS
, LHS
, Expected
);
317 // Empty case, one-element case.
318 testIntersectionSymmetrically({}, {}, {});
319 testIntersectionSymmetrically({1}, {1}, {1});
320 testIntersectionSymmetrically({1}, {2}, {});
322 // Exact overlaps cases: single overlap and multiple overlaps.
323 testIntersectionSymmetrically({1, 2}, {1, 2}, {1, 2});
324 testIntersectionSymmetrically({1, 2, 11, 12}, {1, 2, 11, 12}, {1, 2, 11, 12});
326 // Sliding window: fix {2, 3, 4} as the LHS, and slide a window before/after
328 testIntersectionSymmetrically({2, 3, 4}, {1, 2, 3}, {2, 3});
329 testIntersectionSymmetrically({2, 3, 4}, {2, 3, 4}, {2, 3, 4});
330 testIntersectionSymmetrically({2, 3, 4}, {3, 4, 5}, {3, 4});
332 // No overlap, but we have multiple intervals.
333 testIntersectionSymmetrically({1, 2, 11, 12}, {3, 4, 13, 14}, {});
335 // Multiple overlaps, but at least one of the overlaps forces us to split an
336 // interval (and possibly both do). For ease of understanding, fix LHS to be
337 // {1, 2, 11, 12}, but vary RHS.
338 testIntersectionSymmetrically({1, 2, 11, 12}, {1}, {1});
339 testIntersectionSymmetrically({1, 2, 11, 12}, {2}, {2});
340 testIntersectionSymmetrically({1, 2, 11, 12}, {11}, {11});
341 testIntersectionSymmetrically({1, 2, 11, 12}, {12}, {12});
342 testIntersectionSymmetrically({1, 2, 11, 12}, {1, 11}, {1, 11});
343 testIntersectionSymmetrically({1, 2, 11, 12}, {1, 12}, {1, 12});
344 testIntersectionSymmetrically({1, 2, 11, 12}, {2, 11}, {2, 11});
345 testIntersectionSymmetrically({1, 2, 11, 12}, {2, 12}, {2, 12});
346 testIntersectionSymmetrically({1, 2, 11, 12}, {1, 2, 11}, {1, 2, 11});
347 testIntersectionSymmetrically({1, 2, 11, 12}, {1, 2, 12}, {1, 2, 12});
348 testIntersectionSymmetrically({1, 2, 11, 12}, {1, 11, 12}, {1, 11, 12});
349 testIntersectionSymmetrically({1, 2, 11, 12}, {2, 11, 12}, {2, 11, 12});
350 testIntersectionSymmetrically({1, 2, 11, 12}, {0, 11, 12}, {11, 12});
351 testIntersectionSymmetrically({1, 2, 11, 12}, {3, 11, 12}, {11, 12});
352 testIntersectionSymmetrically({1, 2, 11, 12}, {1, 11, 13}, {1, 11});
353 testIntersectionSymmetrically({1, 2, 11, 12}, {1, 10, 11}, {1, 11});
355 // Partial overlap, but the existing interval covers future overlaps.
356 testIntersectionSymmetrically({1, 2, 3, 4, 5, 6, 7, 8}, {2, 3, 4, 6, 7},
360 // A simple implementation of set intersection-with-complement, used to
361 // double-check the human "expected" answer.
362 void simpleIntersectionWithComplement(UBitVec
&Intersection
, const UBitVec
&LHS
,
363 const UBitVec
&RHS
) {
364 for (unsigned Bit
: LHS
)
366 Intersection
.set(Bit
);
369 TEST(CoalescingBitVectorTest
, IntersectWithComplement
) {
370 UBitVec::Allocator Alloc
;
372 // Check that after doing LHS.intersectWithComplement(RHS), LHS == Expected.
373 auto intersectionWithComplementIs
=
374 [&](std::initializer_list
<unsigned> LHS
,
375 std::initializer_list
<unsigned> RHS
,
376 std::initializer_list
<unsigned> Expected
) {
381 UBitVec
DoubleCheckedExpected(Alloc
);
382 simpleIntersectionWithComplement(DoubleCheckedExpected
, BV1
, BV2
);
383 ASSERT_TRUE(elementsMatch(DoubleCheckedExpected
, Expected
));
384 BV1
.intersectWithComplement(BV2
);
385 ASSERT_TRUE(elementsMatch(BV1
, Expected
));
388 // Empty case, one-element case.
389 intersectionWithComplementIs({}, {}, {});
390 intersectionWithComplementIs({1}, {1}, {});
391 intersectionWithComplementIs({1}, {2}, {1});
393 // Exact overlaps cases: single overlap and multiple overlaps.
394 intersectionWithComplementIs({1, 2}, {1, 2}, {});
395 intersectionWithComplementIs({1, 2, 11, 12}, {1, 2, 11, 12}, {});
397 // Sliding window: fix {2, 3, 4} as the LHS, and slide a window before/after
398 // it. Repeat this swapping LHS and RHS.
399 intersectionWithComplementIs({2, 3, 4}, {1, 2, 3}, {4});
400 intersectionWithComplementIs({2, 3, 4}, {2, 3, 4}, {});
401 intersectionWithComplementIs({2, 3, 4}, {3, 4, 5}, {2});
402 intersectionWithComplementIs({1, 2, 3}, {2, 3, 4}, {1});
403 intersectionWithComplementIs({3, 4, 5}, {2, 3, 4}, {5});
405 // No overlap, but we have multiple intervals.
406 intersectionWithComplementIs({1, 2, 11, 12}, {3, 4, 13, 14}, {1, 2, 11, 12});
408 // Multiple overlaps. For ease of understanding, fix LHS to be
409 // {1, 2, 11, 12}, but vary RHS.
410 intersectionWithComplementIs({1, 2, 11, 12}, {1}, {2, 11, 12});
411 intersectionWithComplementIs({1, 2, 11, 12}, {2}, {1, 11, 12});
412 intersectionWithComplementIs({1, 2, 11, 12}, {11}, {1, 2, 12});
413 intersectionWithComplementIs({1, 2, 11, 12}, {12}, {1, 2, 11});
414 intersectionWithComplementIs({1, 2, 11, 12}, {1, 11}, {2, 12});
415 intersectionWithComplementIs({1, 2, 11, 12}, {1, 12}, {2, 11});
416 intersectionWithComplementIs({1, 2, 11, 12}, {2, 11}, {1, 12});
417 intersectionWithComplementIs({1, 2, 11, 12}, {2, 12}, {1, 11});
418 intersectionWithComplementIs({1, 2, 11, 12}, {1, 2, 11}, {12});
419 intersectionWithComplementIs({1, 2, 11, 12}, {1, 2, 12}, {11});
420 intersectionWithComplementIs({1, 2, 11, 12}, {1, 11, 12}, {2});
421 intersectionWithComplementIs({1, 2, 11, 12}, {2, 11, 12}, {1});
422 intersectionWithComplementIs({1, 2, 11, 12}, {0, 11, 12}, {1, 2});
423 intersectionWithComplementIs({1, 2, 11, 12}, {3, 11, 12}, {1, 2});
424 intersectionWithComplementIs({1, 2, 11, 12}, {1, 11, 13}, {2, 12});
425 intersectionWithComplementIs({1, 2, 11, 12}, {1, 10, 11}, {2, 12});
427 // Partial overlap, but the existing interval covers future overlaps.
428 intersectionWithComplementIs({1, 2, 3, 4, 5, 6, 7, 8}, {2, 3, 4, 6, 7},
432 TEST(CoalescingBitVectorTest
, FindLowerBound
) {
433 U64BitVec::Allocator Alloc
;
435 uint64_t BigNum1
= uint64_t(1) << 32;
436 uint64_t BigNum2
= (uint64_t(1) << 33) + 1;
437 EXPECT_TRUE(BV
.find(BigNum1
) == BV
.end());
439 auto Find1
= BV
.find(BigNum1
);
440 EXPECT_EQ(*Find1
, BigNum1
);
442 auto Find2
= BV
.find(BigNum1
);
443 EXPECT_EQ(*Find2
, BigNum1
);
444 auto Find3
= BV
.find(BigNum2
);
445 EXPECT_EQ(*Find3
, BigNum2
);
447 auto Find4
= BV
.find(BigNum1
);
448 EXPECT_EQ(*Find4
, BigNum2
);
452 EXPECT_EQ(*BV
.find(2), 2u);
453 EXPECT_EQ(*BV
.find(3), 3u);
456 TEST(CoalescingBitVectorTest
, AdvanceToLowerBound
) {
457 U64BitVec::Allocator Alloc
;
459 uint64_t BigNum1
= uint64_t(1) << 32;
460 uint64_t BigNum2
= (uint64_t(1) << 33) + 1;
462 auto advFromBegin
= [&](uint64_t To
) -> U64BitVec::const_iterator
{
463 auto It
= BV
.begin();
464 It
.advanceToLowerBound(To
);
468 EXPECT_TRUE(advFromBegin(BigNum1
) == BV
.end());
470 auto Find1
= advFromBegin(BigNum1
);
471 EXPECT_EQ(*Find1
, BigNum1
);
473 auto Find2
= advFromBegin(BigNum1
);
474 EXPECT_EQ(*Find2
, BigNum1
);
475 auto Find3
= advFromBegin(BigNum2
);
476 EXPECT_EQ(*Find3
, BigNum2
);
478 auto Find4
= advFromBegin(BigNum1
);
479 EXPECT_EQ(*Find4
, BigNum2
);
483 EXPECT_EQ(*advFromBegin(2), 2u);
484 EXPECT_EQ(*advFromBegin(3), 3u);
485 auto It
= BV
.begin();
486 It
.advanceToLowerBound(0);
488 It
.advanceToLowerBound(100);
489 EXPECT_TRUE(It
== BV
.end());
490 It
.advanceToLowerBound(100);
491 EXPECT_TRUE(It
== BV
.end());
494 TEST(CoalescingBitVectorTest
, HalfOpenRange
) {
495 UBitVec::Allocator Alloc
;
501 EXPECT_EQ(*BV
.find(0), 1U); // find(Start) > Start
502 EXPECT_TRUE(rangesMatch(BV
.half_open_range(0, 5), {1, 2, 3}));
503 EXPECT_TRUE(rangesMatch(BV
.half_open_range(1, 4), {1, 2, 3}));
504 EXPECT_TRUE(rangesMatch(BV
.half_open_range(1, 3), {1, 2}));
505 EXPECT_TRUE(rangesMatch(BV
.half_open_range(2, 3), {2}));
506 EXPECT_TRUE(rangesMatch(BV
.half_open_range(2, 4), {2, 3}));
507 EXPECT_TRUE(rangesMatch(BV
.half_open_range(4, 5), {}));
512 BV
.set({1, 2, 11, 12});
514 EXPECT_TRUE(rangesMatch(BV
.half_open_range(0, 15), {1, 2, 11, 12}));
515 EXPECT_TRUE(rangesMatch(BV
.half_open_range(1, 13), {1, 2, 11, 12}));
516 EXPECT_TRUE(rangesMatch(BV
.half_open_range(1, 12), {1, 2, 11}));
518 EXPECT_TRUE(rangesMatch(BV
.half_open_range(0, 5), {1, 2}));
519 EXPECT_TRUE(rangesMatch(BV
.half_open_range(1, 5), {1, 2}));
520 EXPECT_TRUE(rangesMatch(BV
.half_open_range(2, 5), {2}));
521 EXPECT_TRUE(rangesMatch(BV
.half_open_range(1, 2), {1}));
522 EXPECT_TRUE(rangesMatch(BV
.half_open_range(13, 14), {}));
524 EXPECT_TRUE(rangesMatch(BV
.half_open_range(2, 10), {2}));
531 EXPECT_EQ(*BV
.find(0), 1U); // find(Start) == End
532 EXPECT_TRUE(rangesMatch(BV
.half_open_range(0, 1), {}));
539 EXPECT_EQ(*BV
.find(3), 5U); // find(Start) > End
540 EXPECT_TRUE(rangesMatch(BV
.half_open_range(3, 4), {}));
544 TEST(CoalescingBitVectorTest
, Print
) {
547 raw_string_ostream
OS(S
);
548 UBitVec::Allocator Alloc
;
554 BV
.set({1, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20});