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 using KeyT =
typename KeyFunctorT::argument_type;
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 =
static_cast<SparseT*
>(
safe_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 using super = std::iterator<std::bidirectional_iterator_tag, ValueT>;
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");
337 assert(NumFree <= Dense.
size() &&
"Out-of-bounds free entries");
338 return Dense.
size() - NumFree;
347 FreelistIdx = SMSNode::INVALID;
356 assert(Idx < Universe &&
"Key out of range");
358 for (
unsigned i = Sparse[Idx], e = Dense.
size(); i < e; i += Stride) {
359 const unsigned FoundIdx = sparseIndex(Dense[i]);
362 if (Idx == FoundIdx && Dense[i].isValid() && isHead(Dense[i]))
405 I =
iterator(
this, I.Prev(), KeyIndexOf(Key));
415 return make_pair(B, E);
421 unsigned Idx = sparseIndex(Val);
424 unsigned NodeIdx = addValue(Val, SMSNode::INVALID, SMSNode::INVALID);
428 Sparse[Idx] = NodeIdx;
429 Dense[NodeIdx].Prev = NodeIdx;
430 return iterator(
this, NodeIdx, Idx);
434 unsigned HeadIdx = I.Idx;
435 unsigned TailIdx = I.Prev();
436 Dense[TailIdx].Next = NodeIdx;
437 Dense[HeadIdx].Prev = NodeIdx;
438 Dense[NodeIdx].Prev = TailIdx;
440 return iterator(
this, NodeIdx, Idx);
468 assert(I.isKeyed() && !I.isEnd() && !Dense[I.Idx].isTombstone() &&
469 "erasing invalid/end/tombstone iterator");
473 iterator NextI = unlink(Dense[I.Idx]);
476 makeTombstone(I.Idx);
491 if (isSingleton(N)) {
493 assert(N.Next == SMSNode::INVALID &&
"Singleton has next?");
494 return iterator(
this, SMSNode::INVALID, ValIndexOf(N.Data));
499 Sparse[sparseIndex(N)] = N.Next;
500 Dense[N.Next].Prev = N.Prev;
501 return iterator(
this, N.Next, ValIndexOf(N.Data));
506 findIndex(sparseIndex(N)).setPrev(N.Prev);
507 Dense[N.Prev].Next = N.Next;
510 iterator I(
this, N.Prev, ValIndexOf(N.Data));
515 Dense[N.Next].Prev = N.Prev;
516 Dense[N.Prev].Next = N.Next;
517 return iterator(
this, N.Next, ValIndexOf(N.Data));
523 #endif // LLVM_ADT_SPARSEMULTISET_H iterator end()
Returns an iterator past this container.
GCNRegPressure max(const GCNRegPressure &P1, const GCNRegPressure &P2)
iterator_base< SparseMultiSet *> iterator
iterator insert(const ValueT &Val)
Insert a new element at the tail of the subset list.
This class represents lattice values for constants.
SparseMultiSet & operator=(const SparseMultiSet &)=delete
typename super::difference_type difference_type
bool contains(const KeyT &Key) const
Returns true if this set contains an element identified by Key.
size_type count(const KeyT &Key) const
Returns the number of elements identified by Key.
void push_back(const T &Elt)
iterator_base & operator--()
Increment and decrement operators.
std::iterator< std::bidirectional_iterator_tag, ValueT > super
bool operator==(const iterator_base &RHS) const
Comparison operators.
const_iterator find(const KeyT &Key) const
RangePair equal_range(const KeyT &K)
The bounds of the range of items sharing Key K.
size_type size() const
Returns the number of elements in the set.
iterator getHead(const KeyT &Key)
Return the head and tail of the subset's list, otherwise returns end().
An individual mapping from virtual register number to SUnit.
typename super::pointer pointer
iterator getTail(const KeyT &Key)
APInt operator*(APInt a, uint64_t RHS)
typename super::reference reference
iterator_base & operator++()
iterator_base operator++(int)
bool operator!=(const iterator_base &RHS) const
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")
void setUniverse(unsigned U)
Set the universe size which determines the largest key the set can hold.
void clear()
Clears the set.
iterator find(const KeyT &Key)
Find an element by its key.
iterator_base operator--(int)
void eraseAll(const KeyT &K)
Erase all elements with the given key.
static GCRegistry::Add< StatepointGC > D("statepoint-example", "an example strategy for statepoint")
iterator findIndex(unsigned Idx)
Find an element by its index.
typename super::value_type value_type
reference operator*() const
**iterator erase(iterator I)
SparseSetValFunctor - Helper class for selecting SparseSetValTraits.
std::pair< iterator, iterator > RangePair
bool empty() const
Returns true if the set is empty.
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
pointer operator->() const
Fast multiset implementation for objects that can be identified by small unsigned keys...
LLVM_ATTRIBUTE_RETURNS_NONNULL void * safe_calloc(size_t Count, size_t Sz)
Our iterators are iterators over the collection of objects that share a key.
bool operator==(uint64_t V1, const APInt &V2)
const_iterator end() const