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"
21#include "llvm/ADT/iterator.h"
24#include "llvm/Support/Debug.h"
27#include <cassert>
28#include <cstdint>
29#include <functional>
30#include <iterator>
31#include <new>
32#include <vector>
33
34namespace llvm {
35
36//===----------------------------------------------------------------------===//
37// Immutable AVL-Tree Definition.
38//===----------------------------------------------------------------------===//
39
40template <typename ImutInfo> class ImutAVLFactory;
41template <typename ImutInfo> class ImutIntervalAVLFactory;
42template <typename ImutInfo> class ImutAVLTreeInOrderIterator;
43
44template <typename ImutInfo >
45class ImutAVLTree {
46public:
47 using key_type_ref = typename ImutInfo::key_type_ref;
48 using value_type = typename ImutInfo::value_type;
49 using value_type_ref = typename ImutInfo::value_type_ref;
52
53 friend class ImutAVLFactory<ImutInfo>;
54 friend class ImutIntervalAVLFactory<ImutInfo>;
55
56 //===----------------------------------------------------===//
57 // Public Interface.
58 //===----------------------------------------------------===//
59
60 /// Return a pointer to the left subtree. This value
61 /// is NULL if there is no left subtree.
62 ImutAVLTree *getLeft() const { return left; }
63
64 /// Return a pointer to the right subtree. This value is
65 /// NULL if there is no right subtree.
66 ImutAVLTree *getRight() const { return right; }
67
68 /// Returns the height of the tree. A tree with no subtrees has a height of 1.
69 unsigned getHeight() const { return height; }
70
71 /// Returns the data value associated with the tree node.
72 const value_type& getValue() const { return value; }
73
74 /// Finds the subtree associated with the specified key value. This method
75 /// returns NULL if no matching subtree is found.
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 /// Find the subtree associated with the highest ranged key value.
91 ImutAVLTree* getMaxElement() {
92 ImutAVLTree *T = this;
93 ImutAVLTree *Right = T->getRight();
94 while (Right) { T = Right; Right = T->getRight(); }
95 return T;
96 }
97
98 /// Returns the number of nodes in the tree, which includes both leaves and
99 // non-leaf nodes.
100 unsigned size() const {
101 unsigned n = 1;
102 if (const ImutAVLTree* L = getLeft())
103 n += L->size();
104 if (const ImutAVLTree* R = getRight())
105 n += R->size();
106 return n;
107 }
108
109 /// Returns an iterator that iterates over the nodes of the tree in an inorder
110 /// traversal. The returned iterator thus refers to the tree node with the
111 /// minimum data element.
112 iterator begin() const { return iterator(this); }
113
114 /// Returns an iterator for the tree that denotes the end of an inorder
115 /// traversal.
116 iterator end() const { return iterator(); }
117
119 // Compare the keys.
120 if (!ImutInfo::isEqual(ImutInfo::KeyOfValue(getValue()),
121 ImutInfo::KeyOfValue(V)))
122 return false;
123
124 // Also compare the data values.
125 if (!ImutInfo::isDataEqual(ImutInfo::DataOfValue(getValue()),
126 ImutInfo::DataOfValue(V)))
127 return false;
128
129 return true;
130 }
131
132 bool isElementEqual(const ImutAVLTree* RHS) const {
133 return isElementEqual(RHS->getValue());
134 }
135
136 /// Compares two trees for structural equality and returns true if they are
137 /// equal. The worst case performance of this operation is linear in the sizes
138 /// of the trees.
139 bool isEqual(const ImutAVLTree& RHS) const {
140 if (&RHS == this)
141 return true;
142
143 iterator LItr = begin(), LEnd = end();
144 iterator RItr = RHS.begin(), REnd = RHS.end();
145
146 while (LItr != LEnd && RItr != REnd) {
147 if (&*LItr == &*RItr) {
148 LItr.skipSubTree();
149 RItr.skipSubTree();
150 continue;
151 }
152
153 if (!LItr->isElementEqual(&*RItr))
154 return false;
155
156 ++LItr;
157 ++RItr;
158 }
159
160 return LItr == LEnd && RItr == REnd;
161 }
162
163 /// Compares two trees for structural inequality. Performance is the same as
164 /// isEqual.
165 bool isNotEqual(const ImutAVLTree& RHS) const { return !isEqual(RHS); }
166
167 /// Returns true if this tree contains a subtree (node) that has an data
168 /// element that matches the specified key. Complexity is logarithmic in the
169 /// size of the tree.
170 bool contains(key_type_ref K) { return (bool) find(K); }
171
172 /// A utility method that checks that the balancing and ordering invariants of
173 /// the tree are satisfied. It is a recursive method that returns the height
174 /// of the tree, which is then consumed by the enclosing validateTree call.
175 /// External callers should ignore the return value. An invalid tree will
176 /// cause an assertion to fire in a debug build.
177 unsigned validateTree() const {
178 unsigned HL = getLeft() ? getLeft()->validateTree() : 0;
179 unsigned HR = getRight() ? getRight()->validateTree() : 0;
180 (void) HL;
181 (void) HR;
182
183 assert(getHeight() == ( HL > HR ? HL : HR ) + 1
184 && "Height calculation wrong");
185
186 assert((HL > HR ? HL-HR : HR-HL) <= 2
187 && "Balancing invariant violated");
188
189 assert((!getLeft() ||
190 ImutInfo::isLess(ImutInfo::KeyOfValue(getLeft()->getValue()),
191 ImutInfo::KeyOfValue(getValue()))) &&
192 "Value in left child is not less that current value");
193
194 assert((!getRight() ||
195 ImutInfo::isLess(ImutInfo::KeyOfValue(getValue()),
196 ImutInfo::KeyOfValue(getRight()->getValue()))) &&
197 "Current value is not less that value of right child");
198
199 return getHeight();
200 }
201
202 //===----------------------------------------------------===//
203 // Internal values.
204 //===----------------------------------------------------===//
205
206private:
207 Factory *factory;
208 ImutAVLTree *left;
209 ImutAVLTree *right;
210 ImutAVLTree *prev = nullptr;
211 ImutAVLTree *next = nullptr;
212
213 unsigned height : 28;
215 unsigned IsMutable : 1;
217 unsigned IsDigestCached : 1;
219 unsigned IsCanonicalized : 1;
220
221 value_type value;
222 uint32_t digest = 0;
223 uint32_t refCount = 0;
224
225 //===----------------------------------------------------===//
226 // Internal methods (node manipulation; used by Factory).
227 //===----------------------------------------------------===//
228
229private:
230 /// Internal constructor that is only called by ImutAVLFactory.
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 /// 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.
246 bool isMutable() const { return IsMutable; }
247
248 /// Returns true if the digest for this tree is cached. This can only be true
249 /// if the tree is immutable.
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 /// Clears the mutable flag for a tree. After this happens,
264 /// it is an error to call setLeft(), setRight(), and setHeight().
265 void markImmutable() {
266 assert(isMutable() && "Mutable flag already removed.");
267 IsMutable = false;
268 }
269
270 /// Clears the NoCachedDigest flag for a tree.
271 void markedCachedDigest() {
272 assert(!hasCachedDigest() && "NoCachedDigest flag already removed.");
273 IsDigestCached = true;
274 }
275
276 /// Changes the height of the tree. Used internally by ImutAVLFactory.
277 void setHeight(unsigned h) {
278 assert(isMutable() && "Only a mutable tree can have its height changed.");
279 height = h;
280 }
281
282 static uint32_t computeDigest(ImutAVLTree *L, ImutAVLTree *R,
283 value_type_ref V) {
284 uint32_t digest = 0;
285
286 if (L)
287 digest += L->computeDigest();
288
289 // Compute digest of stored data.
290 FoldingSetNodeID ID;
291 ImutInfo::Profile(ID,V);
292 digest += ID.ComputeHash();
293
294 if (R)
295 digest += R->computeDigest();
296
297 return digest;
298 }
299
300 uint32_t computeDigest() {
301 // Check the lowest bit to determine if digest has actually been
302 // pre-computed.
303 if (hasCachedDigest())
304 return digest;
305
306 uint32_t X = computeDigest(getLeft(), getRight(), getValue());
307 digest = X;
308 markedCachedDigest();
309 return X;
310 }
311
312 //===----------------------------------------------------===//
313 // Reference count operations.
314 //===----------------------------------------------------===//
315
316public:
317 void retain() { ++refCount; }
318
319 void release() {
320 assert(refCount > 0);
321 if (--refCount == 0)
322 destroy();
323 }
324
325 void destroy() {
326 if (left)
327 left->release();
328 if (right)
329 right->release();
330 if (IsCanonicalized) {
331 if (next)
332 next->prev = prev;
333
334 if (prev)
335 prev->next = next;
336 else
337 factory->Cache[factory->maskCacheIndex(computeDigest())] = next;
338 }
339
340 // We need to clear the mutability bit in case we are
341 // destroying the node as part of a sweep in ImutAVLFactory::recoverNodes().
342 IsMutable = false;
343 factory->freeNodes.push_back(this);
344 }
345};
346
347template <typename ImutInfo>
349 static void retain(ImutAVLTree<ImutInfo> *Tree) { Tree->retain(); }
350 static void release(ImutAVLTree<ImutInfo> *Tree) { Tree->release(); }
351};
352
353//===----------------------------------------------------------------------===//
354// Immutable AVL-Tree Factory class.
355//===----------------------------------------------------------------------===//
356
357template <typename ImutInfo >
359 friend class ImutAVLTree<ImutInfo>;
360
361 using TreeTy = ImutAVLTree<ImutInfo>;
362 using value_type_ref = typename TreeTy::value_type_ref;
363 using key_type_ref = typename TreeTy::key_type_ref;
364 using CacheTy = DenseMap<unsigned, TreeTy*>;
365
366 CacheTy Cache;
367 uintptr_t Allocator;
368 std::vector<TreeTy*> createdNodes;
369 std::vector<TreeTy*> freeNodes;
370
371 bool ownsAllocator() const {
372 return (Allocator & 0x1) == 0;
373 }
374
375 BumpPtrAllocator& getAllocator() const {
376 return *reinterpret_cast<BumpPtrAllocator*>(Allocator & ~0x1);
377 }
378
379 //===--------------------------------------------------===//
380 // Public interface.
381 //===--------------------------------------------------===//
382
383public:
385 : Allocator(reinterpret_cast<uintptr_t>(new BumpPtrAllocator())) {}
386
388 : Allocator(reinterpret_cast<uintptr_t>(&Alloc) | 0x1) {}
389
391 if (ownsAllocator()) delete &getAllocator();
392 }
393
394 TreeTy* add(TreeTy* T, value_type_ref V) {
395 T = add_internal(V,T);
397 recoverNodes();
398 return T;
399 }
400
401 TreeTy* remove(TreeTy* T, key_type_ref V) {
402 T = remove_internal(V,T);
404 recoverNodes();
405 return T;
406 }
407
408 TreeTy* getEmptyTree() const { return nullptr; }
409
410protected:
411 //===--------------------------------------------------===//
412 // A bunch of quick helper functions used for reasoning
413 // about the properties of trees and their children.
414 // These have succinct names so that the balancing code
415 // is as terse (and readable) as possible.
416 //===--------------------------------------------------===//
417
418 bool isEmpty(TreeTy* T) const { return !T; }
419 unsigned getHeight(TreeTy* T) const { return T ? T->getHeight() : 0; }
420 TreeTy* getLeft(TreeTy* T) const { return T->getLeft(); }
421 TreeTy* getRight(TreeTy* T) const { return T->getRight(); }
422 value_type_ref getValue(TreeTy* T) const { return T->value; }
423
424 // Make sure the index is not the Tombstone or Entry key of the DenseMap.
425 static unsigned maskCacheIndex(unsigned I) { return (I & ~0x02); }
426
427 unsigned incrementHeight(TreeTy* L, TreeTy* R) const {
428 unsigned hl = getHeight(L);
429 unsigned hr = getHeight(R);
430 return (hl > hr ? hl : hr) + 1;
431 }
432
433 static bool compareTreeWithSection(TreeTy* T,
434 typename TreeTy::iterator& TI,
435 typename TreeTy::iterator& TE) {
436 typename TreeTy::iterator I = T->begin(), E = T->end();
437 for ( ; I!=E ; ++I, ++TI) {
438 if (TI == TE || !I->isElementEqual(&*TI))
439 return false;
440 }
441 return true;
442 }
443
444 //===--------------------------------------------------===//
445 // "createNode" is used to generate new tree roots that link
446 // to other trees. The function may also simply move links
447 // in an existing root if that root is still marked mutable.
448 // This is necessary because otherwise our balancing code
449 // would leak memory as it would create nodes that are
450 // then discarded later before the finished tree is
451 // returned to the caller.
452 //===--------------------------------------------------===//
453
454 TreeTy* createNode(TreeTy* L, value_type_ref V, TreeTy* R) {
455 BumpPtrAllocator& A = getAllocator();
456 TreeTy* T;
457 if (!freeNodes.empty()) {
458 T = freeNodes.back();
459 freeNodes.pop_back();
460 assert(T != L);
461 assert(T != R);
462 } else {
463 T = (TreeTy*) A.Allocate<TreeTy>();
464 }
465 new (T) TreeTy(this, L, R, V, incrementHeight(L,R));
466 createdNodes.push_back(T);
467 return T;
468 }
469
470 TreeTy* createNode(TreeTy* newLeft, TreeTy* oldTree, TreeTy* newRight) {
471 return createNode(newLeft, getValue(oldTree), newRight);
472 }
473
475 for (unsigned i = 0, n = createdNodes.size(); i < n; ++i) {
476 TreeTy *N = createdNodes[i];
477 if (N->isMutable() && N->refCount == 0)
478 N->destroy();
479 }
480 createdNodes.clear();
481 }
482
483 /// Used by add_internal and remove_internal to balance a newly created tree.
484 TreeTy* balanceTree(TreeTy* L, value_type_ref V, TreeTy* R) {
485 unsigned hl = getHeight(L);
486 unsigned hr = getHeight(R);
487
488 if (hl > hr + 2) {
489 assert(!isEmpty(L) && "Left tree cannot be empty to have a height >= 2");
490
491 TreeTy *LL = getLeft(L);
492 TreeTy *LR = getRight(L);
493
494 if (getHeight(LL) >= getHeight(LR))
495 return createNode(LL, L, createNode(LR,V,R));
496
497 assert(!isEmpty(LR) && "LR cannot be empty because it has a height >= 1");
498
499 TreeTy *LRL = getLeft(LR);
500 TreeTy *LRR = getRight(LR);
501
502 return createNode(createNode(LL,L,LRL), LR, createNode(LRR,V,R));
503 }
504
505 if (hr > hl + 2) {
506 assert(!isEmpty(R) && "Right tree cannot be empty to have a height >= 2");
507
508 TreeTy *RL = getLeft(R);
509 TreeTy *RR = getRight(R);
510
511 if (getHeight(RR) >= getHeight(RL))
512 return createNode(createNode(L,V,RL), R, RR);
513
514 assert(!isEmpty(RL) && "RL cannot be empty because it has a height >= 1");
515
516 TreeTy *RLL = getLeft(RL);
517 TreeTy *RLR = getRight(RL);
518
519 return createNode(createNode(L,V,RLL), RL, createNode(RLR,R,RR));
520 }
521
522 return createNode(L,V,R);
523 }
524
525 /// add_internal - Creates a new tree that includes the specified
526 /// data and the data from the original tree. If the original tree
527 /// already contained the data item, the original tree is returned.
528 TreeTy *add_internal(value_type_ref V, TreeTy *T) {
529 if (isEmpty(T))
530 return createNode(T, V, T);
531 assert(!T->isMutable());
532
533 key_type_ref K = ImutInfo::KeyOfValue(V);
534 key_type_ref KCurrent = ImutInfo::KeyOfValue(getValue(T));
535
536 if (ImutInfo::isEqual(K, KCurrent)) {
537 // If both key and value are same, return the original tree.
538 if (ImutInfo::isDataEqual(ImutInfo::DataOfValue(V),
539 ImutInfo::DataOfValue(getValue(T))))
540 return T;
541 // Otherwise create a new node with the new value.
542 return createNode(getLeft(T), V, getRight(T));
543 }
544
545 TreeTy *NewL = getLeft(T);
546 TreeTy *NewR = getRight(T);
547 if (ImutInfo::isLess(K, KCurrent))
548 NewL = add_internal(V, NewL);
549 else
550 NewR = add_internal(V, NewR);
551
552 // If no changes were made, return the original tree. Otherwise, balance the
553 // tree and return the new root.
554 return NewL == getLeft(T) && NewR == getRight(T)
555 ? T
556 : balanceTree(NewL, getValue(T), NewR);
557 }
558
559 /// remove_internal - Creates a new tree that includes all the data
560 /// from the original tree except the specified data. If the
561 /// specified data did not exist in the original tree, the original
562 /// tree is returned.
563 TreeTy *remove_internal(key_type_ref K, TreeTy *T) {
564 if (isEmpty(T))
565 return T;
566
567 assert(!T->isMutable());
568
569 key_type_ref KCurrent = ImutInfo::KeyOfValue(getValue(T));
570
571 if (ImutInfo::isEqual(K, KCurrent))
572 return combineTrees(getLeft(T), getRight(T));
573
574 TreeTy *NewL = getLeft(T);
575 TreeTy *NewR = getRight(T);
576 if (ImutInfo::isLess(K, KCurrent))
577 NewL = remove_internal(K, NewL);
578 else
579 NewR = remove_internal(K, NewR);
580
581 // If no changes were made, return the original tree. Otherwise, balance the
582 // tree and return the new root.
583 return NewL == getLeft(T) && NewR == getRight(T)
584 ? T
585 : balanceTree(NewL, getValue(T), NewR);
586 }
587
588 TreeTy* combineTrees(TreeTy* L, TreeTy* R) {
589 if (isEmpty(L))
590 return R;
591 if (isEmpty(R))
592 return L;
593 TreeTy* OldNode;
594 TreeTy* newRight = removeMinBinding(R,OldNode);
595 return balanceTree(L, getValue(OldNode), newRight);
596 }
597
598 TreeTy* removeMinBinding(TreeTy* T, TreeTy*& Noderemoved) {
599 assert(!isEmpty(T));
600 if (isEmpty(getLeft(T))) {
601 Noderemoved = T;
602 return getRight(T);
603 }
604 return balanceTree(removeMinBinding(getLeft(T), Noderemoved),
605 getValue(T), getRight(T));
606 }
607
608 /// Clears the mutable bits of a root and all of its descendants.
609 void markImmutable(TreeTy* T) {
610 if (!T || !T->isMutable())
611 return;
612 T->markImmutable();
615 }
616
617public:
618 TreeTy *getCanonicalTree(TreeTy *TNew) {
619 if (!TNew)
620 return nullptr;
621
622 if (TNew->IsCanonicalized)
623 return TNew;
624
625 // Search the hashtable for another tree with the same digest, and
626 // if find a collision compare those trees by their contents.
627 unsigned digest = TNew->computeDigest();
628 TreeTy *&entry = Cache[maskCacheIndex(digest)];
629 if (entry) {
630 for (TreeTy *T = entry ; T != nullptr; T = T->next) {
631 // Compare the Contents('T') with Contents('TNew')
632 typename TreeTy::iterator TI = T->begin(), TE = T->end();
633 if (!compareTreeWithSection(TNew, TI, TE))
634 continue;
635 if (TI != TE)
636 continue; // T has more contents than TNew.
637 // Trees did match! Return 'T'.
638 if (TNew->refCount == 0)
639 TNew->destroy();
640 return T;
641 }
642 entry->prev = TNew;
643 TNew->next = entry;
644 }
645
646 entry = TNew;
647 TNew->IsCanonicalized = true;
648 return TNew;
649 }
650};
651
652//===----------------------------------------------------------------------===//
653// Immutable AVL-Tree Iterator.
654//===----------------------------------------------------------------------===//
655
656/// Bidirectional in-order iterator over the nodes of an ImutAVLTree.
657///
658/// The iterator keeps the chain of ancestors from the root down to the current
659/// node on an explicit stack of plain node pointers, and decides which way to
660/// move next by inspecting whether it is ascending from a node's left or right
661/// child. This avoids storing any per-node visit-state: there is no need to
662/// remember "have I already visited this node's left/right subtree", because
663/// that is recovered by comparing the child we just left against the parent's
664/// left and right pointers.
665///
666/// A node's parent cannot be cached in the node itself, because these trees are
667/// persistent and structurally shared: a single node may appear as the child of
668/// different parents across different tree versions. The ancestor stack is
669/// therefore the per-traversal parent chain.
670template <typename ImutInfo> class ImutAVLTreeInOrderIterator {
671public:
672 using iterator_category = std::bidirectional_iterator_tag;
674 using difference_type = std::ptrdiff_t;
677
679
680private:
681 // Path[0] is the root and Path.back() is the current node. An empty path is
682 // the end iterator. The invariant is that Path always holds the exact chain
683 // of ancestors of the current node, root-most first.
685
686 // Descend along left children, pushing each node; lands on the minimum of the
687 // subtree rooted at T (i.e. the first node in an in-order traversal of T).
688 void descendToMin(TreeTy *T) {
689 for (; T; T = T->getLeft())
690 Path.push_back(T);
691 }
692
693 // Descend along right children, pushing each node; lands on the maximum of
694 // the subtree rooted at T (i.e. the last node in an in-order traversal of T).
695 void descendToMax(TreeTy *T) {
696 for (; T; T = T->getRight())
697 Path.push_back(T);
698 }
699
700 // Pop the current node and ascend until we reach an ancestor from its *left*
701 // child, i.e. the first ancestor whose subtree is not yet fully visited. That
702 // ancestor is the in-order successor of the subtree we just left; if there is
703 // none, Path is emptied (the end iterator). Shared by operator++ and
704 // skipSubTree, whose only difference is whether the current node's right
705 // subtree is descended into first.
706 void ascendFromRightChild() {
707 TreeTy *Child = Path.pop_back_val();
708 while (!Path.empty() && Path.back()->getRight() == Child)
709 Child = Path.pop_back_val();
710 }
711
712 // Mirror of ascendFromRightChild for reverse traversal (operator--).
713 void ascendFromLeftChild() {
714 TreeTy *Child = Path.pop_back_val();
715 while (!Path.empty() && Path.back()->getLeft() == Child)
716 Child = Path.pop_back_val();
717 }
718
719public:
720 ImutAVLTreeInOrderIterator() = default; // end() iterator.
722 descendToMin(const_cast<TreeTy *>(Root));
723 }
724
725 // Two iterators are equal iff they sit on the same node (or are both end()).
726 // Within a single tree a node has a unique root-to-node path, so the current
727 // node alone identifies the position; comparing the whole path is therefore
728 // unnecessary. Comparing iterators from different trees is not meaningful, as
729 // for any standard container.
731 if (Path.empty() || x.Path.empty())
732 return Path.empty() == x.Path.empty();
733 return Path.back() == x.Path.back();
734 }
736 return !(*this == x);
737 }
738
739 TreeTy &operator*() const { return *Path.back(); }
740 TreeTy *operator->() const { return Path.back(); }
741
743 assert(!Path.empty() && "Incrementing the end iterator");
744 if (TreeTy *R = Path.back()->getRight())
745 // The in-order successor is the minimum of the right subtree.
746 descendToMin(R);
747 else
748 // No right subtree: the successor is the nearest ancestor reached from a
749 // left child.
750 ascendFromRightChild();
751 return *this;
752 }
753
755 assert(!Path.empty() && "Decrementing the end iterator");
756 if (TreeTy *L = Path.back()->getLeft())
757 // The in-order predecessor is the maximum of the left subtree.
758 descendToMax(L);
759 else
760 // Mirror of operator++.
761 ascendFromLeftChild();
762 return *this;
763 }
764
765 /// Move to the in-order successor of the entire subtree rooted at the current
766 /// node, i.e. skip the current node together with its right subtree. This is
767 /// exactly the ascent half of operator++.
768 void skipSubTree() {
769 assert(!Path.empty() && "Skipping past the end iterator");
770 ascendFromRightChild();
771 }
772};
773
774/// Generic iterator that wraps a T::TreeTy::iterator and exposes
775/// iterator::getValue() on dereference.
776template <typename T>
779 ImutAVLValueIterator<T>, typename T::TreeTy::iterator,
780 typename std::iterator_traits<
781 typename T::TreeTy::iterator>::iterator_category,
782 const typename T::value_type> {
786
788 return this->I->getValue();
789 }
790};
791
792//===----------------------------------------------------------------------===//
793// Trait classes for Profile information.
794//===----------------------------------------------------------------------===//
795
796/// Generic profile template. The default behavior is to invoke the
797/// profile method of an object. Specializations for primitive integers
798/// and generic handling of pointers is done below.
799template <typename T>
801 using value_type = const T;
802 using value_type_ref = const T&;
803
807};
808
809/// Profile traits for integers.
810template <typename T>
812 using value_type = const T;
813 using value_type_ref = const T&;
814
816 ID.AddInteger(X);
817 }
818};
819
820#define PROFILE_INTEGER_INFO(X)\
821template<> struct ImutProfileInfo<X> : ImutProfileInteger<X> {};
822
824PROFILE_INTEGER_INFO(unsigned char)
826PROFILE_INTEGER_INFO(unsigned short)
827PROFILE_INTEGER_INFO(unsigned)
830PROFILE_INTEGER_INFO(unsigned long)
831PROFILE_INTEGER_INFO(long long)
832PROFILE_INTEGER_INFO(unsigned long long)
833
834#undef PROFILE_INTEGER_INFO
835
836/// Profile traits for booleans.
837template <>
839 using value_type = const bool;
840 using value_type_ref = const bool&;
841
843 ID.AddBoolean(X);
844 }
845};
846
847/// Generic profile trait for pointer types. We treat pointers as
848/// references to unique objects.
849template <typename T>
851 using value_type = const T*;
853
855 ID.AddPointer(X);
856 }
857};
858
859//===----------------------------------------------------------------------===//
860// Trait classes that contain element comparison operators and type
861// definitions used by ImutAVLTree, ImmutableSet, and ImmutableMap. These
862// inherit from the profile traits (ImutProfileInfo) to include operations
863// for element profiling.
864//===----------------------------------------------------------------------===//
865
866/// Generic definition of comparison operations for elements of immutable
867/// containers that defaults to using std::equal_to<> and std::less<> to perform
868/// comparison of elements.
869template <typename T> struct ImutContainerInfo : ImutProfileInfo<T> {
876
878 static data_type_ref DataOfValue(value_type_ref) { return true; }
879
881 return std::equal_to<key_type>()(LHS,RHS);
882 }
883
885 return std::less<key_type>()(LHS,RHS);
886 }
887
888 static bool isDataEqual(data_type_ref, data_type_ref) { return true; }
889};
890
891/// Specialization for pointer values to treat pointers as references to unique
892/// objects. Pointers are thus compared by their addresses.
893template <typename T> struct ImutContainerInfo<T *> : ImutProfileInfo<T *> {
900
902 static data_type_ref DataOfValue(value_type_ref) { return true; }
903
904 static bool isEqual(key_type_ref LHS, key_type_ref RHS) { return LHS == RHS; }
905
906 static bool isLess(key_type_ref LHS, key_type_ref RHS) { return LHS < RHS; }
907
908 static bool isDataEqual(data_type_ref, data_type_ref) { return true; }
909};
910
911//===----------------------------------------------------------------------===//
912// Immutable Set
913//===----------------------------------------------------------------------===//
914
915template <typename ValT, typename ValInfo = ImutContainerInfo<ValT>>
917public:
918 using value_type = typename ValInfo::value_type;
919 using value_type_ref = typename ValInfo::value_type_ref;
921
922private:
924
925public:
926 /// Constructs a set from a pointer to a tree root. In general one
927 /// should use a Factory object to create sets instead of directly
928 /// invoking the constructor, but there are cases where make this
929 /// constructor public is useful.
930 explicit ImmutableSet(TreeTy *R) : Root(R) {}
931
932 class Factory {
933 typename TreeTy::Factory F;
934 const bool Canonicalize;
935
936 public:
937 Factory(bool canonicalize = true)
938 : Canonicalize(canonicalize) {}
939
940 Factory(BumpPtrAllocator& Alloc, bool canonicalize = true)
941 : F(Alloc), Canonicalize(canonicalize) {}
942
943 Factory(const Factory& RHS) = delete;
944 void operator=(const Factory& RHS) = delete;
945
946 /// Returns an immutable set that contains no elements.
948 return ImmutableSet(F.getEmptyTree());
949 }
950
951 /// Creates a new immutable set that contains all of the values
952 /// of the original set with the addition of the specified value. If
953 /// the original set already included the value, then 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.add(Old.Root.get(), V);
960 return ImmutableSet(Canonicalize ? F.getCanonicalTree(NewT) : NewT);
961 }
962
963 /// Creates a new immutable set that contains all of the values
964 /// of the original set with the exception of the specified value. If
965 /// the original set did not contain the value, the original set is
966 /// returned and no memory is allocated. The time and space complexity
967 /// of this operation is logarithmic in the size of the original set.
968 /// The memory allocated to represent the set is released when the
969 /// factory object that created the set is destroyed.
971 TreeTy *NewT = F.remove(Old.Root.get(), V);
972 return ImmutableSet(Canonicalize ? F.getCanonicalTree(NewT) : NewT);
973 }
974
975 BumpPtrAllocator& getAllocator() { return F.getAllocator(); }
976
977 typename TreeTy::Factory *getTreeFactory() const {
978 return const_cast<typename TreeTy::Factory *>(&F);
979 }
980 };
981
982 friend class Factory;
983
984 /// Returns true if the set contains the specified value.
985 bool contains(value_type_ref V) const {
986 return Root ? Root->contains(V) : false;
987 }
988
989 bool operator==(const ImmutableSet &RHS) const {
990 return Root && RHS.Root ? Root->isEqual(*RHS.Root.get()) : Root == RHS.Root;
991 }
992
993 bool operator!=(const ImmutableSet &RHS) const {
994 return Root && RHS.Root ? Root->isNotEqual(*RHS.Root.get())
995 : Root != RHS.Root;
996 }
997
999 if (Root) { Root->retain(); }
1000 return Root.get();
1001 }
1002
1003 TreeTy *getRootWithoutRetain() const { return Root.get(); }
1004
1005 /// Return true if the set contains no elements.
1006 bool isEmpty() const { return !Root; }
1007
1008 /// Return true if the set contains exactly one element.
1009 /// This method runs in constant time.
1010 bool isSingleton() const { return getHeight() == 1; }
1011
1012 //===--------------------------------------------------===//
1013 // Iterators.
1014 //===--------------------------------------------------===//
1015
1017
1018 iterator begin() const { return iterator(Root.get()); }
1019 iterator end() const { return iterator(); }
1020
1021 //===--------------------------------------------------===//
1022 // Utility methods.
1023 //===--------------------------------------------------===//
1024
1025 unsigned getHeight() const { return Root ? Root->getHeight() : 0; }
1026
1027 static void Profile(FoldingSetNodeID &ID, const ImmutableSet &S) {
1028 ID.AddPointer(S.Root.get());
1029 }
1030
1031 void Profile(FoldingSetNodeID &ID) const { return Profile(ID, *this); }
1032
1033 //===--------------------------------------------------===//
1034 // For testing.
1035 //===--------------------------------------------------===//
1036
1037 void validateTree() const { if (Root) Root->validateTree(); }
1038};
1039
1040// NOTE: This may some day replace the current ImmutableSet.
1041template <typename ValT, typename ValInfo = ImutContainerInfo<ValT>>
1043public:
1044 using value_type = typename ValInfo::value_type;
1045 using value_type_ref = typename ValInfo::value_type_ref;
1047 using FactoryTy = typename TreeTy::Factory;
1048
1049private:
1051 FactoryTy *Factory;
1052
1053public:
1054 /// Constructs a set from a pointer to a tree root. In general one
1055 /// should use a Factory object to create sets instead of directly
1056 /// invoking the constructor, but there are cases where make this
1057 /// constructor public is useful.
1058 ImmutableSetRef(TreeTy *R, FactoryTy *F) : Root(R), Factory(F) {}
1059
1061 return ImmutableSetRef(0, F);
1062 }
1063
1065 return ImmutableSetRef(Factory->add(Root.get(), V), Factory);
1066 }
1067
1069 return ImmutableSetRef(Factory->remove(Root.get(), V), Factory);
1070 }
1071
1072 /// Returns true if the set contains the specified value.
1073 bool contains(value_type_ref V) const {
1074 return Root ? Root->contains(V) : false;
1075 }
1076
1077 ImmutableSet<ValT> asImmutableSet(bool canonicalize = true) const {
1078 return ImmutableSet<ValT>(
1079 canonicalize ? Factory->getCanonicalTree(Root.get()) : Root.get());
1080 }
1081
1082 TreeTy *getRootWithoutRetain() const { return Root.get(); }
1083
1084 bool operator==(const ImmutableSetRef &RHS) const {
1085 return Root && RHS.Root ? Root->isEqual(*RHS.Root.get()) : Root == RHS.Root;
1086 }
1087
1088 bool operator!=(const ImmutableSetRef &RHS) const {
1089 return Root && RHS.Root ? Root->isNotEqual(*RHS.Root.get())
1090 : Root != RHS.Root;
1091 }
1092
1093 /// Return true if the set contains no elements.
1094 bool isEmpty() const { return !Root; }
1095
1096 /// Return true if the set contains exactly one element.
1097 /// This method runs in constant time.
1098 bool isSingleton() const { return getHeight() == 1; }
1099
1100 //===--------------------------------------------------===//
1101 // Iterators.
1102 //===--------------------------------------------------===//
1103
1105
1106 iterator begin() const { return iterator(Root.get()); }
1107 iterator end() const { return iterator(); }
1108
1109 //===--------------------------------------------------===//
1110 // Utility methods.
1111 //===--------------------------------------------------===//
1112
1113 unsigned getHeight() const { return Root ? Root->getHeight() : 0; }
1114
1115 static void Profile(FoldingSetNodeID &ID, const ImmutableSetRef &S) {
1116 ID.AddPointer(S.Root.get());
1117 }
1118
1119 void Profile(FoldingSetNodeID &ID) const { return Profile(ID, *this); }
1120
1121 //===--------------------------------------------------===//
1122 // For testing.
1123 //===--------------------------------------------------===//
1124
1125 void validateTree() const { if (Root) Root->validateTree(); }
1126};
1127
1128} // end namespace llvm
1129
1130#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")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
#define LLVM_PREFERRED_TYPE(T)
\macro LLVM_PREFERRED_TYPE Adjust type of bit-field in debug info.
Definition Compiler.h:731
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 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
static bool compareTreeWithSection(TreeTy *T, typename TreeTy::iterator &TI, typename TreeTy::iterator &TE)
TreeTy * getLeft(TreeTy *T) const
TreeTy * getCanonicalTree(TreeTy *TNew)
TreeTy * add(TreeTy *T, value_type_ref V)
TreeTy * getRight(TreeTy *T) const
TreeTy * getEmptyTree() const
TreeTy * removeMinBinding(TreeTy *T, TreeTy *&Noderemoved)
TreeTy * createNode(TreeTy *newLeft, TreeTy *oldTree, TreeTy *newRight)
TreeTy * combineTrees(TreeTy *L, TreeTy *R)
TreeTy * remove_internal(key_type_ref K, TreeTy *T)
remove_internal - Creates a new tree that includes all the data from the original tree except the spe...
TreeTy * createNode(TreeTy *L, value_type_ref V, TreeTy *R)
unsigned incrementHeight(TreeTy *L, TreeTy *R) const
TreeTy * remove(TreeTy *T, key_type_ref V)
void markImmutable(TreeTy *T)
Clears the mutable bits of a root and all of its descendants.
bool isEmpty(TreeTy *T) const
Bidirectional in-order iterator over the nodes of an ImutAVLTree.
void skipSubTree()
Move to the in-order successor of the entire subtree rooted at the current node, i....
bool operator!=(const ImutAVLTreeInOrderIterator &x) const
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.
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.