LLVM 23.0.0git
ImmutableSet.h
Go to the documentation of this file.
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"
20#include "llvm/ADT/STLExtras.h"
22#include "llvm/ADT/iterator.h"
25#include "llvm/Support/Debug.h"
28#include <cassert>
29#include <cstdint>
30#include <functional>
31#include <iterator>
32#include <new>
33#include <vector>
34
35namespace llvm {
36
37//===----------------------------------------------------------------------===//
38// Immutable AVL-Tree Definition.
39//===----------------------------------------------------------------------===//
40
41template <typename ImutInfo> class ImutAVLFactory;
42template <typename ImutInfo> class ImutIntervalAVLFactory;
43template <typename ImutInfo> class ImutAVLTreeInOrderIterator;
44
45template <typename ImutInfo >
46class ImutAVLTree {
47public:
48 using key_type_ref = typename ImutInfo::key_type_ref;
49 using value_type = typename ImutInfo::value_type;
50 using value_type_ref = typename ImutInfo::value_type_ref;
53
54 friend class ImutAVLFactory<ImutInfo>;
55 friend class ImutIntervalAVLFactory<ImutInfo>;
56
57 //===----------------------------------------------------===//
58 // Public Interface.
59 //===----------------------------------------------------===//
60
61 /// Return a pointer to the left subtree. This value
62 /// is NULL if there is no left subtree.
63 ImutAVLTree *getLeft() const { return left; }
64
65 /// Return a pointer to the right subtree. This value is
66 /// NULL if there is no right subtree.
67 ImutAVLTree *getRight() const { return right; }
68
69 /// Returns the height of the tree. A tree with no subtrees has a height of 1.
70 unsigned getHeight() const { return height; }
71
72 /// Returns the data value associated with the tree node.
73 const value_type& getValue() const { return value; }
74
75 /// Finds the subtree associated with the specified key value. This method
76 /// returns NULL if no matching subtree is found.
77 ImutAVLTree* find(key_type_ref K) {
78 ImutAVLTree *T = this;
79 while (T) {
80 key_type_ref CurrentKey = ImutInfo::KeyOfValue(T->getValue());
81 if (ImutInfo::isEqual(K,CurrentKey))
82 return T;
83 else if (ImutInfo::isLess(K,CurrentKey))
84 T = T->getLeft();
85 else
86 T = T->getRight();
87 }
88 return nullptr;
89 }
90
91 /// Find the subtree associated with the highest ranged key value.
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 /// Returns the number of nodes in the tree, which includes both leaves and
100 // non-leaf nodes.
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 /// Returns an iterator that iterates over the nodes of the tree in an inorder
111 /// traversal. The returned iterator thus refers to the tree node with the
112 /// minimum data element.
113 iterator begin() const { return iterator(this); }
114
115 /// Returns an iterator for the tree that denotes the end of an inorder
116 /// traversal.
117 iterator end() const { return iterator(); }
118
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
133 bool isElementEqual(const ImutAVLTree* RHS) const {
134 return isElementEqual(RHS->getValue());
135 }
136
137 /// Compares two trees for structural equality and returns true if they are
138 /// equal. The worst case performance of this operation is linear in the sizes
139 /// of the trees.
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 /// Compares two trees for structural inequality. Performance is the same as
165 /// isEqual.
166 bool isNotEqual(const ImutAVLTree& RHS) const { return !isEqual(RHS); }
167
168 /// Returns true if this tree contains a subtree (node) that has an data
169 /// element that matches the specified key. Complexity is logarithmic in the
170 /// size of the tree.
171 bool contains(key_type_ref K) { return (bool) find(K); }
172
173 /// A utility method that checks that the balancing and ordering invariants of
174 /// the tree are satisfied. It is a recursive method that returns the height
175 /// of the tree, which is then consumed by the enclosing validateTree call.
176 /// External callers should ignore the return value. An invalid tree will
177 /// cause an assertion to fire in a debug build.
178 unsigned validateTree() const {
179 unsigned HL = getLeft() ? getLeft()->validateTree() : 0;
180 unsigned HR = getRight() ? getRight()->validateTree() : 0;
181 (void) HL;
182 (void) HR;
183
184 assert(getHeight() == ( HL > HR ? HL : HR ) + 1
185 && "Height calculation wrong");
186
187 assert((HL > HR ? HL-HR : HR-HL) <= 2
188 && "Balancing invariant violated");
189
190 assert((!getLeft() ||
191 ImutInfo::isLess(ImutInfo::KeyOfValue(getLeft()->getValue()),
192 ImutInfo::KeyOfValue(getValue()))) &&
193 "Value in left child is not less that current value");
194
195 assert((!getRight() ||
196 ImutInfo::isLess(ImutInfo::KeyOfValue(getValue()),
197 ImutInfo::KeyOfValue(getRight()->getValue()))) &&
198 "Current value is not less that value of right child");
199
200 return getHeight();
201 }
202
203 //===----------------------------------------------------===//
204 // Internal values.
205 //===----------------------------------------------------===//
206
207private:
208 Factory *factory;
209 ImutAVLTree *left;
210 ImutAVLTree *right;
211 ImutAVLTree *prev = nullptr;
212 ImutAVLTree *next = nullptr;
213
214 unsigned height : 28;
216 unsigned IsMutable : 1;
218 unsigned IsDigestCached : 1;
220 unsigned IsCanonicalized : 1;
221
222 value_type value;
223 uint32_t digest = 0;
224 uint32_t refCount = 0;
225
226 //===----------------------------------------------------===//
227 // Internal methods (node manipulation; used by Factory).
228 //===----------------------------------------------------===//
229
230private:
231 /// Internal constructor that is only called by ImutAVLFactory.
233 unsigned height)
234 : factory(f), left(l), right(r), height(height), IsMutable(true),
235 IsDigestCached(false), IsCanonicalized(false), value(v)
236 {
237 if (left) left->retain();
238 if (right) right->retain();
239 }
240
241 /// Returns true if the left and right subtree references
242 /// (as well as height) can be changed. If this method returns false,
243 /// the tree is truly immutable. Trees returned from an ImutAVLFactory
244 /// object should always have this method return true. Further, if this
245 /// method returns false for an instance of ImutAVLTree, all subtrees
246 /// will also have this method return false. The converse is not true.
247 bool isMutable() const { return IsMutable; }
248
249 /// Returns true if the digest for this tree is cached. This can only be true
250 /// if the tree is immutable.
251 bool hasCachedDigest() const { return IsDigestCached; }
252
253 //===----------------------------------------------------===//
254 // Mutating operations. A tree root can be manipulated as
255 // long as its reference has not "escaped" from internal
256 // methods of a factory object (see below). When a tree
257 // pointer is externally viewable by client code, the
258 // internal "mutable bit" is cleared to mark the tree
259 // immutable. Note that a tree that still has its mutable
260 // bit set may have children (subtrees) that are themselves
261 // immutable.
262 //===----------------------------------------------------===//
263
264 /// Clears the mutable flag for a tree. After this happens,
265 /// it is an error to call setLeft(), setRight(), and setHeight().
266 void markImmutable() {
267 assert(isMutable() && "Mutable flag already removed.");
268 IsMutable = false;
269 }
270
271 /// Clears the NoCachedDigest flag for a tree.
272 void markedCachedDigest() {
273 assert(!hasCachedDigest() && "NoCachedDigest flag already removed.");
274 IsDigestCached = true;
275 }
276
277 /// Changes the height of the tree. Used internally by ImutAVLFactory.
278 void setHeight(unsigned h) {
279 assert(isMutable() && "Only a mutable tree can have its height changed.");
280 height = h;
281 }
282
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
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
317public:
318 void retain() { ++refCount; }
319
320 void release() {
321 assert(refCount > 0);
322 if (--refCount == 0)
323 destroy();
324 }
325
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
348template <typename 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
358template <typename ImutInfo >
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
384public:
386 : Allocator(reinterpret_cast<uintptr_t>(new BumpPtrAllocator())) {}
387
389 : Allocator(reinterpret_cast<uintptr_t>(&Alloc) | 0x1) {}
390
392 if (ownsAllocator()) delete &getAllocator();
393 }
394
395 TreeTy* add(TreeTy* T, value_type_ref V) {
396 T = add_internal(V,T);
398 return T;
399 }
400
401 TreeTy* remove(TreeTy* T, key_type_ref V) {
402 T = remove_internal(V,T);
404 return T;
405 }
406
407 TreeTy* getEmptyTree() const { return nullptr; }
408
409protected:
410 //===--------------------------------------------------===//
411 // A bunch of quick helper functions used for reasoning
412 // about the properties of trees and their children.
413 // These have succinct names so that the balancing code
414 // is as terse (and readable) as possible.
415 //===--------------------------------------------------===//
416
417 bool isEmpty(TreeTy* T) const { return !T; }
418 unsigned getHeight(TreeTy* T) const { return T ? T->getHeight() : 0; }
419 TreeTy* getLeft(TreeTy* T) const { return T->getLeft(); }
420 TreeTy* getRight(TreeTy* T) const { return T->getRight(); }
421 value_type_ref getValue(TreeTy* T) const { return T->value; }
422
423 // Make sure the index is not the Tombstone or Entry key of the DenseMap.
424 static unsigned maskCacheIndex(unsigned I) { return (I & ~0x02); }
425
426 unsigned incrementHeight(TreeTy* L, TreeTy* R) const {
427 unsigned hl = getHeight(L);
428 unsigned hr = getHeight(R);
429 return (hl > hr ? hl : hr) + 1;
430 }
431
432 //===--------------------------------------------------===//
433 // "createNode" is used to generate new tree roots that link
434 // to other trees. The function may also simply move links
435 // in an existing root if that root is still marked mutable.
436 // This is necessary because otherwise our balancing code
437 // would leak memory as it would create nodes that are
438 // then discarded later before the finished tree is
439 // returned to the caller.
440 //===--------------------------------------------------===//
441
442 TreeTy* createNode(TreeTy* L, value_type_ref V, TreeTy* R) {
443 BumpPtrAllocator& A = getAllocator();
444 TreeTy* T;
445 if (!freeNodes.empty()) {
446 T = freeNodes.back();
447 freeNodes.pop_back();
448 assert(T != L);
449 assert(T != R);
450 } else {
451 T = (TreeTy*) A.Allocate<TreeTy>();
452 }
453 new (T) TreeTy(this, L, R, V, incrementHeight(L,R));
454 createdNodes.push_back(T);
455 return T;
456 }
457
458 TreeTy* createNode(TreeTy* newLeft, TreeTy* oldTree, TreeTy* newRight) {
459 return createNode(newLeft, getValue(oldTree), newRight);
460 }
461
462 void recoverNodes(TreeTy *Result) {
463 // Mark Result's nodes immutable and reclaim the intermediates discarded
464 // during balancing, in one pass. Nodes are built bottom-up, so a node
465 // precedes its parents in createdNodes; visiting in reverse thus reaches
466 // each node only once its reference count is final. Unreferenced nodes are
467 // unreachable and destroyed; the rest belong to Result. Result is kept
468 // despite its zero count -- the caller has not taken ownership yet.
469 for (TreeTy *N : llvm::reverse(createdNodes)) {
470 if (!N->isMutable())
471 continue; // Already reclaimed while destroying an unreachable parent.
472 if (N != Result && N->refCount == 0)
473 N->destroy();
474 else
475 N->markImmutable();
476 }
477 createdNodes.clear();
478 }
479
480 /// Used by add_internal and remove_internal to balance a newly created tree.
481 TreeTy* balanceTree(TreeTy* L, value_type_ref V, TreeTy* R) {
482 unsigned hl = getHeight(L);
483 unsigned hr = getHeight(R);
484
485 if (hl > hr + 2) {
486 assert(!isEmpty(L) && "Left tree cannot be empty to have a height >= 2");
487
488 TreeTy *LL = getLeft(L);
489 TreeTy *LR = getRight(L);
490
491 if (getHeight(LL) >= getHeight(LR))
492 return createNode(LL, L, createNode(LR,V,R));
493
494 assert(!isEmpty(LR) && "LR cannot be empty because it has a height >= 1");
495
496 TreeTy *LRL = getLeft(LR);
497 TreeTy *LRR = getRight(LR);
498
499 return createNode(createNode(LL,L,LRL), LR, createNode(LRR,V,R));
500 }
501
502 if (hr > hl + 2) {
503 assert(!isEmpty(R) && "Right tree cannot be empty to have a height >= 2");
504
505 TreeTy *RL = getLeft(R);
506 TreeTy *RR = getRight(R);
507
508 if (getHeight(RR) >= getHeight(RL))
509 return createNode(createNode(L,V,RL), R, RR);
510
511 assert(!isEmpty(RL) && "RL cannot be empty because it has a height >= 1");
512
513 TreeTy *RLL = getLeft(RL);
514 TreeTy *RLR = getRight(RL);
515
516 return createNode(createNode(L,V,RLL), RL, createNode(RLR,R,RR));
517 }
518
519 return createNode(L,V,R);
520 }
521
522 /// add_internal - Creates a new tree that includes the specified
523 /// data and the data from the original tree. If the original tree
524 /// already contained the data item, the original tree is returned.
525 TreeTy *add_internal(value_type_ref V, TreeTy *T) {
526 if (isEmpty(T))
527 return createNode(T, V, T);
528 assert(!T->isMutable());
529
530 key_type_ref K = ImutInfo::KeyOfValue(V);
531 key_type_ref KCurrent = ImutInfo::KeyOfValue(getValue(T));
532
533 if (ImutInfo::isEqual(K, KCurrent)) {
534 // If both key and value are same, return the original tree.
535 if (ImutInfo::isDataEqual(ImutInfo::DataOfValue(V),
536 ImutInfo::DataOfValue(getValue(T))))
537 return T;
538 // Otherwise create a new node with the new value.
539 return createNode(getLeft(T), V, getRight(T));
540 }
541
542 TreeTy *NewL = getLeft(T);
543 TreeTy *NewR = getRight(T);
544 if (ImutInfo::isLess(K, KCurrent))
545 NewL = add_internal(V, NewL);
546 else
547 NewR = add_internal(V, NewR);
548
549 // If no changes were made, return the original tree. Otherwise, balance the
550 // tree and return the new root.
551 return NewL == getLeft(T) && NewR == getRight(T)
552 ? T
553 : balanceTree(NewL, getValue(T), NewR);
554 }
555
556 /// remove_internal - Creates a new tree that includes all the data
557 /// from the original tree except the specified data. If the
558 /// specified data did not exist in the original tree, the original
559 /// tree is returned.
560 TreeTy *remove_internal(key_type_ref K, TreeTy *T) {
561 if (isEmpty(T))
562 return T;
563
564 assert(!T->isMutable());
565
566 key_type_ref KCurrent = ImutInfo::KeyOfValue(getValue(T));
567
568 if (ImutInfo::isEqual(K, KCurrent))
569 return combineTrees(getLeft(T), getRight(T));
570
571 TreeTy *NewL = getLeft(T);
572 TreeTy *NewR = getRight(T);
573 if (ImutInfo::isLess(K, KCurrent))
574 NewL = remove_internal(K, NewL);
575 else
576 NewR = remove_internal(K, NewR);
577
578 // If no changes were made, return the original tree. Otherwise, balance the
579 // tree and return the new root.
580 return NewL == getLeft(T) && NewR == getRight(T)
581 ? T
582 : balanceTree(NewL, getValue(T), NewR);
583 }
584
585 TreeTy* combineTrees(TreeTy* L, TreeTy* R) {
586 if (isEmpty(L))
587 return R;
588 if (isEmpty(R))
589 return L;
590 TreeTy* OldNode;
591 TreeTy* newRight = removeMinBinding(R,OldNode);
592 return balanceTree(L, getValue(OldNode), newRight);
593 }
594
595 TreeTy* removeMinBinding(TreeTy* T, TreeTy*& Noderemoved) {
596 assert(!isEmpty(T));
597 if (isEmpty(getLeft(T))) {
598 Noderemoved = T;
599 return getRight(T);
600 }
601 return balanceTree(removeMinBinding(getLeft(T), Noderemoved),
602 getValue(T), getRight(T));
603 }
604
605public:
606 TreeTy *getCanonicalTree(TreeTy *TNew) {
607 if (!TNew)
608 return nullptr;
609
610 if (TNew->IsCanonicalized)
611 return TNew;
612
613 // Search the hashtable for another tree with the same digest, and
614 // if find a collision compare those trees by their contents.
615 unsigned digest = TNew->computeDigest();
616 TreeTy *&entry = Cache[maskCacheIndex(digest)];
617 if (entry) {
618 for (TreeTy *T = entry ; T != nullptr; T = T->next) {
619 // Compare the contents of 'T' with 'TNew'. isEqual skips subtrees that
620 // are shared by pointer, so for structurally-shared persistent trees
621 // (the common case, e.g. one derived from the other) this is linear in
622 // the number of differing nodes rather than in the tree size.
623 if (!TNew->isEqual(*T))
624 continue;
625 // Trees did match! Return 'T'.
626 if (TNew->refCount == 0)
627 TNew->destroy();
628 return T;
629 }
630 entry->prev = TNew;
631 TNew->next = entry;
632 }
633
634 entry = TNew;
635 TNew->IsCanonicalized = true;
636 return TNew;
637 }
638};
639
640//===----------------------------------------------------------------------===//
641// Immutable AVL-Tree Iterator.
642//===----------------------------------------------------------------------===//
643
644/// Bidirectional in-order iterator over the nodes of an ImutAVLTree.
645///
646/// The iterator keeps the chain of ancestors from the root down to the current
647/// node on an explicit stack of plain node pointers, and decides which way to
648/// move next by inspecting whether it is ascending from a node's left or right
649/// child. This avoids storing any per-node visit-state: there is no need to
650/// remember "have I already visited this node's left/right subtree", because
651/// that is recovered by comparing the child we just left against the parent's
652/// left and right pointers.
653///
654/// A node's parent cannot be cached in the node itself, because these trees are
655/// persistent and structurally shared: a single node may appear as the child of
656/// different parents across different tree versions. The ancestor stack is
657/// therefore the per-traversal parent chain.
658template <typename ImutInfo> class ImutAVLTreeInOrderIterator {
659public:
660 using iterator_category = std::bidirectional_iterator_tag;
662 using difference_type = std::ptrdiff_t;
665
667
668private:
669 // Path[0] is the root and Path.back() is the current node. An empty path is
670 // the end iterator. The invariant is that Path always holds the exact chain
671 // of ancestors of the current node, root-most first.
673
674 // Descend along left children, pushing each node; lands on the minimum of the
675 // subtree rooted at T (i.e. the first node in an in-order traversal of T).
676 void descendToMin(TreeTy *T) {
677 for (; T; T = T->getLeft())
678 Path.push_back(T);
679 }
680
681 // Descend along right children, pushing each node; lands on the maximum of
682 // the subtree rooted at T (i.e. the last node in an in-order traversal of T).
683 void descendToMax(TreeTy *T) {
684 for (; T; T = T->getRight())
685 Path.push_back(T);
686 }
687
688 // Pop the current node and ascend until we reach an ancestor from its *left*
689 // child, i.e. the first ancestor whose subtree is not yet fully visited. That
690 // ancestor is the in-order successor of the subtree we just left; if there is
691 // none, Path is emptied (the end iterator). Shared by operator++ and
692 // skipSubTree, whose only difference is whether the current node's right
693 // subtree is descended into first.
694 void ascendFromRightChild() {
695 TreeTy *Child = Path.pop_back_val();
696 while (!Path.empty() && Path.back()->getRight() == Child)
697 Child = Path.pop_back_val();
698 }
699
700 // Mirror of ascendFromRightChild for reverse traversal (operator--).
701 void ascendFromLeftChild() {
702 TreeTy *Child = Path.pop_back_val();
703 while (!Path.empty() && Path.back()->getLeft() == Child)
704 Child = Path.pop_back_val();
705 }
706
707public:
708 ImutAVLTreeInOrderIterator() = default; // end() iterator.
710 descendToMin(const_cast<TreeTy *>(Root));
711 }
712
713 // Two iterators are equal iff they sit on the same node (or are both end()).
714 // Within a single tree a node has a unique root-to-node path, so the current
715 // node alone identifies the position; comparing the whole path is therefore
716 // unnecessary. Comparing iterators from different trees is not meaningful, as
717 // for any standard container.
719 if (Path.empty() || x.Path.empty())
720 return Path.empty() == x.Path.empty();
721 return Path.back() == x.Path.back();
722 }
724 return !(*this == x);
725 }
726
727 TreeTy &operator*() const { return *Path.back(); }
728 TreeTy *operator->() const { return Path.back(); }
729
731 assert(!Path.empty() && "Incrementing the end iterator");
732 if (TreeTy *R = Path.back()->getRight())
733 // The in-order successor is the minimum of the right subtree.
734 descendToMin(R);
735 else
736 // No right subtree: the successor is the nearest ancestor reached from a
737 // left child.
738 ascendFromRightChild();
739 return *this;
740 }
741
743 assert(!Path.empty() && "Decrementing the end iterator");
744 if (TreeTy *L = Path.back()->getLeft())
745 // The in-order predecessor is the maximum of the left subtree.
746 descendToMax(L);
747 else
748 // Mirror of operator++.
749 ascendFromLeftChild();
750 return *this;
751 }
752
753 /// Move to the in-order successor of the entire subtree rooted at the current
754 /// node, i.e. skip the current node together with its right subtree. This is
755 /// exactly the ascent half of operator++.
756 void skipSubTree() {
757 assert(!Path.empty() && "Skipping past the end iterator");
758 ascendFromRightChild();
759 }
760};
761
762/// Generic iterator that wraps a T::TreeTy::iterator and exposes
763/// iterator::getValue() on dereference.
764template <typename T>
767 ImutAVLValueIterator<T>, typename T::TreeTy::iterator,
768 typename std::iterator_traits<
769 typename T::TreeTy::iterator>::iterator_category,
770 const typename T::value_type> {
774
776 return this->I->getValue();
777 }
778};
779
780//===----------------------------------------------------------------------===//
781// Trait classes for Profile information.
782//===----------------------------------------------------------------------===//
783
784/// Generic profile template. The default behavior is to invoke the
785/// profile method of an object. Specializations for primitive integers
786/// and generic handling of pointers is done below.
787template <typename T>
789 using value_type = const T;
790 using value_type_ref = const T&;
791
795};
796
797/// Profile traits for integers.
798template <typename T>
800 using value_type = const T;
801 using value_type_ref = const T&;
802
804 ID.AddInteger(X);
805 }
806};
807
808#define PROFILE_INTEGER_INFO(X)\
809template<> struct ImutProfileInfo<X> : ImutProfileInteger<X> {};
810
812PROFILE_INTEGER_INFO(unsigned char)
814PROFILE_INTEGER_INFO(unsigned short)
815PROFILE_INTEGER_INFO(unsigned)
818PROFILE_INTEGER_INFO(unsigned long)
819PROFILE_INTEGER_INFO(long long)
820PROFILE_INTEGER_INFO(unsigned long long)
821
822#undef PROFILE_INTEGER_INFO
823
824/// Profile traits for booleans.
825template <>
827 using value_type = const bool;
828 using value_type_ref = const bool&;
829
831 ID.AddBoolean(X);
832 }
833};
834
835/// Generic profile trait for pointer types. We treat pointers as
836/// references to unique objects.
837template <typename T>
839 using value_type = const T*;
841
843 ID.AddPointer(X);
844 }
845};
846
847//===----------------------------------------------------------------------===//
848// Trait classes that contain element comparison operators and type
849// definitions used by ImutAVLTree, ImmutableSet, and ImmutableMap. These
850// inherit from the profile traits (ImutProfileInfo) to include operations
851// for element profiling.
852//===----------------------------------------------------------------------===//
853
854/// Generic definition of comparison operations for elements of immutable
855/// containers that defaults to using std::equal_to<> and std::less<> to perform
856/// comparison of elements.
857template <typename T> struct ImutContainerInfo : ImutProfileInfo<T> {
864
866 static data_type_ref DataOfValue(value_type_ref) { return true; }
867
869 return std::equal_to<key_type>()(LHS,RHS);
870 }
871
873 return std::less<key_type>()(LHS,RHS);
874 }
875
876 static bool isDataEqual(data_type_ref, data_type_ref) { return true; }
877};
878
879/// Specialization for pointer values to treat pointers as references to unique
880/// objects. Pointers are thus compared by their addresses.
881template <typename T> struct ImutContainerInfo<T *> : ImutProfileInfo<T *> {
888
890 static data_type_ref DataOfValue(value_type_ref) { return true; }
891
892 static bool isEqual(key_type_ref LHS, key_type_ref RHS) { return LHS == RHS; }
893
894 static bool isLess(key_type_ref LHS, key_type_ref RHS) { return LHS < RHS; }
895
896 static bool isDataEqual(data_type_ref, data_type_ref) { return true; }
897};
898
899//===----------------------------------------------------------------------===//
900// Immutable Set
901//===----------------------------------------------------------------------===//
902
903template <typename ValT, typename ValInfo = ImutContainerInfo<ValT>>
905public:
906 using value_type = typename ValInfo::value_type;
907 using value_type_ref = typename ValInfo::value_type_ref;
909
910private:
912
913public:
914 /// Constructs a set from a pointer to a tree root. In general one
915 /// should use a Factory object to create sets instead of directly
916 /// invoking the constructor, but there are cases where make this
917 /// constructor public is useful.
918 explicit ImmutableSet(TreeTy *R) : Root(R) {}
919
920 class Factory {
921 typename TreeTy::Factory F;
922 const bool Canonicalize;
923
924 public:
925 Factory(bool canonicalize = true)
926 : Canonicalize(canonicalize) {}
927
928 Factory(BumpPtrAllocator& Alloc, bool canonicalize = true)
929 : F(Alloc), Canonicalize(canonicalize) {}
930
931 Factory(const Factory& RHS) = delete;
932 void operator=(const Factory& RHS) = delete;
933
934 /// Returns an immutable set that contains no elements.
936 return ImmutableSet(F.getEmptyTree());
937 }
938
939 /// Creates a new immutable set that contains all of the values
940 /// of the original set with the addition of the specified value. If
941 /// the original set already included the value, then the original set is
942 /// returned and no memory is allocated. The time and space complexity
943 /// of this operation is logarithmic in the size of the original set.
944 /// The memory allocated to represent the set is released when the
945 /// factory object that created the set is destroyed.
947 TreeTy *NewT = F.add(Old.Root.get(), V);
948 return ImmutableSet(Canonicalize ? F.getCanonicalTree(NewT) : NewT);
949 }
950
951 /// Creates a new immutable set that contains all of the values
952 /// of the original set with the exception of the specified value. If
953 /// the original set did not contain the value, the original set is
954 /// returned and no memory is allocated. The time and space complexity
955 /// of this operation is logarithmic in the size of the original set.
956 /// The memory allocated to represent the set is released when the
957 /// factory object that created the set is destroyed.
959 TreeTy *NewT = F.remove(Old.Root.get(), V);
960 return ImmutableSet(Canonicalize ? F.getCanonicalTree(NewT) : NewT);
961 }
962
963 BumpPtrAllocator& getAllocator() { return F.getAllocator(); }
964
965 typename TreeTy::Factory *getTreeFactory() const {
966 return const_cast<typename TreeTy::Factory *>(&F);
967 }
968 };
969
970 friend class Factory;
971
972 /// Returns true if the set contains the specified value.
973 bool contains(value_type_ref V) const {
974 return Root ? Root->contains(V) : false;
975 }
976
977 bool operator==(const ImmutableSet &RHS) const {
978 return Root && RHS.Root ? Root->isEqual(*RHS.Root.get()) : Root == RHS.Root;
979 }
980
981 bool operator!=(const ImmutableSet &RHS) const {
982 return Root && RHS.Root ? Root->isNotEqual(*RHS.Root.get())
983 : Root != RHS.Root;
984 }
985
987 if (Root) { Root->retain(); }
988 return Root.get();
989 }
990
991 TreeTy *getRootWithoutRetain() const { return Root.get(); }
992
993 /// Return true if the set contains no elements.
994 bool isEmpty() const { return !Root; }
995
996 /// Return true if the set contains exactly one element.
997 /// This method runs in constant time.
998 bool isSingleton() const { return getHeight() == 1; }
999
1000 //===--------------------------------------------------===//
1001 // Iterators.
1002 //===--------------------------------------------------===//
1003
1005
1006 iterator begin() const { return iterator(Root.get()); }
1007 iterator end() const { return iterator(); }
1008
1009 //===--------------------------------------------------===//
1010 // Utility methods.
1011 //===--------------------------------------------------===//
1012
1013 unsigned getHeight() const { return Root ? Root->getHeight() : 0; }
1014
1015 static void Profile(FoldingSetNodeID &ID, const ImmutableSet &S) {
1016 ID.AddPointer(S.Root.get());
1017 }
1018
1019 void Profile(FoldingSetNodeID &ID) const { return Profile(ID, *this); }
1020
1021 //===--------------------------------------------------===//
1022 // For testing.
1023 //===--------------------------------------------------===//
1024
1025 void validateTree() const { if (Root) Root->validateTree(); }
1026};
1027
1028// NOTE: This may some day replace the current ImmutableSet.
1029template <typename ValT, typename ValInfo = ImutContainerInfo<ValT>>
1031public:
1032 using value_type = typename ValInfo::value_type;
1033 using value_type_ref = typename ValInfo::value_type_ref;
1035 using FactoryTy = typename TreeTy::Factory;
1036
1037private:
1039 FactoryTy *Factory;
1040
1041public:
1042 /// Constructs a set from a pointer to a tree root. In general one
1043 /// should use a Factory object to create sets instead of directly
1044 /// invoking the constructor, but there are cases where make this
1045 /// constructor public is useful.
1046 ImmutableSetRef(TreeTy *R, FactoryTy *F) : Root(R), Factory(F) {}
1047
1049 return ImmutableSetRef(0, F);
1050 }
1051
1053 return ImmutableSetRef(Factory->add(Root.get(), V), Factory);
1054 }
1055
1057 return ImmutableSetRef(Factory->remove(Root.get(), V), Factory);
1058 }
1059
1060 /// Returns true if the set contains the specified value.
1061 bool contains(value_type_ref V) const {
1062 return Root ? Root->contains(V) : false;
1063 }
1064
1065 ImmutableSet<ValT> asImmutableSet(bool canonicalize = true) const {
1066 return ImmutableSet<ValT>(
1067 canonicalize ? Factory->getCanonicalTree(Root.get()) : Root.get());
1068 }
1069
1070 TreeTy *getRootWithoutRetain() const { return Root.get(); }
1071
1072 bool operator==(const ImmutableSetRef &RHS) const {
1073 return Root && RHS.Root ? Root->isEqual(*RHS.Root.get()) : Root == RHS.Root;
1074 }
1075
1076 bool operator!=(const ImmutableSetRef &RHS) const {
1077 return Root && RHS.Root ? Root->isNotEqual(*RHS.Root.get())
1078 : Root != RHS.Root;
1079 }
1080
1081 /// Return true if the set contains no elements.
1082 bool isEmpty() const { return !Root; }
1083
1084 /// Return true if the set contains exactly one element.
1085 /// This method runs in constant time.
1086 bool isSingleton() const { return getHeight() == 1; }
1087
1088 //===--------------------------------------------------===//
1089 // Iterators.
1090 //===--------------------------------------------------===//
1091
1093
1094 iterator begin() const { return iterator(Root.get()); }
1095 iterator end() const { return iterator(); }
1096
1097 //===--------------------------------------------------===//
1098 // Utility methods.
1099 //===--------------------------------------------------===//
1100
1101 unsigned getHeight() const { return Root ? Root->getHeight() : 0; }
1102
1103 static void Profile(FoldingSetNodeID &ID, const ImmutableSetRef &S) {
1104 ID.AddPointer(S.Root.get());
1105 }
1106
1107 void Profile(FoldingSetNodeID &ID) const { return Profile(ID, *this); }
1108
1109 //===--------------------------------------------------===//
1110 // For testing.
1111 //===--------------------------------------------------===//
1112
1113 void validateTree() const { if (Root) Root->validateTree(); }
1114};
1115
1116} // end namespace llvm
1117
1118#endif // LLVM_ADT_IMMUTABLESET_H
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
This file defines the BumpPtrAllocator interface.
#define X(NUM, ENUM, NAME)
Definition ELF.h:856
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< StatepointGC > D("statepoint-example", "an example strategy for statepoint")
#define LLVM_PREFERRED_TYPE(T)
\macro LLVM_PREFERRED_TYPE Adjust type of bit-field in debug info.
Definition Compiler.h:740
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.
#define F(x, y, z)
Definition MD5.cpp:54
#define I(x, y, z)
Definition MD5.cpp:57
#define T
if(PassOpts->AAPipeline)
This file contains some templates that are useful if you are working with the STL at all.
This file defines the SmallVector class.
Value * RHS
Value * LHS
This class is used to gather all the unique data bits of a node.
Definition FoldingSet.h:208
static void Profile(FoldingSetNodeID &ID, const ImmutableSetRef &S)
void Profile(FoldingSetNodeID &ID) const
ImmutableSetRef add(value_type_ref V)
ImutAVLTree< ValInfo > TreeTy
bool contains(value_type_ref V) const
Returns true if the set contains the specified value.
bool operator!=(const ImmutableSetRef &RHS) const
ImmutableSetRef remove(value_type_ref V)
ImutAVLValueIterator< ImmutableSetRef > iterator
bool isSingleton() const
Return true if the set contains exactly one element.
iterator begin() const
bool isEmpty() const
Return true if the set contains no elements.
typename ValInfo::value_type value_type
ImmutableSetRef(TreeTy *R, FactoryTy *F)
Constructs a set from a pointer to a tree root.
typename ValInfo::value_type_ref value_type_ref
iterator end() const
unsigned getHeight() const
ImmutableSet< ValT > asImmutableSet(bool canonicalize=true) const
typename TreeTy::Factory FactoryTy
static ImmutableSetRef getEmptySet(FactoryTy *F)
void validateTree() const
bool operator==(const ImmutableSetRef &RHS) const
TreeTy * getRootWithoutRetain() const
Factory(const Factory &RHS)=delete
void operator=(const Factory &RHS)=delete
TreeTy::Factory * getTreeFactory() const
BumpPtrAllocator & getAllocator()
Factory(BumpPtrAllocator &Alloc, bool canonicalize=true)
ImmutableSet getEmptySet()
Returns an immutable set that contains no elements.
Factory(bool canonicalize=true)
ImmutableSet remove(ImmutableSet Old, value_type_ref V)
Creates a new immutable set that contains all of the values of the original set with the exception of...
ImmutableSet add(ImmutableSet Old, value_type_ref V)
Creates a new immutable set that contains all of the values of the original set with the addition of ...
bool operator!=(const ImmutableSet &RHS) const
typename ValInfo::value_type value_type
bool operator==(const ImmutableSet &RHS) const
iterator end() const
bool isEmpty() const
Return true if the set contains no elements.
ImmutableSet(TreeTy *R)
Constructs a set from a pointer to a tree root.
bool isSingleton() const
Return true if the set contains exactly one element.
TreeTy * getRootWithoutRetain() const
ImutAVLTree< ValInfo > TreeTy
void validateTree() const
bool contains(value_type_ref V) const
Returns true if the set contains the specified value.
void Profile(FoldingSetNodeID &ID) const
iterator begin() const
unsigned getHeight() const
static void Profile(FoldingSetNodeID &ID, const ImmutableSet &S)
ImutAVLValueIterator< ImmutableSet > iterator
typename ValInfo::value_type_ref value_type_ref
static unsigned maskCacheIndex(unsigned I)
TreeTy * balanceTree(TreeTy *L, value_type_ref V, TreeTy *R)
Used by add_internal and remove_internal to balance a newly created tree.
unsigned getHeight(TreeTy *T) const
ImutAVLFactory(BumpPtrAllocator &Alloc)
TreeTy * add_internal(value_type_ref V, TreeTy *T)
add_internal - Creates a new tree that includes the specified data and the data from the original tre...
value_type_ref getValue(TreeTy *T) const
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)
void recoverNodes(TreeTy *Result)
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)
bool isEmpty(TreeTy *T) const
Bidirectional in-order iterator over the nodes of an ImutAVLTree.
void skipSubTree()
Move to the in-order successor of the entire subtree rooted at the current node, i....
bool operator!=(const ImutAVLTreeInOrderIterator &x) const
ImutAVLTreeInOrderIterator & operator++()
ImutAVLTree< ImutInfo > TreeTy
ImutAVLTreeInOrderIterator & operator--()
std::bidirectional_iterator_tag iterator_category
ImutAVLTreeInOrderIterator(const TreeTy *Root)
bool operator==(const ImutAVLTreeInOrderIterator &x) const
ImutAVLTree< ImutInfo > value_type
unsigned size() const
Returns the number of nodes in the tree, which includes both leaves and.
iterator end() const
Returns an iterator for the tree that denotes the end of an inorder traversal.
const value_type & getValue() const
Returns the data value associated with the tree node.
unsigned getHeight() const
Returns the height of the tree. A tree with no subtrees has a height of 1.
typename ValInfo::key_type_ref key_type_ref
ImutAVLFactory< ValInfo > Factory
ImutAVLTree * find(key_type_ref K)
Finds the subtree associated with the specified key value.
typename ValInfo::value_type_ref value_type_ref
unsigned validateTree() const
A utility method that checks that the balancing and ordering invariants of the tree are satisfied.
bool isNotEqual(const ImutAVLTree &RHS) const
Compares two trees for structural inequality.
bool isEqual(const ImutAVLTree &RHS) const
Compares two trees for structural equality and returns true if they are equal.
ImutAVLTree * getLeft() const
Return a pointer to the left subtree.
ImutAVLTreeInOrderIterator< ValInfo > iterator
typename ValInfo::value_type value_type
ImutAVLTree * getRight() const
Return a pointer to the right subtree.
bool isElementEqual(const ImutAVLTree *RHS) const
bool contains(key_type_ref K)
Returns true if this tree contains a subtree (node) that has an data element that matches the specifi...
ImutAVLTree * getMaxElement()
Find the subtree associated with the highest ranged key value.
iterator begin() const
Returns an iterator that iterates over the nodes of the tree in an inorder traversal.
bool isElementEqual(value_type_ref V) const
A smart pointer to a reference-counted object that inherits from RefCountedBase or ThreadSafeRefCount...
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
Definition CallingConv.h:24
This is an optimization pass for GlobalISel generic memory operations.
auto reverse(ContainerTy &&C)
Definition STLExtras.h:407
BumpPtrAllocatorImpl<> BumpPtrAllocator
The standard BumpPtrAllocator which just uses the default template parameters.
Definition Allocator.h:390
#define N
static void Profile(const T &X, FoldingSetNodeID &ID)
Definition FoldingSet.h:117
Generic iterator that wraps a T::TreeTy::iterator and exposes iterator::getValue() on dereference.
ImutAVLValueIterator::reference operator*() const
ImutAVLValueIterator(typename T::TreeTy *Tree)
static bool isDataEqual(data_type_ref, data_type_ref)
static key_type_ref KeyOfValue(value_type_ref D)
static bool isEqual(key_type_ref LHS, key_type_ref RHS)
typename ImutProfileInfo< T * >::value_type_ref value_type_ref
typename ImutProfileInfo< T * >::value_type value_type
static data_type_ref DataOfValue(value_type_ref)
static bool isLess(key_type_ref LHS, key_type_ref RHS)
Generic definition of comparison operations for elements of immutable containers that defaults to usi...
static bool isLess(key_type_ref LHS, key_type_ref RHS)
typename ImutProfileInfo< T >::value_type value_type
static bool isEqual(key_type_ref LHS, key_type_ref RHS)
static bool isDataEqual(data_type_ref, data_type_ref)
static data_type_ref DataOfValue(value_type_ref)
static key_type_ref KeyOfValue(value_type_ref D)
value_type_ref key_type_ref
typename ImutProfileInfo< T >::value_type_ref value_type_ref
static void Profile(FoldingSetNodeID &ID, value_type_ref X)
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.