xref: /freebsd/contrib/llvm-project/llvm/include/llvm/ADT/ImmutableSet.h (revision bdd1243df58e60e85101c09001d9812a789b6bc4)
1 //===--- ImmutableSet.h - Immutable (functional) set interface --*- C++ -*-===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 ///
9 /// \file
10 /// This file defines the ImutAVLTree and ImmutableSet classes.
11 ///
12 //===----------------------------------------------------------------------===//
13 
14 #ifndef LLVM_ADT_IMMUTABLESET_H
15 #define LLVM_ADT_IMMUTABLESET_H
16 
17 #include "llvm/ADT/DenseMap.h"
18 #include "llvm/ADT/FoldingSet.h"
19 #include "llvm/ADT/IntrusiveRefCntPtr.h"
20 #include "llvm/ADT/SmallVector.h"
21 #include "llvm/ADT/iterator.h"
22 #include "llvm/Support/Allocator.h"
23 #include "llvm/Support/ErrorHandling.h"
24 #include <cassert>
25 #include <cstdint>
26 #include <functional>
27 #include <iterator>
28 #include <new>
29 #include <vector>
30 
31 namespace llvm {
32 
33 //===----------------------------------------------------------------------===//
34 // Immutable AVL-Tree Definition.
35 //===----------------------------------------------------------------------===//
36 
37 template <typename ImutInfo> class ImutAVLFactory;
38 template <typename ImutInfo> class ImutIntervalAVLFactory;
39 template <typename ImutInfo> class ImutAVLTreeInOrderIterator;
40 template <typename ImutInfo> class ImutAVLTreeGenericIterator;
41 
42 template <typename ImutInfo >
43 class ImutAVLTree {
44 public:
45   using key_type_ref = typename ImutInfo::key_type_ref;
46   using value_type = typename ImutInfo::value_type;
47   using value_type_ref = typename ImutInfo::value_type_ref;
48   using Factory = ImutAVLFactory<ImutInfo>;
49   using iterator = ImutAVLTreeInOrderIterator<ImutInfo>;
50 
51   friend class ImutAVLFactory<ImutInfo>;
52   friend class ImutIntervalAVLFactory<ImutInfo>;
53   friend class ImutAVLTreeGenericIterator<ImutInfo>;
54 
55   //===----------------------------------------------------===//
56   // Public Interface.
57   //===----------------------------------------------------===//
58 
59   /// Return a pointer to the left subtree.  This value
60   ///  is NULL if there is no left subtree.
getLeft()61   ImutAVLTree *getLeft() const { return left; }
62 
63   /// Return a pointer to the right subtree.  This value is
64   ///  NULL if there is no right subtree.
getRight()65   ImutAVLTree *getRight() const { return right; }
66 
67   /// getHeight - Returns the height of the tree.  A tree with no subtrees
68   ///  has a height of 1.
getHeight()69   unsigned getHeight() const { return height; }
70 
71   /// getValue - Returns the data value associated with the tree node.
getValue()72   const value_type& getValue() const { return value; }
73 
74   /// find - Finds the subtree associated with the specified key value.
75   ///  This method returns NULL if no matching subtree is found.
find(key_type_ref K)76   ImutAVLTree* find(key_type_ref K) {
77     ImutAVLTree *T = this;
78     while (T) {
79       key_type_ref CurrentKey = ImutInfo::KeyOfValue(T->getValue());
80       if (ImutInfo::isEqual(K,CurrentKey))
81         return T;
82       else if (ImutInfo::isLess(K,CurrentKey))
83         T = T->getLeft();
84       else
85         T = T->getRight();
86     }
87     return nullptr;
88   }
89 
90   /// getMaxElement - Find the subtree associated with the highest ranged
91   ///  key value.
getMaxElement()92   ImutAVLTree* getMaxElement() {
93     ImutAVLTree *T = this;
94     ImutAVLTree *Right = T->getRight();
95     while (Right) { T = Right; Right = T->getRight(); }
96     return T;
97   }
98 
99   /// size - Returns the number of nodes in the tree, which includes
100   ///  both leaves and non-leaf nodes.
size()101   unsigned size() const {
102     unsigned n = 1;
103     if (const ImutAVLTree* L = getLeft())
104       n += L->size();
105     if (const ImutAVLTree* R = getRight())
106       n += R->size();
107     return n;
108   }
109 
110   /// begin - Returns an iterator that iterates over the nodes of the tree
111   ///  in an inorder traversal.  The returned iterator thus refers to the
112   ///  the tree node with the minimum data element.
begin()113   iterator begin() const { return iterator(this); }
114 
115   /// end - Returns an iterator for the tree that denotes the end of an
116   ///  inorder traversal.
end()117   iterator end() const { return iterator(); }
118 
isElementEqual(value_type_ref V)119   bool isElementEqual(value_type_ref V) const {
120     // Compare the keys.
121     if (!ImutInfo::isEqual(ImutInfo::KeyOfValue(getValue()),
122                            ImutInfo::KeyOfValue(V)))
123       return false;
124 
125     // Also compare the data values.
126     if (!ImutInfo::isDataEqual(ImutInfo::DataOfValue(getValue()),
127                                ImutInfo::DataOfValue(V)))
128       return false;
129 
130     return true;
131   }
132 
isElementEqual(const ImutAVLTree * RHS)133   bool isElementEqual(const ImutAVLTree* RHS) const {
134     return isElementEqual(RHS->getValue());
135   }
136 
137   /// isEqual - Compares two trees for structural equality and returns true
138   ///   if they are equal.  This worst case performance of this operation is
139   //    linear in the sizes of the trees.
isEqual(const ImutAVLTree & RHS)140   bool isEqual(const ImutAVLTree& RHS) const {
141     if (&RHS == this)
142       return true;
143 
144     iterator LItr = begin(), LEnd = end();
145     iterator RItr = RHS.begin(), REnd = RHS.end();
146 
147     while (LItr != LEnd && RItr != REnd) {
148       if (&*LItr == &*RItr) {
149         LItr.skipSubTree();
150         RItr.skipSubTree();
151         continue;
152       }
153 
154       if (!LItr->isElementEqual(&*RItr))
155         return false;
156 
157       ++LItr;
158       ++RItr;
159     }
160 
161     return LItr == LEnd && RItr == REnd;
162   }
163 
164   /// isNotEqual - Compares two trees for structural inequality.  Performance
165   ///  is the same is isEqual.
isNotEqual(const ImutAVLTree & RHS)166   bool isNotEqual(const ImutAVLTree& RHS) const { return !isEqual(RHS); }
167 
168   /// contains - Returns true if this tree contains a subtree (node) that
169   ///  has an data element that matches the specified key.  Complexity
170   ///  is logarithmic in the size of the tree.
contains(key_type_ref K)171   bool contains(key_type_ref K) { return (bool) find(K); }
172 
173   /// validateTree - A utility method that checks that the balancing and
174   ///  ordering invariants of the tree are satisfied.  It is a recursive
175   ///  method that returns the height of the tree, which is then consumed
176   ///  by the enclosing validateTree call.  External callers should ignore the
177   ///  return value.  An invalid tree will cause an assertion to fire in
178   ///  a debug build.
validateTree()179   unsigned validateTree() const {
180     unsigned HL = getLeft() ? getLeft()->validateTree() : 0;
181     unsigned HR = getRight() ? getRight()->validateTree() : 0;
182     (void) HL;
183     (void) HR;
184 
185     assert(getHeight() == ( HL > HR ? HL : HR ) + 1
186             && "Height calculation wrong");
187 
188     assert((HL > HR ? HL-HR : HR-HL) <= 2
189            && "Balancing invariant violated");
190 
191     assert((!getLeft() ||
192             ImutInfo::isLess(ImutInfo::KeyOfValue(getLeft()->getValue()),
193                              ImutInfo::KeyOfValue(getValue()))) &&
194            "Value in left child is not less that current value");
195 
196     assert((!getRight() ||
197              ImutInfo::isLess(ImutInfo::KeyOfValue(getValue()),
198                               ImutInfo::KeyOfValue(getRight()->getValue()))) &&
199            "Current value is not less that value of right child");
200 
201     return getHeight();
202   }
203 
204   //===----------------------------------------------------===//
205   // Internal values.
206   //===----------------------------------------------------===//
207 
208 private:
209   Factory *factory;
210   ImutAVLTree *left;
211   ImutAVLTree *right;
212   ImutAVLTree *prev = nullptr;
213   ImutAVLTree *next = nullptr;
214 
215   unsigned height : 28;
216   bool IsMutable : 1;
217   bool IsDigestCached : 1;
218   bool IsCanonicalized : 1;
219 
220   value_type value;
221   uint32_t digest = 0;
222   uint32_t refCount = 0;
223 
224   //===----------------------------------------------------===//
225   // Internal methods (node manipulation; used by Factory).
226   //===----------------------------------------------------===//
227 
228 private:
229   /// ImutAVLTree - Internal constructor that is only called by
230   ///   ImutAVLFactory.
ImutAVLTree(Factory * f,ImutAVLTree * l,ImutAVLTree * r,value_type_ref v,unsigned height)231   ImutAVLTree(Factory *f, ImutAVLTree* l, ImutAVLTree* r, value_type_ref v,
232               unsigned height)
233     : factory(f), left(l), right(r), height(height), IsMutable(true),
234       IsDigestCached(false), IsCanonicalized(false), value(v)
235   {
236     if (left) left->retain();
237     if (right) right->retain();
238   }
239 
240   /// isMutable - Returns true if the left and right subtree references
241   ///  (as well as height) can be changed.  If this method returns false,
242   ///  the tree is truly immutable.  Trees returned from an ImutAVLFactory
243   ///  object should always have this method return true.  Further, if this
244   ///  method returns false for an instance of ImutAVLTree, all subtrees
245   ///  will also have this method return false.  The converse is not true.
isMutable()246   bool isMutable() const { return IsMutable; }
247 
248   /// hasCachedDigest - Returns true if the digest for this tree is cached.
249   ///  This can only be true if the tree is immutable.
hasCachedDigest()250   bool hasCachedDigest() const { return IsDigestCached; }
251 
252   //===----------------------------------------------------===//
253   // Mutating operations.  A tree root can be manipulated as
254   // long as its reference has not "escaped" from internal
255   // methods of a factory object (see below).  When a tree
256   // pointer is externally viewable by client code, the
257   // internal "mutable bit" is cleared to mark the tree
258   // immutable.  Note that a tree that still has its mutable
259   // bit set may have children (subtrees) that are themselves
260   // immutable.
261   //===----------------------------------------------------===//
262 
263   /// markImmutable - Clears the mutable flag for a tree.  After this happens,
264   ///   it is an error to call setLeft(), setRight(), and setHeight().
markImmutable()265   void markImmutable() {
266     assert(isMutable() && "Mutable flag already removed.");
267     IsMutable = false;
268   }
269 
270   /// markedCachedDigest - Clears the NoCachedDigest flag for a tree.
markedCachedDigest()271   void markedCachedDigest() {
272     assert(!hasCachedDigest() && "NoCachedDigest flag already removed.");
273     IsDigestCached = true;
274   }
275 
276   /// setHeight - Changes the height of the tree.  Used internally by
277   ///  ImutAVLFactory.
setHeight(unsigned h)278   void setHeight(unsigned h) {
279     assert(isMutable() && "Only a mutable tree can have its height changed.");
280     height = h;
281   }
282 
computeDigest(ImutAVLTree * L,ImutAVLTree * R,value_type_ref V)283   static uint32_t computeDigest(ImutAVLTree *L, ImutAVLTree *R,
284                                 value_type_ref V) {
285     uint32_t digest = 0;
286 
287     if (L)
288       digest += L->computeDigest();
289 
290     // Compute digest of stored data.
291     FoldingSetNodeID ID;
292     ImutInfo::Profile(ID,V);
293     digest += ID.ComputeHash();
294 
295     if (R)
296       digest += R->computeDigest();
297 
298     return digest;
299   }
300 
computeDigest()301   uint32_t computeDigest() {
302     // Check the lowest bit to determine if digest has actually been
303     // pre-computed.
304     if (hasCachedDigest())
305       return digest;
306 
307     uint32_t X = computeDigest(getLeft(), getRight(), getValue());
308     digest = X;
309     markedCachedDigest();
310     return X;
311   }
312 
313   //===----------------------------------------------------===//
314   // Reference count operations.
315   //===----------------------------------------------------===//
316 
317 public:
retain()318   void retain() { ++refCount; }
319 
release()320   void release() {
321     assert(refCount > 0);
322     if (--refCount == 0)
323       destroy();
324   }
325 
destroy()326   void destroy() {
327     if (left)
328       left->release();
329     if (right)
330       right->release();
331     if (IsCanonicalized) {
332       if (next)
333         next->prev = prev;
334 
335       if (prev)
336         prev->next = next;
337       else
338         factory->Cache[factory->maskCacheIndex(computeDigest())] = next;
339     }
340 
341     // We need to clear the mutability bit in case we are
342     // destroying the node as part of a sweep in ImutAVLFactory::recoverNodes().
343     IsMutable = false;
344     factory->freeNodes.push_back(this);
345   }
346 };
347 
348 template <typename ImutInfo>
349 struct IntrusiveRefCntPtrInfo<ImutAVLTree<ImutInfo>> {
350   static void retain(ImutAVLTree<ImutInfo> *Tree) { Tree->retain(); }
351   static void release(ImutAVLTree<ImutInfo> *Tree) { Tree->release(); }
352 };
353 
354 //===----------------------------------------------------------------------===//
355 // Immutable AVL-Tree Factory class.
356 //===----------------------------------------------------------------------===//
357 
358 template <typename ImutInfo >
359 class ImutAVLFactory {
360   friend class ImutAVLTree<ImutInfo>;
361 
362   using TreeTy = ImutAVLTree<ImutInfo>;
363   using value_type_ref = typename TreeTy::value_type_ref;
364   using key_type_ref = typename TreeTy::key_type_ref;
365   using CacheTy = DenseMap<unsigned, TreeTy*>;
366 
367   CacheTy Cache;
368   uintptr_t Allocator;
369   std::vector<TreeTy*> createdNodes;
370   std::vector<TreeTy*> freeNodes;
371 
372   bool ownsAllocator() const {
373     return (Allocator & 0x1) == 0;
374   }
375 
376   BumpPtrAllocator& getAllocator() const {
377     return *reinterpret_cast<BumpPtrAllocator*>(Allocator & ~0x1);
378   }
379 
380   //===--------------------------------------------------===//
381   // Public interface.
382   //===--------------------------------------------------===//
383 
384 public:
385   ImutAVLFactory()
386     : Allocator(reinterpret_cast<uintptr_t>(new BumpPtrAllocator())) {}
387 
388   ImutAVLFactory(BumpPtrAllocator& Alloc)
389     : Allocator(reinterpret_cast<uintptr_t>(&Alloc) | 0x1) {}
390 
391   ~ImutAVLFactory() {
392     if (ownsAllocator()) delete &getAllocator();
393   }
394 
395   TreeTy* add(TreeTy* T, value_type_ref V) {
396     T = add_internal(V,T);
397     markImmutable(T);
398     recoverNodes();
399     return T;
400   }
401 
402   TreeTy* remove(TreeTy* T, key_type_ref V) {
403     T = remove_internal(V,T);
404     markImmutable(T);
405     recoverNodes();
406     return T;
407   }
408 
409   TreeTy* getEmptyTree() const { return nullptr; }
410 
411 protected:
412   //===--------------------------------------------------===//
413   // A bunch of quick helper functions used for reasoning
414   // about the properties of trees and their children.
415   // These have succinct names so that the balancing code
416   // is as terse (and readable) as possible.
417   //===--------------------------------------------------===//
418 
419   bool            isEmpty(TreeTy* T) const { return !T; }
420   unsigned        getHeight(TreeTy* T) const { return T ? T->getHeight() : 0; }
421   TreeTy*         getLeft(TreeTy* T) const { return T->getLeft(); }
422   TreeTy*         getRight(TreeTy* T) const { return T->getRight(); }
423   value_type_ref  getValue(TreeTy* T) const { return T->value; }
424 
425   // Make sure the index is not the Tombstone or Entry key of the DenseMap.
426   static unsigned maskCacheIndex(unsigned I) { return (I & ~0x02); }
427 
428   unsigned incrementHeight(TreeTy* L, TreeTy* R) const {
429     unsigned hl = getHeight(L);
430     unsigned hr = getHeight(R);
431     return (hl > hr ? hl : hr) + 1;
432   }
433 
434   static bool compareTreeWithSection(TreeTy* T,
435                                      typename TreeTy::iterator& TI,
436                                      typename TreeTy::iterator& TE) {
437     typename TreeTy::iterator I = T->begin(), E = T->end();
438     for ( ; I!=E ; ++I, ++TI) {
439       if (TI == TE || !I->isElementEqual(&*TI))
440         return false;
441     }
442     return true;
443   }
444 
445   //===--------------------------------------------------===//
446   // "createNode" is used to generate new tree roots that link
447   // to other trees.  The function may also simply move links
448   // in an existing root if that root is still marked mutable.
449   // This is necessary because otherwise our balancing code
450   // would leak memory as it would create nodes that are
451   // then discarded later before the finished tree is
452   // returned to the caller.
453   //===--------------------------------------------------===//
454 
455   TreeTy* createNode(TreeTy* L, value_type_ref V, TreeTy* R) {
456     BumpPtrAllocator& A = getAllocator();
457     TreeTy* T;
458     if (!freeNodes.empty()) {
459       T = freeNodes.back();
460       freeNodes.pop_back();
461       assert(T != L);
462       assert(T != R);
463     } else {
464       T = (TreeTy*) A.Allocate<TreeTy>();
465     }
466     new (T) TreeTy(this, L, R, V, incrementHeight(L,R));
467     createdNodes.push_back(T);
468     return T;
469   }
470 
471   TreeTy* createNode(TreeTy* newLeft, TreeTy* oldTree, TreeTy* newRight) {
472     return createNode(newLeft, getValue(oldTree), newRight);
473   }
474 
475   void recoverNodes() {
476     for (unsigned i = 0, n = createdNodes.size(); i < n; ++i) {
477       TreeTy *N = createdNodes[i];
478       if (N->isMutable() && N->refCount == 0)
479         N->destroy();
480     }
481     createdNodes.clear();
482   }
483 
484   /// balanceTree - Used by add_internal and remove_internal to
485   ///  balance a newly created tree.
486   TreeTy* balanceTree(TreeTy* L, value_type_ref V, TreeTy* R) {
487     unsigned hl = getHeight(L);
488     unsigned hr = getHeight(R);
489 
490     if (hl > hr + 2) {
491       assert(!isEmpty(L) && "Left tree cannot be empty to have a height >= 2");
492 
493       TreeTy *LL = getLeft(L);
494       TreeTy *LR = getRight(L);
495 
496       if (getHeight(LL) >= getHeight(LR))
497         return createNode(LL, L, createNode(LR,V,R));
498 
499       assert(!isEmpty(LR) && "LR cannot be empty because it has a height >= 1");
500 
501       TreeTy *LRL = getLeft(LR);
502       TreeTy *LRR = getRight(LR);
503 
504       return createNode(createNode(LL,L,LRL), LR, createNode(LRR,V,R));
505     }
506 
507     if (hr > hl + 2) {
508       assert(!isEmpty(R) && "Right tree cannot be empty to have a height >= 2");
509 
510       TreeTy *RL = getLeft(R);
511       TreeTy *RR = getRight(R);
512 
513       if (getHeight(RR) >= getHeight(RL))
514         return createNode(createNode(L,V,RL), R, RR);
515 
516       assert(!isEmpty(RL) && "RL cannot be empty because it has a height >= 1");
517 
518       TreeTy *RLL = getLeft(RL);
519       TreeTy *RLR = getRight(RL);
520 
521       return createNode(createNode(L,V,RLL), RL, createNode(RLR,R,RR));
522     }
523 
524     return createNode(L,V,R);
525   }
526 
527   /// add_internal - Creates a new tree that includes the specified
528   ///  data and the data from the original tree.  If the original tree
529   ///  already contained the data item, the original tree is returned.
530   TreeTy* add_internal(value_type_ref V, TreeTy* T) {
531     if (isEmpty(T))
532       return createNode(T, V, T);
533     assert(!T->isMutable());
534 
535     key_type_ref K = ImutInfo::KeyOfValue(V);
536     key_type_ref KCurrent = ImutInfo::KeyOfValue(getValue(T));
537 
538     if (ImutInfo::isEqual(K,KCurrent))
539       return createNode(getLeft(T), V, getRight(T));
540     else if (ImutInfo::isLess(K,KCurrent))
541       return balanceTree(add_internal(V, getLeft(T)), getValue(T), getRight(T));
542     else
543       return balanceTree(getLeft(T), getValue(T), add_internal(V, getRight(T)));
544   }
545 
546   /// remove_internal - Creates a new tree that includes all the data
547   ///  from the original tree except the specified data.  If the
548   ///  specified data did not exist in the original tree, the original
549   ///  tree is returned.
550   TreeTy* remove_internal(key_type_ref K, TreeTy* T) {
551     if (isEmpty(T))
552       return T;
553 
554     assert(!T->isMutable());
555 
556     key_type_ref KCurrent = ImutInfo::KeyOfValue(getValue(T));
557 
558     if (ImutInfo::isEqual(K,KCurrent)) {
559       return combineTrees(getLeft(T), getRight(T));
560     } else if (ImutInfo::isLess(K,KCurrent)) {
561       return balanceTree(remove_internal(K, getLeft(T)),
562                                             getValue(T), getRight(T));
563     } else {
564       return balanceTree(getLeft(T), getValue(T),
565                          remove_internal(K, getRight(T)));
566     }
567   }
568 
569   TreeTy* combineTrees(TreeTy* L, TreeTy* R) {
570     if (isEmpty(L))
571       return R;
572     if (isEmpty(R))
573       return L;
574     TreeTy* OldNode;
575     TreeTy* newRight = removeMinBinding(R,OldNode);
576     return balanceTree(L, getValue(OldNode), newRight);
577   }
578 
579   TreeTy* removeMinBinding(TreeTy* T, TreeTy*& Noderemoved) {
580     assert(!isEmpty(T));
581     if (isEmpty(getLeft(T))) {
582       Noderemoved = T;
583       return getRight(T);
584     }
585     return balanceTree(removeMinBinding(getLeft(T), Noderemoved),
586                        getValue(T), getRight(T));
587   }
588 
589   /// markImmutable - Clears the mutable bits of a root and all of its
590   ///  descendants.
591   void markImmutable(TreeTy* T) {
592     if (!T || !T->isMutable())
593       return;
594     T->markImmutable();
595     markImmutable(getLeft(T));
596     markImmutable(getRight(T));
597   }
598 
599 public:
600   TreeTy *getCanonicalTree(TreeTy *TNew) {
601     if (!TNew)
602       return nullptr;
603 
604     if (TNew->IsCanonicalized)
605       return TNew;
606 
607     // Search the hashtable for another tree with the same digest, and
608     // if find a collision compare those trees by their contents.
609     unsigned digest = TNew->computeDigest();
610     TreeTy *&entry = Cache[maskCacheIndex(digest)];
611     do {
612       if (!entry)
613         break;
614       for (TreeTy *T = entry ; T != nullptr; T = T->next) {
615         // Compare the Contents('T') with Contents('TNew')
616         typename TreeTy::iterator TI = T->begin(), TE = T->end();
617         if (!compareTreeWithSection(TNew, TI, TE))
618           continue;
619         if (TI != TE)
620           continue; // T has more contents than TNew.
621         // Trees did match!  Return 'T'.
622         if (TNew->refCount == 0)
623           TNew->destroy();
624         return T;
625       }
626       entry->prev = TNew;
627       TNew->next = entry;
628     }
629     while (false);
630 
631     entry = TNew;
632     TNew->IsCanonicalized = true;
633     return TNew;
634   }
635 };
636 
637 //===----------------------------------------------------------------------===//
638 // Immutable AVL-Tree Iterators.
639 //===----------------------------------------------------------------------===//
640 
641 template <typename ImutInfo> class ImutAVLTreeGenericIterator {
642   SmallVector<uintptr_t,20> stack;
643 
644 public:
645   using iterator_category = std::bidirectional_iterator_tag;
646   using value_type = ImutAVLTree<ImutInfo>;
647   using difference_type = std::ptrdiff_t;
648   using pointer = value_type *;
649   using reference = value_type &;
650 
651   enum VisitFlag { VisitedNone=0x0, VisitedLeft=0x1, VisitedRight=0x3,
652                    Flags=0x3 };
653 
654   using TreeTy = ImutAVLTree<ImutInfo>;
655 
656   ImutAVLTreeGenericIterator() = default;
657   ImutAVLTreeGenericIterator(const TreeTy *Root) {
658     if (Root) stack.push_back(reinterpret_cast<uintptr_t>(Root));
659   }
660 
661   TreeTy &operator*() const {
662     assert(!stack.empty());
663     return *reinterpret_cast<TreeTy *>(stack.back() & ~Flags);
664   }
665   TreeTy *operator->() const { return &*this; }
666 
667   uintptr_t getVisitState() const {
668     assert(!stack.empty());
669     return stack.back() & Flags;
670   }
671 
672   bool atEnd() const { return stack.empty(); }
673 
674   bool atBeginning() const {
675     return stack.size() == 1 && getVisitState() == VisitedNone;
676   }
677 
678   void skipToParent() {
679     assert(!stack.empty());
680     stack.pop_back();
681     if (stack.empty())
682       return;
683     switch (getVisitState()) {
684       case VisitedNone:
685         stack.back() |= VisitedLeft;
686         break;
687       case VisitedLeft:
688         stack.back() |= VisitedRight;
689         break;
690       default:
691         llvm_unreachable("Unreachable.");
692     }
693   }
694 
695   bool operator==(const ImutAVLTreeGenericIterator &x) const {
696     return stack == x.stack;
697   }
698 
699   bool operator!=(const ImutAVLTreeGenericIterator &x) const {
700     return !(*this == x);
701   }
702 
703   ImutAVLTreeGenericIterator &operator++() {
704     assert(!stack.empty());
705     TreeTy* Current = reinterpret_cast<TreeTy*>(stack.back() & ~Flags);
706     assert(Current);
707     switch (getVisitState()) {
708       case VisitedNone:
709         if (TreeTy* L = Current->getLeft())
710           stack.push_back(reinterpret_cast<uintptr_t>(L));
711         else
712           stack.back() |= VisitedLeft;
713         break;
714       case VisitedLeft:
715         if (TreeTy* R = Current->getRight())
716           stack.push_back(reinterpret_cast<uintptr_t>(R));
717         else
718           stack.back() |= VisitedRight;
719         break;
720       case VisitedRight:
721         skipToParent();
722         break;
723       default:
724         llvm_unreachable("Unreachable.");
725     }
726     return *this;
727   }
728 
729   ImutAVLTreeGenericIterator &operator--() {
730     assert(!stack.empty());
731     TreeTy* Current = reinterpret_cast<TreeTy*>(stack.back() & ~Flags);
732     assert(Current);
733     switch (getVisitState()) {
734       case VisitedNone:
735         stack.pop_back();
736         break;
737       case VisitedLeft:
738         stack.back() &= ~Flags; // Set state to "VisitedNone."
739         if (TreeTy* L = Current->getLeft())
740           stack.push_back(reinterpret_cast<uintptr_t>(L) | VisitedRight);
741         break;
742       case VisitedRight:
743         stack.back() &= ~Flags;
744         stack.back() |= VisitedLeft;
745         if (TreeTy* R = Current->getRight())
746           stack.push_back(reinterpret_cast<uintptr_t>(R) | VisitedRight);
747         break;
748       default:
749         llvm_unreachable("Unreachable.");
750     }
751     return *this;
752   }
753 };
754 
755 template <typename ImutInfo> class ImutAVLTreeInOrderIterator {
756   using InternalIteratorTy = ImutAVLTreeGenericIterator<ImutInfo>;
757 
758   InternalIteratorTy InternalItr;
759 
760 public:
761   using iterator_category = std::bidirectional_iterator_tag;
762   using value_type = ImutAVLTree<ImutInfo>;
763   using difference_type = std::ptrdiff_t;
764   using pointer = value_type *;
765   using reference = value_type &;
766 
767   using TreeTy = ImutAVLTree<ImutInfo>;
768 
769   ImutAVLTreeInOrderIterator(const TreeTy* Root) : InternalItr(Root) {
770     if (Root)
771       ++*this; // Advance to first element.
772   }
773 
774   ImutAVLTreeInOrderIterator() : InternalItr() {}
775 
776   bool operator==(const ImutAVLTreeInOrderIterator &x) const {
777     return InternalItr == x.InternalItr;
778   }
779 
780   bool operator!=(const ImutAVLTreeInOrderIterator &x) const {
781     return !(*this == x);
782   }
783 
784   TreeTy &operator*() const { return *InternalItr; }
785   TreeTy *operator->() const { return &*InternalItr; }
786 
787   ImutAVLTreeInOrderIterator &operator++() {
788     do ++InternalItr;
789     while (!InternalItr.atEnd() &&
790            InternalItr.getVisitState() != InternalIteratorTy::VisitedLeft);
791 
792     return *this;
793   }
794 
795   ImutAVLTreeInOrderIterator &operator--() {
796     do --InternalItr;
797     while (!InternalItr.atBeginning() &&
798            InternalItr.getVisitState() != InternalIteratorTy::VisitedLeft);
799 
800     return *this;
801   }
802 
803   void skipSubTree() {
804     InternalItr.skipToParent();
805 
806     while (!InternalItr.atEnd() &&
807            InternalItr.getVisitState() != InternalIteratorTy::VisitedLeft)
808       ++InternalItr;
809   }
810 };
811 
812 /// Generic iterator that wraps a T::TreeTy::iterator and exposes
813 /// iterator::getValue() on dereference.
814 template <typename T>
815 struct ImutAVLValueIterator
816     : iterator_adaptor_base<
817           ImutAVLValueIterator<T>, typename T::TreeTy::iterator,
818           typename std::iterator_traits<
819               typename T::TreeTy::iterator>::iterator_category,
820           const typename T::value_type> {
821   ImutAVLValueIterator() = default;
822   explicit ImutAVLValueIterator(typename T::TreeTy *Tree)
823       : ImutAVLValueIterator::iterator_adaptor_base(Tree) {}
824 
825   typename ImutAVLValueIterator::reference operator*() const {
826     return this->I->getValue();
827   }
828 };
829 
830 //===----------------------------------------------------------------------===//
831 // Trait classes for Profile information.
832 //===----------------------------------------------------------------------===//
833 
834 /// Generic profile template.  The default behavior is to invoke the
835 /// profile method of an object.  Specializations for primitive integers
836 /// and generic handling of pointers is done below.
837 template <typename T>
838 struct ImutProfileInfo {
839   using value_type = const T;
840   using value_type_ref = const T&;
841 
842   static void Profile(FoldingSetNodeID &ID, value_type_ref X) {
843     FoldingSetTrait<T>::Profile(X,ID);
844   }
845 };
846 
847 /// Profile traits for integers.
848 template <typename T>
849 struct ImutProfileInteger {
850   using value_type = const T;
851   using value_type_ref = const T&;
852 
853   static void Profile(FoldingSetNodeID &ID, value_type_ref X) {
854     ID.AddInteger(X);
855   }
856 };
857 
858 #define PROFILE_INTEGER_INFO(X)\
859 template<> struct ImutProfileInfo<X> : ImutProfileInteger<X> {};
860 
861 PROFILE_INTEGER_INFO(char)
862 PROFILE_INTEGER_INFO(unsigned char)
863 PROFILE_INTEGER_INFO(short)
864 PROFILE_INTEGER_INFO(unsigned short)
865 PROFILE_INTEGER_INFO(unsigned)
866 PROFILE_INTEGER_INFO(signed)
867 PROFILE_INTEGER_INFO(long)
868 PROFILE_INTEGER_INFO(unsigned long)
869 PROFILE_INTEGER_INFO(long long)
870 PROFILE_INTEGER_INFO(unsigned long long)
871 
872 #undef PROFILE_INTEGER_INFO
873 
874 /// Profile traits for booleans.
875 template <>
876 struct ImutProfileInfo<bool> {
877   using value_type = const bool;
878   using value_type_ref = const bool&;
879 
880   static void Profile(FoldingSetNodeID &ID, value_type_ref X) {
881     ID.AddBoolean(X);
882   }
883 };
884 
885 /// Generic profile trait for pointer types.  We treat pointers as
886 /// references to unique objects.
887 template <typename T>
888 struct ImutProfileInfo<T*> {
889   using value_type = const T*;
890   using value_type_ref = value_type;
891 
892   static void Profile(FoldingSetNodeID &ID, value_type_ref X) {
893     ID.AddPointer(X);
894   }
895 };
896 
897 //===----------------------------------------------------------------------===//
898 // Trait classes that contain element comparison operators and type
899 //  definitions used by ImutAVLTree, ImmutableSet, and ImmutableMap.  These
900 //  inherit from the profile traits (ImutProfileInfo) to include operations
901 //  for element profiling.
902 //===----------------------------------------------------------------------===//
903 
904 /// ImutContainerInfo - Generic definition of comparison operations for
905 ///   elements of immutable containers that defaults to using
906 ///   std::equal_to<> and std::less<> to perform comparison of elements.
907 template <typename T>
908 struct ImutContainerInfo : public ImutProfileInfo<T> {
909   using value_type = typename ImutProfileInfo<T>::value_type;
910   using value_type_ref = typename ImutProfileInfo<T>::value_type_ref;
911   using key_type = value_type;
912   using key_type_ref = value_type_ref;
913   using data_type = bool;
914   using data_type_ref = bool;
915 
916   static key_type_ref KeyOfValue(value_type_ref D) { return D; }
917   static data_type_ref DataOfValue(value_type_ref) { return true; }
918 
919   static bool isEqual(key_type_ref LHS, key_type_ref RHS) {
920     return std::equal_to<key_type>()(LHS,RHS);
921   }
922 
923   static bool isLess(key_type_ref LHS, key_type_ref RHS) {
924     return std::less<key_type>()(LHS,RHS);
925   }
926 
927   static bool isDataEqual(data_type_ref, data_type_ref) { return true; }
928 };
929 
930 /// ImutContainerInfo - Specialization for pointer values to treat pointers
931 ///  as references to unique objects.  Pointers are thus compared by
932 ///  their addresses.
933 template <typename T>
934 struct ImutContainerInfo<T*> : public ImutProfileInfo<T*> {
935   using value_type = typename ImutProfileInfo<T*>::value_type;
936   using value_type_ref = typename ImutProfileInfo<T*>::value_type_ref;
937   using key_type = value_type;
938   using key_type_ref = value_type_ref;
939   using data_type = bool;
940   using data_type_ref = bool;
941 
942   static key_type_ref KeyOfValue(value_type_ref D) { return D; }
943   static data_type_ref DataOfValue(value_type_ref) { return true; }
944 
945   static bool isEqual(key_type_ref LHS, key_type_ref RHS) { return LHS == RHS; }
946 
947   static bool isLess(key_type_ref LHS, key_type_ref RHS) { return LHS < RHS; }
948 
949   static bool isDataEqual(data_type_ref, data_type_ref) { return true; }
950 };
951 
952 //===----------------------------------------------------------------------===//
953 // Immutable Set
954 //===----------------------------------------------------------------------===//
955 
956 template <typename ValT, typename ValInfo = ImutContainerInfo<ValT>>
957 class ImmutableSet {
958 public:
959   using value_type = typename ValInfo::value_type;
960   using value_type_ref = typename ValInfo::value_type_ref;
961   using TreeTy = ImutAVLTree<ValInfo>;
962 
963 private:
964   IntrusiveRefCntPtr<TreeTy> Root;
965 
966 public:
967   /// Constructs a set from a pointer to a tree root.  In general one
968   /// should use a Factory object to create sets instead of directly
969   /// invoking the constructor, but there are cases where make this
970   /// constructor public is useful.
971   explicit ImmutableSet(TreeTy *R) : Root(R) {}
972 
973   class Factory {
974     typename TreeTy::Factory F;
975     const bool Canonicalize;
976 
977   public:
978     Factory(bool canonicalize = true)
979       : Canonicalize(canonicalize) {}
980 
981     Factory(BumpPtrAllocator& Alloc, bool canonicalize = true)
982       : F(Alloc), Canonicalize(canonicalize) {}
983 
984     Factory(const Factory& RHS) = delete;
985     void operator=(const Factory& RHS) = delete;
986 
987     /// getEmptySet - Returns an immutable set that contains no elements.
988     ImmutableSet getEmptySet() {
989       return ImmutableSet(F.getEmptyTree());
990     }
991 
992     /// add - Creates a new immutable set that contains all of the values
993     ///  of the original set with the addition of the specified value.  If
994     ///  the original set already included the value, then the original set is
995     ///  returned and no memory is allocated.  The time and space complexity
996     ///  of this operation is logarithmic in the size of the original set.
997     ///  The memory allocated to represent the set is released when the
998     ///  factory object that created the set is destroyed.
999     [[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
1172