xref: /llvm-project/llvm/include/llvm/ADT/CoalescingBitVector.h (revision 6b6a542c1d819b47d26e462ac14b89a951615beb)
1b0142cd9SVedant Kumar //===- llvm/ADT/CoalescingBitVector.h - A coalescing bitvector --*- C++ -*-===//
2b0142cd9SVedant Kumar //
3b0142cd9SVedant Kumar // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4b0142cd9SVedant Kumar // See https://llvm.org/LICENSE.txt for license information.
5b0142cd9SVedant Kumar // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6b0142cd9SVedant Kumar //
7b0142cd9SVedant Kumar //===----------------------------------------------------------------------===//
8b0142cd9SVedant Kumar ///
9c95df64cSShivam Gupta /// \file
10c95df64cSShivam Gupta /// A bitvector that uses an IntervalMap to coalesce adjacent elements
11b0142cd9SVedant Kumar /// into intervals.
12b0142cd9SVedant Kumar ///
13b0142cd9SVedant Kumar //===----------------------------------------------------------------------===//
14b0142cd9SVedant Kumar 
15b0142cd9SVedant Kumar #ifndef LLVM_ADT_COALESCINGBITVECTOR_H
16b0142cd9SVedant Kumar #define LLVM_ADT_COALESCINGBITVECTOR_H
17b0142cd9SVedant Kumar 
18b0142cd9SVedant Kumar #include "llvm/ADT/IntervalMap.h"
19a0d5e938Sserge-sans-paille #include "llvm/ADT/STLExtras.h"
20b0142cd9SVedant Kumar #include "llvm/ADT/SmallVector.h"
212ecaf935SVedant Kumar #include "llvm/ADT/iterator_range.h"
22b0142cd9SVedant Kumar #include "llvm/Support/Debug.h"
23b0142cd9SVedant Kumar #include "llvm/Support/raw_ostream.h"
24b0142cd9SVedant Kumar 
25b0142cd9SVedant Kumar #include <initializer_list>
26b0142cd9SVedant Kumar 
27b0142cd9SVedant Kumar namespace llvm {
28b0142cd9SVedant Kumar 
29b0142cd9SVedant Kumar /// A bitvector that, under the hood, relies on an IntervalMap to coalesce
30b0142cd9SVedant Kumar /// elements into intervals. Good for representing sets which predominantly
31b0142cd9SVedant Kumar /// contain contiguous ranges. Bad for representing sets with lots of gaps
32b0142cd9SVedant Kumar /// between elements.
33b0142cd9SVedant Kumar ///
34b0142cd9SVedant Kumar /// Compared to SparseBitVector, CoalescingBitVector offers more predictable
35b0142cd9SVedant Kumar /// performance for non-sequential find() operations.
36b0142cd9SVedant Kumar ///
37259238baSSimon Pilgrim /// \tparam IndexT - The type of the index into the bitvector.
38f26fc568SDimitry Andric template <typename IndexT> class CoalescingBitVector {
39*6b6a542cSJonas Devlieghere   static_assert(std::is_unsigned<IndexT>::value,
40b0142cd9SVedant Kumar                 "Index must be an unsigned integer.");
41b0142cd9SVedant Kumar 
42f26fc568SDimitry Andric   using ThisT = CoalescingBitVector<IndexT>;
43b0142cd9SVedant Kumar 
44b0142cd9SVedant Kumar   /// An interval map for closed integer ranges. The mapped values are unused.
45f26fc568SDimitry Andric   using MapT = IntervalMap<IndexT, char>;
46b0142cd9SVedant Kumar 
47b0142cd9SVedant Kumar   using UnderlyingIterator = typename MapT::const_iterator;
48b0142cd9SVedant Kumar 
49b0142cd9SVedant Kumar   using IntervalT = std::pair<IndexT, IndexT>;
50b0142cd9SVedant Kumar 
51b0142cd9SVedant Kumar public:
52b0142cd9SVedant Kumar   using Allocator = typename MapT::Allocator;
53b0142cd9SVedant Kumar 
54b0142cd9SVedant Kumar   /// Construct by passing in a CoalescingBitVector<IndexT>::Allocator
55b0142cd9SVedant Kumar   /// reference.
CoalescingBitVector(Allocator & Alloc)56b0142cd9SVedant Kumar   CoalescingBitVector(Allocator &Alloc)
574716ebb8SVedant Kumar       : Alloc(&Alloc), Intervals(Alloc) {}
58b0142cd9SVedant Kumar 
59b0142cd9SVedant Kumar   /// \name Copy/move constructors and assignment operators.
60b0142cd9SVedant Kumar   /// @{
61b0142cd9SVedant Kumar 
CoalescingBitVector(const ThisT & Other)62b0142cd9SVedant Kumar   CoalescingBitVector(const ThisT &Other)
634716ebb8SVedant Kumar       : Alloc(Other.Alloc), Intervals(*Other.Alloc) {
64b0142cd9SVedant Kumar     set(Other);
65b0142cd9SVedant Kumar   }
66b0142cd9SVedant Kumar 
67b0142cd9SVedant Kumar   ThisT &operator=(const ThisT &Other) {
68b0142cd9SVedant Kumar     clear();
69b0142cd9SVedant Kumar     set(Other);
70b0142cd9SVedant Kumar     return *this;
71b0142cd9SVedant Kumar   }
72b0142cd9SVedant Kumar 
734716ebb8SVedant Kumar   CoalescingBitVector(ThisT &&Other) = delete;
744716ebb8SVedant Kumar   ThisT &operator=(ThisT &&Other) = delete;
75b0142cd9SVedant Kumar 
76b0142cd9SVedant Kumar   /// @}
77b0142cd9SVedant Kumar 
78b0142cd9SVedant Kumar   /// Clear all the bits.
clear()794716ebb8SVedant Kumar   void clear() { Intervals.clear(); }
80b0142cd9SVedant Kumar 
81b0142cd9SVedant Kumar   /// Check whether no bits are set.
empty()824716ebb8SVedant Kumar   bool empty() const { return Intervals.empty(); }
83b0142cd9SVedant Kumar 
84b0142cd9SVedant Kumar   /// Count the number of set bits.
count()85b0142cd9SVedant Kumar   unsigned count() const {
86b0142cd9SVedant Kumar     unsigned Bits = 0;
874716ebb8SVedant Kumar     for (auto It = Intervals.begin(), End = Intervals.end(); It != End; ++It)
88b0142cd9SVedant Kumar       Bits += 1 + It.stop() - It.start();
89b0142cd9SVedant Kumar     return Bits;
90b0142cd9SVedant Kumar   }
91b0142cd9SVedant Kumar 
92b0142cd9SVedant Kumar   /// Set the bit at \p Index.
93b0142cd9SVedant Kumar   ///
94b0142cd9SVedant Kumar   /// This method does /not/ support setting a bit that has already been set,
95b0142cd9SVedant Kumar   /// for efficiency reasons. If possible, restructure your code to not set the
96b0142cd9SVedant Kumar   /// same bit multiple times, or use \ref test_and_set.
set(IndexT Index)97b0142cd9SVedant Kumar   void set(IndexT Index) {
98b0142cd9SVedant Kumar     assert(!test(Index) && "Setting already-set bits not supported/efficient, "
99b0142cd9SVedant Kumar                            "IntervalMap will assert");
100b0142cd9SVedant Kumar     insert(Index, Index);
101b0142cd9SVedant Kumar   }
102b0142cd9SVedant Kumar 
103b0142cd9SVedant Kumar   /// Set the bits set in \p Other.
104b0142cd9SVedant Kumar   ///
105b0142cd9SVedant Kumar   /// This method does /not/ support setting already-set bits, see \ref set
106b0142cd9SVedant Kumar   /// for the rationale. For a safe set union operation, use \ref operator|=.
set(const ThisT & Other)107b0142cd9SVedant Kumar   void set(const ThisT &Other) {
1084716ebb8SVedant Kumar     for (auto It = Other.Intervals.begin(), End = Other.Intervals.end();
109b0142cd9SVedant Kumar          It != End; ++It)
110b0142cd9SVedant Kumar       insert(It.start(), It.stop());
111b0142cd9SVedant Kumar   }
112b0142cd9SVedant Kumar 
113b0142cd9SVedant Kumar   /// Set the bits at \p Indices. Used for testing, primarily.
set(std::initializer_list<IndexT> Indices)114b0142cd9SVedant Kumar   void set(std::initializer_list<IndexT> Indices) {
115b0142cd9SVedant Kumar     for (IndexT Index : Indices)
116b0142cd9SVedant Kumar       set(Index);
117b0142cd9SVedant Kumar   }
118b0142cd9SVedant Kumar 
119b0142cd9SVedant Kumar   /// Check whether the bit at \p Index is set.
test(IndexT Index)120b0142cd9SVedant Kumar   bool test(IndexT Index) const {
1214716ebb8SVedant Kumar     const auto It = Intervals.find(Index);
1224716ebb8SVedant Kumar     if (It == Intervals.end())
123b0142cd9SVedant Kumar       return false;
124b0142cd9SVedant Kumar     assert(It.stop() >= Index && "Interval must end after Index");
125b0142cd9SVedant Kumar     return It.start() <= Index;
126b0142cd9SVedant Kumar   }
127b0142cd9SVedant Kumar 
128b0142cd9SVedant Kumar   /// Set the bit at \p Index. Supports setting an already-set bit.
test_and_set(IndexT Index)129b0142cd9SVedant Kumar   void test_and_set(IndexT Index) {
130b0142cd9SVedant Kumar     if (!test(Index))
131b0142cd9SVedant Kumar       set(Index);
132b0142cd9SVedant Kumar   }
133b0142cd9SVedant Kumar 
134b0142cd9SVedant Kumar   /// Reset the bit at \p Index. Supports resetting an already-unset bit.
reset(IndexT Index)135b0142cd9SVedant Kumar   void reset(IndexT Index) {
1364716ebb8SVedant Kumar     auto It = Intervals.find(Index);
1374716ebb8SVedant Kumar     if (It == Intervals.end())
138b0142cd9SVedant Kumar       return;
139b0142cd9SVedant Kumar 
140b0142cd9SVedant Kumar     // Split the interval containing Index into up to two parts: one from
141b0142cd9SVedant Kumar     // [Start, Index-1] and another from [Index+1, Stop]. If Index is equal to
142b0142cd9SVedant Kumar     // either Start or Stop, we create one new interval. If Index is equal to
143b0142cd9SVedant Kumar     // both Start and Stop, we simply erase the existing interval.
144b0142cd9SVedant Kumar     IndexT Start = It.start();
145b0142cd9SVedant Kumar     if (Index < Start)
146b0142cd9SVedant Kumar       // The index was not set.
147b0142cd9SVedant Kumar       return;
148b0142cd9SVedant Kumar     IndexT Stop = It.stop();
149b0142cd9SVedant Kumar     assert(Index <= Stop && "Wrong interval for index");
150b0142cd9SVedant Kumar     It.erase();
151b0142cd9SVedant Kumar     if (Start < Index)
152b0142cd9SVedant Kumar       insert(Start, Index - 1);
153b0142cd9SVedant Kumar     if (Index < Stop)
154b0142cd9SVedant Kumar       insert(Index + 1, Stop);
155b0142cd9SVedant Kumar   }
156b0142cd9SVedant Kumar 
157b0142cd9SVedant Kumar   /// Set union. If \p RHS is guaranteed to not overlap with this, \ref set may
158b0142cd9SVedant Kumar   /// be a faster alternative.
159b0142cd9SVedant Kumar   void operator|=(const ThisT &RHS) {
160b0142cd9SVedant Kumar     // Get the overlaps between the two interval maps.
161b0142cd9SVedant Kumar     SmallVector<IntervalT, 8> Overlaps;
162b0142cd9SVedant Kumar     getOverlaps(RHS, Overlaps);
163b0142cd9SVedant Kumar 
164b0142cd9SVedant Kumar     // Insert the non-overlapping parts of all the intervals from RHS.
1654716ebb8SVedant Kumar     for (auto It = RHS.Intervals.begin(), End = RHS.Intervals.end();
166b0142cd9SVedant Kumar          It != End; ++It) {
167b0142cd9SVedant Kumar       IndexT Start = It.start();
168b0142cd9SVedant Kumar       IndexT Stop = It.stop();
169b0142cd9SVedant Kumar       SmallVector<IntervalT, 8> NonOverlappingParts;
170b0142cd9SVedant Kumar       getNonOverlappingParts(Start, Stop, Overlaps, NonOverlappingParts);
171b0142cd9SVedant Kumar       for (IntervalT AdditivePortion : NonOverlappingParts)
172b0142cd9SVedant Kumar         insert(AdditivePortion.first, AdditivePortion.second);
173b0142cd9SVedant Kumar     }
174b0142cd9SVedant Kumar   }
175b0142cd9SVedant Kumar 
176b0142cd9SVedant Kumar   /// Set intersection.
177b0142cd9SVedant Kumar   void operator&=(const ThisT &RHS) {
178b0142cd9SVedant Kumar     // Get the overlaps between the two interval maps (i.e. the intersection).
179b0142cd9SVedant Kumar     SmallVector<IntervalT, 8> Overlaps;
180b0142cd9SVedant Kumar     getOverlaps(RHS, Overlaps);
181b0142cd9SVedant Kumar     // Rebuild the interval map, including only the overlaps.
182b0142cd9SVedant Kumar     clear();
183b0142cd9SVedant Kumar     for (IntervalT Overlap : Overlaps)
184b0142cd9SVedant Kumar       insert(Overlap.first, Overlap.second);
185b0142cd9SVedant Kumar   }
186b0142cd9SVedant Kumar 
187b0142cd9SVedant Kumar   /// Reset all bits present in \p Other.
intersectWithComplement(const ThisT & Other)188b0142cd9SVedant Kumar   void intersectWithComplement(const ThisT &Other) {
189b0142cd9SVedant Kumar     SmallVector<IntervalT, 8> Overlaps;
190b0142cd9SVedant Kumar     if (!getOverlaps(Other, Overlaps)) {
191b0142cd9SVedant Kumar       // If there is no overlap with Other, the intersection is empty.
192b0142cd9SVedant Kumar       return;
193b0142cd9SVedant Kumar     }
194b0142cd9SVedant Kumar 
195b0142cd9SVedant Kumar     // Delete the overlapping intervals. Split up intervals that only partially
196b0142cd9SVedant Kumar     // intersect an overlap.
197b0142cd9SVedant Kumar     for (IntervalT Overlap : Overlaps) {
198b0142cd9SVedant Kumar       IndexT OlapStart, OlapStop;
199b0142cd9SVedant Kumar       std::tie(OlapStart, OlapStop) = Overlap;
200b0142cd9SVedant Kumar 
2014716ebb8SVedant Kumar       auto It = Intervals.find(OlapStart);
202b0142cd9SVedant Kumar       IndexT CurrStart = It.start();
203b0142cd9SVedant Kumar       IndexT CurrStop = It.stop();
204b0142cd9SVedant Kumar       assert(CurrStart <= OlapStart && OlapStop <= CurrStop &&
205b0142cd9SVedant Kumar              "Expected some intersection!");
206b0142cd9SVedant Kumar 
207b0142cd9SVedant Kumar       // Split the overlap interval into up to two parts: one from [CurrStart,
208b0142cd9SVedant Kumar       // OlapStart-1] and another from [OlapStop+1, CurrStop]. If OlapStart is
209b0142cd9SVedant Kumar       // equal to CurrStart, the first split interval is unnecessary. Ditto for
210b0142cd9SVedant Kumar       // when OlapStop is equal to CurrStop, we omit the second split interval.
211b0142cd9SVedant Kumar       It.erase();
212b0142cd9SVedant Kumar       if (CurrStart < OlapStart)
213b0142cd9SVedant Kumar         insert(CurrStart, OlapStart - 1);
214b0142cd9SVedant Kumar       if (OlapStop < CurrStop)
215b0142cd9SVedant Kumar         insert(OlapStop + 1, CurrStop);
216b0142cd9SVedant Kumar     }
217b0142cd9SVedant Kumar   }
218b0142cd9SVedant Kumar 
219b0142cd9SVedant Kumar   bool operator==(const ThisT &RHS) const {
220b0142cd9SVedant Kumar     // We cannot just use std::equal because it checks the dereferenced values
221b0142cd9SVedant Kumar     // of an iterator pair for equality, not the iterators themselves. In our
222b0142cd9SVedant Kumar     // case that results in comparison of the (unused) IntervalMap values.
2234716ebb8SVedant Kumar     auto ItL = Intervals.begin();
2244716ebb8SVedant Kumar     auto ItR = RHS.Intervals.begin();
2254716ebb8SVedant Kumar     while (ItL != Intervals.end() && ItR != RHS.Intervals.end() &&
226b0142cd9SVedant Kumar            ItL.start() == ItR.start() && ItL.stop() == ItR.stop()) {
227b0142cd9SVedant Kumar       ++ItL;
228b0142cd9SVedant Kumar       ++ItR;
229b0142cd9SVedant Kumar     }
2304716ebb8SVedant Kumar     return ItL == Intervals.end() && ItR == RHS.Intervals.end();
231b0142cd9SVedant Kumar   }
232b0142cd9SVedant Kumar 
233b0142cd9SVedant Kumar   bool operator!=(const ThisT &RHS) const { return !operator==(RHS); }
234b0142cd9SVedant Kumar 
2350a92aff7SHamza Sood   class const_iterator {
236b0142cd9SVedant Kumar     friend class CoalescingBitVector;
237b0142cd9SVedant Kumar 
2380a92aff7SHamza Sood   public:
2390a92aff7SHamza Sood     using iterator_category = std::forward_iterator_tag;
2400a92aff7SHamza Sood     using value_type = IndexT;
2410a92aff7SHamza Sood     using difference_type = std::ptrdiff_t;
2420a92aff7SHamza Sood     using pointer = value_type *;
2430a92aff7SHamza Sood     using reference = value_type &;
2440a92aff7SHamza Sood 
2450a92aff7SHamza Sood   private:
246b0142cd9SVedant Kumar     // For performance reasons, make the offset at the end different than the
247b0142cd9SVedant Kumar     // one used in \ref begin, to optimize the common `It == end()` pattern.
248b0142cd9SVedant Kumar     static constexpr unsigned kIteratorAtTheEndOffset = ~0u;
249b0142cd9SVedant Kumar 
250b0142cd9SVedant Kumar     UnderlyingIterator MapIterator;
251b0142cd9SVedant Kumar     unsigned OffsetIntoMapIterator = 0;
252b0142cd9SVedant Kumar 
253b0142cd9SVedant Kumar     // Querying the start/stop of an IntervalMap iterator can be very expensive.
254b0142cd9SVedant Kumar     // Cache these values for performance reasons.
255b0142cd9SVedant Kumar     IndexT CachedStart = IndexT();
256b0142cd9SVedant Kumar     IndexT CachedStop = IndexT();
257b0142cd9SVedant Kumar 
setToEnd()258b0142cd9SVedant Kumar     void setToEnd() {
259b0142cd9SVedant Kumar       OffsetIntoMapIterator = kIteratorAtTheEndOffset;
260b0142cd9SVedant Kumar       CachedStart = IndexT();
261b0142cd9SVedant Kumar       CachedStop = IndexT();
262b0142cd9SVedant Kumar     }
263b0142cd9SVedant Kumar 
264b0142cd9SVedant Kumar     /// MapIterator has just changed, reset the cached state to point to the
265b0142cd9SVedant Kumar     /// start of the new underlying iterator.
resetCache()266b0142cd9SVedant Kumar     void resetCache() {
267b0142cd9SVedant Kumar       if (MapIterator.valid()) {
268b0142cd9SVedant Kumar         OffsetIntoMapIterator = 0;
269b0142cd9SVedant Kumar         CachedStart = MapIterator.start();
270b0142cd9SVedant Kumar         CachedStop = MapIterator.stop();
271b0142cd9SVedant Kumar       } else {
272b0142cd9SVedant Kumar         setToEnd();
273b0142cd9SVedant Kumar       }
274b0142cd9SVedant Kumar     }
275b0142cd9SVedant Kumar 
276b0142cd9SVedant Kumar     /// Advance the iterator to \p Index, if it is contained within the current
277a3fd1a1cSVedant Kumar     /// interval. The public-facing method which supports advancing past the
278a3fd1a1cSVedant Kumar     /// current interval is \ref advanceToLowerBound.
advanceTo(IndexT Index)279b0142cd9SVedant Kumar     void advanceTo(IndexT Index) {
280b0142cd9SVedant Kumar       assert(Index <= CachedStop && "Cannot advance to OOB index");
281b0142cd9SVedant Kumar       if (Index < CachedStart)
282b0142cd9SVedant Kumar         // We're already past this index.
283b0142cd9SVedant Kumar         return;
284b0142cd9SVedant Kumar       OffsetIntoMapIterator = Index - CachedStart;
285b0142cd9SVedant Kumar     }
286b0142cd9SVedant Kumar 
const_iterator(UnderlyingIterator MapIt)287b0142cd9SVedant Kumar     const_iterator(UnderlyingIterator MapIt) : MapIterator(MapIt) {
288b0142cd9SVedant Kumar       resetCache();
289b0142cd9SVedant Kumar     }
290b0142cd9SVedant Kumar 
291b0142cd9SVedant Kumar   public:
const_iterator()292b0142cd9SVedant Kumar     const_iterator() { setToEnd(); }
293b0142cd9SVedant Kumar 
294b0142cd9SVedant Kumar     bool operator==(const const_iterator &RHS) const {
295b0142cd9SVedant Kumar       // Do /not/ compare MapIterator for equality, as this is very expensive.
296b0142cd9SVedant Kumar       // The cached start/stop values make that check unnecessary.
297b0142cd9SVedant Kumar       return std::tie(OffsetIntoMapIterator, CachedStart, CachedStop) ==
298b0142cd9SVedant Kumar              std::tie(RHS.OffsetIntoMapIterator, RHS.CachedStart,
299b0142cd9SVedant Kumar                       RHS.CachedStop);
300b0142cd9SVedant Kumar     }
301b0142cd9SVedant Kumar 
302b0142cd9SVedant Kumar     bool operator!=(const const_iterator &RHS) const {
303b0142cd9SVedant Kumar       return !operator==(RHS);
304b0142cd9SVedant Kumar     }
305b0142cd9SVedant Kumar 
306b0142cd9SVedant Kumar     IndexT operator*() const { return CachedStart + OffsetIntoMapIterator; }
307b0142cd9SVedant Kumar 
308b0142cd9SVedant Kumar     const_iterator &operator++() { // Pre-increment (++It).
309b0142cd9SVedant Kumar       if (CachedStart + OffsetIntoMapIterator < CachedStop) {
310b0142cd9SVedant Kumar         // Keep going within the current interval.
311b0142cd9SVedant Kumar         ++OffsetIntoMapIterator;
312b0142cd9SVedant Kumar       } else {
313b0142cd9SVedant Kumar         // We reached the end of the current interval: advance.
314b0142cd9SVedant Kumar         ++MapIterator;
315b0142cd9SVedant Kumar         resetCache();
316b0142cd9SVedant Kumar       }
317b0142cd9SVedant Kumar       return *this;
318b0142cd9SVedant Kumar     }
319b0142cd9SVedant Kumar 
320b0142cd9SVedant Kumar     const_iterator operator++(int) { // Post-increment (It++).
321b0142cd9SVedant Kumar       const_iterator tmp = *this;
322b0142cd9SVedant Kumar       operator++();
323b0142cd9SVedant Kumar       return tmp;
324b0142cd9SVedant Kumar     }
325a3fd1a1cSVedant Kumar 
326a3fd1a1cSVedant Kumar     /// Advance the iterator to the first set bit AT, OR AFTER, \p Index. If
327a3fd1a1cSVedant Kumar     /// no such set bit exists, advance to end(). This is like std::lower_bound.
328a3fd1a1cSVedant Kumar     /// This is useful if \p Index is close to the current iterator position.
329a3fd1a1cSVedant Kumar     /// However, unlike \ref find(), this has worst-case O(n) performance.
advanceToLowerBound(IndexT Index)330a3fd1a1cSVedant Kumar     void advanceToLowerBound(IndexT Index) {
331a3fd1a1cSVedant Kumar       if (OffsetIntoMapIterator == kIteratorAtTheEndOffset)
332a3fd1a1cSVedant Kumar         return;
333a3fd1a1cSVedant Kumar 
334a3fd1a1cSVedant Kumar       // Advance to the first interval containing (or past) Index, or to end().
335a3fd1a1cSVedant Kumar       while (Index > CachedStop) {
336a3fd1a1cSVedant Kumar         ++MapIterator;
337a3fd1a1cSVedant Kumar         resetCache();
338a3fd1a1cSVedant Kumar         if (OffsetIntoMapIterator == kIteratorAtTheEndOffset)
339a3fd1a1cSVedant Kumar           return;
340a3fd1a1cSVedant Kumar       }
341a3fd1a1cSVedant Kumar 
342a3fd1a1cSVedant Kumar       advanceTo(Index);
343a3fd1a1cSVedant Kumar     }
344b0142cd9SVedant Kumar   };
345b0142cd9SVedant Kumar 
begin()3464716ebb8SVedant Kumar   const_iterator begin() const { return const_iterator(Intervals.begin()); }
347b0142cd9SVedant Kumar 
end()348b0142cd9SVedant Kumar   const_iterator end() const { return const_iterator(); }
349b0142cd9SVedant Kumar 
350b0142cd9SVedant Kumar   /// Return an iterator pointing to the first set bit AT, OR AFTER, \p Index.
351b0142cd9SVedant Kumar   /// If no such set bit exists, return end(). This is like std::lower_bound.
352a3fd1a1cSVedant Kumar   /// This has worst-case logarithmic performance (roughly O(log(gaps between
353a3fd1a1cSVedant Kumar   /// contiguous ranges))).
find(IndexT Index)354b0142cd9SVedant Kumar   const_iterator find(IndexT Index) const {
3554716ebb8SVedant Kumar     auto UnderlyingIt = Intervals.find(Index);
3564716ebb8SVedant Kumar     if (UnderlyingIt == Intervals.end())
357b0142cd9SVedant Kumar       return end();
358b0142cd9SVedant Kumar     auto It = const_iterator(UnderlyingIt);
359b0142cd9SVedant Kumar     It.advanceTo(Index);
360b0142cd9SVedant Kumar     return It;
361b0142cd9SVedant Kumar   }
362b0142cd9SVedant Kumar 
3632ecaf935SVedant Kumar   /// Return a range iterator which iterates over all of the set bits in the
3642ecaf935SVedant Kumar   /// half-open range [Start, End).
half_open_range(IndexT Start,IndexT End)3652ecaf935SVedant Kumar   iterator_range<const_iterator> half_open_range(IndexT Start,
3662ecaf935SVedant Kumar                                                  IndexT End) const {
3672ecaf935SVedant Kumar     assert(Start < End && "Not a valid range");
3682ecaf935SVedant Kumar     auto StartIt = find(Start);
3692ecaf935SVedant Kumar     if (StartIt == end() || *StartIt >= End)
3702ecaf935SVedant Kumar       return {end(), end()};
3712ecaf935SVedant Kumar     auto EndIt = StartIt;
3722ecaf935SVedant Kumar     EndIt.advanceToLowerBound(End);
3732ecaf935SVedant Kumar     return {StartIt, EndIt};
3742ecaf935SVedant Kumar   }
3752ecaf935SVedant Kumar 
print(raw_ostream & OS)376b0142cd9SVedant Kumar   void print(raw_ostream &OS) const {
377b0142cd9SVedant Kumar     OS << "{";
3784716ebb8SVedant Kumar     for (auto It = Intervals.begin(), End = Intervals.end(); It != End;
379b0142cd9SVedant Kumar          ++It) {
380b0142cd9SVedant Kumar       OS << "[" << It.start();
381b0142cd9SVedant Kumar       if (It.start() != It.stop())
382b0142cd9SVedant Kumar         OS << ", " << It.stop();
383b0142cd9SVedant Kumar       OS << "]";
384b0142cd9SVedant Kumar     }
385b0142cd9SVedant Kumar     OS << "}";
386b0142cd9SVedant Kumar   }
387b0142cd9SVedant Kumar 
388b0142cd9SVedant Kumar #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
dump()389b0142cd9SVedant Kumar   LLVM_DUMP_METHOD void dump() const {
390b0142cd9SVedant Kumar     // LLDB swallows the first line of output after callling dump(). Add
391b0142cd9SVedant Kumar     // newlines before/after the braces to work around this.
392b0142cd9SVedant Kumar     dbgs() << "\n";
393b0142cd9SVedant Kumar     print(dbgs());
394b0142cd9SVedant Kumar     dbgs() << "\n";
395b0142cd9SVedant Kumar   }
396b0142cd9SVedant Kumar #endif
397b0142cd9SVedant Kumar 
398b0142cd9SVedant Kumar private:
insert(IndexT Start,IndexT End)3994716ebb8SVedant Kumar   void insert(IndexT Start, IndexT End) { Intervals.insert(Start, End, 0); }
400b0142cd9SVedant Kumar 
401b0142cd9SVedant Kumar   /// Record the overlaps between \p this and \p Other in \p Overlaps. Return
402b0142cd9SVedant Kumar   /// true if there is any overlap.
getOverlaps(const ThisT & Other,SmallVectorImpl<IntervalT> & Overlaps)403b0142cd9SVedant Kumar   bool getOverlaps(const ThisT &Other,
404b0142cd9SVedant Kumar                    SmallVectorImpl<IntervalT> &Overlaps) const {
4054716ebb8SVedant Kumar     for (IntervalMapOverlaps<MapT, MapT> I(Intervals, Other.Intervals);
406b0142cd9SVedant Kumar          I.valid(); ++I)
407b0142cd9SVedant Kumar       Overlaps.emplace_back(I.start(), I.stop());
4081647ff6eSGeorgii Rymar     assert(llvm::is_sorted(Overlaps,
409b0142cd9SVedant Kumar                            [](IntervalT LHS, IntervalT RHS) {
410b0142cd9SVedant Kumar                              return LHS.second < RHS.first;
411b0142cd9SVedant Kumar                            }) &&
412b0142cd9SVedant Kumar            "Overlaps must be sorted");
413b0142cd9SVedant Kumar     return !Overlaps.empty();
414b0142cd9SVedant Kumar   }
415b0142cd9SVedant Kumar 
416b0142cd9SVedant Kumar   /// Given the set of overlaps between this and some other bitvector, and an
417b0142cd9SVedant Kumar   /// interval [Start, Stop] from that bitvector, determine the portions of the
418b0142cd9SVedant Kumar   /// interval which do not overlap with this.
getNonOverlappingParts(IndexT Start,IndexT Stop,const SmallVectorImpl<IntervalT> & Overlaps,SmallVectorImpl<IntervalT> & NonOverlappingParts)419b0142cd9SVedant Kumar   void getNonOverlappingParts(IndexT Start, IndexT Stop,
420b0142cd9SVedant Kumar                               const SmallVectorImpl<IntervalT> &Overlaps,
421b0142cd9SVedant Kumar                               SmallVectorImpl<IntervalT> &NonOverlappingParts) {
422b0142cd9SVedant Kumar     IndexT NextUncoveredBit = Start;
423b0142cd9SVedant Kumar     for (IntervalT Overlap : Overlaps) {
424b0142cd9SVedant Kumar       IndexT OlapStart, OlapStop;
425b0142cd9SVedant Kumar       std::tie(OlapStart, OlapStop) = Overlap;
426b0142cd9SVedant Kumar 
427b0142cd9SVedant Kumar       // [Start;Stop] and [OlapStart;OlapStop] overlap iff OlapStart <= Stop
428b0142cd9SVedant Kumar       // and Start <= OlapStop.
429b0142cd9SVedant Kumar       bool DoesOverlap = OlapStart <= Stop && Start <= OlapStop;
430b0142cd9SVedant Kumar       if (!DoesOverlap)
431b0142cd9SVedant Kumar         continue;
432b0142cd9SVedant Kumar 
433b0142cd9SVedant Kumar       // Cover the range [NextUncoveredBit, OlapStart). This puts the start of
434b0142cd9SVedant Kumar       // the next uncovered range at OlapStop+1.
435b0142cd9SVedant Kumar       if (NextUncoveredBit < OlapStart)
436b0142cd9SVedant Kumar         NonOverlappingParts.emplace_back(NextUncoveredBit, OlapStart - 1);
437b0142cd9SVedant Kumar       NextUncoveredBit = OlapStop + 1;
438b0142cd9SVedant Kumar       if (NextUncoveredBit > Stop)
439b0142cd9SVedant Kumar         break;
440b0142cd9SVedant Kumar     }
441b0142cd9SVedant Kumar     if (NextUncoveredBit <= Stop)
442b0142cd9SVedant Kumar       NonOverlappingParts.emplace_back(NextUncoveredBit, Stop);
443b0142cd9SVedant Kumar   }
444b0142cd9SVedant Kumar 
445b0142cd9SVedant Kumar   Allocator *Alloc;
4464716ebb8SVedant Kumar   MapT Intervals;
447b0142cd9SVedant Kumar };
448b0142cd9SVedant Kumar 
449b0142cd9SVedant Kumar } // namespace llvm
450b0142cd9SVedant Kumar 
451b0142cd9SVedant Kumar #endif // LLVM_ADT_COALESCINGBITVECTOR_H
452