21#ifndef LLVM_ADT_SPARSEMULTISET_H
22#define LLVM_ADT_SPARSEMULTISET_H
83template <
typename ValueT,
typename KeyFunctorT =
identity<
unsigned>,
84 typename SparseT = u
int8_t>
86 static_assert(std::is_unsigned_v<SparseT>,
87 "SparseT must be an unsigned integer type");
96 static constexpr unsigned INVALID = ~0U;
102 SMSNode(ValueT
D,
unsigned P,
unsigned N) :
Data(
D), Prev(
P),
Next(
N) {}
108 bool isTombstone()
const {
return Prev ==
INVALID; }
115 using KeyT =
typename KeyFunctorT::argument_type;
118 SparseT *Sparse =
nullptr;
119 unsigned Universe = 0;
120 KeyFunctorT KeyIndexOf;
126 unsigned FreelistIdx = SMSNode::INVALID;
127 unsigned NumFree = 0;
129 unsigned sparseIndex(
const ValueT &Val)
const {
130 assert(ValIndexOf(Val) < Universe &&
131 "Invalid key in set. Did object mutate?");
132 return ValIndexOf(Val);
134 unsigned sparseIndex(
const SMSNode &
N)
const {
return sparseIndex(
N.Data); }
139 bool isHead(
const SMSNode &
D)
const {
140 assert(
D.isValid() &&
"Invalid node for head");
141 return Dense[
D.Prev].isTail();
146 bool isSingleton(
const SMSNode &
N)
const {
147 assert(
N.isValid() &&
"Invalid node for singleton");
149 return &Dense[
N.Prev] == &
N;
154 unsigned addValue(
const ValueT &V,
unsigned Prev,
unsigned Next) {
156 Dense.push_back(SMSNode(V, Prev,
Next));
157 return Dense.size() - 1;
161 unsigned Idx = FreelistIdx;
162 unsigned NextFree = Dense[Idx].Next;
163 assert(Dense[Idx].isTombstone() &&
"Non-tombstone free?");
165 Dense[Idx] = SMSNode(V, Prev,
Next);
166 FreelistIdx = NextFree;
172 void makeTombstone(
unsigned Idx) {
173 Dense[Idx].Prev = SMSNode::INVALID;
174 Dense[Idx].Next = FreelistIdx;
200 assert(
empty() &&
"Can only resize universe on an empty map");
202 if (U >= Universe / 4 && U <= Universe)
208 Sparse =
static_cast<SparseT *
>(
safe_calloc(U,
sizeof(SparseT)));
214 template <
typename SMSPtrTy>
class iterator_base {
229 iterator_base(SMSPtrTy
P,
unsigned I,
unsigned SI)
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; }
252 assert(isKeyed() && SMS->sparseIndex(SMS->Dense[Idx].Data) == SparseIdx &&
253 "Dereferencing iterator of invalid key or index");
255 return SMS->Dense[Idx].Data;
262 if (SMS ==
RHS.SMS && Idx ==
RHS.Idx) {
263 assert((isEnd() || SparseIdx ==
RHS.SparseIdx) &&
264 "Same dense entry, but different keys?");
275 assert(isKeyed() &&
"Decrementing an invalid iterator");
276 assert((isEnd() || !SMS->isHead(SMS->Dense[Idx])) &&
277 "Decrementing head of list");
281 Idx = SMS->findIndex(SparseIdx).Prev();
288 assert(!isEnd() && isKeyed() &&
"Incrementing an invalid/end iterator");
293 iterator_base
I(*
this);
298 iterator_base
I(*
this);
329 assert(NumFree <= Dense.size() &&
"Out-of-bounds free entries");
330 return Dense.size() - NumFree;
339 FreelistIdx = SMSNode::INVALID;
348 assert(Idx < Universe &&
"Key out of range");
349 const unsigned Stride = std::numeric_limits<SparseT>::max() + 1u;
350 for (
unsigned i = Sparse[Idx], e = Dense.size(); i < e; i += Stride) {
351 const unsigned FoundIdx = sparseIndex(Dense[i]);
354 if (Idx == FoundIdx && Dense[i].
isValid() && isHead(Dense[i]))
403 return std::make_pair(
B,
E);
409 unsigned Idx = sparseIndex(Val);
412 unsigned NodeIdx = addValue(Val, SMSNode::INVALID, SMSNode::INVALID);
416 Sparse[Idx] = NodeIdx;
417 Dense[NodeIdx].Prev = NodeIdx;
418 return iterator(
this, NodeIdx, Idx);
422 unsigned HeadIdx =
I.Idx;
423 unsigned TailIdx =
I.Prev();
424 Dense[TailIdx].Next = NodeIdx;
425 Dense[HeadIdx].Prev = NodeIdx;
426 Dense[NodeIdx].Prev = TailIdx;
428 return iterator(
this, NodeIdx, Idx);
456 assert(
I.isKeyed() && !
I.isEnd() && !Dense[
I.Idx].isTombstone() &&
457 "erasing invalid/end/tombstone iterator");
464 makeTombstone(
I.Idx);
479 if (isSingleton(
N)) {
481 assert(
N.Next == SMSNode::INVALID &&
"Singleton has next?");
482 return iterator(
this, SMSNode::INVALID, ValIndexOf(
N.Data));
487 Sparse[sparseIndex(
N)] =
N.Next;
489 return iterator(
this,
N.Next, ValIndexOf(
N.Data));
495 Dense[
N.Prev].Next =
N.Next;
503 Dense[
N.Next].Prev =
N.Prev;
504 Dense[
N.Prev].Next =
N.Next;
505 return iterator(
this,
N.Next, ValIndexOf(
N.Data));
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static GCRegistry::Add< StatepointGC > D("statepoint-example", "an example strategy for statepoint")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
static bool isValid(const char C)
Returns true if C is a valid mangled character: <0-9a-zA-Z_>.
This file defines the SmallVector class.
This file defines the SparseSet class derived from the version described in Briggs,...
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Our iterators are iterators over the collection of objects that share a key.
iterator_base operator++(int)
friend class SparseMultiSet
bool operator!=(const iterator_base &RHS) const
pointer operator->() const
std::bidirectional_iterator_tag iterator_category
reference operator*() const
iterator_base & operator++()
iterator_base & operator--()
Increment and decrement operators.
bool operator==(const iterator_base &RHS) const
Comparison operators.
iterator_base operator--(int)
std::ptrdiff_t difference_type
iterator find(const KeyT &Key)
Find an element by its key.
bool empty() const
Returns true if the set is empty.
iterator_base< const SparseMultiSet * > const_iterator
bool contains(const KeyT &Key) const
Returns true if this set contains an element identified by Key.
iterator findIndex(unsigned Idx)
Find an element by its index.
void clear()
Clears the set.
iterator erase(iterator I)
Erases an existing element identified by a valid iterator.
size_type size() const
Returns the number of elements in the set.
iterator end()
Returns an iterator past this container.
const_iterator find(const KeyT &Key) const
size_type count(const KeyT &Key) const
Returns the number of elements identified by Key.
iterator insert(const ValueT &Val)
Insert a new element at the tail of the subset list.
SparseMultiSet(const SparseMultiSet &)=delete
const ValueT & const_reference
iterator getHead(const KeyT &Key)
Return the head and tail of the subset's list, otherwise returns end().
const_iterator end() const
iterator getTail(const KeyT &Key)
SparseMultiSet & operator=(const SparseMultiSet &)=delete
void eraseAll(const KeyT &K)
Erase all elements with the given key.
RangePair equal_range(const KeyT &K)
The bounds of the range of items sharing Key K.
const ValueT * const_pointer
iterator_base< SparseMultiSet * > iterator
std::pair< iterator, iterator > RangePair
void setUniverse(unsigned U)
Set the universe size which determines the largest key the set can hold.
This is an optimization pass for GlobalISel generic memory operations.
LLVM_ATTRIBUTE_RETURNS_NONNULL void * safe_calloc(size_t Count, size_t Sz)
LLVM_ATTRIBUTE_VISIBILITY_DEFAULT AnalysisKey InnerAnalysisManagerProxy< AnalysisManagerT, IRUnitT, ExtraArgTs... >::Key
FunctionAddr VTableAddr uintptr_t uintptr_t Data
FunctionAddr VTableAddr Next
SparseSetValFunctor - Helper class for selecting SparseSetValTraits.