File indexing completed on 2026-05-10 08:43:03
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015 #ifndef LLVM_ADT_COALESCINGBITVECTOR_H
0016 #define LLVM_ADT_COALESCINGBITVECTOR_H
0017
0018 #include "llvm/ADT/IntervalMap.h"
0019 #include "llvm/ADT/STLExtras.h"
0020 #include "llvm/ADT/SmallVector.h"
0021 #include "llvm/ADT/iterator_range.h"
0022 #include "llvm/Support/Debug.h"
0023 #include "llvm/Support/raw_ostream.h"
0024
0025 #include <initializer_list>
0026
0027 namespace llvm {
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037
0038 template <typename IndexT> class CoalescingBitVector {
0039 static_assert(std::is_unsigned<IndexT>::value,
0040 "Index must be an unsigned integer.");
0041
0042 using ThisT = CoalescingBitVector<IndexT>;
0043
0044
0045 using MapT = IntervalMap<IndexT, char>;
0046
0047 using UnderlyingIterator = typename MapT::const_iterator;
0048
0049 using IntervalT = std::pair<IndexT, IndexT>;
0050
0051 public:
0052 using Allocator = typename MapT::Allocator;
0053
0054
0055
0056 CoalescingBitVector(Allocator &Alloc)
0057 : Alloc(&Alloc), Intervals(Alloc) {}
0058
0059
0060
0061
0062 CoalescingBitVector(const ThisT &Other)
0063 : Alloc(Other.Alloc), Intervals(*Other.Alloc) {
0064 set(Other);
0065 }
0066
0067 ThisT &operator=(const ThisT &Other) {
0068 clear();
0069 set(Other);
0070 return *this;
0071 }
0072
0073 CoalescingBitVector(ThisT &&Other) = delete;
0074 ThisT &operator=(ThisT &&Other) = delete;
0075
0076
0077
0078
0079 void clear() { Intervals.clear(); }
0080
0081
0082 bool empty() const { return Intervals.empty(); }
0083
0084
0085 unsigned count() const {
0086 unsigned Bits = 0;
0087 for (auto It = Intervals.begin(), End = Intervals.end(); It != End; ++It)
0088 Bits += 1 + It.stop() - It.start();
0089 return Bits;
0090 }
0091
0092
0093
0094
0095
0096
0097 void set(IndexT Index) {
0098 assert(!test(Index) && "Setting already-set bits not supported/efficient, "
0099 "IntervalMap will assert");
0100 insert(Index, Index);
0101 }
0102
0103
0104
0105
0106
0107 void set(const ThisT &Other) {
0108 for (auto It = Other.Intervals.begin(), End = Other.Intervals.end();
0109 It != End; ++It)
0110 insert(It.start(), It.stop());
0111 }
0112
0113
0114 void set(std::initializer_list<IndexT> Indices) {
0115 for (IndexT Index : Indices)
0116 set(Index);
0117 }
0118
0119
0120 bool test(IndexT Index) const {
0121 const auto It = Intervals.find(Index);
0122 if (It == Intervals.end())
0123 return false;
0124 assert(It.stop() >= Index && "Interval must end after Index");
0125 return It.start() <= Index;
0126 }
0127
0128
0129 void test_and_set(IndexT Index) {
0130 if (!test(Index))
0131 set(Index);
0132 }
0133
0134
0135 void reset(IndexT Index) {
0136 auto It = Intervals.find(Index);
0137 if (It == Intervals.end())
0138 return;
0139
0140
0141
0142
0143
0144 IndexT Start = It.start();
0145 if (Index < Start)
0146
0147 return;
0148 IndexT Stop = It.stop();
0149 assert(Index <= Stop && "Wrong interval for index");
0150 It.erase();
0151 if (Start < Index)
0152 insert(Start, Index - 1);
0153 if (Index < Stop)
0154 insert(Index + 1, Stop);
0155 }
0156
0157
0158
0159 void operator|=(const ThisT &RHS) {
0160
0161 SmallVector<IntervalT, 8> Overlaps;
0162 getOverlaps(RHS, Overlaps);
0163
0164
0165 for (auto It = RHS.Intervals.begin(), End = RHS.Intervals.end();
0166 It != End; ++It) {
0167 IndexT Start = It.start();
0168 IndexT Stop = It.stop();
0169 SmallVector<IntervalT, 8> NonOverlappingParts;
0170 getNonOverlappingParts(Start, Stop, Overlaps, NonOverlappingParts);
0171 for (IntervalT AdditivePortion : NonOverlappingParts)
0172 insert(AdditivePortion.first, AdditivePortion.second);
0173 }
0174 }
0175
0176
0177 void operator&=(const ThisT &RHS) {
0178
0179 SmallVector<IntervalT, 8> Overlaps;
0180 getOverlaps(RHS, Overlaps);
0181
0182 clear();
0183 for (IntervalT Overlap : Overlaps)
0184 insert(Overlap.first, Overlap.second);
0185 }
0186
0187
0188 void intersectWithComplement(const ThisT &Other) {
0189 SmallVector<IntervalT, 8> Overlaps;
0190 if (!getOverlaps(Other, Overlaps)) {
0191
0192 return;
0193 }
0194
0195
0196
0197 for (IntervalT Overlap : Overlaps) {
0198 IndexT OlapStart, OlapStop;
0199 std::tie(OlapStart, OlapStop) = Overlap;
0200
0201 auto It = Intervals.find(OlapStart);
0202 IndexT CurrStart = It.start();
0203 IndexT CurrStop = It.stop();
0204 assert(CurrStart <= OlapStart && OlapStop <= CurrStop &&
0205 "Expected some intersection!");
0206
0207
0208
0209
0210
0211 It.erase();
0212 if (CurrStart < OlapStart)
0213 insert(CurrStart, OlapStart - 1);
0214 if (OlapStop < CurrStop)
0215 insert(OlapStop + 1, CurrStop);
0216 }
0217 }
0218
0219 bool operator==(const ThisT &RHS) const {
0220
0221
0222
0223 auto ItL = Intervals.begin();
0224 auto ItR = RHS.Intervals.begin();
0225 while (ItL != Intervals.end() && ItR != RHS.Intervals.end() &&
0226 ItL.start() == ItR.start() && ItL.stop() == ItR.stop()) {
0227 ++ItL;
0228 ++ItR;
0229 }
0230 return ItL == Intervals.end() && ItR == RHS.Intervals.end();
0231 }
0232
0233 bool operator!=(const ThisT &RHS) const { return !operator==(RHS); }
0234
0235 class const_iterator {
0236 friend class CoalescingBitVector;
0237
0238 public:
0239 using iterator_category = std::forward_iterator_tag;
0240 using value_type = IndexT;
0241 using difference_type = std::ptrdiff_t;
0242 using pointer = value_type *;
0243 using reference = value_type &;
0244
0245 private:
0246
0247
0248 static constexpr unsigned kIteratorAtTheEndOffset = ~0u;
0249
0250 UnderlyingIterator MapIterator;
0251 unsigned OffsetIntoMapIterator = 0;
0252
0253
0254
0255 IndexT CachedStart = IndexT();
0256 IndexT CachedStop = IndexT();
0257
0258 void setToEnd() {
0259 OffsetIntoMapIterator = kIteratorAtTheEndOffset;
0260 CachedStart = IndexT();
0261 CachedStop = IndexT();
0262 }
0263
0264
0265
0266 void resetCache() {
0267 if (MapIterator.valid()) {
0268 OffsetIntoMapIterator = 0;
0269 CachedStart = MapIterator.start();
0270 CachedStop = MapIterator.stop();
0271 } else {
0272 setToEnd();
0273 }
0274 }
0275
0276
0277
0278
0279 void advanceTo(IndexT Index) {
0280 assert(Index <= CachedStop && "Cannot advance to OOB index");
0281 if (Index < CachedStart)
0282
0283 return;
0284 OffsetIntoMapIterator = Index - CachedStart;
0285 }
0286
0287 const_iterator(UnderlyingIterator MapIt) : MapIterator(MapIt) {
0288 resetCache();
0289 }
0290
0291 public:
0292 const_iterator() { setToEnd(); }
0293
0294 bool operator==(const const_iterator &RHS) const {
0295
0296
0297 return std::tie(OffsetIntoMapIterator, CachedStart, CachedStop) ==
0298 std::tie(RHS.OffsetIntoMapIterator, RHS.CachedStart,
0299 RHS.CachedStop);
0300 }
0301
0302 bool operator!=(const const_iterator &RHS) const {
0303 return !operator==(RHS);
0304 }
0305
0306 IndexT operator*() const { return CachedStart + OffsetIntoMapIterator; }
0307
0308 const_iterator &operator++() {
0309 if (CachedStart + OffsetIntoMapIterator < CachedStop) {
0310
0311 ++OffsetIntoMapIterator;
0312 } else {
0313
0314 ++MapIterator;
0315 resetCache();
0316 }
0317 return *this;
0318 }
0319
0320 const_iterator operator++(int) {
0321 const_iterator tmp = *this;
0322 operator++();
0323 return tmp;
0324 }
0325
0326
0327
0328
0329
0330 void advanceToLowerBound(IndexT Index) {
0331 if (OffsetIntoMapIterator == kIteratorAtTheEndOffset)
0332 return;
0333
0334
0335 while (Index > CachedStop) {
0336 ++MapIterator;
0337 resetCache();
0338 if (OffsetIntoMapIterator == kIteratorAtTheEndOffset)
0339 return;
0340 }
0341
0342 advanceTo(Index);
0343 }
0344 };
0345
0346 const_iterator begin() const { return const_iterator(Intervals.begin()); }
0347
0348 const_iterator end() const { return const_iterator(); }
0349
0350
0351
0352
0353
0354 const_iterator find(IndexT Index) const {
0355 auto UnderlyingIt = Intervals.find(Index);
0356 if (UnderlyingIt == Intervals.end())
0357 return end();
0358 auto It = const_iterator(UnderlyingIt);
0359 It.advanceTo(Index);
0360 return It;
0361 }
0362
0363
0364
0365 iterator_range<const_iterator> half_open_range(IndexT Start,
0366 IndexT End) const {
0367 assert(Start < End && "Not a valid range");
0368 auto StartIt = find(Start);
0369 if (StartIt == end() || *StartIt >= End)
0370 return {end(), end()};
0371 auto EndIt = StartIt;
0372 EndIt.advanceToLowerBound(End);
0373 return {StartIt, EndIt};
0374 }
0375
0376 void print(raw_ostream &OS) const {
0377 OS << "{";
0378 for (auto It = Intervals.begin(), End = Intervals.end(); It != End;
0379 ++It) {
0380 OS << "[" << It.start();
0381 if (It.start() != It.stop())
0382 OS << ", " << It.stop();
0383 OS << "]";
0384 }
0385 OS << "}";
0386 }
0387
0388 #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
0389 LLVM_DUMP_METHOD void dump() const {
0390
0391
0392 dbgs() << "\n";
0393 print(dbgs());
0394 dbgs() << "\n";
0395 }
0396 #endif
0397
0398 private:
0399 void insert(IndexT Start, IndexT End) { Intervals.insert(Start, End, 0); }
0400
0401
0402
0403 bool getOverlaps(const ThisT &Other,
0404 SmallVectorImpl<IntervalT> &Overlaps) const {
0405 for (IntervalMapOverlaps<MapT, MapT> I(Intervals, Other.Intervals);
0406 I.valid(); ++I)
0407 Overlaps.emplace_back(I.start(), I.stop());
0408 assert(llvm::is_sorted(Overlaps,
0409 [](IntervalT LHS, IntervalT RHS) {
0410 return LHS.second < RHS.first;
0411 }) &&
0412 "Overlaps must be sorted");
0413 return !Overlaps.empty();
0414 }
0415
0416
0417
0418
0419 void getNonOverlappingParts(IndexT Start, IndexT Stop,
0420 const SmallVectorImpl<IntervalT> &Overlaps,
0421 SmallVectorImpl<IntervalT> &NonOverlappingParts) {
0422 IndexT NextUncoveredBit = Start;
0423 for (IntervalT Overlap : Overlaps) {
0424 IndexT OlapStart, OlapStop;
0425 std::tie(OlapStart, OlapStop) = Overlap;
0426
0427
0428
0429 bool DoesOverlap = OlapStart <= Stop && Start <= OlapStop;
0430 if (!DoesOverlap)
0431 continue;
0432
0433
0434
0435 if (NextUncoveredBit < OlapStart)
0436 NonOverlappingParts.emplace_back(NextUncoveredBit, OlapStart - 1);
0437 NextUncoveredBit = OlapStop + 1;
0438 if (NextUncoveredBit > Stop)
0439 break;
0440 }
0441 if (NextUncoveredBit <= Stop)
0442 NonOverlappingParts.emplace_back(NextUncoveredBit, Stop);
0443 }
0444
0445 Allocator *Alloc;
0446 MapT Intervals;
0447 };
0448
0449 }
0450
0451 #endif