21 #ifndef LLVM_ADT_SPARSEMULTISET_H
22 #define LLVM_ADT_SPARSEMULTISET_H
84 typename KeyFunctorT = identity<unsigned>,
85 typename SparseT = uint8_t>
87 static_assert(std::numeric_limits<SparseT>::is_integer &&
88 !std::numeric_limits<SparseT>::is_signed,
89 "SparseT must be an unsigned integer type");
98 static const unsigned INVALID = ~0U;
104 SMSNode(
ValueT D,
unsigned P,
unsigned N) : Data(D), Prev(P), Next(N) { }
107 bool isTail()
const {
108 return Next == INVALID;
112 bool isTombstone()
const {
113 return Prev == INVALID;
118 bool isValid()
const {
return Prev != INVALID; }
121 typedef typename KeyFunctorT::argument_type KeyT;
124 SparseT *Sparse =
nullptr;
125 unsigned Universe = 0;
126 KeyFunctorT KeyIndexOf;
132 unsigned FreelistIdx = SMSNode::INVALID;
133 unsigned NumFree = 0;
135 unsigned sparseIndex(
const ValueT &Val)
const {
136 assert(ValIndexOf(Val) < Universe &&
137 "Invalid key in set. Did object mutate?");
138 return ValIndexOf(Val);
140 unsigned sparseIndex(
const SMSNode &
N)
const {
return sparseIndex(N.Data); }
145 bool isHead(
const SMSNode &
D)
const {
146 assert(D.isValid() &&
"Invalid node for head");
147 return Dense[D.Prev].isTail();
152 bool isSingleton(
const SMSNode &N)
const {
153 assert(N.isValid() &&
"Invalid node for singleton");
155 return &Dense[N.Prev] == &
N;
160 unsigned addValue(
const ValueT& V,
unsigned Prev,
unsigned Next) {
163 return Dense.
size() - 1;
167 unsigned Idx = FreelistIdx;
168 unsigned NextFree = Dense[Idx].Next;
169 assert(Dense[Idx].isTombstone() &&
"Non-tombstone free?");
171 Dense[Idx] = SMSNode(V, Prev, Next);
172 FreelistIdx = NextFree;
178 void makeTombstone(
unsigned Idx) {
179 Dense[Idx].Prev = SMSNode::INVALID;
180 Dense[Idx].Next = FreelistIdx;
206 assert(
empty() &&
"Can only resize universe on an empty map");
208 if (U >= Universe/4 && U <= Universe)
214 Sparse =
reinterpret_cast<SparseT*
>(calloc(U,
sizeof(SparseT)));
220 template<
typename SMSPtrTy>
230 : SMS(P), Idx(I), SparseIdx(SI) { }
234 if (Idx == SMSNode::INVALID)
237 assert(Idx < SMS->Dense.size() &&
"Out of range, non-INVALID Idx?");
242 bool isKeyed()
const {
return SparseIdx < SMS->Universe; }
244 unsigned Prev()
const {
return SMS->Dense[Idx].Prev; }
245 unsigned Next()
const {
return SMS->Dense[Idx].Next; }
247 void setPrev(
unsigned P) { SMS->Dense[Idx].Prev =
P; }
248 void setNext(
unsigned N) { SMS->Dense[Idx].Next =
N; }
251 typedef std::iterator<std::bidirectional_iterator_tag, ValueT>
super;
258 assert(isKeyed() && SMS->sparseIndex(SMS->Dense[Idx].Data) == SparseIdx &&
259 "Dereferencing iterator of invalid key or index");
261 return SMS->Dense[Idx].Data;
268 if (SMS == RHS.SMS && Idx == RHS.Idx) {
269 assert((isEnd() || SparseIdx == RHS.SparseIdx) &&
270 "Same dense entry, but different keys?");
283 assert(isKeyed() &&
"Decrementing an invalid iterator");
284 assert((isEnd() || !SMS->isHead(SMS->Dense[Idx])) &&
285 "Decrementing head of list");
289 Idx = SMS->findIndex(SparseIdx).Prev();
296 assert(!isEnd() && isKeyed() &&
"Incrementing an invalid/end iterator");
336 assert(NumFree <= Dense.
size() &&
"Out-of-bounds free entries");
337 return Dense.
size() - NumFree;
346 FreelistIdx = SMSNode::INVALID;
355 assert(Idx < Universe &&
"Key out of range");
356 const unsigned Stride = std::numeric_limits<SparseT>::max() + 1u;
357 for (
unsigned i = Sparse[Idx], e = Dense.
size();
i < e;
i += Stride) {
358 const unsigned FoundIdx = sparseIndex(Dense[
i]);
361 if (Idx == FoundIdx && Dense[i].
isValid() && isHead(Dense[i]))
404 I =
iterator(
this, I.Prev(), KeyIndexOf(Key));
414 return make_pair(B, E);
420 unsigned Idx = sparseIndex(Val);
423 unsigned NodeIdx = addValue(Val, SMSNode::INVALID, SMSNode::INVALID);
427 Sparse[Idx] = NodeIdx;
428 Dense[NodeIdx].Prev = NodeIdx;
429 return iterator(
this, NodeIdx, Idx);
433 unsigned HeadIdx = I.Idx;
434 unsigned TailIdx = I.Prev();
435 Dense[TailIdx].Next = NodeIdx;
436 Dense[HeadIdx].Prev = NodeIdx;
437 Dense[NodeIdx].Prev = TailIdx;
439 return iterator(
this, NodeIdx, Idx);
467 assert(I.isKeyed() && !I.isEnd() && !Dense[I.Idx].isTombstone() &&
468 "erasing invalid/end/tombstone iterator");
472 iterator NextI = unlink(Dense[I.Idx]);
475 makeTombstone(I.Idx);
490 if (isSingleton(N)) {
492 assert(N.Next == SMSNode::INVALID &&
"Singleton has next?");
493 return iterator(
this, SMSNode::INVALID, ValIndexOf(N.Data));
498 Sparse[sparseIndex(N)] = N.Next;
499 Dense[N.Next].Prev = N.Prev;
500 return iterator(
this, N.Next, ValIndexOf(N.Data));
505 findIndex(sparseIndex(N)).setPrev(N.Prev);
506 Dense[N.Prev].Next = N.Next;
509 iterator I(
this, N.Prev, ValIndexOf(N.Data));
514 Dense[N.Next].Prev = N.Prev;
515 Dense[N.Prev].Next = N.Next;
516 return iterator(
this, N.Next, ValIndexOf(N.Data));
522 #endif // LLVM_ADT_SPARSEMULTISET_H
iterator end()
Returns an iterator past this container.
void push_back(const T &Elt)
super::reference reference
iterator insert(const ValueT &Val)
Insert a new element at the tail of the subset list.
bool contains(const KeyT &Key) const
Returns true if this set contains an element identified by Key.
size_type size() const
Returns the number of elements in the set.
SparseMultiSet & operator=(const SparseMultiSet &)=delete
iterator_base & operator--()
Increment and decrement operators.
const_iterator find(const KeyT &Key) const
RangePair equal_range(const KeyT &K)
The bounds of the range of items sharing Key K.
iterator_base< SparseMultiSet * > iterator
iterator getHead(const KeyT &Key)
Return the head and tail of the subset's list, otherwise returns end().
const ValueT * const_pointer
static GCRegistry::Add< StatepointGC > D("statepoint-example","an example strategy for statepoint")
iterator getTail(const KeyT &Key)
iterator_base & operator++()
iterator_base operator++(int)
static GCRegistry::Add< OcamlGC > B("ocaml","ocaml 3.10-compatible GC")
iterator_base< const SparseMultiSet * > const_iterator
static GCRegistry::Add< CoreCLRGC > E("coreclr","CoreCLR-compatible GC")
super::value_type value_type
void setUniverse(unsigned U)
Set the universe size which determines the largest key the set can hold.
pointer operator->() const
void clear()
Clears the set.
iterator find(const KeyT &Key)
Find an element by its key.
const_iterator end() const
reference operator*() const
iterator_base operator--(int)
super::difference_type difference_type
void eraseAll(const KeyT &K)
Erase all elements with the given key.
INITIALIZE_PASS(HexagonGenMux,"hexagon-mux","Hexagon generate mux instructions", false, false) void HexagonGenMux I isValid()
iterator findIndex(unsigned Idx)
Find an element by its index.
**iterator erase(iterator I)
SparseSetValFunctor - Helper class for selecting SparseSetValTraits.
LLVM_ATTRIBUTE_ALWAYS_INLINE size_type size() const
std::iterator< std::bidirectional_iterator_tag, ValueT > super
bool operator!=(const iterator_base &RHS) const
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
Fast multiset implementation for objects that can be identified by small unsigned keys...
bool empty() const
Returns true if the set is empty.
Our iterators are iterators over the collection of objects that share a key.
const ValueT & const_reference
bool operator==(const iterator_base &RHS) const
Comparison operators.
std::pair< iterator, iterator > RangePair
size_type count(const KeyT &Key) const
Returns the number of elements identified by Key.