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, bool Canonicalize = true>
44
45namespace ImutAVLDetail {
46/// The intrusive doubly-linked chain of same-digest trees in the factory's
47/// canonicalization cache. Held as an (empty) base so that, when
48/// canonicalization is disabled, the empty base optimization removes it
49/// entirely. Kept separate from the cached digest below so that the two
50/// pointers pack without the tail padding that grouping a trailing 32-bit field
51/// with them would introduce.
52template <typename Tree, bool Canonicalize> struct CanonicalLinks {
53 Tree *Prev = nullptr;
54 Tree *Next = nullptr;
55};
56template <typename Tree> struct CanonicalLinks<Tree, false> {};
57
58/// The cached structural digest, used only for canonicalization. Stored as an
59/// LLVM_NO_UNIQUE_ADDRESS member so it occupies no space when disabled and
60/// packs alongside the adjacent 32-bit fields when enabled.
61template <bool Canonicalize> struct CanonicalDigest {
63};
64template <> struct CanonicalDigest<false> {};
65
66/// The factory-side canonicalization cache: digest -> tree chain.
67/// Empty when canonicalization is disabled.
68template <typename Tree, bool Canonicalize> struct CanonicalCache {
70};
71template <typename Tree> struct CanonicalCache<Tree, false> {};
72} // namespace ImutAVLDetail
73
74template <typename ImutInfo, bool Canonicalize = true>
75class ImutAVLTree
76 : private ImutAVLDetail::CanonicalLinks<ImutAVLTree<ImutInfo, Canonicalize>,
77 Canonicalize> {
78public:
79 using key_type_ref = typename ImutInfo::key_type_ref;
80 using value_type = typename ImutInfo::value_type;
81 using value_type_ref = typename ImutInfo::value_type_ref;
84
85 friend class ImutAVLFactory<ImutInfo, Canonicalize>;
86
87private:
89
90public:
91 //===----------------------------------------------------===//
92 // Public Interface.
93 //===----------------------------------------------------===//
94
95 /// Return a pointer to the left subtree. This value
96 /// is NULL if there is no left subtree.
97 ImutAVLTree *getLeft() const { return left; }
98
99 /// Return a pointer to the right subtree. This value is
100 /// NULL if there is no right subtree.
101 ImutAVLTree *getRight() const { return right; }
102
103 /// Returns the height of the tree. A tree with no subtrees has a height of 1.
104 unsigned getHeight() const { return height; }
105
106 /// Returns the data value associated with the tree node.
107 const value_type& getValue() const { return value; }
108
109 /// Finds the subtree associated with the specified key value. This method
110 /// returns NULL if no matching subtree is found.
111 ImutAVLTree* find(key_type_ref K) {
112 ImutAVLTree *T = this;
113 while (T) {
114 key_type_ref CurrentKey = ImutInfo::KeyOfValue(T->getValue());
115 if (ImutInfo::isEqual(K,CurrentKey))
116 return T;
117 else if (ImutInfo::isLess(K,CurrentKey))
118 T = T->getLeft();
119 else
120 T = T->getRight();
121 }
122 return nullptr;
123 }
124
125 /// Find the subtree associated with the highest ranged key value.
126 ImutAVLTree* getMaxElement() {
127 ImutAVLTree *T = this;
128 ImutAVLTree *Right = T->getRight();
129 while (Right) { T = Right; Right = T->getRight(); }
130 return T;
131 }
132
133 /// Returns the number of nodes in the tree, which includes both leaves and
134 // non-leaf nodes.
135 unsigned size() const {
136 unsigned n = 1;
137 if (const ImutAVLTree* L = getLeft())
138 n += L->size();
139 if (const ImutAVLTree* R = getRight())
140 n += R->size();
141 return n;
142 }
143
144 /// Returns an iterator that iterates over the nodes of the tree in an inorder
145 /// traversal. The returned iterator thus refers to the tree node with the
146 /// minimum data element.
147 iterator begin() const { return iterator(this); }
148
149 /// Returns an iterator for the tree that denotes the end of an inorder
150 /// traversal.
151 iterator end() const { return iterator(); }
152
154 // Compare the keys.
155 if (!ImutInfo::isEqual(ImutInfo::KeyOfValue(getValue()),
156 ImutInfo::KeyOfValue(V)))
157 return false;
158
159 // Also compare the data values.
160 if (!ImutInfo::isDataEqual(ImutInfo::DataOfValue(getValue()),
161 ImutInfo::DataOfValue(V)))
162 return false;
163
164 return true;
165 }
166
167 bool isElementEqual(const ImutAVLTree* RHS) const {
168 return isElementEqual(RHS->getValue());
169 }
170
171 /// Compares two trees for structural equality and returns true if they are
172 /// equal. The worst case performance of this operation is linear in the sizes
173 /// of the trees.
174 bool isEqual(const ImutAVLTree& RHS) const {
175 if (&RHS == this)
176 return true;
177
178 iterator LItr = begin(), LEnd = end();
179 iterator RItr = RHS.begin(), REnd = RHS.end();
180
181 while (LItr != LEnd && RItr != REnd) {
182 if (&*LItr == &*RItr) {
183 LItr.skipSubTree();
184 RItr.skipSubTree();
185 continue;
186 }
187
188 if (!LItr->isElementEqual(&*RItr))
189 return false;
190
191 ++LItr;
192 ++RItr;
193 }
194
195 return LItr == LEnd && RItr == REnd;
196 }
197
198 /// Compares two trees for structural inequality. Performance is the same as
199 /// isEqual.
200 bool isNotEqual(const ImutAVLTree& RHS) const { return !isEqual(RHS); }
201
202 /// Returns true if this tree contains a subtree (node) that has an data
203 /// element that matches the specified key. Complexity is logarithmic in the
204 /// size of the tree.
205 bool contains(key_type_ref K) { return (bool) find(K); }
206
207 /// A utility method that checks that the balancing and ordering invariants of
208 /// the tree are satisfied. It is a recursive method that returns the height
209 /// of the tree, which is then consumed by the enclosing validateTree call.
210 /// External callers should ignore the return value. An invalid tree will
211 /// cause an assertion to fire in a debug build.
212 unsigned validateTree() const {
213 unsigned HL = getLeft() ? getLeft()->validateTree() : 0;
214 unsigned HR = getRight() ? getRight()->validateTree() : 0;
215 (void) HL;
216 (void) HR;
217
218 assert(getHeight() == ( HL > HR ? HL : HR ) + 1
219 && "Height calculation wrong");
220
221 assert((HL > HR ? HL-HR : HR-HL) <= 2
222 && "Balancing invariant violated");
223
224 assert((!getLeft() ||
225 ImutInfo::isLess(ImutInfo::KeyOfValue(getLeft()->getValue()),
226 ImutInfo::KeyOfValue(getValue()))) &&
227 "Value in left child is not less that current value");
228
229 assert((!getRight() ||
230 ImutInfo::isLess(ImutInfo::KeyOfValue(getValue()),
231 ImutInfo::KeyOfValue(getRight()->getValue()))) &&
232 "Current value is not less that value of right child");
233
234 return getHeight();
235 }
236
237 //===----------------------------------------------------===//
238 // Internal values.
239 //===----------------------------------------------------===//
240
241private:
242 // Field order places the traversal-hot fields (left, right, value) first so
243 // that in a node that straddles a cache line they land in the earlier line;
244 // the cold factory back-pointer (only touched on create/destroy) goes last.
245 ImutAVLTree *left;
246 ImutAVLTree *right;
247
248 unsigned height : 28;
250 unsigned IsMutable : 1;
252 unsigned IsDigestCached : 1;
254 unsigned IsCanonicalized : 1;
255
256 value_type value;
257 uint32_t refCount = 0;
259 Factory *factory;
260
261 //===----------------------------------------------------===//
262 // Internal methods (node manipulation; used by Factory).
263 //===----------------------------------------------------===//
264
265private:
266 /// Internal constructor that is only called by ImutAVLFactory.
268 unsigned height)
269 : left(l), right(r), height(height), IsMutable(true),
270 IsDigestCached(false), IsCanonicalized(false), value(v), factory(f) {
271 if (left) left->retain();
272 if (right) right->retain();
273 }
274
275 /// Returns true if the left and right subtree references
276 /// (as well as height) can be changed. If this method returns false,
277 /// the tree is truly immutable. Trees returned from an ImutAVLFactory
278 /// object should always have this method return true. Further, if this
279 /// method returns false for an instance of ImutAVLTree, all subtrees
280 /// will also have this method return false. The converse is not true.
281 bool isMutable() const { return IsMutable; }
282
283 /// Returns true if the digest for this tree is cached. This can only be true
284 /// if the tree is immutable.
285 bool hasCachedDigest() const { return IsDigestCached; }
286
287 //===----------------------------------------------------===//
288 // Mutating operations. A tree root can be manipulated as
289 // long as its reference has not "escaped" from internal
290 // methods of a factory object (see below). When a tree
291 // pointer is externally viewable by client code, the
292 // internal "mutable bit" is cleared to mark the tree
293 // immutable. Note that a tree that still has its mutable
294 // bit set may have children (subtrees) that are themselves
295 // immutable.
296 //===----------------------------------------------------===//
297
298 /// Clears the mutable flag for a tree. After this happens,
299 /// it is an error to call setLeft(), setRight(), and setHeight().
300 void markImmutable() {
301 assert(isMutable() && "Mutable flag already removed.");
302 IsMutable = false;
303 }
304
305 /// Clears the NoCachedDigest flag for a tree.
306 void markedCachedDigest() {
307 assert(!hasCachedDigest() && "NoCachedDigest flag already removed.");
308 IsDigestCached = true;
309 }
310
311 /// Changes the height of the tree. Used internally by ImutAVLFactory.
312 void setHeight(unsigned h) {
313 assert(isMutable() && "Only a mutable tree can have its height changed.");
314 height = h;
315 }
316
317 static uint32_t computeDigest(ImutAVLTree *L, ImutAVLTree *R,
319 uint32_t digest = 0;
320
321 if (L)
322 digest += L->computeDigest();
323
324 // Compute digest of stored data.
325 FoldingSetNodeID ID;
326 ImutInfo::Profile(ID,V);
327 digest += ID.computeHash();
328
329 if (R)
330 digest += R->computeDigest();
331
332 return digest;
333 }
334
335 uint32_t computeDigest() {
336 // Check the lowest bit to determine if digest has actually been
337 // pre-computed.
338 if (hasCachedDigest())
339 return digest.Digest;
340
341 uint32_t X = computeDigest(getLeft(), getRight(), getValue());
342 digest.Digest = X;
343 markedCachedDigest();
344 return X;
345 }
346
347 //===----------------------------------------------------===//
348 // Reference count operations.
349 //===----------------------------------------------------===//
350
351public:
352 void retain() { ++refCount; }
353
354 void release() {
355 assert(refCount > 0);
356 if (--refCount == 0)
357 destroy();
358 }
359
361 if (left)
362 left->release();
363 if (right)
364 right->release();
365 if constexpr (Canonicalize) {
366 if (IsCanonicalized) {
367 if (this->Next)
368 this->Next->Prev = this->Prev;
369
370 if (this->Prev)
371 this->Prev->Next = this->Next;
372 else
373 factory->Cache[factory->maskCacheIndex(computeDigest())] = this->Next;
374 }
375 }
376
377 // We need to clear the mutability bit in case we are
378 // destroying the node as part of a sweep in ImutAVLFactory::recoverNodes().
379 IsMutable = false;
380 factory->freeNodes.push_back(this);
381 }
382};
383
384template <typename ImutInfo, bool Canonicalize>
385struct IntrusiveRefCntPtrInfo<ImutAVLTree<ImutInfo, Canonicalize>> {
387 Tree->retain();
388 }
390 Tree->release();
391 }
392};
393
394//===----------------------------------------------------------------------===//
395// Immutable AVL-Tree Factory class.
396//===----------------------------------------------------------------------===//
397
398template <typename ImutInfo, bool Canonicalize>
400 : private ImutAVLDetail::CanonicalCache<ImutAVLTree<ImutInfo, Canonicalize>,
401 Canonicalize> {
402 friend class ImutAVLTree<ImutInfo, Canonicalize>;
403
405 using value_type = typename TreeTy::value_type;
406 using value_type_ref = typename TreeTy::value_type_ref;
407 using key_type_ref = typename TreeTy::key_type_ref;
408
409 uintptr_t Allocator;
410 std::vector<TreeTy*> createdNodes;
411 std::vector<TreeTy*> freeNodes;
412
413 bool ownsAllocator() const {
414 return (Allocator & 0x1) == 0;
415 }
416
417 BumpPtrAllocator& getAllocator() const {
418 return *reinterpret_cast<BumpPtrAllocator*>(Allocator & ~0x1);
419 }
420
421 //===--------------------------------------------------===//
422 // Public interface.
423 //===--------------------------------------------------===//
424
425public:
427 : Allocator(reinterpret_cast<uintptr_t>(new BumpPtrAllocator())) {}
428
430 : Allocator(reinterpret_cast<uintptr_t>(&Alloc) | 0x1) {}
431
433 if (ownsAllocator()) delete &getAllocator();
434 }
435
436 TreeTy* add(TreeTy* T, value_type_ref V) {
437 T = add_internal(V,T);
439 return T;
440 }
441
442 /// Merges \p A and \p B in a single traversal, sharing every subtree that the
443 /// two operands do not overlap. \p Combine(AElem, BElem) produces the element
444 /// stored for a key present in both; \p KeepUnmatched governs keys unique to
445 /// one side (see merge_internal). For merging |B| entries into |A|
446 /// (|B| <= |A|) this costs O(|B| * log(|A|/|B| + 1)) and copies each spine
447 /// node at most once, versus O(|B| * log|A|) repeated \ref add descents.
448 /// \p A and \p B must be immutable. This does not short-circuit equal or
449 /// empty operands (merge_internal handles them correctly but not specially);
450 /// callers that want those fast paths, or size-driven operand ordering,
451 /// should apply them first (see ImmutableSet::Factory::unionSets).
452 template <typename CombineFn>
453 TreeTy *mergeTrees(TreeTy *A, TreeTy *B, CombineFn Combine,
454 bool KeepUnmatched, bool SkipShared = false) {
455 TreeTy *T = merge_internal(A, B, Combine, KeepUnmatched, SkipShared);
457 return T;
458 }
459
460 /// Returns the set union of \p A and \p B (keeping \p A's element on matching
461 /// keys). Shorthand for the fully sharing \ref mergeTrees.
462 TreeTy *unionTrees(TreeTy *A, TreeTy *B) {
463 // With KeepUnmatched=true, unmatched elements are shared as-is and Combine
464 // is invoked only for keys present in both, where it keeps A's element.
465 auto KeepFirst = [](const value_type *L,
466 const value_type *R) -> const value_type & {
467 return L ? *L : *R;
468 };
469 // Set union is idempotent, so identical (pointer-equal) subtrees -- common
470 // once one operand is derived from the other -- can be shared in O(1).
471 return mergeTrees(A, B, KeepFirst, /*KeepUnmatched=*/true,
472 /*SkipShared=*/true);
473 }
474
475 TreeTy* remove(TreeTy* T, key_type_ref V) {
476 T = remove_internal(V,T);
478 return T;
479 }
480
481 TreeTy* getEmptyTree() const { return nullptr; }
482
483protected:
484 //===--------------------------------------------------===//
485 // A bunch of quick helper functions used for reasoning
486 // about the properties of trees and their children.
487 // These have succinct names so that the balancing code
488 // is as terse (and readable) as possible.
489 //===--------------------------------------------------===//
490
491 bool isEmpty(TreeTy* T) const { return !T; }
492 unsigned getHeight(TreeTy* T) const { return T ? T->getHeight() : 0; }
493 TreeTy* getLeft(TreeTy* T) const { return T->getLeft(); }
494 TreeTy* getRight(TreeTy* T) const { return T->getRight(); }
495 value_type_ref getValue(TreeTy* T) const { return T->value; }
496
497 // Make sure the index is not the Tombstone or Entry key of the DenseMap.
498 static unsigned maskCacheIndex(unsigned I) { return (I & ~0x02); }
499
500 unsigned incrementHeight(TreeTy* L, TreeTy* R) const {
501 unsigned hl = getHeight(L);
502 unsigned hr = getHeight(R);
503 return (hl > hr ? hl : hr) + 1;
504 }
505
506 //===--------------------------------------------------===//
507 // "createNode" is used to generate new tree roots that link
508 // to other trees. The function may also simply move links
509 // in an existing root if that root is still marked mutable.
510 // This is necessary because otherwise our balancing code
511 // would leak memory as it would create nodes that are
512 // then discarded later before the finished tree is
513 // returned to the caller.
514 //===--------------------------------------------------===//
515
516 TreeTy* createNode(TreeTy* L, value_type_ref V, TreeTy* R) {
517 BumpPtrAllocator& A = getAllocator();
518 TreeTy* T;
519 if (!freeNodes.empty()) {
520 T = freeNodes.back();
521 freeNodes.pop_back();
522 assert(T != L);
523 assert(T != R);
524 } else {
525 T = (TreeTy*) A.Allocate<TreeTy>();
526 }
527 new (T) TreeTy(this, L, R, V, incrementHeight(L,R));
528 createdNodes.push_back(T);
529 return T;
530 }
531
532 TreeTy* createNode(TreeTy* newLeft, TreeTy* oldTree, TreeTy* newRight) {
533 return createNode(newLeft, getValue(oldTree), newRight);
534 }
535
536 void recoverNodes(TreeTy *Result) {
537 // Mark Result's nodes immutable and reclaim the intermediates discarded
538 // during balancing, in one pass. Nodes are built bottom-up, so a node
539 // precedes its parents in createdNodes; visiting in reverse thus reaches
540 // each node only once its reference count is final. Unreferenced nodes are
541 // unreachable and destroyed; the rest belong to Result. Result is kept
542 // despite its zero count -- the caller has not taken ownership yet.
543 for (TreeTy *N : llvm::reverse(createdNodes)) {
544 if (!N->isMutable())
545 continue; // Already reclaimed while destroying an unreachable parent.
546 if (N != Result && N->refCount == 0)
547 N->destroy();
548 else
549 N->markImmutable();
550 }
551 createdNodes.clear();
552 }
553
554 /// Used by add_internal and remove_internal to balance a newly created tree.
555 TreeTy* balanceTree(TreeTy* L, value_type_ref V, TreeTy* R) {
556 unsigned hl = getHeight(L);
557 unsigned hr = getHeight(R);
558
559 if (hl > hr + 2) {
560 assert(!isEmpty(L) && "Left tree cannot be empty to have a height >= 2");
561
562 TreeTy *LL = getLeft(L);
563 TreeTy *LR = getRight(L);
564
565 if (getHeight(LL) >= getHeight(LR))
566 return createNode(LL, L, createNode(LR,V,R));
567
568 assert(!isEmpty(LR) && "LR cannot be empty because it has a height >= 1");
569
570 TreeTy *LRL = getLeft(LR);
571 TreeTy *LRR = getRight(LR);
572
573 return createNode(createNode(LL,L,LRL), LR, createNode(LRR,V,R));
574 }
575
576 if (hr > hl + 2) {
577 assert(!isEmpty(R) && "Right tree cannot be empty to have a height >= 2");
578
579 TreeTy *RL = getLeft(R);
580 TreeTy *RR = getRight(R);
581
582 if (getHeight(RR) >= getHeight(RL))
583 return createNode(createNode(L,V,RL), R, RR);
584
585 assert(!isEmpty(RL) && "RL cannot be empty because it has a height >= 1");
586
587 TreeTy *RLL = getLeft(RL);
588 TreeTy *RLR = getRight(RL);
589
590 return createNode(createNode(L,V,RLL), RL, createNode(RLR,R,RR));
591 }
592
593 return createNode(L,V,R);
594 }
595
596 /// Combines \p L and \p R with the value \p V (every key in \p L less than
597 /// \p V, every key in \p R greater) into one balanced tree. Unlike
598 /// balanceTree this tolerates an arbitrary height difference between \p L and
599 /// \p R: it descends the taller side's spine and rebalances on the way back
600 /// up, exactly as an insertion would.
601 TreeTy *joinTrees(TreeTy *L, value_type_ref V, TreeTy *R) {
602 if (getHeight(L) > getHeight(R) + 2)
603 return balanceTree(getLeft(L), getValue(L), joinTrees(getRight(L), V, R));
604 if (getHeight(R) > getHeight(L) + 2)
605 return balanceTree(joinTrees(L, V, getLeft(R)), getValue(R), getRight(R));
606 return createNode(L, V, R);
607 }
608
609 /// Splits \p T into \p L (all keys less than \p K) and \p R (all keys greater
610 /// than \p K). If \p K is present in \p T, \p Match is set to point at its
611 /// element (which is dropped from \p L and \p R); otherwise \p Match is null.
612 void splitLookup(TreeTy *T, key_type_ref K, TreeTy *&L,
613 const value_type *&Match, TreeTy *&R) {
614 if (isEmpty(T)) {
615 L = R = getEmptyTree();
616 Match = nullptr;
617 return;
618 }
619 key_type_ref KCurrent = ImutInfo::KeyOfValue(getValue(T));
620 if (ImutInfo::isEqual(K, KCurrent)) {
621 L = getLeft(T);
622 R = getRight(T);
623 // Use the tree accessor, which returns a reference to the stored element
624 // (the factory's getValue returns value_type_ref, which is by value for
625 // pointer-like element types).
626 Match = &T->getValue();
627 } else if (ImutInfo::isLess(K, KCurrent)) {
628 TreeTy *LR;
629 splitLookup(getLeft(T), K, L, Match, LR);
630 R = joinTrees(LR, getValue(T), getRight(T));
631 } else {
632 TreeTy *RL;
633 splitLookup(getRight(T), K, RL, Match, R);
634 L = joinTrees(getLeft(T), getValue(T), RL);
635 }
636 }
637
638 /// Rebuilds \p T with the same shape but each element replaced by
639 /// \p Combine applied to it. \p FromB selects which side of \p Combine the
640 /// element is passed on (it is the sole non-null argument).
641 template <typename CombineFn>
642 TreeTy *transformTree(TreeTy *T, CombineFn &Combine, bool FromB) {
643 if (isEmpty(T))
644 return T;
645 TreeTy *L = transformTree(getLeft(T), Combine, FromB);
646 TreeTy *R = transformTree(getRight(T), Combine, FromB);
647 const value_type &E = getValue(T);
648 return createNode(L, FromB ? Combine(nullptr, &E) : Combine(&E, nullptr),
649 R);
650 }
651
652 /// Merges \p A and \p B by recursing over \p A's structure and splitting \p B
653 /// at each of \p A's keys. For a key in both, the stored element is
654 /// Combine(AElem, BElem). \p KeepUnmatched controls keys unique to one side:
655 /// when true, such elements (and whole non-overlapping subtrees) are taken
656 /// unchanged and shared, and \p Combine is invoked only on keys present in
657 /// both (valid when \p Combine is an identity for a missing side, e.g. a set
658 /// union or a lattice join with an identity element); when false every key is
659 /// passed through \p Combine with the absent side null (needed for a join
660 /// that transforms unmatched keys, e.g. liveness downgrading Must to Maybe).
661 template <typename CombineFn>
662 TreeTy *merge_internal(TreeTy *A, TreeTy *B, CombineFn &Combine,
663 bool KeepUnmatched, bool SkipShared) {
664 // When A and B are the same tree (which happens all the time once B is
665 // derived from A by a small edit, since the untouched side is shared by
666 // pointer), an idempotent merge returns it unchanged in O(1). Only valid
667 // when merge(x, x) == x, so the caller opts in via SkipShared.
668 if (SkipShared && A == B)
669 return A;
670 if (isEmpty(A))
671 return KeepUnmatched ? B : transformTree(B, Combine, /*FromB=*/true);
672 if (isEmpty(B))
673 return KeepUnmatched ? A : transformTree(A, Combine, /*FromB=*/false);
674
675 const value_type &AElem = getValue(A);
676 TreeTy *BL, *BR;
677 const value_type *BMatch;
678 splitLookup(B, ImutInfo::KeyOfValue(AElem), BL, BMatch, BR);
679
680 TreeTy *NewL =
681 merge_internal(getLeft(A), BL, Combine, KeepUnmatched, SkipShared);
682 TreeTy *NewR =
683 merge_internal(getRight(A), BR, Combine, KeepUnmatched, SkipShared);
684
685 if (!BMatch) {
686 // Key present only in A.
687 if (KeepUnmatched) {
688 if (NewL == getLeft(A) && NewR == getRight(A))
689 return A;
690 return joinTrees(NewL, AElem, NewR);
691 }
692 return joinTrees(NewL, Combine(&AElem, nullptr), NewR);
693 }
694 // Key present in both: combine the two elements. Preserve sharing when the
695 // combined value is unchanged and neither subtree moved, so that a join
696 // that only touches a few keys does not rebuild the whole spine.
697 auto NewElem = Combine(&AElem, BMatch);
698 if (NewL == getLeft(A) && NewR == getRight(A) &&
699 ImutInfo::isDataEqual(ImutInfo::DataOfValue(NewElem),
700 ImutInfo::DataOfValue(AElem)))
701 return A;
702 return joinTrees(NewL, NewElem, NewR);
703 }
704
705 /// add_internal - Creates a new tree that includes the specified
706 /// data and the data from the original tree. If the original tree
707 /// already contained the data item, the original tree is returned.
708 TreeTy *add_internal(value_type_ref V, TreeTy *T) {
709 if (isEmpty(T))
710 return createNode(T, V, T);
711 assert(!T->isMutable());
712
713 key_type_ref K = ImutInfo::KeyOfValue(V);
714 key_type_ref KCurrent = ImutInfo::KeyOfValue(getValue(T));
715
716 if (ImutInfo::isEqual(K, KCurrent)) {
717 // If both key and value are same, return the original tree.
718 if (ImutInfo::isDataEqual(ImutInfo::DataOfValue(V),
719 ImutInfo::DataOfValue(getValue(T))))
720 return T;
721 // Otherwise create a new node with the new value.
722 return createNode(getLeft(T), V, getRight(T));
723 }
724
725 TreeTy *NewL = getLeft(T);
726 TreeTy *NewR = getRight(T);
727 if (ImutInfo::isLess(K, KCurrent))
728 NewL = add_internal(V, NewL);
729 else
730 NewR = add_internal(V, NewR);
731
732 // If no changes were made, return the original tree. Otherwise, balance the
733 // tree and return the new root.
734 return NewL == getLeft(T) && NewR == getRight(T)
735 ? T
736 : balanceTree(NewL, getValue(T), NewR);
737 }
738
739 /// remove_internal - Creates a new tree that includes all the data
740 /// from the original tree except the specified data. If the
741 /// specified data did not exist in the original tree, the original
742 /// tree is returned.
743 TreeTy *remove_internal(key_type_ref K, TreeTy *T) {
744 if (isEmpty(T))
745 return T;
746
747 assert(!T->isMutable());
748
749 key_type_ref KCurrent = ImutInfo::KeyOfValue(getValue(T));
750
751 if (ImutInfo::isEqual(K, KCurrent))
752 return combineTrees(getLeft(T), getRight(T));
753
754 TreeTy *NewL = getLeft(T);
755 TreeTy *NewR = getRight(T);
756 if (ImutInfo::isLess(K, KCurrent))
757 NewL = remove_internal(K, NewL);
758 else
759 NewR = remove_internal(K, NewR);
760
761 // If no changes were made, return the original tree. Otherwise, balance the
762 // tree and return the new root.
763 return NewL == getLeft(T) && NewR == getRight(T)
764 ? T
765 : balanceTree(NewL, getValue(T), NewR);
766 }
767
768 TreeTy* combineTrees(TreeTy* L, TreeTy* R) {
769 if (isEmpty(L))
770 return R;
771 if (isEmpty(R))
772 return L;
773 TreeTy* OldNode;
774 TreeTy* newRight = removeMinBinding(R,OldNode);
775 return balanceTree(L, getValue(OldNode), newRight);
776 }
777
778 TreeTy* removeMinBinding(TreeTy* T, TreeTy*& Noderemoved) {
779 assert(!isEmpty(T));
780 if (isEmpty(getLeft(T))) {
781 Noderemoved = T;
782 return getRight(T);
783 }
784 return balanceTree(removeMinBinding(getLeft(T), Noderemoved),
785 getValue(T), getRight(T));
786 }
787
788public:
789 TreeTy *getCanonicalTree(TreeTy *TNew) {
790 static_assert(Canonicalize,
791 "getCanonicalTree requires a canonicalizing factory");
792 if (!TNew)
793 return nullptr;
794
795 if (TNew->IsCanonicalized)
796 return TNew;
797
798 // Search the hashtable for another tree with the same digest, and
799 // if find a collision compare those trees by their contents.
800 unsigned digest = TNew->computeDigest();
801 TreeTy *&entry = this->Cache[maskCacheIndex(digest)];
802 if (entry) {
803 for (TreeTy *T = entry; T != nullptr; T = T->Next) {
804 // Compare the contents of 'T' with 'TNew'. isEqual skips subtrees that
805 // are shared by pointer, so for structurally-shared persistent trees
806 // (the common case, e.g. one derived from the other) this is linear in
807 // the number of differing nodes rather than in the tree size.
808 if (!TNew->isEqual(*T))
809 continue;
810 // Trees did match! Return 'T'.
811 if (TNew->refCount == 0)
812 TNew->destroy();
813 return T;
814 }
815 entry->Prev = TNew;
816 TNew->Next = entry;
817 }
818
819 entry = TNew;
820 TNew->IsCanonicalized = true;
821 return TNew;
822 }
823};
824
825//===----------------------------------------------------------------------===//
826// Immutable AVL-Tree Iterator.
827//===----------------------------------------------------------------------===//
828
829/// Bidirectional in-order iterator over the nodes of an ImutAVLTree.
830///
831/// The iterator keeps the chain of ancestors from the root down to the current
832/// node on an explicit stack of plain node pointers, and decides which way to
833/// move next by inspecting whether it is ascending from a node's left or right
834/// child. This avoids storing any per-node visit-state: there is no need to
835/// remember "have I already visited this node's left/right subtree", because
836/// that is recovered by comparing the child we just left against the parent's
837/// left and right pointers.
838///
839/// A node's parent cannot be cached in the node itself, because these trees are
840/// persistent and structurally shared: a single node may appear as the child of
841/// different parents across different tree versions. The ancestor stack is
842/// therefore the per-traversal parent chain.
843template <typename ImutInfo, bool Canonicalize>
845public:
846 using iterator_category = std::bidirectional_iterator_tag;
848 using difference_type = std::ptrdiff_t;
851
853
854private:
855 // Path[0] is the root and Path.back() is the current node. An empty path is
856 // the end iterator. The invariant is that Path always holds the exact chain
857 // of ancestors of the current node, root-most first.
859
860 // Descend along left children, pushing each node; lands on the minimum of the
861 // subtree rooted at T (i.e. the first node in an in-order traversal of T).
862 void descendToMin(TreeTy *T) {
863 for (; T; T = T->getLeft())
864 Path.push_back(T);
865 }
866
867 // Descend along right children, pushing each node; lands on the maximum of
868 // the subtree rooted at T (i.e. the last node in an in-order traversal of T).
869 void descendToMax(TreeTy *T) {
870 for (; T; T = T->getRight())
871 Path.push_back(T);
872 }
873
874 // Pop the current node and ascend until we reach an ancestor from its *left*
875 // child, i.e. the first ancestor whose subtree is not yet fully visited. That
876 // ancestor is the in-order successor of the subtree we just left; if there is
877 // none, Path is emptied (the end iterator). Shared by operator++ and
878 // skipSubTree, whose only difference is whether the current node's right
879 // subtree is descended into first.
880 void ascendFromRightChild() {
881 TreeTy *Child = Path.pop_back_val();
882 while (!Path.empty() && Path.back()->getRight() == Child)
883 Child = Path.pop_back_val();
884 }
885
886 // Mirror of ascendFromRightChild for reverse traversal (operator--).
887 void ascendFromLeftChild() {
888 TreeTy *Child = Path.pop_back_val();
889 while (!Path.empty() && Path.back()->getLeft() == Child)
890 Child = Path.pop_back_val();
891 }
892
893public:
894 ImutAVLTreeInOrderIterator() = default; // end() iterator.
896 descendToMin(const_cast<TreeTy *>(Root));
897 }
898
899 // Two iterators are equal iff they sit on the same node (or are both end()).
900 // Within a single tree a node has a unique root-to-node path, so the current
901 // node alone identifies the position; comparing the whole path is therefore
902 // unnecessary. Comparing iterators from different trees is not meaningful, as
903 // for any standard container.
905 if (Path.empty() || x.Path.empty())
906 return Path.empty() == x.Path.empty();
907 return Path.back() == x.Path.back();
908 }
910 return !(*this == x);
911 }
912
913 TreeTy &operator*() const { return *Path.back(); }
914 TreeTy *operator->() const { return Path.back(); }
915
917 assert(!Path.empty() && "Incrementing the end iterator");
918 if (TreeTy *R = Path.back()->getRight())
919 // The in-order successor is the minimum of the right subtree.
920 descendToMin(R);
921 else
922 // No right subtree: the successor is the nearest ancestor reached from a
923 // left child.
924 ascendFromRightChild();
925 return *this;
926 }
927
929 assert(!Path.empty() && "Decrementing the end iterator");
930 if (TreeTy *L = Path.back()->getLeft())
931 // The in-order predecessor is the maximum of the left subtree.
932 descendToMax(L);
933 else
934 // Mirror of operator++.
935 ascendFromLeftChild();
936 return *this;
937 }
938
939 /// Move to the in-order successor of the entire subtree rooted at the current
940 /// node, i.e. skip the current node together with its right subtree. This is
941 /// exactly the ascent half of operator++.
942 void skipSubTree() {
943 assert(!Path.empty() && "Skipping past the end iterator");
944 ascendFromRightChild();
945 }
946};
947
948/// Generic iterator that wraps a T::TreeTy::iterator and exposes
949/// iterator::getValue() on dereference.
950template <typename T>
953 ImutAVLValueIterator<T>, typename T::TreeTy::iterator,
954 typename std::iterator_traits<
955 typename T::TreeTy::iterator>::iterator_category,
956 const typename T::value_type> {
960
962 return this->I->getValue();
963 }
964};
965
966//===----------------------------------------------------------------------===//
967// Trait classes for Profile information.
968//===----------------------------------------------------------------------===//
969
970/// Generic profile template. The default behavior is to invoke the
971/// profile method of an object. Specializations for primitive integers
972/// and generic handling of pointers is done below.
973template <typename T>
975 using value_type = const T;
976 using value_type_ref = const T&;
977
981};
982
983/// Profile traits for integers.
984template <typename T>
986 using value_type = const T;
987 using value_type_ref = const T&;
988
990 ID.AddInteger(X);
991 }
992};
993
994#define PROFILE_INTEGER_INFO(X)\
995template<> struct ImutProfileInfo<X> : ImutProfileInteger<X> {};
996
998PROFILE_INTEGER_INFO(unsigned char)
1000PROFILE_INTEGER_INFO(unsigned short)
1001PROFILE_INTEGER_INFO(unsigned)
1004PROFILE_INTEGER_INFO(unsigned long)
1005PROFILE_INTEGER_INFO(long long)
1006PROFILE_INTEGER_INFO(unsigned long long)
1007
1008#undef PROFILE_INTEGER_INFO
1009
1010/// Profile traits for booleans.
1011template <>
1013 using value_type = const bool;
1014 using value_type_ref = const bool&;
1015
1017 ID.AddBoolean(X);
1018 }
1019};
1020
1021/// Generic profile trait for pointer types. We treat pointers as
1022/// references to unique objects.
1023template <typename T>
1025 using value_type = const T*;
1027
1029 ID.AddPointer(X);
1030 }
1031};
1032
1033//===----------------------------------------------------------------------===//
1034// Trait classes that contain element comparison operators and type
1035// definitions used by ImutAVLTree, ImmutableSet, and ImmutableMap. These
1036// inherit from the profile traits (ImutProfileInfo) to include operations
1037// for element profiling.
1038//===----------------------------------------------------------------------===//
1039
1040/// Generic definition of comparison operations for elements of immutable
1041/// containers that defaults to using std::equal_to<> and std::less<> to perform
1042/// comparison of elements.
1043template <typename T> struct ImutContainerInfo : ImutProfileInfo<T> {
1050
1053
1055 return std::equal_to<key_type>()(LHS,RHS);
1056 }
1057
1059 return std::less<key_type>()(LHS,RHS);
1060 }
1061
1062 static bool isDataEqual(data_type_ref, data_type_ref) { return true; }
1063};
1064
1065/// Specialization for pointer values to treat pointers as references to unique
1066/// objects. Pointers are thus compared by their addresses.
1067template <typename T> struct ImutContainerInfo<T *> : ImutProfileInfo<T *> {
1074
1077
1078 static bool isEqual(key_type_ref LHS, key_type_ref RHS) { return LHS == RHS; }
1079
1080 static bool isLess(key_type_ref LHS, key_type_ref RHS) { return LHS < RHS; }
1081
1082 static bool isDataEqual(data_type_ref, data_type_ref) { return true; }
1083};
1084
1085//===----------------------------------------------------------------------===//
1086// Immutable Set
1087//===----------------------------------------------------------------------===//
1088
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
1097private:
1099
1100public:
1101 /// Constructs a set from a pointer to a tree root. In general one
1102 /// should use a Factory object to create sets instead of directly
1103 /// invoking the constructor, but there are cases where make this
1104 /// constructor public is useful.
1105 explicit ImmutableSet(TreeTy *R) : Root(R) {}
1106
1107 class Factory {
1108 typename TreeTy::Factory F;
1109
1110 public:
1111 Factory() = default;
1112
1114
1115 Factory(const Factory& RHS) = delete;
1116 void operator=(const Factory& RHS) = delete;
1117
1118 /// Returns an immutable set that contains no elements.
1120 return ImmutableSet(F.getEmptyTree());
1121 }
1122
1123 /// Creates a new immutable set that contains all of the values
1124 /// of the original set with the addition of the specified value. If
1125 /// the original set already included the value, then the original set is
1126 /// returned and no memory is allocated. The time and space complexity
1127 /// of this operation is logarithmic in the size of the original set.
1128 /// The memory allocated to represent the set is released when the
1129 /// factory object that created the set is destroyed.
1131 TreeTy *NewT = F.add(Old.Root.get(), V);
1132 if constexpr (Canonicalize)
1133 return ImmutableSet(F.getCanonicalTree(NewT));
1134 else
1135 return ImmutableSet(NewT);
1136 }
1137
1138 /// Returns the union of \p A and \p B, computed in a single traversal that
1139 /// shares subtrees of both operands wherever possible (see
1140 /// ImutAVLFactory::unionTrees). This is more efficient than repeatedly
1141 /// adding \p B's elements to \p A when \p B is large.
1143 if (A.Root.get() == B.Root.get() || B.isEmpty())
1144 return A;
1145 if (A.isEmpty())
1146 return B;
1147 // Drive the recursion with the taller tree so the shorter one is the one
1148 // being split.
1149 if (A.getHeight() < B.getHeight())
1150 std::swap(A, B);
1151 if constexpr (Canonicalize) {
1152 // The bulk path does not canonicalize the nodes it creates, so fall
1153 // back to per-element insertion for canonicalizing factories.
1154 for (value_type_ref V : B)
1155 A = add(A, V);
1156 return A;
1157 } else {
1158 return ImmutableSet(F.unionTrees(A.Root.get(), B.Root.get()));
1159 }
1160 }
1161
1162 /// Creates a new immutable set that contains all of the values
1163 /// of the original set with the exception of the specified value. If
1164 /// the original set did not contain the value, the original set is
1165 /// returned and no memory is allocated. The time and space complexity
1166 /// of this operation is logarithmic in the size of the original set.
1167 /// The memory allocated to represent the set is released when the
1168 /// factory object that created the set is destroyed.
1170 TreeTy *NewT = F.remove(Old.Root.get(), V);
1171 if constexpr (Canonicalize)
1172 return ImmutableSet(F.getCanonicalTree(NewT));
1173 else
1174 return ImmutableSet(NewT);
1175 }
1176
1177 BumpPtrAllocator& getAllocator() { return F.getAllocator(); }
1178
1180 return const_cast<typename TreeTy::Factory *>(&F);
1181 }
1182 };
1183
1184 friend class Factory;
1185
1186 /// Returns true if the set contains the specified value.
1188 return Root ? Root->contains(V) : false;
1189 }
1190
1191 /// Compares two sets for equality. For a canonicalizing factory, sets with
1192 /// equal contents share the same tree, so this is an O(1) pointer comparison
1193 /// (like ImmutableList); only sets created by the same factory may be
1194 /// compared. Otherwise it is a structural comparison.
1195 bool operator==(const ImmutableSet &RHS) const {
1196 if constexpr (Canonicalize)
1197 return Root == RHS.Root;
1198 else
1199 return Root && RHS.Root ? Root->isEqual(*RHS.Root.get())
1200 : Root == RHS.Root;
1201 }
1202
1203 bool operator!=(const ImmutableSet &RHS) const {
1204 if constexpr (Canonicalize)
1205 return Root != RHS.Root;
1206 else
1207 return Root && RHS.Root ? Root->isNotEqual(*RHS.Root.get())
1208 : Root != RHS.Root;
1209 }
1210
1212 if (Root) { Root->retain(); }
1213 return Root.get();
1214 }
1215
1216 TreeTy *getRootWithoutRetain() const { return Root.get(); }
1217
1218 /// Return true if the set contains no elements.
1219 bool isEmpty() const { return !Root; }
1220
1221 /// Return true if the set contains exactly one element.
1222 /// This method runs in constant time.
1223 bool isSingleton() const { return getHeight() == 1; }
1224
1225 //===--------------------------------------------------===//
1226 // Iterators.
1227 //===--------------------------------------------------===//
1228
1230
1231 iterator begin() const { return iterator(Root.get()); }
1232 iterator end() const { return iterator(); }
1233
1234 //===--------------------------------------------------===//
1235 // Utility methods.
1236 //===--------------------------------------------------===//
1237
1238 unsigned getHeight() const { return Root ? Root->getHeight() : 0; }
1239
1240 static void Profile(FoldingSetNodeID &ID, const ImmutableSet &S) {
1241 ID.AddPointer(S.Root.get());
1242 }
1243
1244 void Profile(FoldingSetNodeID &ID) const { return Profile(ID, *this); }
1245
1246 //===--------------------------------------------------===//
1247 // For testing.
1248 //===--------------------------------------------------===//
1249
1250 void validateTree() const { if (Root) Root->validateTree(); }
1251};
1252
1253// NOTE: This may some day replace the current ImmutableSet.
1254template <typename ValT, typename ValInfo = ImutContainerInfo<ValT>,
1255 bool Canonicalize = true>
1257public:
1258 using value_type = typename ValInfo::value_type;
1259 using value_type_ref = typename ValInfo::value_type_ref;
1261 using FactoryTy = typename TreeTy::Factory;
1262
1263private:
1265 FactoryTy *Factory;
1266
1267public:
1268 /// Constructs a set from a pointer to a tree root. In general one
1269 /// should use a Factory object to create sets instead of directly
1270 /// invoking the constructor, but there are cases where make this
1271 /// constructor public is useful.
1272 ImmutableSetRef(TreeTy *R, FactoryTy *F) : Root(R), Factory(F) {}
1273
1275 return ImmutableSetRef(0, F);
1276 }
1277
1279 return ImmutableSetRef(Factory->add(Root.get(), V), Factory);
1280 }
1281
1283 return ImmutableSetRef(Factory->remove(Root.get(), V), Factory);
1284 }
1285
1286 /// Returns true if the set contains the specified value.
1288 return Root ? Root->contains(V) : false;
1289 }
1290
1293 if constexpr (Canonicalize)
1294 return SetTy(Factory->getCanonicalTree(Root.get()));
1295 else
1296 return SetTy(Root.get());
1297 }
1298
1299 TreeTy *getRootWithoutRetain() const { return Root.get(); }
1300
1301 bool operator==(const ImmutableSetRef &RHS) const {
1302 return Root && RHS.Root ? Root->isEqual(*RHS.Root.get()) : Root == RHS.Root;
1303 }
1304
1305 bool operator!=(const ImmutableSetRef &RHS) const {
1306 return Root && RHS.Root ? Root->isNotEqual(*RHS.Root.get())
1307 : Root != RHS.Root;
1308 }
1309
1310 /// Return true if the set contains no elements.
1311 bool isEmpty() const { return !Root; }
1312
1313 /// Return true if the set contains exactly one element.
1314 /// This method runs in constant time.
1315 bool isSingleton() const { return getHeight() == 1; }
1316
1317 //===--------------------------------------------------===//
1318 // Iterators.
1319 //===--------------------------------------------------===//
1320
1322
1323 iterator begin() const { return iterator(Root.get()); }
1324 iterator end() const { return iterator(); }
1325
1326 //===--------------------------------------------------===//
1327 // Utility methods.
1328 //===--------------------------------------------------===//
1329
1330 unsigned getHeight() const { return Root ? Root->getHeight() : 0; }
1331
1332 static void Profile(FoldingSetNodeID &ID, const ImmutableSetRef &S) {
1333 ID.AddPointer(S.Root.get());
1334 }
1335
1336 void Profile(FoldingSetNodeID &ID) const { return Profile(ID, *this); }
1337
1338 //===--------------------------------------------------===//
1339 // For testing.
1340 //===--------------------------------------------------===//
1341
1342 void validateTree() const { if (Root) Root->validateTree(); }
1343};
1344
1345} // end namespace llvm
1346
1347#endif // LLVM_ADT_IMMUTABLESET_H
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
AMDGPU Uniform Intrinsic Combine
This file defines the BumpPtrAllocator interface.
#define X(NUM, ENUM, NAME)
Definition ELF.h:665
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")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
#define LLVM_PREFERRED_TYPE(T)
\macro LLVM_PREFERRED_TYPE Adjust type of bit-field in debug info.
Definition Compiler.h:758
#define LLVM_NO_UNIQUE_ADDRESS
Definition Compiler.h:493
#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:366
#define LLVM_ATTRIBUTE_WARN_UNUSED
Definition Compiler.h:240
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:162
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)
ImmutableSet unionSets(ImmutableSet A, ImmutableSet B)
Returns the union of A and B, computed in a single traversal that shares subtrees of both operands wh...
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 * transformTree(TreeTy *T, CombineFn &Combine, bool FromB)
Rebuilds T with the same shape but each element replaced by Combine applied to it.
TreeTy * mergeTrees(TreeTy *A, TreeTy *B, CombineFn Combine, bool KeepUnmatched, bool SkipShared=false)
Merges A and B in a single traversal, sharing every subtree that the two operands do not overlap.
TreeTy * getEmptyTree() const
TreeTy * createNode(TreeTy *newLeft, TreeTy *oldTree, TreeTy *newRight)
unsigned getHeight(TreeTy *T) const
value_type_ref getValue(TreeTy *T) const
TreeTy * joinTrees(TreeTy *L, value_type_ref V, TreeTy *R)
Combines L and R with the value V (every key in L less than V, every key in R greater) into one balan...
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 * unionTrees(TreeTy *A, TreeTy *B)
Returns the set union of A and B (keeping A's element on matching keys).
void splitLookup(TreeTy *T, key_type_ref K, TreeTy *&L, const value_type *&Match, TreeTy *&R)
Splits T into L (all keys less than K) and R (all keys greater than K).
TreeTy * getRight(TreeTy *T) const
TreeTy * merge_internal(TreeTy *A, TreeTy *B, CombineFn &Combine, bool KeepUnmatched, bool SkipShared)
Merges A and B by recursing over A's structure and splitting B at each of A's keys.
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.
This is an optimization pass for GlobalISel generic memory operations.
auto reverse(ContainerTy &&C)
Definition STLExtras.h:408
BumpPtrAllocatorImpl<> BumpPtrAllocator
The standard BumpPtrAllocator which just uses the default template parameters.
Definition Allocator.h:391
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.
Definition BitVector.h:880
#define N
static void Profile(const T &X, FoldingSetNodeID &ID)
Definition FoldingSet.h:235
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.