14 #ifndef LLVM_ADT_IMMUTABLESET_H 15 #define LLVM_ADT_IMMUTABLESET_H 41 template <
typename ImutInfo >
81 else if (ImutInfo::isLess(K,CurrentKey))
121 ImutInfo::KeyOfValue(V)))
125 if (!ImutInfo::isDataEqual(ImutInfo::DataOfValue(
getValue()),
126 ImutInfo::DataOfValue(V)))
146 while (LItr != LEnd && RItr != REnd) {
147 if (&*LItr == &*RItr) {
160 return LItr == LEnd && RItr == REnd;
175 template <
typename Callback>
176 void foreach(Callback&
C) {
199 &&
"Height calculation wrong");
201 assert((HL > HR ? HL-HR : HR-HL) <= 2
202 &&
"Balancing invariant violated");
206 ImutInfo::KeyOfValue(
getValue()))) &&
207 "Value in left child is not less that current value");
211 ImutInfo::isLess(ImutInfo::KeyOfValue(
getValue()),
213 "Current value is not less that value of right child");
229 unsigned height : 28;
231 bool IsDigestCached : 1;
232 bool IsCanonicalized : 1;
247 : factory(f), left(l), right(r), height(height), IsMutable(
true),
248 IsDigestCached(
false), IsCanonicalized(
false), value(v)
251 if (right) right->
retain();
260 bool isMutable()
const {
return IsMutable; }
264 bool hasCachedDigest()
const {
return IsDigestCached; }
279 void markImmutable() {
280 assert(isMutable() &&
"Mutable flag already removed.");
285 void markedCachedDigest() {
286 assert(!hasCachedDigest() &&
"NoCachedDigest flag already removed.");
287 IsDigestCached =
true;
292 void setHeight(
unsigned h) {
293 assert(isMutable() &&
"Only a mutable tree can have its height changed.");
302 digest += L->computeDigest();
306 ImutInfo::Profile(ID,V);
310 digest += R->computeDigest();
318 if (hasCachedDigest())
323 markedCachedDigest();
345 if (IsCanonicalized) {
358 factory->freeNodes.push_back(
this);
366 template <
typename ImutInfo >
377 std::vector<TreeTy*> createdNodes;
378 std::vector<TreeTy*> freeNodes;
380 bool ownsAllocator()
const {
381 return (Allocator & 0x1) == 0;
397 : Allocator(reinterpret_cast<uintptr_t>(&Alloc) | 0x1) {}
400 if (ownsAllocator())
delete &getAllocator();
403 TreeTy*
add(TreeTy*
T, value_type_ref V) {
404 T = add_internal(V,T);
410 TreeTy*
remove(TreeTy*
T, key_type_ref V) {
411 T = remove_internal(V,T);
431 value_type_ref
getValue(TreeTy* T)
const {
return T->value; }
439 return (hl > hr ? hl : hr) + 1;
446 for ( ; I!=
E ; ++
I, ++TI) {
466 if (!freeNodes.empty()) {
467 T = freeNodes.back();
468 freeNodes.pop_back();
474 new (
T) TreeTy(
this, L, R, V, incrementHeight(L,R));
475 createdNodes.push_back(T);
479 TreeTy*
createNode(TreeTy* newLeft, TreeTy* oldTree, TreeTy* newRight) {
480 return createNode(newLeft,
getValue(oldTree), newRight);
484 for (
unsigned i = 0, n = createdNodes.size(); i < n; ++i) {
485 TreeTy *
N = createdNodes[i];
486 if (N->isMutable() && N->refCount == 0)
489 createdNodes.clear();
499 assert(!isEmpty(L) &&
"Left tree cannot be empty to have a height >= 2");
505 return createNode(LL, L, createNode(LR,V,R));
507 assert(!isEmpty(LR) &&
"LR cannot be empty because it has a height >= 1");
512 return createNode(createNode(LL,L,LRL), LR, createNode(LRR,V,R));
516 assert(!isEmpty(R) &&
"Right tree cannot be empty to have a height >= 2");
522 return createNode(createNode(L,V,RL), R, RR);
524 assert(!isEmpty(RL) &&
"RL cannot be empty because it has a height >= 1");
529 return createNode(createNode(L,V,RLL), RL, createNode(RLR,R,RR));
532 return createNode(L,V,R);
540 return createNode(T, V, T);
543 key_type_ref K = ImutInfo::KeyOfValue(V);
544 key_type_ref KCurrent = ImutInfo::KeyOfValue(
getValue(T));
548 else if (ImutInfo::isLess(K,KCurrent))
564 key_type_ref KCurrent = ImutInfo::KeyOfValue(
getValue(T));
568 }
else if (ImutInfo::isLess(K,KCurrent)) {
569 return balanceTree(remove_internal(K,
getLeft(T)),
583 TreeTy* newRight = removeMinBinding(R,OldNode);
584 return balanceTree(L,
getValue(OldNode), newRight);
593 return balanceTree(removeMinBinding(
getLeft(T), Noderemoved),
600 if (!T || !T->isMutable())
612 if (TNew->IsCanonicalized)
617 unsigned digest = TNew->computeDigest();
618 TreeTy *&
entry = Cache[maskCacheIndex(digest)];
622 for (TreeTy *T = entry ; T !=
nullptr; T = T->next) {
625 if (!compareTreeWithSection(TNew, TI, TE))
630 if (TNew->refCount == 0)
640 TNew->IsCanonicalized =
true;
649 template <
typename ImutInfo>
651 :
public std::iterator<std::bidirectional_iterator_tag,
652 ImutAVLTree<ImutInfo>> {
656 enum VisitFlag { VisitedNone=0x0, VisitedLeft=0x1, VisitedRight=0x3,
663 if (Root) stack.
push_back(reinterpret_cast<uintptr_t>(Root));
668 return *
reinterpret_cast<TreeTy *
>(stack.
back() & ~Flags);
674 return stack.
back() & Flags;
680 return stack.
size() == 1 && getVisitState() == VisitedNone;
688 switch (getVisitState()) {
690 stack.
back() |= VisitedLeft;
693 stack.
back() |= VisitedRight;
701 return stack == x.stack;
705 return !(*
this == x);
710 TreeTy* Current =
reinterpret_cast<TreeTy*
>(stack.
back() & ~Flags);
712 switch (getVisitState()) {
714 if (TreeTy* L = Current->getLeft())
715 stack.
push_back(reinterpret_cast<uintptr_t>(L));
717 stack.
back() |= VisitedLeft;
720 if (TreeTy* R = Current->getRight())
721 stack.
push_back(reinterpret_cast<uintptr_t>(R));
723 stack.
back() |= VisitedRight;
736 TreeTy* Current =
reinterpret_cast<TreeTy*
>(stack.
back() & ~Flags);
738 switch (getVisitState()) {
743 stack.
back() &= ~Flags;
744 if (TreeTy* L = Current->getLeft())
745 stack.
push_back(reinterpret_cast<uintptr_t>(L) | VisitedRight);
748 stack.
back() &= ~Flags;
749 stack.
back() |= VisitedLeft;
750 if (TreeTy* R = Current->getRight())
751 stack.
push_back(reinterpret_cast<uintptr_t>(R) | VisitedRight);
760 template <
typename ImutInfo>
762 :
public std::iterator<std::bidirectional_iterator_tag,
763 ImutAVLTree<ImutInfo>> {
766 InternalIteratorTy InternalItr;
779 return InternalItr == x.InternalItr;
783 return !(*
this == x);
791 while (!InternalItr.atEnd() &&
792 InternalItr.getVisitState() != InternalIteratorTy::VisitedLeft);
799 while (!InternalItr.atBeginning() &&
800 InternalItr.getVisitState() != InternalIteratorTy::VisitedLeft);
806 InternalItr.skipToParent();
808 while (!InternalItr.atEnd() &&
809 InternalItr.getVisitState() != InternalIteratorTy::VisitedLeft)
816 template <
typename T>
819 ImutAVLValueIterator<T>, typename T::TreeTy::iterator,
820 typename std::iterator_traits<
821 typename T::TreeTy::iterator>::iterator_category,
822 const typename T::value_type> {
827 typename ImutAVLValueIterator::reference
operator*()
const {
828 return this->
I->getValue();
839 template <
typename T>
850 template <
typename T>
860 #define PROFILE_INTEGER_INFO(X)\ 861 template<> struct ImutProfileInfo<X> : ImutProfileInteger<X> {}; 874 #undef PROFILE_INTEGER_INFO 889 template <
typename T>
909 template <
typename T>
922 return std::equal_to<key_type>()(LHS,RHS);
926 return std::less<key_type>()(LHS,RHS);
935 template <
typename T>
958 template <
typename ValT,
typename ValInfo = ImutContainerInfo<ValT>>
974 if (Root) { Root->
retain(); }
978 if (Root) { Root->
retain(); }
986 if (Root != X.Root) {
987 if (X.Root) { X.Root->
retain(); }
996 const bool Canonicalize;
1006 void operator=(
const Factory& RHS) =
delete;
1021 TreeTy *NewT = F.
add(Old.Root, V);
1033 TreeTy *NewT = F.
remove(Old.Root, V);
1048 return Root ? Root->
contains(V) :
false;
1052 return Root && RHS.Root ? Root->
isEqual(*RHS.Root) : Root == RHS.Root;
1056 return Root && RHS.Root ? Root->
isNotEqual(*RHS.Root) : Root != RHS.Root;
1060 if (Root) { Root->
retain(); }
1075 template <
typename Callback>
1076 void foreach(Callback&
C) {
if (Root) Root->
foreach(C); }
1078 template <
typename Callback>
1079 void foreach() {
if (Root) { Callback
C; Root->
foreach(C); } }
1110 template <
typename ValT,
typename ValInfo = ImutContainerInfo<ValT>>
1130 if (Root) { Root->
retain(); }
1135 Factory(X.Factory) {
1136 if (Root) { Root->
retain(); }
1140 if (Root) { Root->
release(); }
1144 if (Root != X.Root) {
1145 if (X.Root) { X.Root->
retain(); }
1146 if (Root) { Root->
release(); }
1148 Factory = X.Factory;
1167 return Root ? Root->
contains(V) :
false;
1172 Factory->getCanonicalTree(Root) : Root);
1180 return Root && RHS.Root ? Root->
isEqual(*RHS.Root) : Root == RHS.Root;
1184 return Root && RHS.Root ? Root->
isNotEqual(*RHS.Root) : Root != RHS.Root;
1224 #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.
void AddPointer(const void *Ptr)
Add* - Add various data types to Bit data.
ImmutableSetRef(const ImmutableSetRef &X)
static void Profile(FoldingSetNodeID &ID, value_type_ref X)
static GCMetadataPrinterRegistry::Add< ErlangGCPrinter > X("erlang", "erlang-compatible garbage collector")
TreeTy * getRootWithoutRetain() const
static void Profile(FoldingSetNodeID &ID, value_type_ref X)
static bool isDataEqual(data_type_ref, data_type_ref)
Generic profile trait for pointer types.
This class represents lattice values for constants.
TreeTy * balanceTree(TreeTy *L, value_type_ref V, TreeTy *R)
balanceTree - Used by add_internal and remove_internal to balance a newly created tree...
typename ImutInfo::value_type value_type
static data_type_ref DataOfValue(value_type_ref)
void Profile(FoldingSetNodeID &ID) const
TreeTy * add(TreeTy *T, value_type_ref V)
LLVM_NODISCARD 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...
iterator begin() const
begin - Returns an iterator that iterates over the nodes of the tree in an inorder traversal...
void push_back(const T &Elt)
typename ImutInfo::key_type_ref key_type_ref
ImutAVLValueIterator::reference operator*() const
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--()
typename TreeTy::Factory FactoryTy
bool operator==(const ImutAVLTreeGenericIterator &x) const
bool isEmpty() const
isEmpty - Return true if the set contains no elements.
TreeTy * createNode(TreeTy *newLeft, TreeTy *oldTree, TreeTy *newRight)
ImutAVLTreeGenericIterator(const TreeTy *Root)
TreeTy & operator*() const
static void Profile(const T &X, FoldingSetNodeID &ID)
ImmutableSet & operator=(const ImmutableSet &X)
bool isNotEqual(const ImutAVLTree &RHS) const
isNotEqual - Compares two trees for structural inequality.
unsigned ComputeHash() const
ComputeHash - Compute a strong hash value for this FoldingSetNodeID, used to lookup the node in the F...
This file defines the MallocAllocator and BumpPtrAllocator interfaces.
TreeTy::Factory * getTreeFactory() const
ImutAVLTree * getMaxElement()
getMaxElement - Find the subtree associated with the highest ranged key value.
#define LLVM_NODISCARD
LLVM_NODISCARD - Warn if a type or return value is discarded.
TreeTy * getRight(TreeTy *T) const
static ImmutableSetRef getEmptySet(FactoryTy *F)
TreeTy * createNode(TreeTy *L, value_type_ref V, TreeTy *R)
ImutAVLTreeInOrderIterator & operator++()
bool isEqual(const ImutAVLTree &RHS) const
isEqual - Compares two trees for structural equality and returns true if they are equal...
TreeTy * operator->() const
Generic profile template.
typename ImutProfileInfo< T * >::value_type_ref value_type_ref
void AddInteger(signed I)
static bool isEqual(key_type_ref LHS, key_type_ref RHS)
static void Profile(FoldingSetNodeID &ID, const ImmutableSet &S)
ImutAVLFactory< ImutInfo > Factory
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)
void Profile(FoldingSetNodeID &ID) const
#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)
unsigned validateTree() const
validateTree - A utility method that checks that the balancing and ordering invariants of the tree ar...
ImmutableSetRef(TreeTy *R, FactoryTy *F)
Constructs a set from a pointer to a tree root.
bool operator!=(const ImmutableSet &RHS) const
ImutAVLValueIterator(typename T::TreeTy *Tree)
TreeTy * operator->() const
value_type_ref key_type_ref
Profile traits for integers.
void foreach(Callback &C)
foreach - A member template the accepts invokes operator() on a functor object (specifed by Callback)...
bool isElementEqual(const ImutAVLTree *RHS) const
static void Profile(FoldingSetNodeID &ID, const ImmutableSetRef &S)
bool operator!=(const ImmutableSetRef &RHS) const
ImutAVLTreeInOrderIterator()
bool operator!=(const ImutAVLTreeGenericIterator &x) const
FoldingSetNodeID - This class is used to gather all the unique data bits of a node.
iterator end() const
end - Returns an iterator for the tree that denotes the end of an inorder traversal.
Factory(bool canonicalize=true)
bool isEmpty() const
isEmpty - Return true if the set contains no elements.
TreeTy * getLeft(TreeTy *T) const
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 isEmpty(TreeTy *T) 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.
bool operator==(const ImmutableSetRef &RHS) const
CRTP base class for adapting an iterator to a different type.
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
bool contains(value_type_ref V) const
Returns true if the set contains the specified value.
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.
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)
ImutAVLTreeInOrderIterator(const TreeTy *Root)
static bool isEqual(key_type_ref LHS, key_type_ref RHS)
bool isSingleton() const
isSingleton - Return true if the set contains exactly one element.
typename ImutInfo::value_type_ref value_type_ref
void validateTree() const
bool contains(value_type_ref V) const
Returns true if the set contains the specified value.
value_type_ref getValue(TreeTy *T) const
bool operator!=(const ImutAVLTreeInOrderIterator &x) 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 ...
TreeTy * getRootWithoutRetain() const
bool operator==(const ImutAVLTreeInOrderIterator &x) const
const value_type & getValue() const
getValue - Returns the data value associated with the tree node.
unsigned getHeight() const
Factory(BumpPtrAllocator &Alloc, bool canonicalize=true)
uintptr_t getVisitState() const
typename ValInfo::value_type_ref value_type_ref
typename ValInfo::value_type value_type
typename ImutProfileInfo< T * >::value_type value_type
static GCRegistry::Add< StatepointGC > D("statepoint-example", "an example strategy for statepoint")
unsigned getHeight(TreeTy *T) const
ImmutableSetRef & operator=(const ImmutableSetRef &X)
static key_type_ref KeyOfValue(value_type_ref D)
TreeTy * getCanonicalTree(TreeTy *TNew)
static bool isDataEqual(data_type_ref, data_type_ref)
TreeTy * combineTrees(TreeTy *L, TreeTy *R)
TreeTy * removeMinBinding(TreeTy *T, TreeTy *&Noderemoved)
ImutAVLFactory(BumpPtrAllocator &Alloc)
unsigned size() const
size - Returns the number of nodes in the tree, which includes both leaves and non-leaf nodes...
ImutAVLTreeInOrderIterator< ImutInfo > iterator
ImutAVLTreeGenericIterator & operator++()
void validateTree() const
static key_type_ref KeyOfValue(value_type_ref D)
ImmutableSet(TreeTy *R)
Constructs a set from a pointer to a tree root.
LLVM_NODISCARD bool empty() const
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
bool isSingleton() const
isSingleton - Return true if the set contains exactly one element.
static bool isLess(key_type_ref LHS, key_type_ref RHS)
ImmutableSet(const ImmutableSet &X)
static bool isLess(key_type_ref LHS, key_type_ref RHS)
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
ImutAVLTree * getRight() const
Return a pointer to the right subtree.
static void Profile(FoldingSetNodeID &ID, value_type_ref X)
ImmutableSet< ValT > asImmutableSet(bool canonicalize=true) const
unsigned getHeight() const
typename ValInfo::value_type_ref value_type_ref
print Instructions which execute on loop entry
bool isElementEqual(value_type_ref V) const
unsigned incrementHeight(TreeTy *L, TreeTy *R) const
TreeTy & operator*() const
ImutContainerInfo - Generic definition of comparison operations for elements of immutable containers ...
static unsigned maskCacheIndex(unsigned I)
bool operator==(const ImmutableSet &RHS) const
typename ValInfo::value_type value_type
ImutAVLTree * getLeft() const
Return a pointer to the left subtree.