File indexing completed on 2026-05-10 08:43:09
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021 #ifndef LLVM_ADT_SPARSEMULTISET_H
0022 #define LLVM_ADT_SPARSEMULTISET_H
0023
0024 #include "llvm/ADT/identity.h"
0025 #include "llvm/ADT/SmallVector.h"
0026 #include "llvm/ADT/SparseSet.h"
0027 #include <cassert>
0028 #include <cstdint>
0029 #include <cstdlib>
0030 #include <iterator>
0031 #include <limits>
0032 #include <utility>
0033
0034 namespace llvm {
0035
0036
0037
0038
0039
0040
0041
0042
0043
0044
0045
0046
0047
0048
0049
0050
0051
0052
0053
0054
0055
0056
0057
0058
0059
0060
0061
0062
0063
0064
0065
0066
0067
0068
0069
0070
0071
0072
0073
0074
0075
0076
0077
0078
0079
0080
0081
0082
0083 template<typename ValueT,
0084 typename KeyFunctorT = identity<unsigned>,
0085 typename SparseT = uint8_t>
0086 class SparseMultiSet {
0087 static_assert(std::is_unsigned_v<SparseT>,
0088 "SparseT must be an unsigned integer type");
0089
0090
0091
0092
0093
0094
0095
0096 struct SMSNode {
0097 static constexpr unsigned INVALID = ~0U;
0098
0099 ValueT Data;
0100 unsigned Prev;
0101 unsigned Next;
0102
0103 SMSNode(ValueT D, unsigned P, unsigned N) : Data(D), Prev(P), Next(N) {}
0104
0105
0106 bool isTail() const {
0107 return Next == INVALID;
0108 }
0109
0110
0111 bool isTombstone() const {
0112 return Prev == INVALID;
0113 }
0114
0115
0116
0117 bool isValid() const { return Prev != INVALID; }
0118 };
0119
0120 using KeyT = typename KeyFunctorT::argument_type;
0121 using DenseT = SmallVector<SMSNode, 8>;
0122 DenseT Dense;
0123 SparseT *Sparse = nullptr;
0124 unsigned Universe = 0;
0125 KeyFunctorT KeyIndexOf;
0126 SparseSetValFunctor<KeyT, ValueT, KeyFunctorT> ValIndexOf;
0127
0128
0129
0130
0131 unsigned FreelistIdx = SMSNode::INVALID;
0132 unsigned NumFree = 0;
0133
0134 unsigned sparseIndex(const ValueT &Val) const {
0135 assert(ValIndexOf(Val) < Universe &&
0136 "Invalid key in set. Did object mutate?");
0137 return ValIndexOf(Val);
0138 }
0139 unsigned sparseIndex(const SMSNode &N) const { return sparseIndex(N.Data); }
0140
0141
0142
0143
0144 bool isHead(const SMSNode &D) const {
0145 assert(D.isValid() && "Invalid node for head");
0146 return Dense[D.Prev].isTail();
0147 }
0148
0149
0150
0151 bool isSingleton(const SMSNode &N) const {
0152 assert(N.isValid() && "Invalid node for singleton");
0153
0154 return &Dense[N.Prev] == &N;
0155 }
0156
0157
0158
0159 unsigned addValue(const ValueT& V, unsigned Prev, unsigned Next) {
0160 if (NumFree == 0) {
0161 Dense.push_back(SMSNode(V, Prev, Next));
0162 return Dense.size() - 1;
0163 }
0164
0165
0166 unsigned Idx = FreelistIdx;
0167 unsigned NextFree = Dense[Idx].Next;
0168 assert(Dense[Idx].isTombstone() && "Non-tombstone free?");
0169
0170 Dense[Idx] = SMSNode(V, Prev, Next);
0171 FreelistIdx = NextFree;
0172 --NumFree;
0173 return Idx;
0174 }
0175
0176
0177 void makeTombstone(unsigned Idx) {
0178 Dense[Idx].Prev = SMSNode::INVALID;
0179 Dense[Idx].Next = FreelistIdx;
0180 FreelistIdx = Idx;
0181 ++NumFree;
0182 }
0183
0184 public:
0185 using value_type = ValueT;
0186 using reference = ValueT &;
0187 using const_reference = const ValueT &;
0188 using pointer = ValueT *;
0189 using const_pointer = const ValueT *;
0190 using size_type = unsigned;
0191
0192 SparseMultiSet() = default;
0193 SparseMultiSet(const SparseMultiSet &) = delete;
0194 SparseMultiSet &operator=(const SparseMultiSet &) = delete;
0195 ~SparseMultiSet() { free(Sparse); }
0196
0197
0198
0199
0200
0201
0202 void setUniverse(unsigned U) {
0203
0204
0205 assert(empty() && "Can only resize universe on an empty map");
0206
0207 if (U >= Universe/4 && U <= Universe)
0208 return;
0209 free(Sparse);
0210
0211
0212
0213 Sparse = static_cast<SparseT*>(safe_calloc(U, sizeof(SparseT)));
0214 Universe = U;
0215 }
0216
0217
0218
0219 template <typename SMSPtrTy> class iterator_base {
0220 friend class SparseMultiSet;
0221
0222 public:
0223 using iterator_category = std::bidirectional_iterator_tag;
0224 using value_type = ValueT;
0225 using difference_type = std::ptrdiff_t;
0226 using pointer = value_type *;
0227 using reference = value_type &;
0228
0229 private:
0230 SMSPtrTy SMS;
0231 unsigned Idx;
0232 unsigned SparseIdx;
0233
0234 iterator_base(SMSPtrTy P, unsigned I, unsigned SI)
0235 : SMS(P), Idx(I), SparseIdx(SI) {}
0236
0237
0238 bool isEnd() const {
0239 if (Idx == SMSNode::INVALID)
0240 return true;
0241
0242 assert(Idx < SMS->Dense.size() && "Out of range, non-INVALID Idx?");
0243 return false;
0244 }
0245
0246
0247 bool isKeyed() const { return SparseIdx < SMS->Universe; }
0248
0249 unsigned Prev() const { return SMS->Dense[Idx].Prev; }
0250 unsigned Next() const { return SMS->Dense[Idx].Next; }
0251
0252 void setPrev(unsigned P) { SMS->Dense[Idx].Prev = P; }
0253 void setNext(unsigned N) { SMS->Dense[Idx].Next = N; }
0254
0255 public:
0256 reference operator*() const {
0257 assert(isKeyed() && SMS->sparseIndex(SMS->Dense[Idx].Data) == SparseIdx &&
0258 "Dereferencing iterator of invalid key or index");
0259
0260 return SMS->Dense[Idx].Data;
0261 }
0262 pointer operator->() const { return &operator*(); }
0263
0264
0265 bool operator==(const iterator_base &RHS) const {
0266
0267 if (SMS == RHS.SMS && Idx == RHS.Idx) {
0268 assert((isEnd() || SparseIdx == RHS.SparseIdx) &&
0269 "Same dense entry, but different keys?");
0270 return true;
0271 }
0272
0273 return false;
0274 }
0275
0276 bool operator!=(const iterator_base &RHS) const {
0277 return !operator==(RHS);
0278 }
0279
0280
0281 iterator_base &operator--() {
0282 assert(isKeyed() && "Decrementing an invalid iterator");
0283 assert((isEnd() || !SMS->isHead(SMS->Dense[Idx])) &&
0284 "Decrementing head of list");
0285
0286
0287 if (isEnd())
0288 Idx = SMS->findIndex(SparseIdx).Prev();
0289 else
0290 Idx = Prev();
0291
0292 return *this;
0293 }
0294 iterator_base &operator++() {
0295 assert(!isEnd() && isKeyed() && "Incrementing an invalid/end iterator");
0296 Idx = Next();
0297 return *this;
0298 }
0299 iterator_base operator--(int) {
0300 iterator_base I(*this);
0301 --*this;
0302 return I;
0303 }
0304 iterator_base operator++(int) {
0305 iterator_base I(*this);
0306 ++*this;
0307 return I;
0308 }
0309 };
0310
0311 using iterator = iterator_base<SparseMultiSet *>;
0312 using const_iterator = iterator_base<const SparseMultiSet *>;
0313
0314
0315 using RangePair = std::pair<iterator, iterator>;
0316
0317
0318
0319 iterator end() { return iterator(this, SMSNode::INVALID, SMSNode::INVALID); }
0320 const_iterator end() const {
0321 return const_iterator(this, SMSNode::INVALID, SMSNode::INVALID);
0322 }
0323
0324
0325
0326
0327
0328 bool empty() const { return size() == 0; }
0329
0330
0331
0332
0333
0334
0335 size_type size() const {
0336 assert(NumFree <= Dense.size() && "Out-of-bounds free entries");
0337 return Dense.size() - NumFree;
0338 }
0339
0340
0341
0342 void clear() {
0343
0344 Dense.clear();
0345 NumFree = 0;
0346 FreelistIdx = SMSNode::INVALID;
0347 }
0348
0349
0350
0351
0352
0353
0354 iterator findIndex(unsigned Idx) {
0355 assert(Idx < Universe && "Key out of range");
0356 const unsigned Stride = std::numeric_limits<SparseT>::max() + 1u;
0357 for (unsigned i = Sparse[Idx], e = Dense.size(); i < e; i += Stride) {
0358 const unsigned FoundIdx = sparseIndex(Dense[i]);
0359
0360
0361 if (Idx == FoundIdx && Dense[i].isValid() && isHead(Dense[i]))
0362 return iterator(this, i, Idx);
0363
0364 if (!Stride)
0365 break;
0366 }
0367 return end();
0368 }
0369
0370
0371
0372
0373
0374
0375 iterator find(const KeyT &Key) {
0376 return findIndex(KeyIndexOf(Key));
0377 }
0378
0379 const_iterator find(const KeyT &Key) const {
0380 iterator I = const_cast<SparseMultiSet*>(this)->findIndex(KeyIndexOf(Key));
0381 return const_iterator(I.SMS, I.Idx, KeyIndexOf(Key));
0382 }
0383
0384
0385
0386 size_type count(const KeyT &Key) const {
0387 unsigned Ret = 0;
0388 for (const_iterator It = find(Key); It != end(); ++It)
0389 ++Ret;
0390
0391 return Ret;
0392 }
0393
0394
0395 bool contains(const KeyT &Key) const {
0396 return find(Key) != end();
0397 }
0398
0399
0400 iterator getHead(const KeyT &Key) { return find(Key); }
0401 iterator getTail(const KeyT &Key) {
0402 iterator I = find(Key);
0403 if (I != end())
0404 I = iterator(this, I.Prev(), KeyIndexOf(Key));
0405 return I;
0406 }
0407
0408
0409
0410
0411 RangePair equal_range(const KeyT &K) {
0412 iterator B = find(K);
0413 iterator E = iterator(this, SMSNode::INVALID, B.SparseIdx);
0414 return std::make_pair(B, E);
0415 }
0416
0417
0418
0419 iterator insert(const ValueT &Val) {
0420 unsigned Idx = sparseIndex(Val);
0421 iterator I = findIndex(Idx);
0422
0423 unsigned NodeIdx = addValue(Val, SMSNode::INVALID, SMSNode::INVALID);
0424
0425 if (I == end()) {
0426
0427 Sparse[Idx] = NodeIdx;
0428 Dense[NodeIdx].Prev = NodeIdx;
0429 return iterator(this, NodeIdx, Idx);
0430 }
0431
0432
0433 unsigned HeadIdx = I.Idx;
0434 unsigned TailIdx = I.Prev();
0435 Dense[TailIdx].Next = NodeIdx;
0436 Dense[HeadIdx].Prev = NodeIdx;
0437 Dense[NodeIdx].Prev = TailIdx;
0438
0439 return iterator(this, NodeIdx, Idx);
0440 }
0441
0442
0443
0444
0445
0446
0447
0448
0449
0450
0451
0452
0453
0454
0455
0456
0457
0458
0459
0460
0461
0462
0463
0464
0465
0466 iterator erase(iterator I) {
0467 assert(I.isKeyed() && !I.isEnd() && !Dense[I.Idx].isTombstone() &&
0468 "erasing invalid/end/tombstone iterator");
0469
0470
0471
0472 iterator NextI = unlink(Dense[I.Idx]);
0473
0474
0475 makeTombstone(I.Idx);
0476
0477 return NextI;
0478 }
0479
0480
0481
0482 void eraseAll(const KeyT &K) {
0483 for (iterator I = find(K); I != end(); )
0484 I = erase(I);
0485 }
0486
0487 private:
0488
0489 iterator unlink(const SMSNode &N) {
0490 if (isSingleton(N)) {
0491
0492 assert(N.Next == SMSNode::INVALID && "Singleton has next?");
0493 return iterator(this, SMSNode::INVALID, ValIndexOf(N.Data));
0494 }
0495
0496 if (isHead(N)) {
0497
0498 Sparse[sparseIndex(N)] = N.Next;
0499 Dense[N.Next].Prev = N.Prev;
0500 return iterator(this, N.Next, ValIndexOf(N.Data));
0501 }
0502
0503 if (N.isTail()) {
0504
0505 findIndex(sparseIndex(N)).setPrev(N.Prev);
0506 Dense[N.Prev].Next = N.Next;
0507
0508
0509 iterator I(this, N.Prev, ValIndexOf(N.Data));
0510 return ++I;
0511 }
0512
0513
0514 Dense[N.Next].Prev = N.Prev;
0515 Dense[N.Prev].Next = N.Next;
0516 return iterator(this, N.Next, ValIndexOf(N.Data));
0517 }
0518 };
0519
0520 }
0521
0522 #endif