LLVM 24.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, bool Canonicalize = true> class ImutAVLFactory;
42template <typename ImutInfo> class ImutIntervalAVLFactory;
43template <typename ImutInfo, bool Canonicalize = true>
45
46namespace ImutAVLDetail {
47/// The intrusive doubly-linked chain of same-digest trees in the factory's
48/// canonicalization cache. Held as an (empty) base so that, when
49/// canonicalization is disabled, the empty base optimization removes it
50/// entirely. Kept separate from the cached digest below so that the two
51/// pointers pack without the tail padding that grouping a trailing 32-bit field
52/// with them would introduce.
53template <typename Tree, bool Canonicalize> struct CanonicalLinks {
54 Tree *Prev = nullptr;
55 Tree *Next = nullptr;
56};
57template <typename Tree> struct CanonicalLinks<Tree, false> {};
58
59/// The cached structural digest, used only for canonicalization. Stored as an
60/// LLVM_NO_UNIQUE_ADDRESS member so it occupies no space when disabled and
61/// packs alongside the adjacent 32-bit fields when enabled.
62template <bool Canonicalize> struct CanonicalDigest {
64};
65template <> struct CanonicalDigest<false> {};
66
67/// The factory-side canonicalization cache: digest -> tree chain.
68/// Empty when canonicalization is disabled.
69template <typename Tree, bool Canonicalize> struct CanonicalCache {
71};
72template <typename Tree> struct CanonicalCache<Tree, false> {};
73} // namespace ImutAVLDetail
74
75template <typename ImutInfo, bool Canonicalize = true>
76class ImutAVLTree
77 : private ImutAVLDetail::CanonicalLinks<ImutAVLTree<ImutInfo, Canonicalize>,
78 Canonicalize> {
79public:
80 using key_type_ref = typename ImutInfo::key_type_ref;
81 using value_type = typename ImutInfo::value_type;
82 using value_type_ref = typename ImutInfo::value_type_ref;
85
86 friend class ImutAVLFactory<ImutInfo, Canonicalize>;
87 friend class ImutIntervalAVLFactory<ImutInfo>;
88
89private:
91
92public:
93 //===----------------------------------------------------===//
94 // Public Interface.
95 //===----------------------------------------------------===//
96
97 /// Return a pointer to the left subtree. This value
98 /// is NULL if there is no left subtree.
99 ImutAVLTree *getLeft() const { return left; }
100
101 /// Return a pointer to the right subtree. This value is
102 /// NULL if there is no right subtree.
103 ImutAVLTree *getRight() const { return right; }
104
105 /// Returns the height of the tree. A tree with no subtrees has a height of 1.
106 unsigned getHeight() const { return height; }
107
108 /// Returns the data value associated with the tree node.
109 const value_type& getValue() const { return value; }
110
111 /// Finds the subtree associated with the specified key value. This method
112 /// returns NULL if no matching subtree is found.
113 ImutAVLTree* find(key_type_ref K) {
114 ImutAVLTree *T = this;
115 while (T) {
116 key_type_ref CurrentKey = ImutInfo::KeyOfValue(T->getValue());
117 if (ImutInfo::isEqual(K,CurrentKey))
118 return T;
119 else if (ImutInfo::isLess(K,CurrentKey))
120 T = T->getLeft();
121 else
122 T = T->getRight();
123 }
124 return nullptr;
125 }
126
127 /// Find the subtree associated with the highest ranged key value.
128 ImutAVLTree* getMaxElement() {
129 ImutAVLTree *T = this;
130 ImutAVLTree *Right = T->getRight();
131 while (Right) { T = Right; Right = T->getRight(); }
132 return T;
133 }
134
135 /// Returns the number of nodes in the tree, which includes both leaves and
136 // non-leaf nodes.
137 unsigned size() const {
138 unsigned n = 1;
139 if (const ImutAVLTree* L = getLeft())
140 n += L->size();
141 if (const ImutAVLTree* R = getRight())
142 n += R->size();
143 return n;
144 }
145
146 /// Returns an iterator that iterates over the nodes of the tree in an inorder
147 /// traversal. The returned iterator thus refers to the tree node with the
148 /// minimum data element.
149 iterator begin() const { return iterator(this); }
150
151 /// Returns an iterator for the tree that denotes the end of an inorder
152 /// traversal.
153 iterator end() const { return iterator(); }
154
156 // Compare the keys.
157 if (!ImutInfo::isEqual(ImutInfo::KeyOfValue(getValue()),
158 ImutInfo::KeyOfValue(V)))
159 return false;
160
161 // Also compare the data values.
162 if (!ImutInfo::isDataEqual(ImutInfo::DataOfValue(getValue()),
163 ImutInfo::DataOfValue(V)))
164 return false;
165
166 return true;
167 }
168
169 bool isElementEqual(const ImutAVLTree* RHS) const {
170 return isElementEqual(RHS->getValue());
171 }
172
173 /// Compares two trees for structural equality and returns true if they are
174 /// equal. The worst case performance of this operation is linear in the sizes
175 /// of the trees.
176 bool isEqual(const ImutAVLTree& RHS) const {
177 if (&RHS == this)
178 return true;
179
180 iterator LItr = begin(), LEnd = end();
181 iterator RItr = RHS.begin(), REnd = RHS.end();
182
183 while (LItr != LEnd && RItr != REnd) {
184 if (&*LItr == &*RItr) {
185 LItr.skipSubTree();
186 RItr.skipSubTree();
187 continue;
188 }
189
190 if (!LItr->isElementEqual(&*RItr))
191 return false;
192
193 ++LItr;
194 ++RItr;
195 }
196
197 return LItr == LEnd && RItr == REnd;
198 }
199
200 /// Compares two trees for structural inequality. Performance is the same as
201 /// isEqual.
202 bool isNotEqual(const ImutAVLTree& RHS) const { return !isEqual(RHS); }
203
204 /// Returns true if this tree contains a subtree (node) that has an data
205 /// element that matches the specified key. Complexity is logarithmic in the
206 /// size of the tree.
207 bool contains(key_type_ref K) { return (bool) find(K); }
208
209 /// A utility method that checks that the balancing and ordering invariants of
210 /// the tree are satisfied. It is a recursive method that returns the height
211 /// of the tree, which is then consumed by the enclosing validateTree call.
212 /// External callers should ignore the return value. An invalid tree will
213 /// cause an assertion to fire in a debug build.
214 unsigned validateTree() const {
215 unsigned HL = getLeft() ? getLeft()->validateTree() : 0;
216 unsigned HR = getRight() ? getRight()->validateTree() : 0;
217 (void) HL;
218 (void) HR;
219
220 assert(getHeight() == ( HL > HR ? HL : HR ) + 1
221 && "Height calculation wrong");
222
223 assert((HL > HR ? HL-HR : HR-HL) <= 2
224 && "Balancing invariant violated");
225
226 assert((!getLeft() ||
227 ImutInfo::isLess(ImutInfo::KeyOfValue(getLeft()->getValue()),
228 ImutInfo::KeyOfValue(getValue()))) &&
229 "Value in left child is not less that current value");
230
231 assert((!getRight() ||
232 ImutInfo::isLess(ImutInfo::KeyOfValue(getValue()),
233 ImutInfo::KeyOfValue(getRight()->getValue()))) &&
234 "Current value is not less that value of right child");
235
236 return getHeight();
237 }
238
239 //===----------------------------------------------------===//
240 // Internal values.
241 //===----------------------------------------------------===//
242
243private:
244 // Field order places the traversal-hot fields (left, right, value) first so
245 // that in a node that straddles a cache line they land in the earlier line;
246 // the cold factory back-pointer (only touched on create/destroy) goes last.
247 ImutAVLTree *left;
248 ImutAVLTree *right;
249
250 unsigned height : 28;
252 unsigned IsMutable : 1;
254 unsigned IsDigestCached : 1;
256 unsigned IsCanonicalized : 1;
257
258 value_type value;
259 uint32_t refCount = 0;
261 Factory *factory;
262
263 //===----------------------------------------------------===//
264 // Internal methods (node manipulation; used by Factory).
265 //===----------------------------------------------------===//
266
267private:
268 /// Internal constructor that is only called by ImutAVLFactory.
270 unsigned height)
271 : left(l), right(r), height(height), IsMutable(true),
272 IsDigestCached(false), IsCanonicalized(false), value(v), factory(f) {
273 if (left) left->retain();
274 if (right) right->retain();
275 }
276
277 /// Returns true if the left and right subtree references
278 /// (as well as height) can be changed. If this method returns false,
279 /// the tree is truly immutable. Trees returned from an ImutAVLFactory
280 /// object should always have this method return true. Further, if this
281 /// method returns false for an instance of ImutAVLTree, all subtrees
282 /// will also have this method return false. The converse is not true.
283 bool isMutable() const { return IsMutable; }
284
285 /// Returns true if the digest for this tree is cached. This can only be true
286 /// if the tree is immutable.
287 bool hasCachedDigest() const { return IsDigestCached; }
288
289 //===----------------------------------------------------===//
290 // Mutating operations. A tree root can be manipulated as
291 // long as its reference has not "escaped" from internal
292 // methods of a factory object (see below). When a tree
293 // pointer is externally viewable by client code, the
294 // internal "mutable bit" is cleared to mark the tree
295 // immutable. Note that a tree that still has its mutable
296 // bit set may have children (subtrees) that are themselves
297 // immutable.
298 //===----------------------------------------------------===//
299
300 /// Clears the mutable flag for a tree. After this happens,
301 /// it is an error to call setLeft(), setRight(), and setHeight().
302 void markImmutable() {
303 assert(isMutable() && "Mutable flag already removed.");
304 IsMutable = false;
305 }
306
307 /// Clears the NoCachedDigest flag for a tree.
308 void markedCachedDigest() {
309 assert(!hasCachedDigest() && "NoCachedDigest flag already removed.");
310 IsDigestCached = true;
311 }
312
313 /// Changes the height of the tree. Used internally by ImutAVLFactory.
314 void setHeight(unsigned h) {
315 assert(isMutable() && "Only a mutable tree can have its height changed.");
316 height = h;
317 }
318
319 static uint32_t computeDigest(ImutAVLTree *L, ImutAVLTree *R,
320 value_type_ref V) {
321 uint32_t digest = 0;
322
323 if (L)
324 digest += L->computeDigest();
325
326 // Compute digest of stored data.
327 FoldingSetNodeID ID;
328 ImutInfo::Profile(ID,V);
329 digest += ID.ComputeHash();
330
331 if (R)
332 digest += R->computeDigest();
333
334 return digest;
335 }
336
337 uint32_t computeDigest() {
338 // Check the lowest bit to determine if digest has actually been
339 // pre-computed.
340 if (hasCachedDigest())
341 return digest.Digest;
342
343 uint32_t X = computeDigest(getLeft(), getRight(), getValue());
344 digest.Digest = X;
345 markedCachedDigest();
346 return X;
347 }
348
349 //===----------------------------------------------------===//
350 // Reference count operations.
351 //===----------------------------------------------------===//
352
353public:
354 void retain() { ++refCount; }
355
356 void release() {
357 assert(refCount > 0);
358 if (--refCount == 0)
359 destroy();
360 }
361
363 if (left)
364 left->release();
365 if (right)
366 right->release();
367 if constexpr (Canonicalize) {
368 if (IsCanonicalized) {
369 if (this->Next)
370 this->Next->Prev = this->Prev;
371
372 if (this->Prev)
373 this->Prev->Next = this->Next;
374 else
375 factory->Cache[factory->maskCacheIndex(computeDigest())] = this->Next;
376 }
377 }
378
379 // We need to clear the mutability bit in case we are
380 // destroying the node as part of a sweep in ImutAVLFactory::recoverNodes().
381 IsMutable = false;
382 factory->freeNodes.push_back(this);
383 }
384};
385
386template <typename ImutInfo, bool Canonicalize>
387struct IntrusiveRefCntPtrInfo<ImutAVLTree<ImutInfo, Canonicalize>> {
389 Tree->retain();
390 }
392 Tree->release();
393 }
394};
395
396//===----------------------------------------------------------------------===//
397// Immutable AVL-Tree Factory class.
398//===----------------------------------------------------------------------===//
399
400template <typename ImutInfo, bool Canonicalize>
402 : private ImutAVLDetail::CanonicalCache<ImutAVLTree<ImutInfo, Canonicalize>,
403 Canonicalize> {
404 friend class ImutAVLTree<ImutInfo, Canonicalize>;
405
407 using value_type_ref = typename TreeTy::value_type_ref;
408 using key_type_ref = typename TreeTy::key_type_ref;
409
410 uintptr_t Allocator;
411 std::vector<TreeTy*> createdNodes;
412 std::vector<TreeTy*> freeNodes;
413
414 bool ownsAllocator() const {
415 return (Allocator & 0x1) == 0;
416 }
417
418 BumpPtrAllocator& getAllocator() const {
419 return *reinterpret_cast<BumpPtrAllocator*>(Allocator & ~0x1);
420 }
421
422 //===--------------------------------------------------===//
423 // Public interface.
424 //===--------------------------------------------------===//
425
426public:
428 : Allocator(reinterpret_cast<uintptr_t>(new BumpPtrAllocator())) {}
429
431 : Allocator(reinterpret_cast<uintptr_t>(&Alloc) | 0x1) {}
432
434 if (ownsAllocator()) delete &getAllocator();
435 }
436
437 TreeTy* add(TreeTy* T, value_type_ref V) {
438 T = add_internal(V,T);
440 return T;
441 }
442
443 TreeTy* remove(TreeTy* T, key_type_ref V) {
444 T = remove_internal(V,T);
446 return T;
447 }
448
449 TreeTy* getEmptyTree() const { return nullptr; }
450
451protected:
452 //===--------------------------------------------------===//
453 // A bunch of quick helper functions used for reasoning
454 // about the properties of trees and their children.
455 // These have succinct names so that the balancing code
456 // is as terse (and readable) as possible.
457 //===--------------------------------------------------===//
458
459 bool isEmpty(TreeTy* T) const { return !T; }
460 unsigned getHeight(TreeTy* T) const { return T ? T->getHeight() : 0; }
461 TreeTy* getLeft(TreeTy* T) const { return T->getLeft(); }
462 TreeTy* getRight(TreeTy* T) const { return T->getRight(); }
463 value_type_ref getValue(TreeTy* T) const { return T->value; }
464
465 // Make sure the index is not the Tombstone or Entry key of the DenseMap.
466 static unsigned maskCacheIndex(unsigned I) { return (I & ~0x02); }
467
468 unsigned incrementHeight(TreeTy* L, TreeTy* R) const {
469 unsigned hl = getHeight(L);
470 unsigned hr = getHeight(R);
471 return (hl > hr ? hl : hr) + 1;
472 }
473
474 //===--------------------------------------------------===//
475 // "createNode" is used to generate new tree roots that link
476 // to other trees. The function may also simply move links
477 // in an existing root if that root is still marked mutable.
478 // This is necessary because otherwise our balancing code
479 // would leak memory as it would create nodes that are
480 // then discarded later before the finished tree is
481 // returned to the caller.
482 //===--------------------------------------------------===//
483
484 TreeTy* createNode(TreeTy* L, value_type_ref V, TreeTy* R) {
485 BumpPtrAllocator& A = getAllocator();
486 TreeTy* T;
487 if (!freeNodes.empty()) {
488 T = freeNodes.back();
489 freeNodes.pop_back();
490 assert(T != L);
491 assert(T != R);
492 } else {
493 T = (TreeTy*) A.Allocate<TreeTy>();
494 }
495 new (T) TreeTy(this, L, R, V, incrementHeight(L,R));
496 createdNodes.push_back(T);
497 return T;
498 }
499
500 TreeTy* createNode(TreeTy* newLeft, TreeTy* oldTree, TreeTy* newRight) {
501 return createNode(newLeft, getValue(oldTree), newRight);
502 }
503
504 void recoverNodes(TreeTy *Result) {
505 // Mark Result's nodes immutable and reclaim the intermediates discarded
506 // during balancing, in one pass. Nodes are built bottom-up, so a node
507 // precedes its parents in createdNodes; visiting in reverse thus reaches
508 // each node only once its reference count is final. Unreferenced nodes are
509 // unreachable and destroyed; the rest belong to Result. Result is kept
510 // despite its zero count -- the caller has not taken ownership yet.
511 for (TreeTy *N : llvm::reverse(createdNodes)) {
512 if (!N->isMutable())
513 continue; // Already reclaimed while destroying an unreachable parent.
514 if (N != Result && N->refCount == 0)
515 N->destroy();
516 else
517 N->markImmutable();
518 }
519 createdNodes.clear();
520 }
521
522 /// Used by add_internal and remove_internal to balance a newly created tree.
523 TreeTy* balanceTree(TreeTy* L, value_type_ref V, TreeTy* R) {
524 unsigned hl = getHeight(L);
525 unsigned hr = getHeight(R);
526
527 if (hl > hr + 2) {
528 assert(!isEmpty(L) && "Left tree cannot be empty to have a height >= 2");
529
530 TreeTy *LL = getLeft(L);
531 TreeTy *LR = getRight(L);
532
533 if (getHeight(LL) >= getHeight(LR))
534 return createNode(LL, L, createNode(LR,V,R));
535
536 assert(!isEmpty(LR) && "LR cannot be empty because it has a height >= 1");
537
538 TreeTy *LRL = getLeft(LR);
539 TreeTy *LRR = getRight(LR);
540
541 return createNode(createNode(LL,L,LRL), LR, createNode(LRR,V,R));
542 }
543
544 if (hr > hl + 2) {
545 assert(!isEmpty(R) && "Right tree cannot be empty to have a height >= 2");
546
547 TreeTy *RL = getLeft(R);
548 TreeTy *RR = getRight(R);
549
550 if (getHeight(RR) >= getHeight(RL))
551 return createNode(createNode(L,V,RL), R, RR);
552
553 assert(!isEmpty(RL) && "RL cannot be empty because it has a height >= 1");
554
555 TreeTy *RLL = getLeft(RL);
556 TreeTy *RLR = getRight(RL);
557
558 return createNode(createNode(L,V,RLL), RL, createNode(RLR,R,RR));
559 }
560
561 return createNode(L,V,R);
562 }
563
564 /// add_internal - Creates a new tree that includes the specified
565 /// data and the data from the original tree. If the original tree
566 /// already contained the data item, the original tree is returned.
567 TreeTy *add_internal(value_type_ref V, TreeTy *T) {
568 if (isEmpty(T))
569 return createNode(T, V, T);
570 assert(!T->isMutable());
571
572 key_type_ref K = ImutInfo::KeyOfValue(V);
573 key_type_ref KCurrent = ImutInfo::KeyOfValue(getValue(T));
574
575 if (ImutInfo::isEqual(K, KCurrent)) {
576 // If both key and value are same, return the original tree.
577 if (ImutInfo::isDataEqual(ImutInfo::DataOfValue(V),
578 ImutInfo::DataOfValue(getValue(T))))
579 return T;
580 // Otherwise create a new node with the new value.
581 return createNode(getLeft(T), V, getRight(T));
582 }
583
584 TreeTy *NewL = getLeft(T);
585 TreeTy *NewR = getRight(T);
586 if (ImutInfo::isLess(K, KCurrent))
587 NewL = add_internal(V, NewL);
588 else
589 NewR = add_internal(V, NewR);
590
591 // If no changes were made, return the original tree. Otherwise, balance the
592 // tree and return the new root.
593 return NewL == getLeft(T) && NewR == getRight(T)
594 ? T
595 : balanceTree(NewL, getValue(T), NewR);
596 }
597
598 /// remove_internal - Creates a new tree that includes all the data
599 /// from the original tree except the specified data. If the
600 /// specified data did not exist in the original tree, the original
601 /// tree is returned.
602 TreeTy *remove_internal(key_type_ref K, TreeTy *T) {
603 if (isEmpty(T))
604 return T;
605
606 assert(!T->isMutable());
607
608 key_type_ref KCurrent = ImutInfo::KeyOfValue(getValue(T));
609
610 if (ImutInfo::isEqual(K, KCurrent))
611 return combineTrees(getLeft(T), getRight(T));
612
613 TreeTy *NewL = getLeft(T);
614 TreeTy *NewR = getRight(T);
615 if (ImutInfo::isLess(K, KCurrent))
616 NewL = remove_internal(K, NewL);
617 else
618 NewR = remove_internal(K, NewR);
619
620 // If no changes were made, return the original tree. Otherwise, balance the
621 // tree and return the new root.
622 return NewL == getLeft(T) && NewR == getRight(T)
623 ? T
624 : balanceTree(NewL, getValue(T), NewR);
625 }
626
627 TreeTy* combineTrees(TreeTy* L, TreeTy* R) {
628 if (isEmpty(L))
629 return R;
630 if (isEmpty(R))
631 return L;
632 TreeTy* OldNode;
633 TreeTy* newRight = removeMinBinding(R,OldNode);
634 return balanceTree(L, getValue(OldNode), newRight);
635 }
636
637 TreeTy* removeMinBinding(TreeTy* T, TreeTy*& Noderemoved) {
638 assert(!isEmpty(T));
639 if (isEmpty(getLeft(T))) {
640 Noderemoved = T;
641 return getRight(T);
642 }
643 return balanceTree(removeMinBinding(getLeft(T), Noderemoved),
644 getValue(T), getRight(T));
645 }
646
647public:
648 TreeTy *getCanonicalTree(TreeTy *TNew) {
649 static_assert(Canonicalize,
650 "getCanonicalTree requires a canonicalizing factory");
651 if (!TNew)
652 return nullptr;
653
654 if (TNew->IsCanonicalized)
655 return TNew;
656
657 // Search the hashtable for another tree with the same digest, and
658 // if find a collision compare those trees by their contents.
659 unsigned digest = TNew->computeDigest();
660 TreeTy *&entry = this->Cache[maskCacheIndex(digest)];
661 if (entry) {
662 for (TreeTy *T = entry; T != nullptr; T = T->Next) {
663 // Compare the contents of 'T' with 'TNew'. isEqual skips subtrees that
664 // are shared by pointer, so for structurally-shared persistent trees
665 // (the common case, e.g. one derived from the other) this is linear in
666 // the number of differing nodes rather than in the tree size.
667 if (!TNew->isEqual(*T))
668 continue;
669 // Trees did match! Return 'T'.
670 if (TNew->refCount == 0)
671 TNew->destroy();
672 return T;
673 }
674 entry->Prev = TNew;
675 TNew->Next = entry;
676 }
677
678 entry = TNew;
679 TNew->IsCanonicalized = true;
680 return TNew;
681 }
682};
683
684//===----------------------------------------------------------------------===//
685// Immutable AVL-Tree Iterator.
686//===----------------------------------------------------------------------===//
687
688/// Bidirectional in-order iterator over the nodes of an ImutAVLTree.
689///
690/// The iterator keeps the chain of ancestors from the root down to the current
691/// node on an explicit stack of plain node pointers, and decides which way to
692/// move next by inspecting whether it is ascending from a node's left or right
693/// child. This avoids storing any per-node visit-state: there is no need to
694/// remember "have I already visited this node's left/right subtree", because
695/// that is recovered by comparing the child we just left against the parent's
696/// left and right pointers.
697///
698/// A node's parent cannot be cached in the node itself, because these trees are
699/// persistent and structurally shared: a single node may appear as the child of
700/// different parents across different tree versions. The ancestor stack is
701/// therefore the per-traversal parent chain.
702template <typename ImutInfo, bool Canonicalize>
704public:
705 using iterator_category = std::bidirectional_iterator_tag;
707 using difference_type = std::ptrdiff_t;
710
712
713private:
714 // Path[0] is the root and Path.back() is the current node. An empty path is
715 // the end iterator. The invariant is that Path always holds the exact chain
716 // of ancestors of the current node, root-most first.
718
719 // Descend along left children, pushing each node; lands on the minimum of the
720 // subtree rooted at T (i.e. the first node in an in-order traversal of T).
721 void descendToMin(TreeTy *T) {
722 for (; T; T = T->getLeft())
723 Path.push_back(T);
724 }
725
726 // Descend along right children, pushing each node; lands on the maximum of
727 // the subtree rooted at T (i.e. the last node in an in-order traversal of T).
728 void descendToMax(TreeTy *T) {
729 for (; T; T = T->getRight())
730 Path.push_back(T);
731 }
732
733 // Pop the current node and ascend until we reach an ancestor from its *left*
734 // child, i.e. the first ancestor whose subtree is not yet fully visited. That
735 // ancestor is the in-order successor of the subtree we just left; if there is
736 // none, Path is emptied (the end iterator). Shared by operator++ and
737 // skipSubTree, whose only difference is whether the current node's right
738 // subtree is descended into first.
739 void ascendFromRightChild() {
740 TreeTy *Child = Path.pop_back_val();
741 while (!Path.empty() && Path.back()->getRight() == Child)
742 Child = Path.pop_back_val();
743 }
744
745 // Mirror of ascendFromRightChild for reverse traversal (operator--).
746 void ascendFromLeftChild() {
747 TreeTy *Child = Path.pop_back_val();
748 while (!Path.empty() && Path.back()->getLeft() == Child)
749 Child = Path.pop_back_val();
750 }
751
752public:
753 ImutAVLTreeInOrderIterator() = default; // end() iterator.
755 descendToMin(const_cast<TreeTy *>(Root));
756 }
757
758 // Two iterators are equal iff they sit on the same node (or are both end()).
759 // Within a single tree a node has a unique root-to-node path, so the current
760 // node alone identifies the position; comparing the whole path is therefore
761 // unnecessary. Comparing iterators from different trees is not meaningful, as
762 // for any standard container.
764 if (Path.empty() || x.Path.empty())
765 return Path.empty() == x.Path.empty();
766 return Path.back() == x.Path.back();
767 }
769 return !(*this == x);
770 }
771
772 TreeTy &operator*() const { return *Path.back(); }
773 TreeTy *operator->() const { return Path.back(); }
774
776 assert(!Path.empty() && "Incrementing the end iterator");
777 if (TreeTy *R = Path.back()->getRight())
778 // The in-order successor is the minimum of the right subtree.
779 descendToMin(R);
780 else
781 // No right subtree: the successor is the nearest ancestor reached from a
782 // left child.
783 ascendFromRightChild();
784 return *this;
785 }
786
788 assert(!Path.empty() && "Decrementing the end iterator");
789 if (TreeTy *L = Path.back()->getLeft())
790 // The in-order predecessor is the maximum of the left subtree.
791 descendToMax(L);
792 else
793 // Mirror of operator++.
794 ascendFromLeftChild();
795 return *this;
796 }
797
798 /// Move to the in-order successor of the entire subtree rooted at the current
799 /// node, i.e. skip the current node together with its right subtree. This is
800 /// exactly the ascent half of operator++.
801 void skipSubTree() {
802 assert(!Path.empty() && "Skipping past the end iterator");
803 ascendFromRightChild();
804 }
805};
806
807/// Generic iterator that wraps a T::TreeTy::iterator and exposes
808/// iterator::getValue() on dereference.
809template <typename T>
812 ImutAVLValueIterator<T>, typename T::TreeTy::iterator,
813 typename std::iterator_traits<
814 typename T::TreeTy::iterator>::iterator_category,
815 const typename T::value_type> {
819
821 return this->I->getValue();
822 }
823};
824
825//===----------------------------------------------------------------------===//
826// Trait classes for Profile information.
827//===----------------------------------------------------------------------===//
828
829/// Generic profile template. The default behavior is to invoke the
830/// profile method of an object. Specializations for primitive integers
831/// and generic handling of pointers is done below.
832template <typename T>
834 using value_type = const T;
835 using value_type_ref = const T&;
836
840};
841
842/// Profile traits for integers.
843template <typename T>
845 using value_type = const T;
846 using value_type_ref = const T&;
847
849 ID.AddInteger(X);
850 }
851};
852
853#define PROFILE_INTEGER_INFO(X)\
854template<> struct ImutProfileInfo<X> : ImutProfileInteger<X> {};
855
857PROFILE_INTEGER_INFO(unsigned char)
859PROFILE_INTEGER_INFO(unsigned short)
860PROFILE_INTEGER_INFO(unsigned)
863PROFILE_INTEGER_INFO(unsigned long)
864PROFILE_INTEGER_INFO(long long)
865PROFILE_INTEGER_INFO(unsigned long long)
866
867#undef PROFILE_INTEGER_INFO
868
869/// Profile traits for booleans.
870template <>
872 using value_type = const bool;
873 using value_type_ref = const bool&;
874
876 ID.AddBoolean(X);
877 }
878};
879
880/// Generic profile trait for pointer types. We treat pointers as
881/// references to unique objects.
882template <typename T>
884 using value_type = const T*;
886
888 ID.AddPointer(X);
889 }
890};
891
892//===----------------------------------------------------------------------===//
893// Trait classes that contain element comparison operators and type
894// definitions used by ImutAVLTree, ImmutableSet, and ImmutableMap. These
895// inherit from the profile traits (ImutProfileInfo) to include operations
896// for element profiling.
897//===----------------------------------------------------------------------===//
898
899/// Generic definition of comparison operations for elements of immutable
900/// containers that defaults to using std::equal_to<> and std::less<> to perform
901/// comparison of elements.
902template <typename T> struct ImutContainerInfo : ImutProfileInfo<T> {
909
911 static data_type_ref DataOfValue(value_type_ref) { return true; }
912
914 return std::equal_to<key_type>()(LHS,RHS);
915 }
916
918 return std::less<key_type>()(LHS,RHS);
919 }
920
921 static bool isDataEqual(data_type_ref, data_type_ref) { return true; }
922};
923
924/// Specialization for pointer values to treat pointers as references to unique
925/// objects. Pointers are thus compared by their addresses.
926template <typename T> struct ImutContainerInfo<T *> : ImutProfileInfo<T *> {
933
935 static data_type_ref DataOfValue(value_type_ref) { return true; }
936
937 static bool isEqual(key_type_ref LHS, key_type_ref RHS) { return LHS == RHS; }
938
939 static bool isLess(key_type_ref LHS, key_type_ref RHS) { return LHS < RHS; }
940
941 static bool isDataEqual(data_type_ref, data_type_ref) { return true; }
942};
943
944//===----------------------------------------------------------------------===//
945// Immutable Set
946//===----------------------------------------------------------------------===//
947
948template <typename ValT, typename ValInfo = ImutContainerInfo<ValT>,
949 bool Canonicalize = true>
951public:
952 using value_type = typename ValInfo::value_type;
953 using value_type_ref = typename ValInfo::value_type_ref;
955
956private:
958
959public:
960 /// Constructs a set from a pointer to a tree root. In general one
961 /// should use a Factory object to create sets instead of directly
962 /// invoking the constructor, but there are cases where make this
963 /// constructor public is useful.
964 explicit ImmutableSet(TreeTy *R) : Root(R) {}
965
966 class Factory {
967 typename TreeTy::Factory F;
968
969 public:
970 Factory() = default;
971
973
974 Factory(const Factory& RHS) = delete;
975 void operator=(const Factory& RHS) = delete;
976
977 /// Returns an immutable set that contains no elements.
979 return ImmutableSet(F.getEmptyTree());
980 }
981
982 /// Creates a new immutable set that contains all of the values
983 /// of the original set with the addition of the specified value. If
984 /// the original set already included the value, then the original set is
985 /// returned and no memory is allocated. The time and space complexity
986 /// of this operation is logarithmic in the size of the original set.
987 /// The memory allocated to represent the set is released when the
988 /// factory object that created the set is destroyed.
990 TreeTy *NewT = F.add(Old.Root.get(), V);
991 if constexpr (Canonicalize)
992 return ImmutableSet(F.getCanonicalTree(NewT));
993 else
994 return ImmutableSet(NewT);
995 }
996
997 /// Creates a new immutable set that contains all of the values
998 /// of the original set with the exception of the specified value. If
999 /// the original set did not contain the value, the original set is
1000 /// returned and no memory is allocated. The time and space complexity
1001 /// of this operation is logarithmic in the size of the original set.
1002 /// The memory allocated to represent the set is released when the
1003 /// factory object that created the set is destroyed.
1005 TreeTy *NewT = F.remove(Old.Root.get(), V);
1006 if constexpr (Canonicalize)
1007 return ImmutableSet(F.getCanonicalTree(NewT));
1008 else
1009 return ImmutableSet(NewT);
1010 }
1011
1012 BumpPtrAllocator& getAllocator() { return F.getAllocator(); }
1013
1015 return const_cast<typename TreeTy::Factory *>(&F);
1016 }
1017 };
1018
1019 friend class Factory;
1020
1021 /// Returns true if the set contains the specified value.
1022 bool contains(value_type_ref V) const {
1023 return Root ? Root->contains(V) : false;
1024 }
1025
1026 /// Compares two sets for equality. For a canonicalizing factory, sets with
1027 /// equal contents share the same tree, so this is an O(1) pointer comparison
1028 /// (like ImmutableList); only sets created by the same factory may be
1029 /// compared. Otherwise it is a structural comparison.
1030 bool operator==(const ImmutableSet &RHS) const {
1031 if constexpr (Canonicalize)
1032 return Root == RHS.Root;
1033 else
1034 return Root && RHS.Root ? Root->isEqual(*RHS.Root.get())
1035 : Root == RHS.Root;
1036 }
1037
1038 bool operator!=(const ImmutableSet &RHS) const {
1039 if constexpr (Canonicalize)
1040 return Root != RHS.Root;
1041 else
1042 return Root && RHS.Root ? Root->isNotEqual(*RHS.Root.get())
1043 : Root != RHS.Root;
1044 }
1045
1047 if (Root) { Root->retain(); }
1048 return Root.get();
1049 }
1050
1051 TreeTy *getRootWithoutRetain() const { return Root.get(); }
1052
1053 /// Return true if the set contains no elements.
1054 bool isEmpty() const { return !Root; }
1055
1056 /// Return true if the set contains exactly one element.
1057 /// This method runs in constant time.
1058 bool isSingleton() const { return getHeight() == 1; }
1059
1060 //===--------------------------------------------------===//
1061 // Iterators.
1062 //===--------------------------------------------------===//
1063
1065
1066 iterator begin() const { return iterator(Root.get()); }
1067 iterator end() const { return iterator(); }
1068
1069 //===--------------------------------------------------===//
1070 // Utility methods.
1071 //===--------------------------------------------------===//
1072
1073 unsigned getHeight() const { return Root ? Root->getHeight() : 0; }
1074
1075 static void Profile(FoldingSetNodeID &ID, const ImmutableSet &S) {
1076 ID.AddPointer(S.Root.get());
1077 }
1078
1079 void Profile(FoldingSetNodeID &ID) const { return Profile(ID, *this); }
1080
1081 //===--------------------------------------------------===//
1082 // For testing.
1083 //===--------------------------------------------------===//
1084
1085 void validateTree() const { if (Root) Root->validateTree(); }
1086};
1087
1088// NOTE: This may some day replace the current ImmutableSet.
1089template <typename ValT, typename ValInfo = ImutContainerInfo<ValT>,
1090 bool Canonicalize = true>
1092public:
1093 using value_type = typename ValInfo::value_type;
1094 using value_type_ref = typename ValInfo::value_type_ref;
1096 using FactoryTy = typename TreeTy::Factory;
1097
1098private:
1100 FactoryTy *Factory;
1101
1102public:
1103 /// Constructs a set from a pointer to a tree root. In general one
1104 /// should use a Factory object to create sets instead of directly
1105 /// invoking the constructor, but there are cases where make this
1106 /// constructor public is useful.
1107 ImmutableSetRef(TreeTy *R, FactoryTy *F) : Root(R), Factory(F) {}
1108
1110 return ImmutableSetRef(0, F);
1111 }
1112
1114 return ImmutableSetRef(Factory->add(Root.get(), V), Factory);
1115 }
1116
1118 return ImmutableSetRef(Factory->remove(Root.get(), V), Factory);
1119 }
1120
1121 /// Returns true if the set contains the specified value.
1122 bool contains(value_type_ref V) const {
1123 return Root ? Root->contains(V) : false;
1124 }
1125
1128 if constexpr (Canonicalize)
1129 return SetTy(Factory->getCanonicalTree(Root.get()));
1130 else
1131 return SetTy(Root.get());
1132 }
1133
1134 TreeTy *getRootWithoutRetain() const { return Root.get(); }
1135
1136 bool operator==(const ImmutableSetRef &RHS) const {
1137 return Root && RHS.Root ? Root->isEqual(*RHS.Root.get()) : Root == RHS.Root;
1138 }
1139
1140 bool operator!=(const ImmutableSetRef &RHS) const {
1141 return Root && RHS.Root ? Root->isNotEqual(*RHS.Root.get())
1142 : Root != RHS.Root;
1143 }
1144
1145 /// Return true if the set contains no elements.
1146 bool isEmpty() const { return !Root; }
1147
1148 /// Return true if the set contains exactly one element.
1149 /// This method runs in constant time.
1150 bool isSingleton() const { return getHeight() == 1; }
1151
1152 //===--------------------------------------------------===//
1153 // Iterators.
1154 //===--------------------------------------------------===//
1155
1157
1158 iterator begin() const { return iterator(Root.get()); }
1159 iterator end() const { return iterator(); }
1160
1161 //===--------------------------------------------------===//
1162 // Utility methods.
1163 //===--------------------------------------------------===//
1164
1165 unsigned getHeight() const { return Root ? Root->getHeight() : 0; }
1166
1167 static void Profile(FoldingSetNodeID &ID, const ImmutableSetRef &S) {
1168 ID.AddPointer(S.Root.get());
1169 }
1170
1171 void Profile(FoldingSetNodeID &ID) const { return Profile(ID, *this); }
1172
1173 //===--------------------------------------------------===//
1174 // For testing.
1175 //===--------------------------------------------------===//
1176
1177 void validateTree() const { if (Root) Root->validateTree(); }
1178};
1179
1180} // end namespace llvm
1181
1182#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
#define LLVM_NO_UNIQUE_ADDRESS
Definition Compiler.h:475
#define LLVM_ATTRIBUTE_NOINLINE
LLVM_ATTRIBUTE_NOINLINE - On compilers where we have a directive to do so, mark a method "not for inl...
Definition Compiler.h:348
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
unsigned getHeight() const
bool operator==(const ImmutableSetRef &RHS) const
ImmutableSet< ValT, ValInfo, Canonicalize > asImmutableSet() const
ImutAVLTree< ValInfo, Canonicalize > TreeTy
bool contains(value_type_ref V) const
Returns true if the set contains the specified value.
bool operator!=(const ImmutableSetRef &RHS) const
typename ValInfo::value_type_ref value_type_ref
ImmutableSetRef(TreeTy *R, FactoryTy *F)
Constructs a set from a pointer to a tree root.
void Profile(FoldingSetNodeID &ID) const
bool isEmpty() const
Return true if the set contains no elements.
iterator end() const
TreeTy * getRootWithoutRetain() const
void validateTree() const
typename TreeTy::Factory FactoryTy
static ImmutableSetRef getEmptySet(FactoryTy *F)
ImmutableSetRef remove(value_type_ref V)
typename ValInfo::value_type value_type
iterator begin() const
ImutAVLValueIterator< ImmutableSetRef > iterator
static void Profile(FoldingSetNodeID &ID, const ImmutableSetRef &S)
bool isSingleton() const
Return true if the set contains exactly one element.
ImmutableSetRef add(value_type_ref V)
Factory(BumpPtrAllocator &Alloc)
void operator=(const Factory &RHS)=delete
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 ...
BumpPtrAllocator & getAllocator()
Factory(const Factory &RHS)=delete
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 getEmptySet()
Returns an immutable set that contains no elements.
TreeTy::Factory * getTreeFactory() const
TreeTy * getRootWithoutRetain() const
bool isEmpty() const
Return true if the set contains no elements.
bool isSingleton() const
Return true if the set contains exactly one element.
static void Profile(FoldingSetNodeID &ID, const ImmutableSet &S)
bool contains(value_type_ref V) const
Returns true if the set contains the specified value.
iterator end() const
ImutAVLTree< ValInfo, Canonicalize > TreeTy
ImmutableSet(TreeTy *R)
Constructs a set from a pointer to a tree root.
bool operator!=(const ImmutableSet &RHS) const
iterator begin() const
typename ValInfo::value_type_ref value_type_ref
unsigned getHeight() const
ImutAVLValueIterator< ImmutableSet > iterator
bool operator==(const ImmutableSet &RHS) const
Compares two sets for equality.
void validateTree() const
void Profile(FoldingSetNodeID &ID) const
typename ValInfo::value_type value_type
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...
ImutAVLFactory(BumpPtrAllocator &Alloc)
unsigned incrementHeight(TreeTy *L, TreeTy *R) const
TreeTy * remove(TreeTy *T, key_type_ref V)
TreeTy * getLeft(TreeTy *T) const
TreeTy * getEmptyTree() const
TreeTy * createNode(TreeTy *newLeft, TreeTy *oldTree, TreeTy *newRight)
unsigned getHeight(TreeTy *T) const
value_type_ref getValue(TreeTy *T) const
bool isEmpty(TreeTy *T) const
TreeTy * combineTrees(TreeTy *L, TreeTy *R)
TreeTy * balanceTree(TreeTy *L, value_type_ref V, TreeTy *R)
Used by add_internal and remove_internal to balance a newly created tree.
void recoverNodes(TreeTy *Result)
TreeTy * add(TreeTy *T, value_type_ref V)
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 * getCanonicalTree(TreeTy *TNew)
TreeTy * removeMinBinding(TreeTy *T, TreeTy *&Noderemoved)
TreeTy * getRight(TreeTy *T) const
TreeTy * createNode(TreeTy *L, value_type_ref V, TreeTy *R)
static unsigned maskCacheIndex(unsigned I)
Bidirectional in-order iterator over the nodes of an ImutAVLTree.
bool operator!=(const ImutAVLTreeInOrderIterator &x) const
ImutAVLTree< ImutInfo, Canonicalize > value_type
ImutAVLTree< ImutInfo, Canonicalize > TreeTy
ImutAVLTreeInOrderIterator & operator++()
void skipSubTree()
Move to the in-order successor of the entire subtree rooted at the current node, i....
ImutAVLTreeInOrderIterator & operator--()
std::bidirectional_iterator_tag iterator_category
bool operator==(const ImutAVLTreeInOrderIterator &x) const
ImutAVLTreeInOrderIterator(const TreeTy *Root)
unsigned getHeight() const
Returns the height of the tree. A tree with no subtrees has a height of 1.
iterator end() const
Returns an iterator for the tree that denotes the end of an inorder traversal.
typename ValInfo::key_type_ref key_type_ref
ImutAVLTreeInOrderIterator< ValInfo, Canonicalize > iterator
ImutAVLTree * find(key_type_ref K)
Finds the subtree associated with the specified key value.
typename ValInfo::value_type value_type
bool isNotEqual(const ImutAVLTree &RHS) const
Compares two trees for structural inequality.
bool contains(key_type_ref K)
Returns true if this tree contains a subtree (node) that has an data element that matches the specifi...
unsigned size() const
Returns the number of nodes in the tree, which includes both leaves and.
ImutAVLTree * getRight() const
Return a pointer to the right subtree.
ImutAVLTree * getMaxElement()
Find the subtree associated with the highest ranged key value.
ImutAVLFactory< ValInfo, Canonicalize > Factory
bool isElementEqual(const ImutAVLTree *RHS) const
LLVM_ATTRIBUTE_NOINLINE void destroy()
bool isEqual(const ImutAVLTree &RHS) const
Compares two trees for structural equality and returns true if they are equal.
unsigned validateTree() const
A utility method that checks that the balancing and ordering invariants of the tree are satisfied.
const value_type & getValue() const
Returns the data value associated with the tree node.
bool isElementEqual(value_type_ref V) const
typename ValInfo::value_type_ref value_type_ref
iterator begin() const
Returns an iterator that iterates over the nodes of the tree in an inorder traversal.
ImutAVLTree * getLeft() const
Return a pointer to the left subtree.
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
The factory-side canonicalization cache: digest -> tree chain.
DenseMap< unsigned, Tree * > Cache
The cached structural digest, used only for canonicalization.
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, Canonicalize > *Tree)
Class you can specialize to provide custom retain/release functionality for a type.