14#ifndef LLVM_ADT_IMMUTABLESET_H
15#define LLVM_ADT_IMMUTABLESET_H
44template <
typename ImutInfo >
62 ImutAVLTree *
getLeft()
const {
return left; }
66 ImutAVLTree *
getRight()
const {
return right; }
77 ImutAVLTree *
T =
this;
79 key_type_ref CurrentKey = ImutInfo::KeyOfValue(
T->getValue());
80 if (ImutInfo::isEqual(K,CurrentKey))
82 else if (ImutInfo::isLess(K,CurrentKey))
92 ImutAVLTree *
T =
this;
93 ImutAVLTree *
Right =
T->getRight();
102 if (
const ImutAVLTree* L =
getLeft())
104 if (
const ImutAVLTree* R =
getRight())
120 if (!ImutInfo::isEqual(ImutInfo::KeyOfValue(
getValue()),
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;
184 &&
"Height calculation wrong");
186 assert((HL > HR ? HL-HR : HR-HL) <= 2
187 &&
"Balancing invariant violated");
191 ImutInfo::KeyOfValue(
getValue()))) &&
192 "Value in left child is not less that current value");
195 ImutInfo::isLess(ImutInfo::KeyOfValue(
getValue()),
197 "Current value is not less that value of right child");
213 unsigned height : 28;
215 unsigned IsMutable : 1;
217 unsigned IsDigestCached : 1;
219 unsigned IsCanonicalized : 1;
233 : factory(f), left(l), right(r), height(height), IsMutable(
true),
234 IsDigestCached(
false), IsCanonicalized(
false), value(v)
246 bool isMutable()
const {
return IsMutable; }
250 bool hasCachedDigest()
const {
return IsDigestCached; }
265 void markImmutable() {
266 assert(isMutable() &&
"Mutable flag already removed.");
271 void markedCachedDigest() {
272 assert(!hasCachedDigest() &&
"NoCachedDigest flag already removed.");
273 IsDigestCached =
true;
277 void setHeight(
unsigned h) {
278 assert(isMutable() &&
"Only a mutable tree can have its height changed.");
282 static uint32_t computeDigest(ImutAVLTree *L, ImutAVLTree *R,
287 digest +=
L->computeDigest();
291 ImutInfo::Profile(
ID,V);
292 digest +=
ID.ComputeHash();
295 digest +=
R->computeDigest();
300 uint32_t computeDigest() {
303 if (hasCachedDigest())
308 markedCachedDigest();
330 if (IsCanonicalized) {
337 factory->Cache[factory->maskCacheIndex(computeDigest())] = next;
343 factory->freeNodes.push_back(
this);
347template <
typename ImutInfo>
357template <
typename ImutInfo >
368 std::vector<TreeTy*> createdNodes;
369 std::vector<TreeTy*> freeNodes;
371 bool ownsAllocator()
const {
372 return (Allocator & 0x1) == 0;
391 if (ownsAllocator())
delete &getAllocator();
394 TreeTy*
add(TreeTy*
T, value_type_ref V) {
420 TreeTy*
getLeft(TreeTy*
T)
const {
return T->getLeft(); }
422 value_type_ref
getValue(TreeTy*
T)
const {
return T->value; }
430 return (hl > hr ? hl : hr) + 1;
437 for ( ;
I!=
E ; ++
I, ++TI) {
438 if (TI == TE || !
I->isElementEqual(&*TI))
457 if (!freeNodes.empty()) {
458 T = freeNodes.back();
459 freeNodes.pop_back();
463 T = (TreeTy*)
A.Allocate<TreeTy>();
466 createdNodes.push_back(
T);
470 TreeTy*
createNode(TreeTy* newLeft, TreeTy* oldTree, TreeTy* newRight) {
475 for (
unsigned i = 0, n = createdNodes.size(); i < n; ++i) {
476 TreeTy *
N = createdNodes[i];
477 if (
N->isMutable() &&
N->refCount == 0)
480 createdNodes.clear();
489 assert(!
isEmpty(L) &&
"Left tree cannot be empty to have a height >= 2");
497 assert(!
isEmpty(LR) &&
"LR cannot be empty because it has a height >= 1");
506 assert(!
isEmpty(R) &&
"Right tree cannot be empty to have a height >= 2");
514 assert(!
isEmpty(RL) &&
"RL cannot be empty because it has a height >= 1");
533 key_type_ref K = ImutInfo::KeyOfValue(V);
534 key_type_ref KCurrent = ImutInfo::KeyOfValue(
getValue(
T));
536 if (ImutInfo::isEqual(K, KCurrent)) {
538 if (ImutInfo::isDataEqual(ImutInfo::DataOfValue(V),
547 if (ImutInfo::isLess(K, KCurrent))
569 key_type_ref KCurrent = ImutInfo::KeyOfValue(
getValue(
T));
571 if (ImutInfo::isEqual(K, KCurrent))
576 if (ImutInfo::isLess(K, KCurrent))
610 if (!
T || !
T->isMutable())
622 if (TNew->IsCanonicalized)
627 unsigned digest = TNew->computeDigest();
630 for (TreeTy *
T = entry ;
T !=
nullptr;
T =
T->next) {
638 if (TNew->refCount == 0)
647 TNew->IsCanonicalized =
true;
689 for (;
T;
T =
T->getLeft())
696 for (;
T;
T =
T->getRight())
706 void ascendFromRightChild() {
707 TreeTy *Child = Path.pop_back_val();
708 while (!Path.empty() && Path.back()->getRight() == Child)
709 Child = Path.pop_back_val();
713 void ascendFromLeftChild() {
714 TreeTy *Child = Path.pop_back_val();
715 while (!Path.empty() && Path.back()->getLeft() == Child)
716 Child = Path.pop_back_val();
722 descendToMin(
const_cast<TreeTy *
>(Root));
731 if (Path.empty() || x.Path.empty())
732 return Path.empty() == x.Path.empty();
733 return Path.back() == x.Path.back();
736 return !(*
this == x);
743 assert(!Path.empty() &&
"Incrementing the end iterator");
744 if (
TreeTy *R = Path.back()->getRight())
750 ascendFromRightChild();
755 assert(!Path.empty() &&
"Decrementing the end iterator");
756 if (
TreeTy *L = Path.back()->getLeft())
761 ascendFromLeftChild();
769 assert(!Path.empty() &&
"Skipping past the end iterator");
770 ascendFromRightChild();
779 ImutAVLValueIterator<T>, typename T::TreeTy::iterator,
780 typename std::iterator_traits<
781 typename T::TreeTy::iterator>::iterator_category,
782 const typename T::value_type> {
788 return this->
I->getValue();
820#define PROFILE_INTEGER_INFO(X)\
821template<> struct ImutProfileInfo<X> : ImutProfileInteger<X> {};
834#undef PROFILE_INTEGER_INFO
881 return std::equal_to<key_type>()(
LHS,
RHS);
885 return std::less<key_type>()(
LHS,
RHS);
915template <
typename ValT,
typename ValInfo = ImutContainerInfo<ValT>>
934 const bool Canonicalize;
938 : Canonicalize(canonicalize) {}
941 : F(
Alloc), Canonicalize(canonicalize) {}
959 TreeTy *NewT = F.add(Old.Root.get(), V);
960 return ImmutableSet(Canonicalize ? F.getCanonicalTree(NewT) : NewT);
971 TreeTy *NewT = F.remove(Old.Root.get(), V);
972 return ImmutableSet(Canonicalize ? F.getCanonicalTree(NewT) : NewT);
986 return Root ? Root->contains(V) :
false;
990 return Root &&
RHS.Root ? Root->isEqual(*
RHS.Root.get()) : Root ==
RHS.Root;
994 return Root &&
RHS.Root ? Root->isNotEqual(*
RHS.Root.get())
999 if (Root) { Root->retain(); }
1025 unsigned getHeight()
const {
return Root ? Root->getHeight() : 0; }
1028 ID.AddPointer(S.Root.get());
1041template <
typename ValT,
typename ValInfo = ImutContainerInfo<ValT>>
1074 return Root ? Root->contains(V) :
false;
1079 canonicalize ? Factory->getCanonicalTree(Root.get()) : Root.get());
1085 return Root &&
RHS.Root ? Root->isEqual(*
RHS.Root.get()) : Root ==
RHS.Root;
1089 return Root &&
RHS.Root ? Root->isNotEqual(*
RHS.Root.get())
1113 unsigned getHeight()
const {
return Root ? Root->getHeight() : 0; }
1116 ID.AddPointer(S.Root.get());
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
This file defines the BumpPtrAllocator interface.
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< StatepointGC > D("statepoint-example", "an example strategy for statepoint")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
#define LLVM_PREFERRED_TYPE(T)
\macro LLVM_PREFERRED_TYPE Adjust type of bit-field in debug info.
This file defines the DenseMap class.
This file defines a hash set that can be used to remove duplication of nodes in a graph.
#define PROFILE_INTEGER_INFO(X)
This file defines the RefCountedBase, ThreadSafeRefCountedBase, and IntrusiveRefCntPtr classes.
This file defines the SmallVector class.
This class is used to gather all the unique data bits of a node.
static void Profile(FoldingSetNodeID &ID, const ImmutableSetRef &S)
void Profile(FoldingSetNodeID &ID) const
ImmutableSetRef add(value_type_ref V)
ImutAVLTree< ValInfo > TreeTy
bool contains(value_type_ref V) const
Returns true if the set contains the specified value.
bool operator!=(const ImmutableSetRef &RHS) const
ImmutableSetRef remove(value_type_ref V)
ImutAVLValueIterator< ImmutableSetRef > iterator
bool isSingleton() const
Return true if the set contains exactly one element.
bool isEmpty() const
Return true if the set contains no elements.
typename ValInfo::value_type value_type
ImmutableSetRef(TreeTy *R, FactoryTy *F)
Constructs a set from a pointer to a tree root.
typename ValInfo::value_type_ref value_type_ref
unsigned getHeight() const
ImmutableSet< ValT > asImmutableSet(bool canonicalize=true) const
typename TreeTy::Factory FactoryTy
static ImmutableSetRef getEmptySet(FactoryTy *F)
void validateTree() const
bool operator==(const ImmutableSetRef &RHS) const
TreeTy * getRootWithoutRetain() const
Factory(const Factory &RHS)=delete
void operator=(const Factory &RHS)=delete
TreeTy::Factory * getTreeFactory() const
BumpPtrAllocator & getAllocator()
Factory(BumpPtrAllocator &Alloc, bool canonicalize=true)
ImmutableSet getEmptySet()
Returns an immutable set that contains no elements.
Factory(bool canonicalize=true)
ImmutableSet remove(ImmutableSet Old, value_type_ref V)
Creates a new immutable set that contains all of the values of the original set with the exception of...
ImmutableSet add(ImmutableSet Old, value_type_ref V)
Creates a new immutable set that contains all of the values of the original set with the addition of ...
bool operator!=(const ImmutableSet &RHS) const
typename ValInfo::value_type value_type
bool operator==(const ImmutableSet &RHS) const
bool isEmpty() const
Return true if the set contains no elements.
ImmutableSet(TreeTy *R)
Constructs a set from a pointer to a tree root.
bool isSingleton() const
Return true if the set contains exactly one element.
TreeTy * getRootWithoutRetain() const
ImutAVLTree< ValInfo > TreeTy
void validateTree() const
bool contains(value_type_ref V) const
Returns true if the set contains the specified value.
void Profile(FoldingSetNodeID &ID) const
unsigned getHeight() const
static void Profile(FoldingSetNodeID &ID, const ImmutableSet &S)
ImutAVLValueIterator< ImmutableSet > iterator
typename ValInfo::value_type_ref value_type_ref
static unsigned maskCacheIndex(unsigned I)
TreeTy * balanceTree(TreeTy *L, value_type_ref V, TreeTy *R)
Used by add_internal and remove_internal to balance a newly created tree.
unsigned getHeight(TreeTy *T) const
ImutAVLFactory(BumpPtrAllocator &Alloc)
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...
value_type_ref getValue(TreeTy *T) const
static bool compareTreeWithSection(TreeTy *T, typename TreeTy::iterator &TI, typename TreeTy::iterator &TE)
TreeTy * getLeft(TreeTy *T) const
TreeTy * getCanonicalTree(TreeTy *TNew)
TreeTy * add(TreeTy *T, value_type_ref V)
TreeTy * getRight(TreeTy *T) const
TreeTy * getEmptyTree() const
TreeTy * removeMinBinding(TreeTy *T, TreeTy *&Noderemoved)
TreeTy * createNode(TreeTy *newLeft, TreeTy *oldTree, TreeTy *newRight)
TreeTy * combineTrees(TreeTy *L, TreeTy *R)
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...
TreeTy * createNode(TreeTy *L, value_type_ref V, TreeTy *R)
unsigned incrementHeight(TreeTy *L, TreeTy *R) const
TreeTy * remove(TreeTy *T, key_type_ref V)
void markImmutable(TreeTy *T)
Clears the mutable bits of a root and all of its descendants.
bool isEmpty(TreeTy *T) const
Bidirectional in-order iterator over the nodes of an ImutAVLTree.
void skipSubTree()
Move to the in-order successor of the entire subtree rooted at the current node, i....
bool operator!=(const ImutAVLTreeInOrderIterator &x) const
TreeTy * operator->() const
ImutAVLTreeInOrderIterator & operator++()
ImutAVLTree< ImutInfo > TreeTy
ImutAVLTreeInOrderIterator & operator--()
std::bidirectional_iterator_tag iterator_category
TreeTy & operator*() const
ImutAVLTreeInOrderIterator()=default
ImutAVLTreeInOrderIterator(const TreeTy *Root)
bool operator==(const ImutAVLTreeInOrderIterator &x) const
ImutAVLTree< ImutInfo > value_type
std::ptrdiff_t difference_type
unsigned size() const
Returns the number of nodes in the tree, which includes both leaves and.
iterator end() const
Returns an iterator for the tree that denotes the end of an inorder traversal.
const value_type & getValue() const
Returns the data value associated with the tree node.
unsigned getHeight() const
Returns the height of the tree. A tree with no subtrees has a height of 1.
typename ValInfo::key_type_ref key_type_ref
ImutAVLFactory< ValInfo > Factory
ImutAVLTree * find(key_type_ref K)
Finds the subtree associated with the specified key value.
typename ValInfo::value_type_ref value_type_ref
unsigned validateTree() const
A utility method that checks that the balancing and ordering invariants of the tree are satisfied.
bool isNotEqual(const ImutAVLTree &RHS) const
Compares two trees for structural inequality.
bool isEqual(const ImutAVLTree &RHS) const
Compares two trees for structural equality and returns true if they are equal.
ImutAVLTree * getLeft() const
Return a pointer to the left subtree.
ImutAVLTreeInOrderIterator< ValInfo > iterator
typename ValInfo::value_type value_type
ImutAVLTree * getRight() const
Return a pointer to the right subtree.
bool isElementEqual(const ImutAVLTree *RHS) const
bool contains(key_type_ref K)
Returns true if this tree contains a subtree (node) that has an data element that matches the specifi...
ImutAVLTree * getMaxElement()
Find the subtree associated with the highest ranged key value.
iterator begin() const
Returns an iterator that iterates over the nodes of the tree in an inorder traversal.
bool isElementEqual(value_type_ref V) const
A smart pointer to a reference-counted object that inherits from RefCountedBase or ThreadSafeRefCount...
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
iterator_adaptor_base()=default
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
This is an optimization pass for GlobalISel generic memory operations.
BumpPtrAllocatorImpl<> BumpPtrAllocator
The standard BumpPtrAllocator which just uses the default template parameters.
static void Profile(const T &X, FoldingSetNodeID &ID)
Generic iterator that wraps a T::TreeTy::iterator and exposes iterator::getValue() on dereference.
ImutAVLValueIterator()=default
ImutAVLValueIterator::reference operator*() const
ImutAVLValueIterator(typename T::TreeTy *Tree)
static bool isDataEqual(data_type_ref, data_type_ref)
value_type_ref key_type_ref
static key_type_ref KeyOfValue(value_type_ref D)
static bool isEqual(key_type_ref LHS, key_type_ref RHS)
typename ImutProfileInfo< T * >::value_type_ref value_type_ref
typename ImutProfileInfo< T * >::value_type value_type
static data_type_ref DataOfValue(value_type_ref)
static bool isLess(key_type_ref LHS, key_type_ref RHS)
Generic definition of comparison operations for elements of immutable containers that defaults to usi...
static bool isLess(key_type_ref LHS, key_type_ref RHS)
typename ImutProfileInfo< T >::value_type value_type
static bool isEqual(key_type_ref LHS, key_type_ref RHS)
static bool isDataEqual(data_type_ref, data_type_ref)
static data_type_ref DataOfValue(value_type_ref)
static key_type_ref KeyOfValue(value_type_ref D)
value_type_ref key_type_ref
typename ImutProfileInfo< T >::value_type_ref value_type_ref
static void Profile(FoldingSetNodeID &ID, value_type_ref X)
value_type value_type_ref
const bool & value_type_ref
static void Profile(FoldingSetNodeID &ID, value_type_ref X)
Generic profile template.
static void Profile(FoldingSetNodeID &ID, value_type_ref X)
Profile traits for integers.
static void Profile(FoldingSetNodeID &ID, value_type_ref X)
static void retain(ImutAVLTree< ImutInfo > *Tree)
Class you can specialize to provide custom retain/release functionality for a type.