14 #ifndef LLVM_ADT_IMMUTABLESET_H
15 #define LLVM_ADT_IMMUTABLESET_H
41 template <
typename ImutInfo >
83 else if (ImutInfo::isLess(K,CurrentKey))
123 ImutInfo::KeyOfValue(V)))
127 if (!ImutInfo::isDataEqual(ImutInfo::DataOfValue(
getValue()),
128 ImutInfo::DataOfValue(V)))
148 while (LItr != LEnd && RItr != REnd) {
149 if (&*LItr == &*RItr) {
162 return LItr == LEnd && RItr == REnd;
177 template <
typename Callback>
178 void foreach(Callback&
C) {
201 &&
"Height calculation wrong");
203 assert((HL > HR ? HL-HR : HR-HL) <= 2
204 &&
"Balancing invariant violated");
208 ImutInfo::KeyOfValue(
getValue()))) &&
209 "Value in left child is not less that current value");
213 ImutInfo::isLess(ImutInfo::KeyOfValue(
getValue()),
215 "Current value is not less that value of right child");
231 unsigned height : 28;
232 unsigned IsMutable : 1;
233 unsigned IsDigestCached : 1;
234 unsigned IsCanonicalized : 1;
249 : factory(f), left(l), right(r), prev(nullptr), next(nullptr),
250 height(height), IsMutable(
true), IsDigestCached(
false),
251 IsCanonicalized(0), value(v), digest(0), refCount(0)
254 if (right) right->
retain();
263 bool isMutable()
const {
return IsMutable; }
267 bool hasCachedDigest()
const {
return IsDigestCached; }
282 void markImmutable() {
283 assert(isMutable() &&
"Mutable flag already removed.");
288 void markedCachedDigest() {
289 assert(!hasCachedDigest() &&
"NoCachedDigest flag already removed.");
290 IsDigestCached =
true;
295 void setHeight(
unsigned h) {
296 assert(isMutable() &&
"Only a mutable tree can have its height changed.");
300 static uint32_t computeDigest(ImutAVLTree *
L, ImutAVLTree *R,
305 digest += L->computeDigest();
309 ImutInfo::Profile(ID,V);
310 digest += ID.ComputeHash();
313 digest += R->computeDigest();
321 if (hasCachedDigest())
326 markedCachedDigest();
348 if (IsCanonicalized) {
361 factory->freeNodes.push_back(
this);
369 template <
typename ImutInfo >
370 class ImutAVLFactory {
380 std::vector<TreeTy*> createdNodes;
381 std::vector<TreeTy*> freeNodes;
383 bool ownsAllocator()
const {
400 :
Allocator(reinterpret_cast<uintptr_t>(&Alloc) | 0x1) {}
403 if (ownsAllocator())
delete &getAllocator();
442 return (hl > hr ? hl : hr) + 1;
449 for ( ; I!=
E ; ++
I, ++TI) {
469 if (!freeNodes.empty()) {
470 T = freeNodes.back();
471 freeNodes.pop_back();
478 createdNodes.push_back(T);
487 for (
unsigned i = 0, n = createdNodes.size();
i < n; ++
i) {
489 if (N->isMutable() && N->refCount == 0)
492 createdNodes.clear();
502 assert(!
isEmpty(L) &&
"Left tree cannot be empty to have a height >= 2");
510 assert(!
isEmpty(LR) &&
"LR cannot be empty because it has a height >= 1");
519 assert(!
isEmpty(R) &&
"Right tree cannot be empty to have a height >= 2");
527 assert(!
isEmpty(RL) &&
"RL cannot be empty because it has a height >= 1");
546 key_type_ref K = ImutInfo::KeyOfValue(V);
547 key_type_ref KCurrent = ImutInfo::KeyOfValue(
getValue(T));
551 else if (ImutInfo::isLess(K,KCurrent))
567 key_type_ref KCurrent = ImutInfo::KeyOfValue(
getValue(T));
571 }
else if (ImutInfo::isLess(K,KCurrent)) {
603 if (!T || !T->isMutable())
615 if (TNew->IsCanonicalized)
620 unsigned digest = TNew->computeDigest();
625 for (
TreeTy *
T = entry ;
T !=
nullptr;
T =
T->next) {
633 if (TNew->refCount == 0)
643 TNew->IsCanonicalized =
true;
652 template <
typename ImutInfo>
653 class ImutAVLTreeGenericIterator
654 :
public std::iterator<std::bidirectional_iterator_tag,
655 ImutAVLTree<ImutInfo>> {
656 SmallVector<uintptr_t,20> stack;
666 if (Root) stack.
push_back(reinterpret_cast<uintptr_t>(Root));
704 return stack == x.stack;
708 return !(*
this == x);
718 stack.
push_back(reinterpret_cast<uintptr_t>(L));
724 stack.
push_back(reinterpret_cast<uintptr_t>(R));
763 template <
typename ImutInfo>
764 class ImutAVLTreeInOrderIterator
765 :
public std::iterator<std::bidirectional_iterator_tag,
766 ImutAVLTree<ImutInfo>> {
767 typedef ImutAVLTreeGenericIterator<ImutInfo> InternalIteratorTy;
768 InternalIteratorTy InternalItr;
781 return InternalItr == x.InternalItr;
785 return !(*
this == x);
793 while (!InternalItr.atEnd() &&
794 InternalItr.getVisitState() != InternalIteratorTy::VisitedLeft);
801 while (!InternalItr.atBeginning() &&
802 InternalItr.getVisitState() != InternalIteratorTy::VisitedLeft);
808 InternalItr.skipToParent();
810 while (!InternalItr.atEnd() &&
811 InternalItr.getVisitState() != InternalIteratorTy::VisitedLeft)
818 template <
typename T>
821 ImutAVLValueIterator<T>, typename T::TreeTy::iterator,
822 typename std::iterator_traits<
823 typename T::TreeTy::iterator>::iterator_category,
824 const typename T::value_type> {
829 typename ImutAVLValueIterator::reference
operator*()
const {
830 return this->
I->getValue();
841 template <
typename T>
852 template <
typename T>
862 #define PROFILE_INTEGER_INFO(X)\
863 template<> struct ImutProfileInfo<X> : ImutProfileInteger<X> {};
876 #undef PROFILE_INTEGER_INFO
891 template <
typename T>
911 template <
typename T>
924 return std::equal_to<key_type>()(LHS,RHS);
928 return std::less<key_type>()(LHS,RHS);
937 template <
typename T>
949 static bool isEqual(key_type_ref LHS, key_type_ref RHS) {
return LHS == RHS; }
951 static bool isLess(key_type_ref LHS, key_type_ref RHS) {
return LHS < RHS; }
953 static bool isDataEqual(data_type_ref, data_type_ref) {
return true; }
960 template <
typename ValT,
typename ValInfo = ImutContainerInfo<ValT>>
976 if (Root) { Root->
retain(); }
980 if (Root) { Root->
retain(); }
984 if (Root != X.Root) {
985 if (X.Root) { X.Root->
retain(); }
998 const bool Canonicalize;
1002 : Canonicalize(canonicalize) {}
1005 : F(Alloc), Canonicalize(canonicalize) {}
1050 return Root ? Root->
contains(V) :
false;
1054 return Root && RHS.Root ? Root->
isEqual(*RHS.Root) : Root == RHS.Root;
1058 return Root && RHS.Root ? Root->
isNotEqual(*RHS.Root) : Root != RHS.Root;
1062 if (Root) { Root->
retain(); }
1077 template <
typename Callback>
1078 void foreach(Callback& C) {
if (Root) Root->
foreach(C); }
1080 template <
typename Callback>
1081 void foreach() {
if (Root) { Callback
C; Root->
foreach(C); } }
1112 template <
typename ValT,
typename ValInfo = ImutContainerInfo<ValT>>
1132 if (Root) { Root->
retain(); }
1137 Factory(X.Factory) {
1138 if (Root) { Root->
retain(); }
1142 if (Root != X.Root) {
1143 if (X.Root) { X.Root->
retain(); }
1144 if (Root) { Root->
release(); }
1146 Factory = X.Factory;
1151 if (Root) { Root->
release(); }
1168 return Root ? Root->
contains(V) :
false;
1181 return Root && RHS.Root ? Root->
isEqual(*RHS.Root) : Root == RHS.Root;
1185 return Root && RHS.Root ? Root->
isNotEqual(*RHS.Root) : Root != RHS.Root;
1225 #endif // LLVM_ADT_IMMUTABLESET_H
Generic iterator that wraps a T::TreeTy::iterator and exposes iterator::getValue() on dereference...
unsigned getHeight() const
getHeight - Returns the height of the tree.
ImutAVLTree< ValInfo > TreeTy
void validateTree() const
ImmutableSet add(ImmutableSet Old, value_type_ref V)
add - Creates a new immutable set that contains all of the values of the original set with the additi...
void AddPointer(const void *Ptr)
Add* - Add various data types to Bit data.
ImmutableSetRef(const ImmutableSetRef &X)
void push_back(const T &Elt)
static void Profile(FoldingSetNodeID &ID, value_type_ref X)
ImutAVLValueIterator()=default
unsigned validateTree() const
validateTree - A utility method that checks that the balancing and ordering invariants of the tree ar...
static void Profile(FoldingSetNodeID &ID, value_type_ref X)
static bool isDataEqual(data_type_ref, data_type_ref)
Generic profile trait for pointer types.
ValInfo::value_type value_type
TreeTy * balanceTree(TreeTy *L, value_type_ref V, TreeTy *R)
balanceTree - Used by add_internal and remove_internal to balance a newly created tree...
ImutAVLTree * getLeft() const
Return a pointer to the left subtree.
ValInfo::value_type_ref value_type_ref
static data_type_ref DataOfValue(value_type_ref)
bool operator==(const ImmutableSetRef &RHS) const
TreeTy * add(TreeTy *T, value_type_ref V)
ImutInfo::key_type_ref key_type_ref
ImutProfileInfo< T * >::value_type value_type
bool contains(value_type_ref V) const
Returns true if the set contains the specified value.
ImutAVLTree< ValInfo > TreeTy
BumpPtrAllocator & getAllocator()
TreeTy * remove_internal(key_type_ref K, TreeTy *T)
remove_internal - Creates a new tree that includes all the data from the original tree except the spe...
ImutAVLTreeInOrderIterator & operator--()
bool contains(value_type_ref V) const
Returns true if the set contains the specified value.
void Profile(FoldingSetNodeID &ID) const
TreeTy * getRootWithoutRetain() const
TreeTy & operator*() const
TreeTy * createNode(TreeTy *newLeft, TreeTy *oldTree, TreeTy *newRight)
ImutAVLTreeGenericIterator(const TreeTy *Root)
bool isNotEqual(const ImutAVLTree &RHS) const
isNotEqual - Compares two trees for structural inequality.
bool isSingleton() const
isSingleton - Return true if the set contains exactly one element.
static void Profile(const T &X, FoldingSetNodeID &ID)
ImmutableSet & operator=(const ImmutableSet &X)
TreeTy::Factory * getTreeFactory() const
This file defines the MallocAllocator and BumpPtrAllocator interfaces.
bool isElementEqual(const ImutAVLTree *RHS) const
ImutAVLTree * getMaxElement()
getMaxElement - Find the subtree associated with the highest ranged key value.
static ImmutableSetRef getEmptySet(FactoryTy *F)
TreeTy * createNode(TreeTy *L, value_type_ref V, TreeTy *R)
ImutAVLTreeInOrderIterator & operator++()
Generic profile template.
static GCRegistry::Add< StatepointGC > D("statepoint-example","an example strategy for statepoint")
void AddInteger(signed I)
static bool isEqual(key_type_ref LHS, key_type_ref RHS)
TreeTy * operator->() const
static void Profile(FoldingSetNodeID &ID, const ImmutableSet &S)
static bool compareTreeWithSection(TreeTy *T, typename TreeTy::iterator &TI, typename TreeTy::iterator &TE)
static data_type_ref DataOfValue(value_type_ref)
ImmutableSetRef add(value_type_ref V)
unsigned getHeight() const
LLVM_NODISCARD bool empty() const
bool isSingleton() const
isSingleton - Return true if the set contains exactly one element.
ImutInfo::value_type_ref value_type_ref
#define PROFILE_INTEGER_INFO(X)
ImmutableSet getEmptySet()
getEmptySet - Returns an immutable set that contains no elements.
static bool isEqual(const Function &Caller, const Function &Callee)
iterator begin() const
begin - Returns an iterator that iterates over the nodes of the tree in an inorder traversal...
ImutAVLFactory< ImutInfo > Factory
Function Alias Analysis false
ImmutableSetRef(TreeTy *R, FactoryTy *F)
Constructs a set from a pointer to a tree root.
ImutAVLValueIterator(typename T::TreeTy *Tree)
ImutAVLValueIterator< ImmutableSetRef > iterator
value_type_ref key_type_ref
Profile traits for integers.
ImutAVLTree< ImutInfo > TreeTy
void foreach(Callback &C)
foreach - A member template the accepts invokes operator() on a functor object (specifed by Callback)...
static void Profile(FoldingSetNodeID &ID, const ImmutableSetRef &S)
ImutAVLTreeInOrderIterator()
static GCRegistry::Add< CoreCLRGC > E("coreclr","CoreCLR-compatible GC")
bool operator!=(const ImutAVLTreeInOrderIterator &x) const
FoldingSetNodeID - This class is used to gather all the unique data bits of a node.
Factory(bool canonicalize=true)
const bool & value_type_ref
TreeTy * add_internal(value_type_ref V, TreeTy *T)
add_internal - Creates a new tree that includes the specified data and the data from the original tre...
bool operator!=(const ImmutableSetRef &RHS) const
TreeTy * getEmptyTree() const
TreeTy * remove(TreeTy *T, key_type_ref V)
ImutAVLTreeGenericIterator & operator--()
Allocate memory in an ever growing pool, as if by bump-pointer.
CRTP base class for adapting an iterator to a different type.
TreeTy * operator->() const
bool operator==(const ImutAVLTreeInOrderIterator &x) const
LLVM_ATTRIBUTE_RETURNS_NONNULL LLVM_ATTRIBUTE_RETURNS_NOALIAS void * Allocate(size_t Size, size_t Alignment)
Allocate space at the specified alignment.
ImutAVLTree * find(key_type_ref K)
find - Finds the subtree associated with the specified key value.
ImutAVLTree * getRight() const
Return a pointer to the right subtree.
Greedy Register Allocator
void markImmutable(TreeTy *T)
markImmutable - Clears the mutable bits of a root and all of its descendants.
static void Profile(FoldingSetNodeID &ID, value_type_ref X)
static GCMetadataPrinterRegistry::Add< ErlangGCPrinter > X("erlang","erlang-compatible garbage collector")
bool isElementEqual(value_type_ref V) const
ImutAVLTreeInOrderIterator(const TreeTy *Root)
unsigned size() const
size - Returns the number of nodes in the tree, which includes both leaves and non-leaf nodes...
bool isEmpty() const
isEmpty - Return true if the set contains no elements.
static bool isEqual(key_type_ref LHS, key_type_ref RHS)
void operator=(const Factory &RHS)=delete
TreeTy * getRight(TreeTy *T) const
value_type_ref getValue(TreeTy *T) const
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
bool contains(key_type_ref K)
contains - Returns true if this tree contains a subtree (node) that has an data element that matches ...
bool operator!=(const ImmutableSet &RHS) const
TreeTy & operator*() const
ImutAVLTreeInOrderIterator< ImutInfo > iterator
TreeTy * getRootWithoutRetain() const
unsigned getHeight() const
ImutProfileInfo< T >::value_type value_type
Factory(BumpPtrAllocator &Alloc, bool canonicalize=true)
bool operator==(const ImutAVLTreeGenericIterator &x) const
iterator end() const
end - Returns an iterator for the tree that denotes the end of an inorder traversal.
ImutProfileInfo< T * >::value_type_ref value_type_ref
ImutInfo::value_type value_type
bool isEmpty() const
isEmpty - Return true if the set contains no elements.
static GCRegistry::Add< ShadowStackGC > C("shadow-stack","Very portable GC for uncooperative code generators")
ImmutableSetRef & operator=(const ImmutableSetRef &X)
static key_type_ref KeyOfValue(value_type_ref D)
void validateTree() const
unsigned incrementHeight(TreeTy *L, TreeTy *R) const
TreeTy * getCanonicalTree(TreeTy *TNew)
TreeTy::Factory FactoryTy
ImutProfileInfo< T >::value_type_ref value_type_ref
static bool isDataEqual(data_type_ref, data_type_ref)
TreeTy * combineTrees(TreeTy *L, TreeTy *R)
TreeTy * removeMinBinding(TreeTy *T, TreeTy *&Noderemoved)
ImutAVLFactory(BumpPtrAllocator &Alloc)
ImutAVLTreeGenericIterator()=default
ImutAVLTree< ImutInfo > TreeTy
bool operator!=(const ImutAVLTreeGenericIterator &x) const
ImutAVLTreeGenericIterator & operator++()
static key_type_ref KeyOfValue(value_type_ref D)
ImmutableSet(TreeTy *R)
Constructs a set from a pointer to a tree root.
uintptr_t getVisitState() const
const value_type & getValue() const
getValue - Returns the data value associated with the tree node.
LLVM_ATTRIBUTE_ALWAYS_INLINE size_type size() const
static bool isLess(key_type_ref LHS, key_type_ref RHS)
ImmutableSet(const ImmutableSet &X)
ValInfo::value_type_ref value_type_ref
bool isEmpty(TreeTy *T) const
void Profile(FoldingSetNodeID &ID) const
static bool isLess(key_type_ref LHS, key_type_ref RHS)
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
bool operator==(const ImmutableSet &RHS) const
ValInfo::value_type value_type
static void Profile(FoldingSetNodeID &ID, value_type_ref X)
value_type value_type_ref
ImutAVLValueIterator::reference operator*() const
ImutAVLValueIterator< ImmutableSet > iterator
bool isEqual(const ImutAVLTree &RHS) const
isEqual - Compares two trees for structural equality and returns true if they are equal...
value_type_ref key_type_ref
TreeTy * getLeft(TreeTy *T) const
ImmutableSet< ValT > asImmutableSet(bool canonicalize=true) const
static GCRegistry::Add< ErlangGC > A("erlang","erlang-compatible garbage collector")
unsigned getHeight(TreeTy *T) const
ImutContainerInfo - Generic definition of comparison operations for elements of immutable containers ...
static unsigned maskCacheIndex(unsigned I)