14#ifndef LLVM_ADT_IMMUTABLESET_H
15#define LLVM_ADT_IMMUTABLESET_H
45template <
typename ImutInfo >
64 ImutAVLTree *
getLeft()
const {
return left; }
68 ImutAVLTree *
getRight()
const {
return right; }
80 ImutAVLTree *
T =
this;
82 key_type_ref CurrentKey = ImutInfo::KeyOfValue(
T->getValue());
83 if (ImutInfo::isEqual(K,CurrentKey))
85 else if (ImutInfo::isLess(K,CurrentKey))
96 ImutAVLTree *
T =
this;
97 ImutAVLTree *
Right =
T->getRight();
106 if (
const ImutAVLTree* L =
getLeft())
108 if (
const ImutAVLTree* R =
getRight())
124 if (!ImutInfo::isEqual(ImutInfo::KeyOfValue(
getValue()),
125 ImutInfo::KeyOfValue(V)))
129 if (!ImutInfo::isDataEqual(ImutInfo::DataOfValue(
getValue()),
130 ImutInfo::DataOfValue(V)))
150 while (LItr != LEnd && RItr != REnd) {
151 if (&*LItr == &*RItr) {
164 return LItr == LEnd && RItr == REnd;
189 &&
"Height calculation wrong");
191 assert((HL > HR ? HL-HR : HR-HL) <= 2
192 &&
"Balancing invariant violated");
196 ImutInfo::KeyOfValue(
getValue()))) &&
197 "Value in left child is not less that current value");
200 ImutInfo::isLess(ImutInfo::KeyOfValue(
getValue()),
202 "Current value is not less that value of right child");
218 unsigned height : 28;
220 unsigned IsMutable : 1;
222 unsigned IsDigestCached : 1;
224 unsigned IsCanonicalized : 1;
239 : factory(f), left(l), right(r), height(height), IsMutable(
true),
240 IsDigestCached(
false), IsCanonicalized(
false), value(v)
252 bool isMutable()
const {
return IsMutable; }
256 bool hasCachedDigest()
const {
return IsDigestCached; }
271 void markImmutable() {
272 assert(isMutable() &&
"Mutable flag already removed.");
277 void markedCachedDigest() {
278 assert(!hasCachedDigest() &&
"NoCachedDigest flag already removed.");
279 IsDigestCached =
true;
284 void setHeight(
unsigned h) {
285 assert(isMutable() &&
"Only a mutable tree can have its height changed.");
289 static uint32_t computeDigest(ImutAVLTree *L, ImutAVLTree *R,
294 digest +=
L->computeDigest();
298 ImutInfo::Profile(
ID,V);
299 digest +=
ID.ComputeHash();
302 digest +=
R->computeDigest();
307 uint32_t computeDigest() {
310 if (hasCachedDigest())
315 markedCachedDigest();
337 if (IsCanonicalized) {
344 factory->Cache[factory->maskCacheIndex(computeDigest())] = next;
350 factory->freeNodes.push_back(
this);
354template <
typename ImutInfo>
364template <
typename ImutInfo >
375 std::vector<TreeTy*> createdNodes;
376 std::vector<TreeTy*> freeNodes;
378 bool ownsAllocator()
const {
379 return (Allocator & 0x1) == 0;
395 : Allocator(reinterpret_cast<uintptr_t>(&
Alloc) | 0x1) {}
398 if (ownsAllocator())
delete &getAllocator();
401 TreeTy*
add(TreeTy*
T, value_type_ref V) {
427 TreeTy*
getLeft(TreeTy*
T)
const {
return T->getLeft(); }
429 value_type_ref
getValue(TreeTy*
T)
const {
return T->value; }
437 return (hl > hr ? hl : hr) + 1;
444 for ( ;
I!=
E ; ++
I, ++TI) {
445 if (TI == TE || !
I->isElementEqual(&*TI))
464 if (!freeNodes.empty()) {
465 T = freeNodes.back();
466 freeNodes.pop_back();
470 T = (TreeTy*)
A.Allocate<TreeTy>();
473 createdNodes.push_back(
T);
477 TreeTy*
createNode(TreeTy* newLeft, TreeTy* oldTree, TreeTy* newRight) {
482 for (
unsigned i = 0, n = createdNodes.size(); i < n; ++i) {
483 TreeTy *
N = createdNodes[i];
484 if (
N->isMutable() &&
N->refCount == 0)
487 createdNodes.clear();
497 assert(!
isEmpty(L) &&
"Left tree cannot be empty to have a height >= 2");
505 assert(!
isEmpty(LR) &&
"LR cannot be empty because it has a height >= 1");
514 assert(!
isEmpty(R) &&
"Right tree cannot be empty to have a height >= 2");
522 assert(!
isEmpty(RL) &&
"RL cannot be empty because it has a height >= 1");
541 key_type_ref K = ImutInfo::KeyOfValue(V);
542 key_type_ref KCurrent = ImutInfo::KeyOfValue(
getValue(
T));
544 if (ImutInfo::isEqual(K, KCurrent)) {
546 if (ImutInfo::isDataEqual(ImutInfo::DataOfValue(V),
555 if (ImutInfo::isLess(K, KCurrent))
577 key_type_ref KCurrent = ImutInfo::KeyOfValue(
getValue(
T));
579 if (ImutInfo::isEqual(K, KCurrent))
584 if (ImutInfo::isLess(K, KCurrent))
619 if (!
T || !
T->isMutable())
631 if (TNew->IsCanonicalized)
636 unsigned digest = TNew->computeDigest();
641 for (TreeTy *
T = entry ;
T !=
nullptr;
T =
T->next) {
649 if (TNew->refCount == 0)
659 TNew->IsCanonicalized =
true;
685 if (Root) stack.push_back(
reinterpret_cast<uintptr_t
>(Root));
690 return *
reinterpret_cast<TreeTy *
>(stack.back() & ~
Flags);
696 return stack.back() &
Flags;
699 bool atEnd()
const {
return stack.empty(); }
723 return stack == x.stack;
727 return !(*
this == x);
737 stack.push_back(
reinterpret_cast<uintptr_t
>(L));
743 stack.push_back(
reinterpret_cast<uintptr_t
>(R));
767 stack.push_back(
reinterpret_cast<uintptr_t
>(L) |
VisitedRight);
773 stack.push_back(
reinterpret_cast<uintptr_t
>(R) |
VisitedRight);
785 InternalIteratorTy InternalItr;
804 return InternalItr == x.InternalItr;
808 return !(*
this == x);
816 while (!InternalItr.atEnd() &&
817 InternalItr.getVisitState() != InternalIteratorTy::VisitedLeft);
824 while (!InternalItr.atBeginning() &&
825 InternalItr.getVisitState() != InternalIteratorTy::VisitedLeft);
831 InternalItr.skipToParent();
833 while (!InternalItr.atEnd() &&
834 InternalItr.getVisitState() != InternalIteratorTy::VisitedLeft)
844 ImutAVLValueIterator<T>, typename T::TreeTy::iterator,
845 typename std::iterator_traits<
846 typename T::TreeTy::iterator>::iterator_category,
847 const typename T::value_type> {
853 return this->
I->getValue();
885#define PROFILE_INTEGER_INFO(X)\
886template<> struct ImutProfileInfo<X> : ImutProfileInteger<X> {};
899#undef PROFILE_INTEGER_INFO
947 return std::equal_to<key_type>()(
LHS,
RHS);
951 return std::less<key_type>()(
LHS,
RHS);
983template <
typename ValT,
typename ValInfo = ImutContainerInfo<ValT>>
1002 const bool Canonicalize;
1006 : Canonicalize(canonicalize) {}
1009 : F(
Alloc), Canonicalize(canonicalize) {}
1027 TreeTy *NewT = F.add(Old.Root.get(), V);
1028 return ImmutableSet(Canonicalize ? F.getCanonicalTree(NewT) : NewT);
1039 TreeTy *NewT = F.remove(Old.Root.get(), V);
1040 return ImmutableSet(Canonicalize ? F.getCanonicalTree(NewT) : NewT);
1054 return Root ? Root->contains(V) :
false;
1058 return Root &&
RHS.Root ? Root->isEqual(*
RHS.Root.get()) : Root ==
RHS.Root;
1062 return Root &&
RHS.Root ? Root->isNotEqual(*
RHS.Root.get())
1067 if (Root) { Root->retain(); }
1093 unsigned getHeight()
const {
return Root ? Root->getHeight() : 0; }
1096 ID.AddPointer(S.Root.get());
1109template <
typename ValT,
typename ValInfo = ImutContainerInfo<ValT>>
1142 return Root ? Root->contains(V) :
false;
1147 canonicalize ? Factory->getCanonicalTree(Root.get()) : Root.get());
1153 return Root &&
RHS.Root ? Root->isEqual(*
RHS.Root.get()) : Root ==
RHS.Root;
1157 return Root &&
RHS.Root ? Root->isNotEqual(*
RHS.Root.get())
1181 unsigned getHeight()
const {
return Root ? Root->getHeight() : 0; }
1184 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.
static TableGen::Emitter::OptClass< SkeletonEmitter > X("gen-skeleton-class", "Generate example skeleton class")
FoldingSetNodeID - 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
isSingleton - Return true if the set contains exactly one element.
bool isEmpty() const
isEmpty - 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()
getEmptySet - Returns an immutable set that contains no elements.
Factory(bool canonicalize=true)
ImmutableSet remove(ImmutableSet Old, value_type_ref V)
remove - Creates a new immutable set that contains all of the values of the original set with the exc...
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...
bool operator!=(const ImmutableSet &RHS) const
typename ValInfo::value_type value_type
bool operator==(const ImmutableSet &RHS) const
bool isEmpty() const
isEmpty - Return true if the set contains no elements.
ImmutableSet(TreeTy *R)
Constructs a set from a pointer to a tree root.
bool isSingleton() const
isSingleton - 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)
balanceTree - 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)
markImmutable - Clears the mutable bits of a root and all of its descendants.
bool isEmpty(TreeTy *T) const
ImutAVLTreeGenericIterator()=default
ImutAVLTree< ImutInfo > value_type
std::ptrdiff_t difference_type
bool operator==(const ImutAVLTreeGenericIterator &x) const
std::bidirectional_iterator_tag iterator_category
ImutAVLTreeGenericIterator(const TreeTy *Root)
ImutAVLTree< ImutInfo > TreeTy
ImutAVLTreeGenericIterator & operator--()
TreeTy & operator*() const
TreeTy * operator->() const
uintptr_t getVisitState() const
bool operator!=(const ImutAVLTreeGenericIterator &x) const
ImutAVLTreeGenericIterator & operator++()
bool operator!=(const ImutAVLTreeInOrderIterator &x) const
TreeTy * operator->() const
ImutAVLTreeInOrderIterator & operator++()
ImutAVLTree< ImutInfo > TreeTy
ImutAVLTreeInOrderIterator & operator--()
std::bidirectional_iterator_tag iterator_category
ImutAVLTreeInOrderIterator()
TreeTy & operator*() const
ImutAVLTreeInOrderIterator(const TreeTy *Root)
bool operator==(const ImutAVLTreeInOrderIterator &x) const
ImutAVLTree< ImutInfo > value_type
std::ptrdiff_t difference_type
unsigned size() const
size - Returns the number of nodes in the tree, which includes both leaves and non-leaf nodes.
iterator end() const
end - Returns an iterator for the tree that denotes the end of an inorder traversal.
const value_type & getValue() const
getValue - Returns the data value associated with the tree node.
unsigned getHeight() const
getHeight - Returns the height of the tree.
typename ValInfo::key_type_ref key_type_ref
ImutAVLFactory< ValInfo > Factory
ImutAVLTree * find(key_type_ref K)
find - Finds the subtree associated with the specified key value.
typename ValInfo::value_type_ref value_type_ref
unsigned validateTree() const
validateTree - A utility method that checks that the balancing and ordering invariants of the tree ar...
bool isNotEqual(const ImutAVLTree &RHS) const
isNotEqual - Compares two trees for structural inequality.
bool isEqual(const ImutAVLTree &RHS) const
isEqual - 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)
contains - Returns true if this tree contains a subtree (node) that has an data element that matches ...
ImutAVLTree * getMaxElement()
getMaxElement - Find the subtree associated with the highest ranged key value.
iterator begin() const
begin - 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...
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
iterator_adaptor_base()=default
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
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)
ImutContainerInfo - Generic definition of comparison operations for elements of immutable containers ...
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.