Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-05-10 08:43:06

0001 //===--- ImmutableSet.h - Immutable (functional) set interface --*- C++ -*-===//
0002 //
0003 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
0004 // See https://llvm.org/LICENSE.txt for license information.
0005 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
0006 //
0007 //===----------------------------------------------------------------------===//
0008 ///
0009 /// \file
0010 /// This file defines the ImutAVLTree and ImmutableSet classes.
0011 ///
0012 //===----------------------------------------------------------------------===//
0013 
0014 #ifndef LLVM_ADT_IMMUTABLESET_H
0015 #define LLVM_ADT_IMMUTABLESET_H
0016 
0017 #include "llvm/ADT/DenseMap.h"
0018 #include "llvm/ADT/FoldingSet.h"
0019 #include "llvm/ADT/IntrusiveRefCntPtr.h"
0020 #include "llvm/ADT/SmallVector.h"
0021 #include "llvm/ADT/iterator.h"
0022 #include "llvm/Support/Allocator.h"
0023 #include "llvm/Support/ErrorHandling.h"
0024 #include <cassert>
0025 #include <cstdint>
0026 #include <functional>
0027 #include <iterator>
0028 #include <new>
0029 #include <vector>
0030 
0031 namespace llvm {
0032 
0033 //===----------------------------------------------------------------------===//
0034 // Immutable AVL-Tree Definition.
0035 //===----------------------------------------------------------------------===//
0036 
0037 template <typename ImutInfo> class ImutAVLFactory;
0038 template <typename ImutInfo> class ImutIntervalAVLFactory;
0039 template <typename ImutInfo> class ImutAVLTreeInOrderIterator;
0040 template <typename ImutInfo> class ImutAVLTreeGenericIterator;
0041 
0042 template <typename ImutInfo >
0043 class ImutAVLTree {
0044 public:
0045   using key_type_ref = typename ImutInfo::key_type_ref;
0046   using value_type = typename ImutInfo::value_type;
0047   using value_type_ref = typename ImutInfo::value_type_ref;
0048   using Factory = ImutAVLFactory<ImutInfo>;
0049   using iterator = ImutAVLTreeInOrderIterator<ImutInfo>;
0050 
0051   friend class ImutAVLFactory<ImutInfo>;
0052   friend class ImutIntervalAVLFactory<ImutInfo>;
0053   friend class ImutAVLTreeGenericIterator<ImutInfo>;
0054 
0055   //===----------------------------------------------------===//
0056   // Public Interface.
0057   //===----------------------------------------------------===//
0058 
0059   /// Return a pointer to the left subtree.  This value
0060   ///  is NULL if there is no left subtree.
0061   ImutAVLTree *getLeft() const { return left; }
0062 
0063   /// Return a pointer to the right subtree.  This value is
0064   ///  NULL if there is no right subtree.
0065   ImutAVLTree *getRight() const { return right; }
0066 
0067   /// getHeight - Returns the height of the tree.  A tree with no subtrees
0068   ///  has a height of 1.
0069   unsigned getHeight() const { return height; }
0070 
0071   /// getValue - Returns the data value associated with the tree node.
0072   const value_type& getValue() const { return value; }
0073 
0074   /// find - Finds the subtree associated with the specified key value.
0075   ///  This method returns NULL if no matching subtree is found.
0076   ImutAVLTree* find(key_type_ref K) {
0077     ImutAVLTree *T = this;
0078     while (T) {
0079       key_type_ref CurrentKey = ImutInfo::KeyOfValue(T->getValue());
0080       if (ImutInfo::isEqual(K,CurrentKey))
0081         return T;
0082       else if (ImutInfo::isLess(K,CurrentKey))
0083         T = T->getLeft();
0084       else
0085         T = T->getRight();
0086     }
0087     return nullptr;
0088   }
0089 
0090   /// getMaxElement - Find the subtree associated with the highest ranged
0091   ///  key value.
0092   ImutAVLTree* getMaxElement() {
0093     ImutAVLTree *T = this;
0094     ImutAVLTree *Right = T->getRight();
0095     while (Right) { T = Right; Right = T->getRight(); }
0096     return T;
0097   }
0098 
0099   /// size - Returns the number of nodes in the tree, which includes
0100   ///  both leaves and non-leaf nodes.
0101   unsigned size() const {
0102     unsigned n = 1;
0103     if (const ImutAVLTree* L = getLeft())
0104       n += L->size();
0105     if (const ImutAVLTree* R = getRight())
0106       n += R->size();
0107     return n;
0108   }
0109 
0110   /// begin - Returns an iterator that iterates over the nodes of the tree
0111   ///  in an inorder traversal.  The returned iterator thus refers to the
0112   ///  the tree node with the minimum data element.
0113   iterator begin() const { return iterator(this); }
0114 
0115   /// end - Returns an iterator for the tree that denotes the end of an
0116   ///  inorder traversal.
0117   iterator end() const { return iterator(); }
0118 
0119   bool isElementEqual(value_type_ref V) const {
0120     // Compare the keys.
0121     if (!ImutInfo::isEqual(ImutInfo::KeyOfValue(getValue()),
0122                            ImutInfo::KeyOfValue(V)))
0123       return false;
0124 
0125     // Also compare the data values.
0126     if (!ImutInfo::isDataEqual(ImutInfo::DataOfValue(getValue()),
0127                                ImutInfo::DataOfValue(V)))
0128       return false;
0129 
0130     return true;
0131   }
0132 
0133   bool isElementEqual(const ImutAVLTree* RHS) const {
0134     return isElementEqual(RHS->getValue());
0135   }
0136 
0137   /// isEqual - Compares two trees for structural equality and returns true
0138   ///   if they are equal.  This worst case performance of this operation is
0139   //    linear in the sizes of the trees.
0140   bool isEqual(const ImutAVLTree& RHS) const {
0141     if (&RHS == this)
0142       return true;
0143 
0144     iterator LItr = begin(), LEnd = end();
0145     iterator RItr = RHS.begin(), REnd = RHS.end();
0146 
0147     while (LItr != LEnd && RItr != REnd) {
0148       if (&*LItr == &*RItr) {
0149         LItr.skipSubTree();
0150         RItr.skipSubTree();
0151         continue;
0152       }
0153 
0154       if (!LItr->isElementEqual(&*RItr))
0155         return false;
0156 
0157       ++LItr;
0158       ++RItr;
0159     }
0160 
0161     return LItr == LEnd && RItr == REnd;
0162   }
0163 
0164   /// isNotEqual - Compares two trees for structural inequality.  Performance
0165   ///  is the same is isEqual.
0166   bool isNotEqual(const ImutAVLTree& RHS) const { return !isEqual(RHS); }
0167 
0168   /// contains - Returns true if this tree contains a subtree (node) that
0169   ///  has an data element that matches the specified key.  Complexity
0170   ///  is logarithmic in the size of the tree.
0171   bool contains(key_type_ref K) { return (bool) find(K); }
0172 
0173   /// validateTree - A utility method that checks that the balancing and
0174   ///  ordering invariants of the tree are satisfied.  It is a recursive
0175   ///  method that returns the height of the tree, which is then consumed
0176   ///  by the enclosing validateTree call.  External callers should ignore the
0177   ///  return value.  An invalid tree will cause an assertion to fire in
0178   ///  a debug build.
0179   unsigned validateTree() const {
0180     unsigned HL = getLeft() ? getLeft()->validateTree() : 0;
0181     unsigned HR = getRight() ? getRight()->validateTree() : 0;
0182     (void) HL;
0183     (void) HR;
0184 
0185     assert(getHeight() == ( HL > HR ? HL : HR ) + 1
0186             && "Height calculation wrong");
0187 
0188     assert((HL > HR ? HL-HR : HR-HL) <= 2
0189            && "Balancing invariant violated");
0190 
0191     assert((!getLeft() ||
0192             ImutInfo::isLess(ImutInfo::KeyOfValue(getLeft()->getValue()),
0193                              ImutInfo::KeyOfValue(getValue()))) &&
0194            "Value in left child is not less that current value");
0195 
0196     assert((!getRight() ||
0197              ImutInfo::isLess(ImutInfo::KeyOfValue(getValue()),
0198                               ImutInfo::KeyOfValue(getRight()->getValue()))) &&
0199            "Current value is not less that value of right child");
0200 
0201     return getHeight();
0202   }
0203 
0204   //===----------------------------------------------------===//
0205   // Internal values.
0206   //===----------------------------------------------------===//
0207 
0208 private:
0209   Factory *factory;
0210   ImutAVLTree *left;
0211   ImutAVLTree *right;
0212   ImutAVLTree *prev = nullptr;
0213   ImutAVLTree *next = nullptr;
0214 
0215   unsigned height : 28;
0216   bool IsMutable : 1;
0217   bool IsDigestCached : 1;
0218   bool IsCanonicalized : 1;
0219 
0220   value_type value;
0221   uint32_t digest = 0;
0222   uint32_t refCount = 0;
0223 
0224   //===----------------------------------------------------===//
0225   // Internal methods (node manipulation; used by Factory).
0226   //===----------------------------------------------------===//
0227 
0228 private:
0229   /// ImutAVLTree - Internal constructor that is only called by
0230   ///   ImutAVLFactory.
0231   ImutAVLTree(Factory *f, ImutAVLTree* l, ImutAVLTree* r, value_type_ref v,
0232               unsigned height)
0233     : factory(f), left(l), right(r), height(height), IsMutable(true),
0234       IsDigestCached(false), IsCanonicalized(false), value(v)
0235   {
0236     if (left) left->retain();
0237     if (right) right->retain();
0238   }
0239 
0240   /// isMutable - Returns true if the left and right subtree references
0241   ///  (as well as height) can be changed.  If this method returns false,
0242   ///  the tree is truly immutable.  Trees returned from an ImutAVLFactory
0243   ///  object should always have this method return true.  Further, if this
0244   ///  method returns false for an instance of ImutAVLTree, all subtrees
0245   ///  will also have this method return false.  The converse is not true.
0246   bool isMutable() const { return IsMutable; }
0247 
0248   /// hasCachedDigest - Returns true if the digest for this tree is cached.
0249   ///  This can only be true if the tree is immutable.
0250   bool hasCachedDigest() const { return IsDigestCached; }
0251 
0252   //===----------------------------------------------------===//
0253   // Mutating operations.  A tree root can be manipulated as
0254   // long as its reference has not "escaped" from internal
0255   // methods of a factory object (see below).  When a tree
0256   // pointer is externally viewable by client code, the
0257   // internal "mutable bit" is cleared to mark the tree
0258   // immutable.  Note that a tree that still has its mutable
0259   // bit set may have children (subtrees) that are themselves
0260   // immutable.
0261   //===----------------------------------------------------===//
0262 
0263   /// markImmutable - Clears the mutable flag for a tree.  After this happens,
0264   ///   it is an error to call setLeft(), setRight(), and setHeight().
0265   void markImmutable() {
0266     assert(isMutable() && "Mutable flag already removed.");
0267     IsMutable = false;
0268   }
0269 
0270   /// markedCachedDigest - Clears the NoCachedDigest flag for a tree.
0271   void markedCachedDigest() {
0272     assert(!hasCachedDigest() && "NoCachedDigest flag already removed.");
0273     IsDigestCached = true;
0274   }
0275 
0276   /// setHeight - Changes the height of the tree.  Used internally by
0277   ///  ImutAVLFactory.
0278   void setHeight(unsigned h) {
0279     assert(isMutable() && "Only a mutable tree can have its height changed.");
0280     height = h;
0281   }
0282 
0283   static uint32_t computeDigest(ImutAVLTree *L, ImutAVLTree *R,
0284                                 value_type_ref V) {
0285     uint32_t digest = 0;
0286 
0287     if (L)
0288       digest += L->computeDigest();
0289 
0290     // Compute digest of stored data.
0291     FoldingSetNodeID ID;
0292     ImutInfo::Profile(ID,V);
0293     digest += ID.ComputeHash();
0294 
0295     if (R)
0296       digest += R->computeDigest();
0297 
0298     return digest;
0299   }
0300 
0301   uint32_t computeDigest() {
0302     // Check the lowest bit to determine if digest has actually been
0303     // pre-computed.
0304     if (hasCachedDigest())
0305       return digest;
0306 
0307     uint32_t X = computeDigest(getLeft(), getRight(), getValue());
0308     digest = X;
0309     markedCachedDigest();
0310     return X;
0311   }
0312 
0313   //===----------------------------------------------------===//
0314   // Reference count operations.
0315   //===----------------------------------------------------===//
0316 
0317 public:
0318   void retain() { ++refCount; }
0319 
0320   void release() {
0321     assert(refCount > 0);
0322     if (--refCount == 0)
0323       destroy();
0324   }
0325 
0326   void destroy() {
0327     if (left)
0328       left->release();
0329     if (right)
0330       right->release();
0331     if (IsCanonicalized) {
0332       if (next)
0333         next->prev = prev;
0334 
0335       if (prev)
0336         prev->next = next;
0337       else
0338         factory->Cache[factory->maskCacheIndex(computeDigest())] = next;
0339     }
0340 
0341     // We need to clear the mutability bit in case we are
0342     // destroying the node as part of a sweep in ImutAVLFactory::recoverNodes().
0343     IsMutable = false;
0344     factory->freeNodes.push_back(this);
0345   }
0346 };
0347 
0348 template <typename ImutInfo>
0349 struct IntrusiveRefCntPtrInfo<ImutAVLTree<ImutInfo>> {
0350   static void retain(ImutAVLTree<ImutInfo> *Tree) { Tree->retain(); }
0351   static void release(ImutAVLTree<ImutInfo> *Tree) { Tree->release(); }
0352 };
0353 
0354 //===----------------------------------------------------------------------===//
0355 // Immutable AVL-Tree Factory class.
0356 //===----------------------------------------------------------------------===//
0357 
0358 template <typename ImutInfo >
0359 class ImutAVLFactory {
0360   friend class ImutAVLTree<ImutInfo>;
0361 
0362   using TreeTy = ImutAVLTree<ImutInfo>;
0363   using value_type_ref = typename TreeTy::value_type_ref;
0364   using key_type_ref = typename TreeTy::key_type_ref;
0365   using CacheTy = DenseMap<unsigned, TreeTy*>;
0366 
0367   CacheTy Cache;
0368   uintptr_t Allocator;
0369   std::vector<TreeTy*> createdNodes;
0370   std::vector<TreeTy*> freeNodes;
0371 
0372   bool ownsAllocator() const {
0373     return (Allocator & 0x1) == 0;
0374   }
0375 
0376   BumpPtrAllocator& getAllocator() const {
0377     return *reinterpret_cast<BumpPtrAllocator*>(Allocator & ~0x1);
0378   }
0379 
0380   //===--------------------------------------------------===//
0381   // Public interface.
0382   //===--------------------------------------------------===//
0383 
0384 public:
0385   ImutAVLFactory()
0386     : Allocator(reinterpret_cast<uintptr_t>(new BumpPtrAllocator())) {}
0387 
0388   ImutAVLFactory(BumpPtrAllocator& Alloc)
0389     : Allocator(reinterpret_cast<uintptr_t>(&Alloc) | 0x1) {}
0390 
0391   ~ImutAVLFactory() {
0392     if (ownsAllocator()) delete &getAllocator();
0393   }
0394 
0395   TreeTy* add(TreeTy* T, value_type_ref V) {
0396     T = add_internal(V,T);
0397     markImmutable(T);
0398     recoverNodes();
0399     return T;
0400   }
0401 
0402   TreeTy* remove(TreeTy* T, key_type_ref V) {
0403     T = remove_internal(V,T);
0404     markImmutable(T);
0405     recoverNodes();
0406     return T;
0407   }
0408 
0409   TreeTy* getEmptyTree() const { return nullptr; }
0410 
0411 protected:
0412   //===--------------------------------------------------===//
0413   // A bunch of quick helper functions used for reasoning
0414   // about the properties of trees and their children.
0415   // These have succinct names so that the balancing code
0416   // is as terse (and readable) as possible.
0417   //===--------------------------------------------------===//
0418 
0419   bool            isEmpty(TreeTy* T) const { return !T; }
0420   unsigned        getHeight(TreeTy* T) const { return T ? T->getHeight() : 0; }
0421   TreeTy*         getLeft(TreeTy* T) const { return T->getLeft(); }
0422   TreeTy*         getRight(TreeTy* T) const { return T->getRight(); }
0423   value_type_ref  getValue(TreeTy* T) const { return T->value; }
0424 
0425   // Make sure the index is not the Tombstone or Entry key of the DenseMap.
0426   static unsigned maskCacheIndex(unsigned I) { return (I & ~0x02); }
0427 
0428   unsigned incrementHeight(TreeTy* L, TreeTy* R) const {
0429     unsigned hl = getHeight(L);
0430     unsigned hr = getHeight(R);
0431     return (hl > hr ? hl : hr) + 1;
0432   }
0433 
0434   static bool compareTreeWithSection(TreeTy* T,
0435                                      typename TreeTy::iterator& TI,
0436                                      typename TreeTy::iterator& TE) {
0437     typename TreeTy::iterator I = T->begin(), E = T->end();
0438     for ( ; I!=E ; ++I, ++TI) {
0439       if (TI == TE || !I->isElementEqual(&*TI))
0440         return false;
0441     }
0442     return true;
0443   }
0444 
0445   //===--------------------------------------------------===//
0446   // "createNode" is used to generate new tree roots that link
0447   // to other trees.  The function may also simply move links
0448   // in an existing root if that root is still marked mutable.
0449   // This is necessary because otherwise our balancing code
0450   // would leak memory as it would create nodes that are
0451   // then discarded later before the finished tree is
0452   // returned to the caller.
0453   //===--------------------------------------------------===//
0454 
0455   TreeTy* createNode(TreeTy* L, value_type_ref V, TreeTy* R) {
0456     BumpPtrAllocator& A = getAllocator();
0457     TreeTy* T;
0458     if (!freeNodes.empty()) {
0459       T = freeNodes.back();
0460       freeNodes.pop_back();
0461       assert(T != L);
0462       assert(T != R);
0463     } else {
0464       T = (TreeTy*) A.Allocate<TreeTy>();
0465     }
0466     new (T) TreeTy(this, L, R, V, incrementHeight(L,R));
0467     createdNodes.push_back(T);
0468     return T;
0469   }
0470 
0471   TreeTy* createNode(TreeTy* newLeft, TreeTy* oldTree, TreeTy* newRight) {
0472     return createNode(newLeft, getValue(oldTree), newRight);
0473   }
0474 
0475   void recoverNodes() {
0476     for (unsigned i = 0, n = createdNodes.size(); i < n; ++i) {
0477       TreeTy *N = createdNodes[i];
0478       if (N->isMutable() && N->refCount == 0)
0479         N->destroy();
0480     }
0481     createdNodes.clear();
0482   }
0483 
0484   /// balanceTree - Used by add_internal and remove_internal to
0485   ///  balance a newly created tree.
0486   TreeTy* balanceTree(TreeTy* L, value_type_ref V, TreeTy* R) {
0487     unsigned hl = getHeight(L);
0488     unsigned hr = getHeight(R);
0489 
0490     if (hl > hr + 2) {
0491       assert(!isEmpty(L) && "Left tree cannot be empty to have a height >= 2");
0492 
0493       TreeTy *LL = getLeft(L);
0494       TreeTy *LR = getRight(L);
0495 
0496       if (getHeight(LL) >= getHeight(LR))
0497         return createNode(LL, L, createNode(LR,V,R));
0498 
0499       assert(!isEmpty(LR) && "LR cannot be empty because it has a height >= 1");
0500 
0501       TreeTy *LRL = getLeft(LR);
0502       TreeTy *LRR = getRight(LR);
0503 
0504       return createNode(createNode(LL,L,LRL), LR, createNode(LRR,V,R));
0505     }
0506 
0507     if (hr > hl + 2) {
0508       assert(!isEmpty(R) && "Right tree cannot be empty to have a height >= 2");
0509 
0510       TreeTy *RL = getLeft(R);
0511       TreeTy *RR = getRight(R);
0512 
0513       if (getHeight(RR) >= getHeight(RL))
0514         return createNode(createNode(L,V,RL), R, RR);
0515 
0516       assert(!isEmpty(RL) && "RL cannot be empty because it has a height >= 1");
0517 
0518       TreeTy *RLL = getLeft(RL);
0519       TreeTy *RLR = getRight(RL);
0520 
0521       return createNode(createNode(L,V,RLL), RL, createNode(RLR,R,RR));
0522     }
0523 
0524     return createNode(L,V,R);
0525   }
0526 
0527   /// add_internal - Creates a new tree that includes the specified
0528   ///  data and the data from the original tree.  If the original tree
0529   ///  already contained the data item, the original tree is returned.
0530   TreeTy* add_internal(value_type_ref V, TreeTy* T) {
0531     if (isEmpty(T))
0532       return createNode(T, V, T);
0533     assert(!T->isMutable());
0534 
0535     key_type_ref K = ImutInfo::KeyOfValue(V);
0536     key_type_ref KCurrent = ImutInfo::KeyOfValue(getValue(T));
0537 
0538     if (ImutInfo::isEqual(K,KCurrent))
0539       return createNode(getLeft(T), V, getRight(T));
0540     else if (ImutInfo::isLess(K,KCurrent))
0541       return balanceTree(add_internal(V, getLeft(T)), getValue(T), getRight(T));
0542     else
0543       return balanceTree(getLeft(T), getValue(T), add_internal(V, getRight(T)));
0544   }
0545 
0546   /// remove_internal - Creates a new tree that includes all the data
0547   ///  from the original tree except the specified data.  If the
0548   ///  specified data did not exist in the original tree, the original
0549   ///  tree is returned.
0550   TreeTy* remove_internal(key_type_ref K, TreeTy* T) {
0551     if (isEmpty(T))
0552       return T;
0553 
0554     assert(!T->isMutable());
0555 
0556     key_type_ref KCurrent = ImutInfo::KeyOfValue(getValue(T));
0557 
0558     if (ImutInfo::isEqual(K,KCurrent)) {
0559       return combineTrees(getLeft(T), getRight(T));
0560     } else if (ImutInfo::isLess(K,KCurrent)) {
0561       return balanceTree(remove_internal(K, getLeft(T)),
0562                                             getValue(T), getRight(T));
0563     } else {
0564       return balanceTree(getLeft(T), getValue(T),
0565                          remove_internal(K, getRight(T)));
0566     }
0567   }
0568 
0569   TreeTy* combineTrees(TreeTy* L, TreeTy* R) {
0570     if (isEmpty(L))
0571       return R;
0572     if (isEmpty(R))
0573       return L;
0574     TreeTy* OldNode;
0575     TreeTy* newRight = removeMinBinding(R,OldNode);
0576     return balanceTree(L, getValue(OldNode), newRight);
0577   }
0578 
0579   TreeTy* removeMinBinding(TreeTy* T, TreeTy*& Noderemoved) {
0580     assert(!isEmpty(T));
0581     if (isEmpty(getLeft(T))) {
0582       Noderemoved = T;
0583       return getRight(T);
0584     }
0585     return balanceTree(removeMinBinding(getLeft(T), Noderemoved),
0586                        getValue(T), getRight(T));
0587   }
0588 
0589   /// markImmutable - Clears the mutable bits of a root and all of its
0590   ///  descendants.
0591   void markImmutable(TreeTy* T) {
0592     if (!T || !T->isMutable())
0593       return;
0594     T->markImmutable();
0595     markImmutable(getLeft(T));
0596     markImmutable(getRight(T));
0597   }
0598 
0599 public:
0600   TreeTy *getCanonicalTree(TreeTy *TNew) {
0601     if (!TNew)
0602       return nullptr;
0603 
0604     if (TNew->IsCanonicalized)
0605       return TNew;
0606 
0607     // Search the hashtable for another tree with the same digest, and
0608     // if find a collision compare those trees by their contents.
0609     unsigned digest = TNew->computeDigest();
0610     TreeTy *&entry = Cache[maskCacheIndex(digest)];
0611     do {
0612       if (!entry)
0613         break;
0614       for (TreeTy *T = entry ; T != nullptr; T = T->next) {
0615         // Compare the Contents('T') with Contents('TNew')
0616         typename TreeTy::iterator TI = T->begin(), TE = T->end();
0617         if (!compareTreeWithSection(TNew, TI, TE))
0618           continue;
0619         if (TI != TE)
0620           continue; // T has more contents than TNew.
0621         // Trees did match!  Return 'T'.
0622         if (TNew->refCount == 0)
0623           TNew->destroy();
0624         return T;
0625       }
0626       entry->prev = TNew;
0627       TNew->next = entry;
0628     }
0629     while (false);
0630 
0631     entry = TNew;
0632     TNew->IsCanonicalized = true;
0633     return TNew;
0634   }
0635 };
0636 
0637 //===----------------------------------------------------------------------===//
0638 // Immutable AVL-Tree Iterators.
0639 //===----------------------------------------------------------------------===//
0640 
0641 template <typename ImutInfo> class ImutAVLTreeGenericIterator {
0642   SmallVector<uintptr_t,20> stack;
0643 
0644 public:
0645   using iterator_category = std::bidirectional_iterator_tag;
0646   using value_type = ImutAVLTree<ImutInfo>;
0647   using difference_type = std::ptrdiff_t;
0648   using pointer = value_type *;
0649   using reference = value_type &;
0650 
0651   enum VisitFlag { VisitedNone=0x0, VisitedLeft=0x1, VisitedRight=0x3,
0652                    Flags=0x3 };
0653 
0654   using TreeTy = ImutAVLTree<ImutInfo>;
0655 
0656   ImutAVLTreeGenericIterator() = default;
0657   ImutAVLTreeGenericIterator(const TreeTy *Root) {
0658     if (Root) stack.push_back(reinterpret_cast<uintptr_t>(Root));
0659   }
0660 
0661   TreeTy &operator*() const {
0662     assert(!stack.empty());
0663     return *reinterpret_cast<TreeTy *>(stack.back() & ~Flags);
0664   }
0665   TreeTy *operator->() const { return &*this; }
0666 
0667   uintptr_t getVisitState() const {
0668     assert(!stack.empty());
0669     return stack.back() & Flags;
0670   }
0671 
0672   bool atEnd() const { return stack.empty(); }
0673 
0674   bool atBeginning() const {
0675     return stack.size() == 1 && getVisitState() == VisitedNone;
0676   }
0677 
0678   void skipToParent() {
0679     assert(!stack.empty());
0680     stack.pop_back();
0681     if (stack.empty())
0682       return;
0683     switch (getVisitState()) {
0684       case VisitedNone:
0685         stack.back() |= VisitedLeft;
0686         break;
0687       case VisitedLeft:
0688         stack.back() |= VisitedRight;
0689         break;
0690       default:
0691         llvm_unreachable("Unreachable.");
0692     }
0693   }
0694 
0695   bool operator==(const ImutAVLTreeGenericIterator &x) const {
0696     return stack == x.stack;
0697   }
0698 
0699   bool operator!=(const ImutAVLTreeGenericIterator &x) const {
0700     return !(*this == x);
0701   }
0702 
0703   ImutAVLTreeGenericIterator &operator++() {
0704     assert(!stack.empty());
0705     TreeTy* Current = reinterpret_cast<TreeTy*>(stack.back() & ~Flags);
0706     assert(Current);
0707     switch (getVisitState()) {
0708       case VisitedNone:
0709         if (TreeTy* L = Current->getLeft())
0710           stack.push_back(reinterpret_cast<uintptr_t>(L));
0711         else
0712           stack.back() |= VisitedLeft;
0713         break;
0714       case VisitedLeft:
0715         if (TreeTy* R = Current->getRight())
0716           stack.push_back(reinterpret_cast<uintptr_t>(R));
0717         else
0718           stack.back() |= VisitedRight;
0719         break;
0720       case VisitedRight:
0721         skipToParent();
0722         break;
0723       default:
0724         llvm_unreachable("Unreachable.");
0725     }
0726     return *this;
0727   }
0728 
0729   ImutAVLTreeGenericIterator &operator--() {
0730     assert(!stack.empty());
0731     TreeTy* Current = reinterpret_cast<TreeTy*>(stack.back() & ~Flags);
0732     assert(Current);
0733     switch (getVisitState()) {
0734       case VisitedNone:
0735         stack.pop_back();
0736         break;
0737       case VisitedLeft:
0738         stack.back() &= ~Flags; // Set state to "VisitedNone."
0739         if (TreeTy* L = Current->getLeft())
0740           stack.push_back(reinterpret_cast<uintptr_t>(L) | VisitedRight);
0741         break;
0742       case VisitedRight:
0743         stack.back() &= ~Flags;
0744         stack.back() |= VisitedLeft;
0745         if (TreeTy* R = Current->getRight())
0746           stack.push_back(reinterpret_cast<uintptr_t>(R) | VisitedRight);
0747         break;
0748       default:
0749         llvm_unreachable("Unreachable.");
0750     }
0751     return *this;
0752   }
0753 };
0754 
0755 template <typename ImutInfo> class ImutAVLTreeInOrderIterator {
0756   using InternalIteratorTy = ImutAVLTreeGenericIterator<ImutInfo>;
0757 
0758   InternalIteratorTy InternalItr;
0759 
0760 public:
0761   using iterator_category = std::bidirectional_iterator_tag;
0762   using value_type = ImutAVLTree<ImutInfo>;
0763   using difference_type = std::ptrdiff_t;
0764   using pointer = value_type *;
0765   using reference = value_type &;
0766 
0767   using TreeTy = ImutAVLTree<ImutInfo>;
0768 
0769   ImutAVLTreeInOrderIterator(const TreeTy* Root) : InternalItr(Root) {
0770     if (Root)
0771       ++*this; // Advance to first element.
0772   }
0773 
0774   ImutAVLTreeInOrderIterator() : InternalItr() {}
0775 
0776   bool operator==(const ImutAVLTreeInOrderIterator &x) const {
0777     return InternalItr == x.InternalItr;
0778   }
0779 
0780   bool operator!=(const ImutAVLTreeInOrderIterator &x) const {
0781     return !(*this == x);
0782   }
0783 
0784   TreeTy &operator*() const { return *InternalItr; }
0785   TreeTy *operator->() const { return &*InternalItr; }
0786 
0787   ImutAVLTreeInOrderIterator &operator++() {
0788     do ++InternalItr;
0789     while (!InternalItr.atEnd() &&
0790            InternalItr.getVisitState() != InternalIteratorTy::VisitedLeft);
0791 
0792     return *this;
0793   }
0794 
0795   ImutAVLTreeInOrderIterator &operator--() {
0796     do --InternalItr;
0797     while (!InternalItr.atBeginning() &&
0798            InternalItr.getVisitState() != InternalIteratorTy::VisitedLeft);
0799 
0800     return *this;
0801   }
0802 
0803   void skipSubTree() {
0804     InternalItr.skipToParent();
0805 
0806     while (!InternalItr.atEnd() &&
0807            InternalItr.getVisitState() != InternalIteratorTy::VisitedLeft)
0808       ++InternalItr;
0809   }
0810 };
0811 
0812 /// Generic iterator that wraps a T::TreeTy::iterator and exposes
0813 /// iterator::getValue() on dereference.
0814 template <typename T>
0815 struct ImutAVLValueIterator
0816     : iterator_adaptor_base<
0817           ImutAVLValueIterator<T>, typename T::TreeTy::iterator,
0818           typename std::iterator_traits<
0819               typename T::TreeTy::iterator>::iterator_category,
0820           const typename T::value_type> {
0821   ImutAVLValueIterator() = default;
0822   explicit ImutAVLValueIterator(typename T::TreeTy *Tree)
0823       : ImutAVLValueIterator::iterator_adaptor_base(Tree) {}
0824 
0825   typename ImutAVLValueIterator::reference operator*() const {
0826     return this->I->getValue();
0827   }
0828 };
0829 
0830 //===----------------------------------------------------------------------===//
0831 // Trait classes for Profile information.
0832 //===----------------------------------------------------------------------===//
0833 
0834 /// Generic profile template.  The default behavior is to invoke the
0835 /// profile method of an object.  Specializations for primitive integers
0836 /// and generic handling of pointers is done below.
0837 template <typename T>
0838 struct ImutProfileInfo {
0839   using value_type = const T;
0840   using value_type_ref = const T&;
0841 
0842   static void Profile(FoldingSetNodeID &ID, value_type_ref X) {
0843     FoldingSetTrait<T>::Profile(X,ID);
0844   }
0845 };
0846 
0847 /// Profile traits for integers.
0848 template <typename T>
0849 struct ImutProfileInteger {
0850   using value_type = const T;
0851   using value_type_ref = const T&;
0852 
0853   static void Profile(FoldingSetNodeID &ID, value_type_ref X) {
0854     ID.AddInteger(X);
0855   }
0856 };
0857 
0858 #define PROFILE_INTEGER_INFO(X)\
0859 template<> struct ImutProfileInfo<X> : ImutProfileInteger<X> {};
0860 
0861 PROFILE_INTEGER_INFO(char)
0862 PROFILE_INTEGER_INFO(unsigned char)
0863 PROFILE_INTEGER_INFO(short)
0864 PROFILE_INTEGER_INFO(unsigned short)
0865 PROFILE_INTEGER_INFO(unsigned)
0866 PROFILE_INTEGER_INFO(signed)
0867 PROFILE_INTEGER_INFO(long)
0868 PROFILE_INTEGER_INFO(unsigned long)
0869 PROFILE_INTEGER_INFO(long long)
0870 PROFILE_INTEGER_INFO(unsigned long long)
0871 
0872 #undef PROFILE_INTEGER_INFO
0873 
0874 /// Profile traits for booleans.
0875 template <>
0876 struct ImutProfileInfo<bool> {
0877   using value_type = const bool;
0878   using value_type_ref = const bool&;
0879 
0880   static void Profile(FoldingSetNodeID &ID, value_type_ref X) {
0881     ID.AddBoolean(X);
0882   }
0883 };
0884 
0885 /// Generic profile trait for pointer types.  We treat pointers as
0886 /// references to unique objects.
0887 template <typename T>
0888 struct ImutProfileInfo<T*> {
0889   using value_type = const T*;
0890   using value_type_ref = value_type;
0891 
0892   static void Profile(FoldingSetNodeID &ID, value_type_ref X) {
0893     ID.AddPointer(X);
0894   }
0895 };
0896 
0897 //===----------------------------------------------------------------------===//
0898 // Trait classes that contain element comparison operators and type
0899 //  definitions used by ImutAVLTree, ImmutableSet, and ImmutableMap.  These
0900 //  inherit from the profile traits (ImutProfileInfo) to include operations
0901 //  for element profiling.
0902 //===----------------------------------------------------------------------===//
0903 
0904 /// ImutContainerInfo - Generic definition of comparison operations for
0905 ///   elements of immutable containers that defaults to using
0906 ///   std::equal_to<> and std::less<> to perform comparison of elements.
0907 template <typename T>
0908 struct ImutContainerInfo : public ImutProfileInfo<T> {
0909   using value_type = typename ImutProfileInfo<T>::value_type;
0910   using value_type_ref = typename ImutProfileInfo<T>::value_type_ref;
0911   using key_type = value_type;
0912   using key_type_ref = value_type_ref;
0913   using data_type = bool;
0914   using data_type_ref = bool;
0915 
0916   static key_type_ref KeyOfValue(value_type_ref D) { return D; }
0917   static data_type_ref DataOfValue(value_type_ref) { return true; }
0918 
0919   static bool isEqual(key_type_ref LHS, key_type_ref RHS) {
0920     return std::equal_to<key_type>()(LHS,RHS);
0921   }
0922 
0923   static bool isLess(key_type_ref LHS, key_type_ref RHS) {
0924     return std::less<key_type>()(LHS,RHS);
0925   }
0926 
0927   static bool isDataEqual(data_type_ref, data_type_ref) { return true; }
0928 };
0929 
0930 /// ImutContainerInfo - Specialization for pointer values to treat pointers
0931 ///  as references to unique objects.  Pointers are thus compared by
0932 ///  their addresses.
0933 template <typename T>
0934 struct ImutContainerInfo<T*> : public ImutProfileInfo<T*> {
0935   using value_type = typename ImutProfileInfo<T*>::value_type;
0936   using value_type_ref = typename ImutProfileInfo<T*>::value_type_ref;
0937   using key_type = value_type;
0938   using key_type_ref = value_type_ref;
0939   using data_type = bool;
0940   using data_type_ref = bool;
0941 
0942   static key_type_ref KeyOfValue(value_type_ref D) { return D; }
0943   static data_type_ref DataOfValue(value_type_ref) { return true; }
0944 
0945   static bool isEqual(key_type_ref LHS, key_type_ref RHS) { return LHS == RHS; }
0946 
0947   static bool isLess(key_type_ref LHS, key_type_ref RHS) { return LHS < RHS; }
0948 
0949   static bool isDataEqual(data_type_ref, data_type_ref) { return true; }
0950 };
0951 
0952 //===----------------------------------------------------------------------===//
0953 // Immutable Set
0954 //===----------------------------------------------------------------------===//
0955 
0956 template <typename ValT, typename ValInfo = ImutContainerInfo<ValT>>
0957 class ImmutableSet {
0958 public:
0959   using value_type = typename ValInfo::value_type;
0960   using value_type_ref = typename ValInfo::value_type_ref;
0961   using TreeTy = ImutAVLTree<ValInfo>;
0962 
0963 private:
0964   IntrusiveRefCntPtr<TreeTy> Root;
0965 
0966 public:
0967   /// Constructs a set from a pointer to a tree root.  In general one
0968   /// should use a Factory object to create sets instead of directly
0969   /// invoking the constructor, but there are cases where make this
0970   /// constructor public is useful.
0971   explicit ImmutableSet(TreeTy *R) : Root(R) {}
0972 
0973   class Factory {
0974     typename TreeTy::Factory F;
0975     const bool Canonicalize;
0976 
0977   public:
0978     Factory(bool canonicalize = true)
0979       : Canonicalize(canonicalize) {}
0980 
0981     Factory(BumpPtrAllocator& Alloc, bool canonicalize = true)
0982       : F(Alloc), Canonicalize(canonicalize) {}
0983 
0984     Factory(const Factory& RHS) = delete;
0985     void operator=(const Factory& RHS) = delete;
0986 
0987     /// getEmptySet - Returns an immutable set that contains no elements.
0988     ImmutableSet getEmptySet() {
0989       return ImmutableSet(F.getEmptyTree());
0990     }
0991 
0992     /// add - Creates a new immutable set that contains all of the values
0993     ///  of the original set with the addition of the specified value.  If
0994     ///  the original set already included the value, then the original set is
0995     ///  returned and no memory is allocated.  The time and space complexity
0996     ///  of this operation is logarithmic in the size of the original set.
0997     ///  The memory allocated to represent the set is released when the
0998     ///  factory object that created the set is destroyed.
0999     [[nodiscard]] ImmutableSet add(ImmutableSet Old, value_type_ref V) {
1000       TreeTy *NewT = F.add(Old.Root.get(), V);
1001       return ImmutableSet(Canonicalize ? F.getCanonicalTree(NewT) : NewT);
1002     }
1003 
1004     /// remove - Creates a new immutable set that contains all of the values
1005     ///  of the original set with the exception of the specified value.  If
1006     ///  the original set did not contain the value, the original set is
1007     ///  returned and no memory is allocated.  The time and space complexity
1008     ///  of this operation is logarithmic in the size of the original set.
1009     ///  The memory allocated to represent the set is released when the
1010     ///  factory object that created the set is destroyed.
1011     [[nodiscard]] ImmutableSet remove(ImmutableSet Old, value_type_ref V) {
1012       TreeTy *NewT = F.remove(Old.Root.get(), V);
1013       return ImmutableSet(Canonicalize ? F.getCanonicalTree(NewT) : NewT);
1014     }
1015 
1016     BumpPtrAllocator& getAllocator() { return F.getAllocator(); }
1017 
1018     typename TreeTy::Factory *getTreeFactory() const {
1019       return const_cast<typename TreeTy::Factory *>(&F);
1020     }
1021   };
1022 
1023   friend class Factory;
1024 
1025   /// Returns true if the set contains the specified value.
1026   bool contains(value_type_ref V) const {
1027     return Root ? Root->contains(V) : false;
1028   }
1029 
1030   bool operator==(const ImmutableSet &RHS) const {
1031     return Root && RHS.Root ? Root->isEqual(*RHS.Root.get()) : Root == RHS.Root;
1032   }
1033 
1034   bool operator!=(const ImmutableSet &RHS) const {
1035     return Root && RHS.Root ? Root->isNotEqual(*RHS.Root.get())
1036                             : Root != RHS.Root;
1037   }
1038 
1039   TreeTy *getRoot() {
1040     if (Root) { Root->retain(); }
1041     return Root.get();
1042   }
1043 
1044   TreeTy *getRootWithoutRetain() const { return Root.get(); }
1045 
1046   /// isEmpty - Return true if the set contains no elements.
1047   bool isEmpty() const { return !Root; }
1048 
1049   /// isSingleton - Return true if the set contains exactly one element.
1050   ///   This method runs in constant time.
1051   bool isSingleton() const { return getHeight() == 1; }
1052 
1053   //===--------------------------------------------------===//
1054   // Iterators.
1055   //===--------------------------------------------------===//
1056 
1057   using iterator = ImutAVLValueIterator<ImmutableSet>;
1058 
1059   iterator begin() const { return iterator(Root.get()); }
1060   iterator end() const { return iterator(); }
1061 
1062   //===--------------------------------------------------===//
1063   // Utility methods.
1064   //===--------------------------------------------------===//
1065 
1066   unsigned getHeight() const { return Root ? Root->getHeight() : 0; }
1067 
1068   static void Profile(FoldingSetNodeID &ID, const ImmutableSet &S) {
1069     ID.AddPointer(S.Root.get());
1070   }
1071 
1072   void Profile(FoldingSetNodeID &ID) const { return Profile(ID, *this); }
1073 
1074   //===--------------------------------------------------===//
1075   // For testing.
1076   //===--------------------------------------------------===//
1077 
1078   void validateTree() const { if (Root) Root->validateTree(); }
1079 };
1080 
1081 // NOTE: This may some day replace the current ImmutableSet.
1082 template <typename ValT, typename ValInfo = ImutContainerInfo<ValT>>
1083 class ImmutableSetRef {
1084 public:
1085   using value_type = typename ValInfo::value_type;
1086   using value_type_ref = typename ValInfo::value_type_ref;
1087   using TreeTy = ImutAVLTree<ValInfo>;
1088   using FactoryTy = typename TreeTy::Factory;
1089 
1090 private:
1091   IntrusiveRefCntPtr<TreeTy> Root;
1092   FactoryTy *Factory;
1093 
1094 public:
1095   /// Constructs a set from a pointer to a tree root.  In general one
1096   /// should use a Factory object to create sets instead of directly
1097   /// invoking the constructor, but there are cases where make this
1098   /// constructor public is useful.
1099   ImmutableSetRef(TreeTy *R, FactoryTy *F) : Root(R), Factory(F) {}
1100 
1101   static ImmutableSetRef getEmptySet(FactoryTy *F) {
1102     return ImmutableSetRef(0, F);
1103   }
1104 
1105   ImmutableSetRef add(value_type_ref V) {
1106     return ImmutableSetRef(Factory->add(Root.get(), V), Factory);
1107   }
1108 
1109   ImmutableSetRef remove(value_type_ref V) {
1110     return ImmutableSetRef(Factory->remove(Root.get(), V), Factory);
1111   }
1112 
1113   /// Returns true if the set contains the specified value.
1114   bool contains(value_type_ref V) const {
1115     return Root ? Root->contains(V) : false;
1116   }
1117 
1118   ImmutableSet<ValT> asImmutableSet(bool canonicalize = true) const {
1119     return ImmutableSet<ValT>(
1120         canonicalize ? Factory->getCanonicalTree(Root.get()) : Root.get());
1121   }
1122 
1123   TreeTy *getRootWithoutRetain() const { return Root.get(); }
1124 
1125   bool operator==(const ImmutableSetRef &RHS) const {
1126     return Root && RHS.Root ? Root->isEqual(*RHS.Root.get()) : Root == RHS.Root;
1127   }
1128 
1129   bool operator!=(const ImmutableSetRef &RHS) const {
1130     return Root && RHS.Root ? Root->isNotEqual(*RHS.Root.get())
1131                             : Root != RHS.Root;
1132   }
1133 
1134   /// isEmpty - Return true if the set contains no elements.
1135   bool isEmpty() const { return !Root; }
1136 
1137   /// isSingleton - Return true if the set contains exactly one element.
1138   ///   This method runs in constant time.
1139   bool isSingleton() const { return getHeight() == 1; }
1140 
1141   //===--------------------------------------------------===//
1142   // Iterators.
1143   //===--------------------------------------------------===//
1144 
1145   using iterator = ImutAVLValueIterator<ImmutableSetRef>;
1146 
1147   iterator begin() const { return iterator(Root.get()); }
1148   iterator end() const { return iterator(); }
1149 
1150   //===--------------------------------------------------===//
1151   // Utility methods.
1152   //===--------------------------------------------------===//
1153 
1154   unsigned getHeight() const { return Root ? Root->getHeight() : 0; }
1155 
1156   static void Profile(FoldingSetNodeID &ID, const ImmutableSetRef &S) {
1157     ID.AddPointer(S.Root.get());
1158   }
1159 
1160   void Profile(FoldingSetNodeID &ID) const { return Profile(ID, *this); }
1161 
1162   //===--------------------------------------------------===//
1163   // For testing.
1164   //===--------------------------------------------------===//
1165 
1166   void validateTree() const { if (Root) Root->validateTree(); }
1167 };
1168 
1169 } // end namespace llvm
1170 
1171 #endif // LLVM_ADT_IMMUTABLESET_H