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 = typename TreeTy::value_type;
408 using value_type_ref = typename TreeTy::value_type_ref;
409 using key_type_ref = typename TreeTy::key_type_ref;
410
411 uintptr_t Allocator;
412 std::vector<TreeTy*> createdNodes;
413 std::vector<TreeTy*> freeNodes;
414
415 bool ownsAllocator() const {
416 return (Allocator & 0x1) == 0;
417 }
418
419 BumpPtrAllocator& getAllocator() const {
420 return *reinterpret_cast<BumpPtrAllocator*>(Allocator & ~0x1);
421 }
422
423 //===--------------------------------------------------===//
424 // Public interface.
425 //===--------------------------------------------------===//
426
427public:
429 : Allocator(reinterpret_cast<uintptr_t>(new BumpPtrAllocator())) {}
430
432 : Allocator(reinterpret_cast<uintptr_t>(&Alloc) | 0x1) {}
433
435 if (ownsAllocator()) delete &getAllocator();
436 }
437
438 TreeTy* add(TreeTy* T, value_type_ref V) {
439 T = add_internal(V,T);
441 return T;
442 }
443
444 /// Merges \p A and \p B in a single traversal, sharing every subtree that the
445 /// two operands do not overlap. \p Combine(AElem, BElem) produces the element
446 /// stored for a key present in both; \p KeepUnmatched governs keys unique to
447 /// one side (see merge_internal). For merging |B| entries into |A|
448 /// (|B| <= |A|) this costs O(|B| * log(|A|/|B| + 1)) and copies each spine
449 /// node at most once, versus O(|B| * log|A|) repeated \ref add descents.
450 /// \p A and \p B must be immutable. This does not short-circuit equal or
451 /// empty operands (merge_internal handles them correctly but not specially);
452 /// callers that want those fast paths, or size-driven operand ordering,
453 /// should apply them first (see ImmutableSet::Factory::unionSets).
454 template <typename CombineFn>
455 TreeTy *mergeTrees(TreeTy *A, TreeTy *B, CombineFn Combine,
456 bool KeepUnmatched, bool SkipShared = false) {
457 TreeTy *T = merge_internal(A, B, Combine, KeepUnmatched, SkipShared);
459 return T;
460 }
461
462 /// Returns the set union of \p A and \p B (keeping \p A's element on matching
463 /// keys). Shorthand for the fully sharing \ref mergeTrees.
464 TreeTy *unionTrees(TreeTy *A, TreeTy *B) {
465 // With KeepUnmatched=true, unmatched elements are shared as-is and Combine
466 // is invoked only for keys present in both, where it keeps A's element.
467 auto KeepFirst = [](const value_type *L,
468 const value_type *R) -> const value_type & {
469 return L ? *L : *R;
470 };
471 // Set union is idempotent, so identical (pointer-equal) subtrees -- common
472 // once one operand is derived from the other -- can be shared in O(1).
473 return mergeTrees(A, B, KeepFirst, /*KeepUnmatched=*/true,
474 /*SkipShared=*/true);
475 }
476
477 TreeTy* remove(TreeTy* T, key_type_ref V) {
478 T = remove_internal(V,T);
480 return T;
481 }
482
483 TreeTy* getEmptyTree() const { return nullptr; }
484
485protected:
486 //===--------------------------------------------------===//
487 // A bunch of quick helper functions used for reasoning
488 // about the properties of trees and their children.
489 // These have succinct names so that the balancing code
490 // is as terse (and readable) as possible.
491 //===--------------------------------------------------===//
492
493 bool isEmpty(TreeTy* T) const { return !T; }
494 unsigned getHeight(TreeTy* T) const { return T ? T->getHeight() : 0; }
495 TreeTy* getLeft(TreeTy* T) const { return T->getLeft(); }
496 TreeTy* getRight(TreeTy* T) const { return T->getRight(); }
497 value_type_ref getValue(TreeTy* T) const { return T->value; }
498
499 // Make sure the index is not the Tombstone or Entry key of the DenseMap.
500 static unsigned maskCacheIndex(unsigned I) { return (I & ~0x02); }
501
502 unsigned incrementHeight(TreeTy* L, TreeTy* R) const {
503 unsigned hl = getHeight(L);
504 unsigned hr = getHeight(R);
505 return (hl > hr ? hl : hr) + 1;
506 }
507
508 //===--------------------------------------------------===//
509 // "createNode" is used to generate new tree roots that link
510 // to other trees. The function may also simply move links
511 // in an existing root if that root is still marked mutable.
512 // This is necessary because otherwise our balancing code
513 // would leak memory as it would create nodes that are
514 // then discarded later before the finished tree is
515 // returned to the caller.
516 //===--------------------------------------------------===//
517
518 TreeTy* createNode(TreeTy* L, value_type_ref V, TreeTy* R) {
519 BumpPtrAllocator& A = getAllocator();
520 TreeTy* T;
521 if (!freeNodes.empty()) {
522 T = freeNodes.back();
523 freeNodes.pop_back();
524 assert(T != L);
525 assert(T != R);
526 } else {
527 T = (TreeTy*) A.Allocate<TreeTy>();
528 }
529 new (T) TreeTy(this, L, R, V, incrementHeight(L,R));
530 createdNodes.push_back(T);
531 return T;
532 }
533
534 TreeTy* createNode(TreeTy* newLeft, TreeTy* oldTree, TreeTy* newRight) {
535 return createNode(newLeft, getValue(oldTree), newRight);
536 }
537
538 void recoverNodes(TreeTy *Result) {
539 // Mark Result's nodes immutable and reclaim the intermediates discarded
540 // during balancing, in one pass. Nodes are built bottom-up, so a node
541 // precedes its parents in createdNodes; visiting in reverse thus reaches
542 // each node only once its reference count is final. Unreferenced nodes are
543 // unreachable and destroyed; the rest belong to Result. Result is kept
544 // despite its zero count -- the caller has not taken ownership yet.
545 for (TreeTy *N : llvm::reverse(createdNodes)) {
546 if (!N->isMutable())
547 continue; // Already reclaimed while destroying an unreachable parent.
548 if (N != Result && N->refCount == 0)
549 N->destroy();
550 else
551 N->markImmutable();
552 }
553 createdNodes.clear();
554 }
555
556 /// Used by add_internal and remove_internal to balance a newly created tree.
557 TreeTy* balanceTree(TreeTy* L, value_type_ref V, TreeTy* R) {
558 unsigned hl = getHeight(L);
559 unsigned hr = getHeight(R);
560
561 if (hl > hr + 2) {
562 assert(!isEmpty(L) && "Left tree cannot be empty to have a height >= 2");
563
564 TreeTy *LL = getLeft(L);
565 TreeTy *LR = getRight(L);
566
567 if (getHeight(LL) >= getHeight(LR))
568 return createNode(LL, L, createNode(LR,V,R));
569
570 assert(!isEmpty(LR) && "LR cannot be empty because it has a height >= 1");
571
572 TreeTy *LRL = getLeft(LR);
573 TreeTy *LRR = getRight(LR);
574
575 return createNode(createNode(LL,L,LRL), LR, createNode(LRR,V,R));
576 }
577
578 if (hr > hl + 2) {
579 assert(!isEmpty(R) && "Right tree cannot be empty to have a height >= 2");
580
581 TreeTy *RL = getLeft(R);
582 TreeTy *RR = getRight(R);
583
584 if (getHeight(RR) >= getHeight(RL))
585 return createNode(createNode(L,V,RL), R, RR);
586
587 assert(!isEmpty(RL) && "RL cannot be empty because it has a height >= 1");
588
589 TreeTy *RLL = getLeft(RL);
590 TreeTy *RLR = getRight(RL);
591
592 return createNode(createNode(L,V,RLL), RL, createNode(RLR,R,RR));
593 }
594
595 return createNode(L,V,R);
596 }
597
598 /// Combines \p L and \p R with the value \p V (every key in \p L less than
599 /// \p V, every key in \p R greater) into one balanced tree. Unlike
600 /// balanceTree this tolerates an arbitrary height difference between \p L and
601 /// \p R: it descends the taller side's spine and rebalances on the way back
602 /// up, exactly as an insertion would.
603 TreeTy *joinTrees(TreeTy *L, value_type_ref V, TreeTy *R) {
604 if (getHeight(L) > getHeight(R) + 2)
605 return balanceTree(getLeft(L), getValue(L), joinTrees(getRight(L), V, R));
606 if (getHeight(R) > getHeight(L) + 2)
607 return balanceTree(joinTrees(L, V, getLeft(R)), getValue(R), getRight(R));
608 return createNode(L, V, R);
609 }
610
611 /// Splits \p T into \p L (all keys less than \p K) and \p R (all keys greater
612 /// than \p K). If \p K is present in \p T, \p Match is set to point at its
613 /// element (which is dropped from \p L and \p R); otherwise \p Match is null.
614 void splitLookup(TreeTy *T, key_type_ref K, TreeTy *&L,
615 const value_type *&Match, TreeTy *&R) {
616 if (isEmpty(T)) {
617 L = R = getEmptyTree();
618 Match = nullptr;
619 return;
620 }
621 key_type_ref KCurrent = ImutInfo::KeyOfValue(getValue(T));
622 if (ImutInfo::isEqual(K, KCurrent)) {
623 L = getLeft(T);
624 R = getRight(T);
625 // Use the tree accessor, which returns a reference to the stored element
626 // (the factory's getValue returns value_type_ref, which is by value for
627 // pointer-like element types).
628 Match = &T->getValue();
629 } else if (ImutInfo::isLess(K, KCurrent)) {
630 TreeTy *LR;
631 splitLookup(getLeft(T), K, L, Match, LR);
632 R = joinTrees(LR, getValue(T), getRight(T));
633 } else {
634 TreeTy *RL;
635 splitLookup(getRight(T), K, RL, Match, R);
636 L = joinTrees(getLeft(T), getValue(T), RL);
637 }
638 }
639
640 /// Rebuilds \p T with the same shape but each element replaced by
641 /// \p Combine applied to it. \p FromB selects which side of \p Combine the
642 /// element is passed on (it is the sole non-null argument).
643 template <typename CombineFn>
644 TreeTy *transformTree(TreeTy *T, CombineFn &Combine, bool FromB) {
645 if (isEmpty(T))
646 return T;
647 TreeTy *L = transformTree(getLeft(T), Combine, FromB);
648 TreeTy *R = transformTree(getRight(T), Combine, FromB);
649 const value_type &E = getValue(T);
650 return createNode(L, FromB ? Combine(nullptr, &E) : Combine(&E, nullptr),
651 R);
652 }
653
654 /// Merges \p A and \p B by recursing over \p A's structure and splitting \p B
655 /// at each of \p A's keys. For a key in both, the stored element is
656 /// Combine(AElem, BElem). \p KeepUnmatched controls keys unique to one side:
657 /// when true, such elements (and whole non-overlapping subtrees) are taken
658 /// unchanged and shared, and \p Combine is invoked only on keys present in
659 /// both (valid when \p Combine is an identity for a missing side, e.g. a set
660 /// union or a lattice join with an identity element); when false every key is
661 /// passed through \p Combine with the absent side null (needed for a join
662 /// that transforms unmatched keys, e.g. liveness downgrading Must to Maybe).
663 template <typename CombineFn>
664 TreeTy *merge_internal(TreeTy *A, TreeTy *B, CombineFn &Combine,
665 bool KeepUnmatched, bool SkipShared) {
666 // When A and B are the same tree (which happens all the time once B is
667 // derived from A by a small edit, since the untouched side is shared by
668 // pointer), an idempotent merge returns it unchanged in O(1). Only valid
669 // when merge(x, x) == x, so the caller opts in via SkipShared.
670 if (SkipShared && A == B)
671 return A;
672 if (isEmpty(A))
673 return KeepUnmatched ? B : transformTree(B, Combine, /*FromB=*/true);
674 if (isEmpty(B))
675 return KeepUnmatched ? A : transformTree(A, Combine, /*FromB=*/false);
676
677 const value_type &AElem = getValue(A);
678 TreeTy *BL, *BR;
679 const value_type *BMatch;
680 splitLookup(B, ImutInfo::KeyOfValue(AElem), BL, BMatch, BR);
681
682 TreeTy *NewL =
683 merge_internal(getLeft(A), BL, Combine, KeepUnmatched, SkipShared);
684 TreeTy *NewR =
685 merge_internal(getRight(A), BR, Combine, KeepUnmatched, SkipShared);
686
687 if (!BMatch) {
688 // Key present only in A.
689 if (KeepUnmatched) {
690 if (NewL == getLeft(A) && NewR == getRight(A))
691 return A;
692 return joinTrees(NewL, AElem, NewR);
693 }
694 return joinTrees(NewL, Combine(&AElem, nullptr), NewR);
695 }
696 // Key present in both: combine the two elements. Preserve sharing when the
697 // combined value is unchanged and neither subtree moved, so that a join
698 // that only touches a few keys does not rebuild the whole spine.
699 auto NewElem = Combine(&AElem, BMatch);
700 if (NewL == getLeft(A) && NewR == getRight(A) &&
701 ImutInfo::isDataEqual(ImutInfo::DataOfValue(NewElem),
702 ImutInfo::DataOfValue(AElem)))
703 return A;
704 return joinTrees(NewL, NewElem, NewR);
705 }
706
707 /// add_internal - Creates a new tree that includes the specified
708 /// data and the data from the original tree. If the original tree
709 /// already contained the data item, the original tree is returned.
710 TreeTy *add_internal(value_type_ref V, TreeTy *T) {
711 if (isEmpty(T))
712 return createNode(T, V, T);
713 assert(!T->isMutable());
714
715 key_type_ref K = ImutInfo::KeyOfValue(V);
716 key_type_ref KCurrent = ImutInfo::KeyOfValue(getValue(T));
717
718 if (ImutInfo::isEqual(K, KCurrent)) {
719 // If both key and value are same, return the original tree.
720 if (ImutInfo::isDataEqual(ImutInfo::DataOfValue(V),
721 ImutInfo::DataOfValue(getValue(T))))
722 return T;
723 // Otherwise create a new node with the new value.
724 return createNode(getLeft(T), V, getRight(T));
725 }
726
727 TreeTy *NewL = getLeft(T);
728 TreeTy *NewR = getRight(T);
729 if (ImutInfo::isLess(K, KCurrent))
730 NewL = add_internal(V, NewL);
731 else
732 NewR = add_internal(V, NewR);
733
734 // If no changes were made, return the original tree. Otherwise, balance the
735 // tree and return the new root.
736 return NewL == getLeft(T) && NewR == getRight(T)
737 ? T
738 : balanceTree(NewL, getValue(T), NewR);
739 }
740
741 /// remove_internal - Creates a new tree that includes all the data
742 /// from the original tree except the specified data. If the
743 /// specified data did not exist in the original tree, the original
744 /// tree is returned.
745 TreeTy *remove_internal(key_type_ref K, TreeTy *T) {
746 if (isEmpty(T))
747 return T;
748
749 assert(!T->isMutable());
750
751 key_type_ref KCurrent = ImutInfo::KeyOfValue(getValue(T));
752
753 if (ImutInfo::isEqual(K, KCurrent))
754 return combineTrees(getLeft(T), getRight(T));
755
756 TreeTy *NewL = getLeft(T);
757 TreeTy *NewR = getRight(T);
758 if (ImutInfo::isLess(K, KCurrent))
759 NewL = remove_internal(K, NewL);
760 else
761 NewR = remove_internal(K, NewR);
762
763 // If no changes were made, return the original tree. Otherwise, balance the
764 // tree and return the new root.
765 return NewL == getLeft(T) && NewR == getRight(T)
766 ? T
767 : balanceTree(NewL, getValue(T), NewR);
768 }
769
770 TreeTy* combineTrees(TreeTy* L, TreeTy* R) {
771 if (isEmpty(L))
772 return R;
773 if (isEmpty(R))
774 return L;
775 TreeTy* OldNode;
776 TreeTy* newRight = removeMinBinding(R,OldNode);
777 return balanceTree(L, getValue(OldNode), newRight);
778 }
779
780 TreeTy* removeMinBinding(TreeTy* T, TreeTy*& Noderemoved) {
781 assert(!isEmpty(T));
782 if (isEmpty(getLeft(T))) {
783 Noderemoved = T;
784 return getRight(T);
785 }
786 return balanceTree(removeMinBinding(getLeft(T), Noderemoved),
787 getValue(T), getRight(T));
788 }
789
790public:
791 TreeTy *getCanonicalTree(TreeTy *TNew) {
792 static_assert(Canonicalize,
793 "getCanonicalTree requires a canonicalizing factory");
794 if (!TNew)
795 return nullptr;
796
797 if (TNew->IsCanonicalized)
798 return TNew;
799
800 // Search the hashtable for another tree with the same digest, and
801 // if find a collision compare those trees by their contents.
802 unsigned digest = TNew->computeDigest();
803 TreeTy *&entry = this->Cache[maskCacheIndex(digest)];
804 if (entry) {
805 for (TreeTy *T = entry; T != nullptr; T = T->Next) {
806 // Compare the contents of 'T' with 'TNew'. isEqual skips subtrees that
807 // are shared by pointer, so for structurally-shared persistent trees
808 // (the common case, e.g. one derived from the other) this is linear in
809 // the number of differing nodes rather than in the tree size.
810 if (!TNew->isEqual(*T))
811 continue;
812 // Trees did match! Return 'T'.
813 if (TNew->refCount == 0)
814 TNew->destroy();
815 return T;
816 }
817 entry->Prev = TNew;
818 TNew->Next = entry;
819 }
820
821 entry = TNew;
822 TNew->IsCanonicalized = true;
823 return TNew;
824 }
825};
826
827//===----------------------------------------------------------------------===//
828// Immutable AVL-Tree Iterator.
829//===----------------------------------------------------------------------===//
830
831/// Bidirectional in-order iterator over the nodes of an ImutAVLTree.
832///
833/// The iterator keeps the chain of ancestors from the root down to the current
834/// node on an explicit stack of plain node pointers, and decides which way to
835/// move next by inspecting whether it is ascending from a node's left or right
836/// child. This avoids storing any per-node visit-state: there is no need to
837/// remember "have I already visited this node's left/right subtree", because
838/// that is recovered by comparing the child we just left against the parent's
839/// left and right pointers.
840///
841/// A node's parent cannot be cached in the node itself, because these trees are
842/// persistent and structurally shared: a single node may appear as the child of
843/// different parents across different tree versions. The ancestor stack is
844/// therefore the per-traversal parent chain.
845template <typename ImutInfo, bool Canonicalize>
847public:
848 using iterator_category = std::bidirectional_iterator_tag;
850 using difference_type = std::ptrdiff_t;
853
855
856private:
857 // Path[0] is the root and Path.back() is the current node. An empty path is
858 // the end iterator. The invariant is that Path always holds the exact chain
859 // of ancestors of the current node, root-most first.
861
862 // Descend along left children, pushing each node; lands on the minimum of the
863 // subtree rooted at T (i.e. the first node in an in-order traversal of T).
864 void descendToMin(TreeTy *T) {
865 for (; T; T = T->getLeft())
866 Path.push_back(T);
867 }
868
869 // Descend along right children, pushing each node; lands on the maximum of
870 // the subtree rooted at T (i.e. the last node in an in-order traversal of T).
871 void descendToMax(TreeTy *T) {
872 for (; T; T = T->getRight())
873 Path.push_back(T);
874 }
875
876 // Pop the current node and ascend until we reach an ancestor from its *left*
877 // child, i.e. the first ancestor whose subtree is not yet fully visited. That
878 // ancestor is the in-order successor of the subtree we just left; if there is
879 // none, Path is emptied (the end iterator). Shared by operator++ and
880 // skipSubTree, whose only difference is whether the current node's right
881 // subtree is descended into first.
882 void ascendFromRightChild() {
883 TreeTy *Child = Path.pop_back_val();
884 while (!Path.empty() && Path.back()->getRight() == Child)
885 Child = Path.pop_back_val();
886 }
887
888 // Mirror of ascendFromRightChild for reverse traversal (operator--).
889 void ascendFromLeftChild() {
890 TreeTy *Child = Path.pop_back_val();
891 while (!Path.empty() && Path.back()->getLeft() == Child)
892 Child = Path.pop_back_val();
893 }
894
895public:
896 ImutAVLTreeInOrderIterator() = default; // end() iterator.
898 descendToMin(const_cast<TreeTy *>(Root));
899 }
900
901 // Two iterators are equal iff they sit on the same node (or are both end()).
902 // Within a single tree a node has a unique root-to-node path, so the current
903 // node alone identifies the position; comparing the whole path is therefore
904 // unnecessary. Comparing iterators from different trees is not meaningful, as
905 // for any standard container.
907 if (Path.empty() || x.Path.empty())
908 return Path.empty() == x.Path.empty();
909 return Path.back() == x.Path.back();
910 }
912 return !(*this == x);
913 }
914
915 TreeTy &operator*() const { return *Path.back(); }
916 TreeTy *operator->() const { return Path.back(); }
917
919 assert(!Path.empty() && "Incrementing the end iterator");
920 if (TreeTy *R = Path.back()->getRight())
921 // The in-order successor is the minimum of the right subtree.
922 descendToMin(R);
923 else
924 // No right subtree: the successor is the nearest ancestor reached from a
925 // left child.
926 ascendFromRightChild();
927 return *this;
928 }
929
931 assert(!Path.empty() && "Decrementing the end iterator");
932 if (TreeTy *L = Path.back()->getLeft())
933 // The in-order predecessor is the maximum of the left subtree.
934 descendToMax(L);
935 else
936 // Mirror of operator++.
937 ascendFromLeftChild();
938 return *this;
939 }
940
941 /// Move to the in-order successor of the entire subtree rooted at the current
942 /// node, i.e. skip the current node together with its right subtree. This is
943 /// exactly the ascent half of operator++.
944 void skipSubTree() {
945 assert(!Path.empty() && "Skipping past the end iterator");
946 ascendFromRightChild();
947 }
948};
949
950/// Generic iterator that wraps a T::TreeTy::iterator and exposes
951/// iterator::getValue() on dereference.
952template <typename T>
955 ImutAVLValueIterator<T>, typename T::TreeTy::iterator,
956 typename std::iterator_traits<
957 typename T::TreeTy::iterator>::iterator_category,
958 const typename T::value_type> {
962
964 return this->I->getValue();
965 }
966};
967
968//===----------------------------------------------------------------------===//
969// Trait classes for Profile information.
970//===----------------------------------------------------------------------===//
971
972/// Generic profile template. The default behavior is to invoke the
973/// profile method of an object. Specializations for primitive integers
974/// and generic handling of pointers is done below.
975template <typename T>
977 using value_type = const T;
978 using value_type_ref = const T&;
979
983};
984
985/// Profile traits for integers.
986template <typename T>
988 using value_type = const T;
989 using value_type_ref = const T&;
990
992 ID.AddInteger(X);
993 }
994};
995
996#define PROFILE_INTEGER_INFO(X)\
997template<> struct ImutProfileInfo<X> : ImutProfileInteger<X> {};
998
1000PROFILE_INTEGER_INFO(unsigned char)
1002PROFILE_INTEGER_INFO(unsigned short)
1003PROFILE_INTEGER_INFO(unsigned)
1006PROFILE_INTEGER_INFO(unsigned long)
1007PROFILE_INTEGER_INFO(long long)
1008PROFILE_INTEGER_INFO(unsigned long long)
1009
1010#undef PROFILE_INTEGER_INFO
1011
1012/// Profile traits for booleans.
1013template <>
1015 using value_type = const bool;
1016 using value_type_ref = const bool&;
1017
1019 ID.AddBoolean(X);
1020 }
1021};
1022
1023/// Generic profile trait for pointer types. We treat pointers as
1024/// references to unique objects.
1025template <typename T>
1027 using value_type = const T*;
1029
1031 ID.AddPointer(X);
1032 }
1033};
1034
1035//===----------------------------------------------------------------------===//
1036// Trait classes that contain element comparison operators and type
1037// definitions used by ImutAVLTree, ImmutableSet, and ImmutableMap. These
1038// inherit from the profile traits (ImutProfileInfo) to include operations
1039// for element profiling.
1040//===----------------------------------------------------------------------===//
1041
1042/// Generic definition of comparison operations for elements of immutable
1043/// containers that defaults to using std::equal_to<> and std::less<> to perform
1044/// comparison of elements.
1045template <typename T> struct ImutContainerInfo : ImutProfileInfo<T> {
1052
1055
1057 return std::equal_to<key_type>()(LHS,RHS);
1058 }
1059
1061 return std::less<key_type>()(LHS,RHS);
1062 }
1063
1064 static bool isDataEqual(data_type_ref, data_type_ref) { return true; }
1065};
1066
1067/// Specialization for pointer values to treat pointers as references to unique
1068/// objects. Pointers are thus compared by their addresses.
1069template <typename T> struct ImutContainerInfo<T *> : ImutProfileInfo<T *> {
1076
1079
1080 static bool isEqual(key_type_ref LHS, key_type_ref RHS) { return LHS == RHS; }
1081
1082 static bool isLess(key_type_ref LHS, key_type_ref RHS) { return LHS < RHS; }
1083
1084 static bool isDataEqual(data_type_ref, data_type_ref) { return true; }
1085};
1086
1087//===----------------------------------------------------------------------===//
1088// Immutable Set
1089//===----------------------------------------------------------------------===//
1090
1091template <typename ValT, typename ValInfo = ImutContainerInfo<ValT>,
1092 bool Canonicalize = true>
1094public:
1095 using value_type = typename ValInfo::value_type;
1096 using value_type_ref = typename ValInfo::value_type_ref;
1098
1099private:
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 explicit ImmutableSet(TreeTy *R) : Root(R) {}
1108
1109 class Factory {
1110 typename TreeTy::Factory F;
1111
1112 public:
1113 Factory() = default;
1114
1116
1117 Factory(const Factory& RHS) = delete;
1118 void operator=(const Factory& RHS) = delete;
1119
1120 /// Returns an immutable set that contains no elements.
1122 return ImmutableSet(F.getEmptyTree());
1123 }
1124
1125 /// Creates a new immutable set that contains all of the values
1126 /// of the original set with the addition of the specified value. If
1127 /// the original set already included the value, then the original set is
1128 /// returned and no memory is allocated. The time and space complexity
1129 /// of this operation is logarithmic in the size of the original set.
1130 /// The memory allocated to represent the set is released when the
1131 /// factory object that created the set is destroyed.
1133 TreeTy *NewT = F.add(Old.Root.get(), V);
1134 if constexpr (Canonicalize)
1135 return ImmutableSet(F.getCanonicalTree(NewT));
1136 else
1137 return ImmutableSet(NewT);
1138 }
1139
1140 /// Returns the union of \p A and \p B, computed in a single traversal that
1141 /// shares subtrees of both operands wherever possible (see
1142 /// ImutAVLFactory::unionTrees). This is more efficient than repeatedly
1143 /// adding \p B's elements to \p A when \p B is large.
1145 if (A.Root.get() == B.Root.get() || B.isEmpty())
1146 return A;
1147 if (A.isEmpty())
1148 return B;
1149 // Drive the recursion with the taller tree so the shorter one is the one
1150 // being split.
1151 if (A.getHeight() < B.getHeight())
1152 std::swap(A, B);
1153 if constexpr (Canonicalize) {
1154 // The bulk path does not canonicalize the nodes it creates, so fall
1155 // back to per-element insertion for canonicalizing factories.
1156 for (value_type_ref V : B)
1157 A = add(A, V);
1158 return A;
1159 } else {
1160 return ImmutableSet(F.unionTrees(A.Root.get(), B.Root.get()));
1161 }
1162 }
1163
1164 /// Creates a new immutable set that contains all of the values
1165 /// of the original set with the exception of the specified value. If
1166 /// the original set did not contain the value, the original set is
1167 /// returned and no memory is allocated. The time and space complexity
1168 /// of this operation is logarithmic in the size of the original set.
1169 /// The memory allocated to represent the set is released when the
1170 /// factory object that created the set is destroyed.
1172 TreeTy *NewT = F.remove(Old.Root.get(), V);
1173 if constexpr (Canonicalize)
1174 return ImmutableSet(F.getCanonicalTree(NewT));
1175 else
1176 return ImmutableSet(NewT);
1177 }
1178
1179 BumpPtrAllocator& getAllocator() { return F.getAllocator(); }
1180
1182 return const_cast<typename TreeTy::Factory *>(&F);
1183 }
1184 };
1185
1186 friend class Factory;
1187
1188 /// Returns true if the set contains the specified value.
1189 bool contains(value_type_ref V) const {
1190 return Root ? Root->contains(V) : false;
1191 }
1192
1193 /// Compares two sets for equality. For a canonicalizing factory, sets with
1194 /// equal contents share the same tree, so this is an O(1) pointer comparison
1195 /// (like ImmutableList); only sets created by the same factory may be
1196 /// compared. Otherwise it is a structural comparison.
1197 bool operator==(const ImmutableSet &RHS) const {
1198 if constexpr (Canonicalize)
1199 return Root == RHS.Root;
1200 else
1201 return Root && RHS.Root ? Root->isEqual(*RHS.Root.get())
1202 : Root == RHS.Root;
1203 }
1204
1205 bool operator!=(const ImmutableSet &RHS) const {
1206 if constexpr (Canonicalize)
1207 return Root != RHS.Root;
1208 else
1209 return Root && RHS.Root ? Root->isNotEqual(*RHS.Root.get())
1210 : Root != RHS.Root;
1211 }
1212
1214 if (Root) { Root->retain(); }
1215 return Root.get();
1216 }
1217
1218 TreeTy *getRootWithoutRetain() const { return Root.get(); }
1219
1220 /// Return true if the set contains no elements.
1221 bool isEmpty() const { return !Root; }
1222
1223 /// Return true if the set contains exactly one element.
1224 /// This method runs in constant time.
1225 bool isSingleton() const { return getHeight() == 1; }
1226
1227 //===--------------------------------------------------===//
1228 // Iterators.
1229 //===--------------------------------------------------===//
1230
1232
1233 iterator begin() const { return iterator(Root.get()); }
1234 iterator end() const { return iterator(); }
1235
1236 //===--------------------------------------------------===//
1237 // Utility methods.
1238 //===--------------------------------------------------===//
1239
1240 unsigned getHeight() const { return Root ? Root->getHeight() : 0; }
1241
1242 static void Profile(FoldingSetNodeID &ID, const ImmutableSet &S) {
1243 ID.AddPointer(S.Root.get());
1244 }
1245
1246 void Profile(FoldingSetNodeID &ID) const { return Profile(ID, *this); }
1247
1248 //===--------------------------------------------------===//
1249 // For testing.
1250 //===--------------------------------------------------===//
1251
1252 void validateTree() const { if (Root) Root->validateTree(); }
1253};
1254
1255// NOTE: This may some day replace the current ImmutableSet.
1256template <typename ValT, typename ValInfo = ImutContainerInfo<ValT>,
1257 bool Canonicalize = true>
1259public:
1260 using value_type = typename ValInfo::value_type;
1261 using value_type_ref = typename ValInfo::value_type_ref;
1263 using FactoryTy = typename TreeTy::Factory;
1264
1265private:
1267 FactoryTy *Factory;
1268
1269public:
1270 /// Constructs a set from a pointer to a tree root. In general one
1271 /// should use a Factory object to create sets instead of directly
1272 /// invoking the constructor, but there are cases where make this
1273 /// constructor public is useful.
1274 ImmutableSetRef(TreeTy *R, FactoryTy *F) : Root(R), Factory(F) {}
1275
1277 return ImmutableSetRef(0, F);
1278 }
1279
1281 return ImmutableSetRef(Factory->add(Root.get(), V), Factory);
1282 }
1283
1285 return ImmutableSetRef(Factory->remove(Root.get(), V), Factory);
1286 }
1287
1288 /// Returns true if the set contains the specified value.
1289 bool contains(value_type_ref V) const {
1290 return Root ? Root->contains(V) : false;
1291 }
1292
1295 if constexpr (Canonicalize)
1296 return SetTy(Factory->getCanonicalTree(Root.get()));
1297 else
1298 return SetTy(Root.get());
1299 }
1300
1301 TreeTy *getRootWithoutRetain() const { return Root.get(); }
1302
1303 bool operator==(const ImmutableSetRef &RHS) const {
1304 return Root && RHS.Root ? Root->isEqual(*RHS.Root.get()) : Root == RHS.Root;
1305 }
1306
1307 bool operator!=(const ImmutableSetRef &RHS) const {
1308 return Root && RHS.Root ? Root->isNotEqual(*RHS.Root.get())
1309 : Root != RHS.Root;
1310 }
1311
1312 /// Return true if the set contains no elements.
1313 bool isEmpty() const { return !Root; }
1314
1315 /// Return true if the set contains exactly one element.
1316 /// This method runs in constant time.
1317 bool isSingleton() const { return getHeight() == 1; }
1318
1319 //===--------------------------------------------------===//
1320 // Iterators.
1321 //===--------------------------------------------------===//
1322
1324
1325 iterator begin() const { return iterator(Root.get()); }
1326 iterator end() const { return iterator(); }
1327
1328 //===--------------------------------------------------===//
1329 // Utility methods.
1330 //===--------------------------------------------------===//
1331
1332 unsigned getHeight() const { return Root ? Root->getHeight() : 0; }
1333
1334 static void Profile(FoldingSetNodeID &ID, const ImmutableSetRef &S) {
1335 ID.AddPointer(S.Root.get());
1336 }
1337
1338 void Profile(FoldingSetNodeID &ID) const { return Profile(ID, *this); }
1339
1340 //===--------------------------------------------------===//
1341 // For testing.
1342 //===--------------------------------------------------===//
1343
1344 void validateTree() const { if (Root) Root->validateTree(); }
1345};
1346
1347} // end namespace llvm
1348
1349#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:856
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< StatepointGC > D("statepoint-example", "an example strategy for statepoint")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
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: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)
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.
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
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: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.