LLVM 23.0.0git
ImmutableSet.h
Go to the documentation of this file.
1//===--- ImmutableSet.h - Immutable (functional) set interface --*- C++ -*-===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8///
9/// \file
10/// This file defines the ImutAVLTree and ImmutableSet classes.
11///
12//===----------------------------------------------------------------------===//
13
14#ifndef LLVM_ADT_IMMUTABLESET_H
15#define LLVM_ADT_IMMUTABLESET_H
16
17#include "llvm/ADT/DenseMap.h"
18#include "llvm/ADT/FoldingSet.h"
21#include "llvm/ADT/iterator.h"
24#include "llvm/Support/Debug.h"
27#include <cassert>
28#include <cstdint>
29#include <functional>
30#include <iterator>
31#include <new>
32#include <vector>
33
34namespace llvm {
35
36//===----------------------------------------------------------------------===//
37// Immutable AVL-Tree Definition.
38//===----------------------------------------------------------------------===//
39
40template <typename ImutInfo> class ImutAVLFactory;
41template <typename ImutInfo> class ImutIntervalAVLFactory;
42template <typename ImutInfo> class ImutAVLTreeInOrderIterator;
43template <typename ImutInfo> class ImutAVLTreeGenericIterator;
44
45template <typename ImutInfo >
46class ImutAVLTree {
47public:
48 using key_type_ref = typename ImutInfo::key_type_ref;
49 using value_type = typename ImutInfo::value_type;
50 using value_type_ref = typename ImutInfo::value_type_ref;
53
54 friend class ImutAVLFactory<ImutInfo>;
55 friend class ImutIntervalAVLFactory<ImutInfo>;
56 friend class ImutAVLTreeGenericIterator<ImutInfo>;
57
58 //===----------------------------------------------------===//
59 // Public Interface.
60 //===----------------------------------------------------===//
61
62 /// Return a pointer to the left subtree. This value
63 /// is NULL if there is no left subtree.
64 ImutAVLTree *getLeft() const { return left; }
65
66 /// Return a pointer to the right subtree. This value is
67 /// NULL if there is no right subtree.
68 ImutAVLTree *getRight() const { return right; }
69
70 /// Returns the height of the tree. A tree with no subtrees has a height of 1.
71 unsigned getHeight() const { return height; }
72
73 /// Returns the data value associated with the tree node.
74 const value_type& getValue() const { return value; }
75
76 /// Finds the subtree associated with the specified key value. This method
77 /// returns NULL if no matching subtree is found.
78 ImutAVLTree* find(key_type_ref K) {
79 ImutAVLTree *T = this;
80 while (T) {
81 key_type_ref CurrentKey = ImutInfo::KeyOfValue(T->getValue());
82 if (ImutInfo::isEqual(K,CurrentKey))
83 return T;
84 else if (ImutInfo::isLess(K,CurrentKey))
85 T = T->getLeft();
86 else
87 T = T->getRight();
88 }
89 return nullptr;
90 }
91
92 /// Find the subtree associated with the highest ranged key value.
93 ImutAVLTree* getMaxElement() {
94 ImutAVLTree *T = this;
95 ImutAVLTree *Right = T->getRight();
96 while (Right) { T = Right; Right = T->getRight(); }
97 return T;
98 }
99
100 /// Returns the number of nodes in the tree, which includes both leaves and
101 // non-leaf nodes.
102 unsigned size() const {
103 unsigned n = 1;
104 if (const ImutAVLTree* L = getLeft())
105 n += L->size();
106 if (const ImutAVLTree* R = getRight())
107 n += R->size();
108 return n;
109 }
110
111 /// Returns an iterator that iterates over the nodes of the tree in an inorder
112 /// traversal. The returned iterator thus refers to the tree node with the
113 /// minimum data element.
114 iterator begin() const { return iterator(this); }
115
116 /// Returns an iterator for the tree that denotes the end of an inorder
117 /// traversal.
118 iterator end() const { return iterator(); }
119
121 // Compare the keys.
122 if (!ImutInfo::isEqual(ImutInfo::KeyOfValue(getValue()),
123 ImutInfo::KeyOfValue(V)))
124 return false;
125
126 // Also compare the data values.
127 if (!ImutInfo::isDataEqual(ImutInfo::DataOfValue(getValue()),
128 ImutInfo::DataOfValue(V)))
129 return false;
130
131 return true;
132 }
133
134 bool isElementEqual(const ImutAVLTree* RHS) const {
135 return isElementEqual(RHS->getValue());
136 }
137
138 /// Compares two trees for structural equality and returns true if they are
139 /// equal. The worst case performance of this operation is linear in the sizes
140 /// of the trees.
141 bool isEqual(const ImutAVLTree& RHS) const {
142 if (&RHS == this)
143 return true;
144
145 iterator LItr = begin(), LEnd = end();
146 iterator RItr = RHS.begin(), REnd = RHS.end();
147
148 while (LItr != LEnd && RItr != REnd) {
149 if (&*LItr == &*RItr) {
150 LItr.skipSubTree();
151 RItr.skipSubTree();
152 continue;
153 }
154
155 if (!LItr->isElementEqual(&*RItr))
156 return false;
157
158 ++LItr;
159 ++RItr;
160 }
161
162 return LItr == LEnd && RItr == REnd;
163 }
164
165 /// Compares two trees for structural inequality. Performance is the same as
166 /// isEqual.
167 bool isNotEqual(const ImutAVLTree& RHS) const { return !isEqual(RHS); }
168
169 /// Returns true if this tree contains a subtree (node) that has an data
170 /// element that matches the specified key. Complexity is logarithmic in the
171 /// size of the tree.
172 bool contains(key_type_ref K) { return (bool) find(K); }
173
174 /// A utility method that checks that the balancing and ordering invariants of
175 /// the tree are satisfied. It is a recursive method that returns the height
176 /// of the tree, which is then consumed by the enclosing validateTree call.
177 /// External callers should ignore the return value. An invalid tree will
178 /// cause an assertion to fire in a debug build.
179 unsigned validateTree() const {
180 unsigned HL = getLeft() ? getLeft()->validateTree() : 0;
181 unsigned HR = getRight() ? getRight()->validateTree() : 0;
182 (void) HL;
183 (void) HR;
184
185 assert(getHeight() == ( HL > HR ? HL : HR ) + 1
186 && "Height calculation wrong");
187
188 assert((HL > HR ? HL-HR : HR-HL) <= 2
189 && "Balancing invariant violated");
190
191 assert((!getLeft() ||
192 ImutInfo::isLess(ImutInfo::KeyOfValue(getLeft()->getValue()),
193 ImutInfo::KeyOfValue(getValue()))) &&
194 "Value in left child is not less that current value");
195
196 assert((!getRight() ||
197 ImutInfo::isLess(ImutInfo::KeyOfValue(getValue()),
198 ImutInfo::KeyOfValue(getRight()->getValue()))) &&
199 "Current value is not less that value of right child");
200
201 return getHeight();
202 }
203
204 //===----------------------------------------------------===//
205 // Internal values.
206 //===----------------------------------------------------===//
207
208private:
209 Factory *factory;
210 ImutAVLTree *left;
211 ImutAVLTree *right;
212 ImutAVLTree *prev = nullptr;
213 ImutAVLTree *next = nullptr;
214
215 unsigned height : 28;
217 unsigned IsMutable : 1;
219 unsigned IsDigestCached : 1;
221 unsigned IsCanonicalized : 1;
222
223 value_type value;
224 uint32_t digest = 0;
225 uint32_t refCount = 0;
226
227 //===----------------------------------------------------===//
228 // Internal methods (node manipulation; used by Factory).
229 //===----------------------------------------------------===//
230
231private:
232 /// Internal constructor that is only called by ImutAVLFactory.
234 unsigned height)
235 : factory(f), left(l), right(r), height(height), IsMutable(true),
236 IsDigestCached(false), IsCanonicalized(false), value(v)
237 {
238 if (left) left->retain();
239 if (right) right->retain();
240 }
241
242 /// Returns true if the left and right subtree references
243 /// (as well as height) can be changed. If this method returns false,
244 /// the tree is truly immutable. Trees returned from an ImutAVLFactory
245 /// object should always have this method return true. Further, if this
246 /// method returns false for an instance of ImutAVLTree, all subtrees
247 /// will also have this method return false. The converse is not true.
248 bool isMutable() const { return IsMutable; }
249
250 /// Returns true if the digest for this tree is cached. This can only be true
251 /// if the tree is immutable.
252 bool hasCachedDigest() const { return IsDigestCached; }
253
254 //===----------------------------------------------------===//
255 // Mutating operations. A tree root can be manipulated as
256 // long as its reference has not "escaped" from internal
257 // methods of a factory object (see below). When a tree
258 // pointer is externally viewable by client code, the
259 // internal "mutable bit" is cleared to mark the tree
260 // immutable. Note that a tree that still has its mutable
261 // bit set may have children (subtrees) that are themselves
262 // immutable.
263 //===----------------------------------------------------===//
264
265 /// Clears the mutable flag for a tree. After this happens,
266 /// it is an error to call setLeft(), setRight(), and setHeight().
267 void markImmutable() {
268 assert(isMutable() && "Mutable flag already removed.");
269 IsMutable = false;
270 }
271
272 /// Clears the NoCachedDigest flag for a tree.
273 void markedCachedDigest() {
274 assert(!hasCachedDigest() && "NoCachedDigest flag already removed.");
275 IsDigestCached = true;
276 }
277
278 /// Changes the height of the tree. Used internally by ImutAVLFactory.
279 void setHeight(unsigned h) {
280 assert(isMutable() && "Only a mutable tree can have its height changed.");
281 height = h;
282 }
283
284 static uint32_t computeDigest(ImutAVLTree *L, ImutAVLTree *R,
285 value_type_ref V) {
286 uint32_t digest = 0;
287
288 if (L)
289 digest += L->computeDigest();
290
291 // Compute digest of stored data.
292 FoldingSetNodeID ID;
293 ImutInfo::Profile(ID,V);
294 digest += ID.ComputeHash();
295
296 if (R)
297 digest += R->computeDigest();
298
299 return digest;
300 }
301
302 uint32_t computeDigest() {
303 // Check the lowest bit to determine if digest has actually been
304 // pre-computed.
305 if (hasCachedDigest())
306 return digest;
307
308 uint32_t X = computeDigest(getLeft(), getRight(), getValue());
309 digest = X;
310 markedCachedDigest();
311 return X;
312 }
313
314 //===----------------------------------------------------===//
315 // Reference count operations.
316 //===----------------------------------------------------===//
317
318public:
319 void retain() { ++refCount; }
320
321 void release() {
322 assert(refCount > 0);
323 if (--refCount == 0)
324 destroy();
325 }
326
327 void destroy() {
328 if (left)
329 left->release();
330 if (right)
331 right->release();
332 if (IsCanonicalized) {
333 if (next)
334 next->prev = prev;
335
336 if (prev)
337 prev->next = next;
338 else
339 factory->Cache[factory->maskCacheIndex(computeDigest())] = next;
340 }
341
342 // We need to clear the mutability bit in case we are
343 // destroying the node as part of a sweep in ImutAVLFactory::recoverNodes().
344 IsMutable = false;
345 factory->freeNodes.push_back(this);
346 }
347};
348
349template <typename ImutInfo>
351 static void retain(ImutAVLTree<ImutInfo> *Tree) { Tree->retain(); }
352 static void release(ImutAVLTree<ImutInfo> *Tree) { Tree->release(); }
353};
354
355//===----------------------------------------------------------------------===//
356// Immutable AVL-Tree Factory class.
357//===----------------------------------------------------------------------===//
358
359template <typename ImutInfo >
361 friend class ImutAVLTree<ImutInfo>;
362
363 using TreeTy = ImutAVLTree<ImutInfo>;
364 using value_type_ref = typename TreeTy::value_type_ref;
365 using key_type_ref = typename TreeTy::key_type_ref;
366 using CacheTy = DenseMap<unsigned, TreeTy*>;
367
368 CacheTy Cache;
369 uintptr_t Allocator;
370 std::vector<TreeTy*> createdNodes;
371 std::vector<TreeTy*> freeNodes;
372
373 bool ownsAllocator() const {
374 return (Allocator & 0x1) == 0;
375 }
376
377 BumpPtrAllocator& getAllocator() const {
378 return *reinterpret_cast<BumpPtrAllocator*>(Allocator & ~0x1);
379 }
380
381 //===--------------------------------------------------===//
382 // Public interface.
383 //===--------------------------------------------------===//
384
385public:
387 : Allocator(reinterpret_cast<uintptr_t>(new BumpPtrAllocator())) {}
388
390 : Allocator(reinterpret_cast<uintptr_t>(&Alloc) | 0x1) {}
391
393 if (ownsAllocator()) delete &getAllocator();
394 }
395
396 TreeTy* add(TreeTy* T, value_type_ref V) {
397 T = add_internal(V,T);
399 recoverNodes();
400 return T;
401 }
402
403 TreeTy* remove(TreeTy* T, key_type_ref V) {
404 T = remove_internal(V,T);
406 recoverNodes();
407 return T;
408 }
409
410 TreeTy* getEmptyTree() const { return nullptr; }
411
412protected:
413 //===--------------------------------------------------===//
414 // A bunch of quick helper functions used for reasoning
415 // about the properties of trees and their children.
416 // These have succinct names so that the balancing code
417 // is as terse (and readable) as possible.
418 //===--------------------------------------------------===//
419
420 bool isEmpty(TreeTy* T) const { return !T; }
421 unsigned getHeight(TreeTy* T) const { return T ? T->getHeight() : 0; }
422 TreeTy* getLeft(TreeTy* T) const { return T->getLeft(); }
423 TreeTy* getRight(TreeTy* T) const { return T->getRight(); }
424 value_type_ref getValue(TreeTy* T) const { return T->value; }
425
426 // Make sure the index is not the Tombstone or Entry key of the DenseMap.
427 static unsigned maskCacheIndex(unsigned I) { return (I & ~0x02); }
428
429 unsigned incrementHeight(TreeTy* L, TreeTy* R) const {
430 unsigned hl = getHeight(L);
431 unsigned hr = getHeight(R);
432 return (hl > hr ? hl : hr) + 1;
433 }
434
435 static bool compareTreeWithSection(TreeTy* T,
436 typename TreeTy::iterator& TI,
437 typename TreeTy::iterator& TE) {
438 typename TreeTy::iterator I = T->begin(), E = T->end();
439 for ( ; I!=E ; ++I, ++TI) {
440 if (TI == TE || !I->isElementEqual(&*TI))
441 return false;
442 }
443 return true;
444 }
445
446 //===--------------------------------------------------===//
447 // "createNode" is used to generate new tree roots that link
448 // to other trees. The function may also simply move links
449 // in an existing root if that root is still marked mutable.
450 // This is necessary because otherwise our balancing code
451 // would leak memory as it would create nodes that are
452 // then discarded later before the finished tree is
453 // returned to the caller.
454 //===--------------------------------------------------===//
455
456 TreeTy* createNode(TreeTy* L, value_type_ref V, TreeTy* R) {
457 BumpPtrAllocator& A = getAllocator();
458 TreeTy* T;
459 if (!freeNodes.empty()) {
460 T = freeNodes.back();
461 freeNodes.pop_back();
462 assert(T != L);
463 assert(T != R);
464 } else {
465 T = (TreeTy*) A.Allocate<TreeTy>();
466 }
467 new (T) TreeTy(this, L, R, V, incrementHeight(L,R));
468 createdNodes.push_back(T);
469 return T;
470 }
471
472 TreeTy* createNode(TreeTy* newLeft, TreeTy* oldTree, TreeTy* newRight) {
473 return createNode(newLeft, getValue(oldTree), newRight);
474 }
475
477 for (unsigned i = 0, n = createdNodes.size(); i < n; ++i) {
478 TreeTy *N = createdNodes[i];
479 if (N->isMutable() && N->refCount == 0)
480 N->destroy();
481 }
482 createdNodes.clear();
483 }
484
485 /// Used by add_internal and remove_internal to balance a newly created tree.
486 TreeTy* balanceTree(TreeTy* L, value_type_ref V, TreeTy* R) {
487 unsigned hl = getHeight(L);
488 unsigned hr = getHeight(R);
489
490 if (hl > hr + 2) {
491 assert(!isEmpty(L) && "Left tree cannot be empty to have a height >= 2");
492
493 TreeTy *LL = getLeft(L);
494 TreeTy *LR = getRight(L);
495
496 if (getHeight(LL) >= getHeight(LR))
497 return createNode(LL, L, createNode(LR,V,R));
498
499 assert(!isEmpty(LR) && "LR cannot be empty because it has a height >= 1");
500
501 TreeTy *LRL = getLeft(LR);
502 TreeTy *LRR = getRight(LR);
503
504 return createNode(createNode(LL,L,LRL), LR, createNode(LRR,V,R));
505 }
506
507 if (hr > hl + 2) {
508 assert(!isEmpty(R) && "Right tree cannot be empty to have a height >= 2");
509
510 TreeTy *RL = getLeft(R);
511 TreeTy *RR = getRight(R);
512
513 if (getHeight(RR) >= getHeight(RL))
514 return createNode(createNode(L,V,RL), R, RR);
515
516 assert(!isEmpty(RL) && "RL cannot be empty because it has a height >= 1");
517
518 TreeTy *RLL = getLeft(RL);
519 TreeTy *RLR = getRight(RL);
520
521 return createNode(createNode(L,V,RLL), RL, createNode(RLR,R,RR));
522 }
523
524 return createNode(L,V,R);
525 }
526
527 /// add_internal - Creates a new tree that includes the specified
528 /// data and the data from the original tree. If the original tree
529 /// already contained the data item, the original tree is returned.
530 TreeTy *add_internal(value_type_ref V, TreeTy *T) {
531 if (isEmpty(T))
532 return createNode(T, V, T);
533 assert(!T->isMutable());
534
535 key_type_ref K = ImutInfo::KeyOfValue(V);
536 key_type_ref KCurrent = ImutInfo::KeyOfValue(getValue(T));
537
538 if (ImutInfo::isEqual(K, KCurrent)) {
539 // If both key and value are same, return the original tree.
540 if (ImutInfo::isDataEqual(ImutInfo::DataOfValue(V),
541 ImutInfo::DataOfValue(getValue(T))))
542 return T;
543 // Otherwise create a new node with the new value.
544 return createNode(getLeft(T), V, getRight(T));
545 }
546
547 TreeTy *NewL = getLeft(T);
548 TreeTy *NewR = getRight(T);
549 if (ImutInfo::isLess(K, KCurrent))
550 NewL = add_internal(V, NewL);
551 else
552 NewR = add_internal(V, NewR);
553
554 // If no changes were made, return the original tree. Otherwise, balance the
555 // tree and return the new root.
556 return NewL == getLeft(T) && NewR == getRight(T)
557 ? T
558 : balanceTree(NewL, getValue(T), NewR);
559 }
560
561 /// remove_internal - Creates a new tree that includes all the data
562 /// from the original tree except the specified data. If the
563 /// specified data did not exist in the original tree, the original
564 /// tree is returned.
565 TreeTy *remove_internal(key_type_ref K, TreeTy *T) {
566 if (isEmpty(T))
567 return T;
568
569 assert(!T->isMutable());
570
571 key_type_ref KCurrent = ImutInfo::KeyOfValue(getValue(T));
572
573 if (ImutInfo::isEqual(K, KCurrent))
574 return combineTrees(getLeft(T), getRight(T));
575
576 TreeTy *NewL = getLeft(T);
577 TreeTy *NewR = getRight(T);
578 if (ImutInfo::isLess(K, KCurrent))
579 NewL = remove_internal(K, NewL);
580 else
581 NewR = remove_internal(K, NewR);
582
583 // If no changes were made, return the original tree. Otherwise, balance the
584 // tree and return the new root.
585 return NewL == getLeft(T) && NewR == getRight(T)
586 ? T
587 : balanceTree(NewL, getValue(T), NewR);
588 }
589
590 TreeTy* combineTrees(TreeTy* L, TreeTy* R) {
591 if (isEmpty(L))
592 return R;
593 if (isEmpty(R))
594 return L;
595 TreeTy* OldNode;
596 TreeTy* newRight = removeMinBinding(R,OldNode);
597 return balanceTree(L, getValue(OldNode), newRight);
598 }
599
600 TreeTy* removeMinBinding(TreeTy* T, TreeTy*& Noderemoved) {
601 assert(!isEmpty(T));
602 if (isEmpty(getLeft(T))) {
603 Noderemoved = T;
604 return getRight(T);
605 }
606 return balanceTree(removeMinBinding(getLeft(T), Noderemoved),
607 getValue(T), getRight(T));
608 }
609
610 /// Clears the mutable bits of a root and all of its descendants.
611 void markImmutable(TreeTy* T) {
612 if (!T || !T->isMutable())
613 return;
614 T->markImmutable();
617 }
618
619public:
620 TreeTy *getCanonicalTree(TreeTy *TNew) {
621 if (!TNew)
622 return nullptr;
623
624 if (TNew->IsCanonicalized)
625 return TNew;
626
627 // Search the hashtable for another tree with the same digest, and
628 // if find a collision compare those trees by their contents.
629 unsigned digest = TNew->computeDigest();
630 TreeTy *&entry = Cache[maskCacheIndex(digest)];
631 if (entry) {
632 for (TreeTy *T = entry ; T != nullptr; T = T->next) {
633 // Compare the Contents('T') with Contents('TNew')
634 typename TreeTy::iterator TI = T->begin(), TE = T->end();
635 if (!compareTreeWithSection(TNew, TI, TE))
636 continue;
637 if (TI != TE)
638 continue; // T has more contents than TNew.
639 // Trees did match! Return 'T'.
640 if (TNew->refCount == 0)
641 TNew->destroy();
642 return T;
643 }
644 entry->prev = TNew;
645 TNew->next = entry;
646 }
647
648 entry = TNew;
649 TNew->IsCanonicalized = true;
650 return TNew;
651 }
652};
653
654//===----------------------------------------------------------------------===//
655// Immutable AVL-Tree Iterators.
656//===----------------------------------------------------------------------===//
657
658template <typename ImutInfo> class ImutAVLTreeGenericIterator {
660
661public:
662 using iterator_category = std::bidirectional_iterator_tag;
664 using difference_type = std::ptrdiff_t;
667
669 Flags=0x3 };
670
672
675 if (Root) stack.push_back(reinterpret_cast<uintptr_t>(Root));
676 }
677
678 TreeTy &operator*() const {
679 assert(!stack.empty());
680 return *reinterpret_cast<TreeTy *>(stack.back() & ~Flags);
681 }
682 TreeTy *operator->() const { return &*this; }
683
684 uintptr_t getVisitState() const {
685 assert(!stack.empty());
686 return stack.back() & Flags;
687 }
688
689 bool atEnd() const { return stack.empty(); }
690
691 bool atBeginning() const {
692 return stack.size() == 1 && getVisitState() == VisitedNone;
693 }
694
696 assert(!stack.empty());
697 stack.pop_back();
698 if (stack.empty())
699 return;
700 switch (getVisitState()) {
701 case VisitedNone:
702 stack.back() |= VisitedLeft;
703 break;
704 case VisitedLeft:
705 stack.back() |= VisitedRight;
706 break;
707 default:
708 llvm_unreachable("Unreachable.");
709 }
710 }
711
713 return stack == x.stack;
714 }
715
717 return !(*this == x);
718 }
719
721 assert(!stack.empty());
722 TreeTy* Current = reinterpret_cast<TreeTy*>(stack.back() & ~Flags);
723 assert(Current);
724 switch (getVisitState()) {
725 case VisitedNone:
726 if (TreeTy* L = Current->getLeft())
727 stack.push_back(reinterpret_cast<uintptr_t>(L));
728 else
729 stack.back() |= VisitedLeft;
730 break;
731 case VisitedLeft:
732 if (TreeTy* R = Current->getRight())
733 stack.push_back(reinterpret_cast<uintptr_t>(R));
734 else
735 stack.back() |= VisitedRight;
736 break;
737 case VisitedRight:
738 skipToParent();
739 break;
740 default:
741 llvm_unreachable("Unreachable.");
742 }
743 return *this;
744 }
745
747 assert(!stack.empty());
748 TreeTy* Current = reinterpret_cast<TreeTy*>(stack.back() & ~Flags);
749 assert(Current);
750 switch (getVisitState()) {
751 case VisitedNone:
752 stack.pop_back();
753 break;
754 case VisitedLeft:
755 stack.back() &= ~Flags; // Set state to "VisitedNone."
756 if (TreeTy* L = Current->getLeft())
757 stack.push_back(reinterpret_cast<uintptr_t>(L) | VisitedRight);
758 break;
759 case VisitedRight:
760 stack.back() &= ~Flags;
761 stack.back() |= VisitedLeft;
762 if (TreeTy* R = Current->getRight())
763 stack.push_back(reinterpret_cast<uintptr_t>(R) | VisitedRight);
764 break;
765 default:
766 llvm_unreachable("Unreachable.");
767 }
768 return *this;
769 }
770};
771
772template <typename ImutInfo> class ImutAVLTreeInOrderIterator {
773 using InternalIteratorTy = ImutAVLTreeGenericIterator<ImutInfo>;
774
775 InternalIteratorTy InternalItr;
776
777public:
778 using iterator_category = std::bidirectional_iterator_tag;
780 using difference_type = std::ptrdiff_t;
783
785
786 ImutAVLTreeInOrderIterator(const TreeTy* Root) : InternalItr(Root) {
787 if (Root)
788 ++*this; // Advance to first element.
789 }
790
791 ImutAVLTreeInOrderIterator() : InternalItr() {}
792
794 return InternalItr == x.InternalItr;
795 }
796
798 return !(*this == x);
799 }
800
801 TreeTy &operator*() const { return *InternalItr; }
802 TreeTy *operator->() const { return &*InternalItr; }
803
805 do ++InternalItr;
806 while (!InternalItr.atEnd() &&
807 InternalItr.getVisitState() != InternalIteratorTy::VisitedLeft);
808
809 return *this;
810 }
811
813 do --InternalItr;
814 while (!InternalItr.atBeginning() &&
815 InternalItr.getVisitState() != InternalIteratorTy::VisitedLeft);
816
817 return *this;
818 }
819
820 void skipSubTree() {
821 InternalItr.skipToParent();
822
823 while (!InternalItr.atEnd() &&
824 InternalItr.getVisitState() != InternalIteratorTy::VisitedLeft)
825 ++InternalItr;
826 }
827};
828
829/// Generic iterator that wraps a T::TreeTy::iterator and exposes
830/// iterator::getValue() on dereference.
831template <typename T>
834 ImutAVLValueIterator<T>, typename T::TreeTy::iterator,
835 typename std::iterator_traits<
836 typename T::TreeTy::iterator>::iterator_category,
837 const typename T::value_type> {
839 explicit ImutAVLValueIterator(typename T::TreeTy *Tree)
841
843 return this->I->getValue();
844 }
845};
846
847//===----------------------------------------------------------------------===//
848// Trait classes for Profile information.
849//===----------------------------------------------------------------------===//
850
851/// Generic profile template. The default behavior is to invoke the
852/// profile method of an object. Specializations for primitive integers
853/// and generic handling of pointers is done below.
854template <typename T>
856 using value_type = const T;
857 using value_type_ref = const T&;
858
862};
863
864/// Profile traits for integers.
865template <typename T>
867 using value_type = const T;
868 using value_type_ref = const T&;
869
871 ID.AddInteger(X);
872 }
873};
874
875#define PROFILE_INTEGER_INFO(X)\
876template<> struct ImutProfileInfo<X> : ImutProfileInteger<X> {};
877
879PROFILE_INTEGER_INFO(unsigned char)
881PROFILE_INTEGER_INFO(unsigned short)
882PROFILE_INTEGER_INFO(unsigned)
885PROFILE_INTEGER_INFO(unsigned long)
886PROFILE_INTEGER_INFO(long long)
887PROFILE_INTEGER_INFO(unsigned long long)
888
889#undef PROFILE_INTEGER_INFO
890
891/// Profile traits for booleans.
892template <>
894 using value_type = const bool;
895 using value_type_ref = const bool&;
896
898 ID.AddBoolean(X);
899 }
900};
901
902/// Generic profile trait for pointer types. We treat pointers as
903/// references to unique objects.
904template <typename T>
906 using value_type = const T*;
908
910 ID.AddPointer(X);
911 }
912};
913
914//===----------------------------------------------------------------------===//
915// Trait classes that contain element comparison operators and type
916// definitions used by ImutAVLTree, ImmutableSet, and ImmutableMap. These
917// inherit from the profile traits (ImutProfileInfo) to include operations
918// for element profiling.
919//===----------------------------------------------------------------------===//
920
921/// Generic definition of comparison operations for elements of immutable
922/// containers that defaults to using std::equal_to<> and std::less<> to perform
923/// comparison of elements.
924template <typename T> struct ImutContainerInfo : ImutProfileInfo<T> {
931
933 static data_type_ref DataOfValue(value_type_ref) { return true; }
934
936 return std::equal_to<key_type>()(LHS,RHS);
937 }
938
940 return std::less<key_type>()(LHS,RHS);
941 }
942
943 static bool isDataEqual(data_type_ref, data_type_ref) { return true; }
944};
945
946/// Specialization for pointer values to treat pointers as references to unique
947/// objects. Pointers are thus compared by their addresses.
948template <typename T> struct ImutContainerInfo<T *> : ImutProfileInfo<T *> {
955
957 static data_type_ref DataOfValue(value_type_ref) { return true; }
958
959 static bool isEqual(key_type_ref LHS, key_type_ref RHS) { return LHS == RHS; }
960
961 static bool isLess(key_type_ref LHS, key_type_ref RHS) { return LHS < RHS; }
962
963 static bool isDataEqual(data_type_ref, data_type_ref) { return true; }
964};
965
966//===----------------------------------------------------------------------===//
967// Immutable Set
968//===----------------------------------------------------------------------===//
969
970template <typename ValT, typename ValInfo = ImutContainerInfo<ValT>>
972public:
973 using value_type = typename ValInfo::value_type;
974 using value_type_ref = typename ValInfo::value_type_ref;
976
977private:
979
980public:
981 /// Constructs a set from a pointer to a tree root. In general one
982 /// should use a Factory object to create sets instead of directly
983 /// invoking the constructor, but there are cases where make this
984 /// constructor public is useful.
985 explicit ImmutableSet(TreeTy *R) : Root(R) {}
986
987 class Factory {
988 typename TreeTy::Factory F;
989 const bool Canonicalize;
990
991 public:
992 Factory(bool canonicalize = true)
993 : Canonicalize(canonicalize) {}
994
995 Factory(BumpPtrAllocator& Alloc, bool canonicalize = true)
996 : F(Alloc), Canonicalize(canonicalize) {}
997
998 Factory(const Factory& RHS) = delete;
999 void operator=(const Factory& RHS) = delete;
1000
1001 /// Returns an immutable set that contains no elements.
1003 return ImmutableSet(F.getEmptyTree());
1004 }
1005
1006 /// Creates a new immutable set that contains all of the values
1007 /// of the original set with the addition of the specified value. If
1008 /// the original set already included the value, then the original set is
1009 /// returned and no memory is allocated. The time and space complexity
1010 /// of this operation is logarithmic in the size of the original set.
1011 /// The memory allocated to represent the set is released when the
1012 /// factory object that created the set is destroyed.
1014 TreeTy *NewT = F.add(Old.Root.get(), V);
1015 return ImmutableSet(Canonicalize ? F.getCanonicalTree(NewT) : NewT);
1016 }
1017
1018 /// Creates a new immutable set that contains all of the values
1019 /// of the original set with the exception of the specified value. If
1020 /// the original set did not contain the value, the original set is
1021 /// returned and no memory is allocated. The time and space complexity
1022 /// of this operation is logarithmic in the size of the original set.
1023 /// The memory allocated to represent the set is released when the
1024 /// factory object that created the set is destroyed.
1026 TreeTy *NewT = F.remove(Old.Root.get(), V);
1027 return ImmutableSet(Canonicalize ? F.getCanonicalTree(NewT) : NewT);
1028 }
1029
1030 BumpPtrAllocator& getAllocator() { return F.getAllocator(); }
1031
1033 return const_cast<typename TreeTy::Factory *>(&F);
1034 }
1035 };
1036
1037 friend class Factory;
1038
1039 /// Returns true if the set contains the specified value.
1040 bool contains(value_type_ref V) const {
1041 return Root ? Root->contains(V) : false;
1042 }
1043
1044 bool operator==(const ImmutableSet &RHS) const {
1045 return Root && RHS.Root ? Root->isEqual(*RHS.Root.get()) : Root == RHS.Root;
1046 }
1047
1048 bool operator!=(const ImmutableSet &RHS) const {
1049 return Root && RHS.Root ? Root->isNotEqual(*RHS.Root.get())
1050 : Root != RHS.Root;
1051 }
1052
1054 if (Root) { Root->retain(); }
1055 return Root.get();
1056 }
1057
1058 TreeTy *getRootWithoutRetain() const { return Root.get(); }
1059
1060 /// Return true if the set contains no elements.
1061 bool isEmpty() const { return !Root; }
1062
1063 /// Return true if the set contains exactly one element.
1064 /// This method runs in constant time.
1065 bool isSingleton() const { return getHeight() == 1; }
1066
1067 //===--------------------------------------------------===//
1068 // Iterators.
1069 //===--------------------------------------------------===//
1070
1072
1073 iterator begin() const { return iterator(Root.get()); }
1074 iterator end() const { return iterator(); }
1075
1076 //===--------------------------------------------------===//
1077 // Utility methods.
1078 //===--------------------------------------------------===//
1079
1080 unsigned getHeight() const { return Root ? Root->getHeight() : 0; }
1081
1082 static void Profile(FoldingSetNodeID &ID, const ImmutableSet &S) {
1083 ID.AddPointer(S.Root.get());
1084 }
1085
1086 void Profile(FoldingSetNodeID &ID) const { return Profile(ID, *this); }
1087
1088 //===--------------------------------------------------===//
1089 // For testing.
1090 //===--------------------------------------------------===//
1091
1092 void validateTree() const { if (Root) Root->validateTree(); }
1093};
1094
1095// NOTE: This may some day replace the current ImmutableSet.
1096template <typename ValT, typename ValInfo = ImutContainerInfo<ValT>>
1098public:
1099 using value_type = typename ValInfo::value_type;
1100 using value_type_ref = typename ValInfo::value_type_ref;
1102 using FactoryTy = typename TreeTy::Factory;
1103
1104private:
1106 FactoryTy *Factory;
1107
1108public:
1109 /// Constructs a set from a pointer to a tree root. In general one
1110 /// should use a Factory object to create sets instead of directly
1111 /// invoking the constructor, but there are cases where make this
1112 /// constructor public is useful.
1113 ImmutableSetRef(TreeTy *R, FactoryTy *F) : Root(R), Factory(F) {}
1114
1116 return ImmutableSetRef(0, F);
1117 }
1118
1120 return ImmutableSetRef(Factory->add(Root.get(), V), Factory);
1121 }
1122
1124 return ImmutableSetRef(Factory->remove(Root.get(), V), Factory);
1125 }
1126
1127 /// Returns true if the set contains the specified value.
1128 bool contains(value_type_ref V) const {
1129 return Root ? Root->contains(V) : false;
1130 }
1131
1132 ImmutableSet<ValT> asImmutableSet(bool canonicalize = true) const {
1133 return ImmutableSet<ValT>(
1134 canonicalize ? Factory->getCanonicalTree(Root.get()) : Root.get());
1135 }
1136
1137 TreeTy *getRootWithoutRetain() const { return Root.get(); }
1138
1139 bool operator==(const ImmutableSetRef &RHS) const {
1140 return Root && RHS.Root ? Root->isEqual(*RHS.Root.get()) : Root == RHS.Root;
1141 }
1142
1143 bool operator!=(const ImmutableSetRef &RHS) const {
1144 return Root && RHS.Root ? Root->isNotEqual(*RHS.Root.get())
1145 : Root != RHS.Root;
1146 }
1147
1148 /// Return true if the set contains no elements.
1149 bool isEmpty() const { return !Root; }
1150
1151 /// Return true if the set contains exactly one element.
1152 /// This method runs in constant time.
1153 bool isSingleton() const { return getHeight() == 1; }
1154
1155 //===--------------------------------------------------===//
1156 // Iterators.
1157 //===--------------------------------------------------===//
1158
1160
1161 iterator begin() const { return iterator(Root.get()); }
1162 iterator end() const { return iterator(); }
1163
1164 //===--------------------------------------------------===//
1165 // Utility methods.
1166 //===--------------------------------------------------===//
1167
1168 unsigned getHeight() const { return Root ? Root->getHeight() : 0; }
1169
1170 static void Profile(FoldingSetNodeID &ID, const ImmutableSetRef &S) {
1171 ID.AddPointer(S.Root.get());
1172 }
1173
1174 void Profile(FoldingSetNodeID &ID) const { return Profile(ID, *this); }
1175
1176 //===--------------------------------------------------===//
1177 // For testing.
1178 //===--------------------------------------------------===//
1179
1180 void validateTree() const { if (Root) Root->validateTree(); }
1181};
1182
1183} // end namespace llvm
1184
1185#endif // LLVM_ADT_IMMUTABLESET_H
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
This file defines the BumpPtrAllocator interface.
#define X(NUM, ENUM, NAME)
Definition ELF.h:851
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< StatepointGC > D("statepoint-example", "an example strategy for statepoint")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
#define LLVM_PREFERRED_TYPE(T)
\macro LLVM_PREFERRED_TYPE Adjust type of bit-field in debug info.
Definition Compiler.h:729
This file defines the DenseMap class.
This file defines a hash set that can be used to remove duplication of nodes in a graph.
#define PROFILE_INTEGER_INFO(X)
This file defines the RefCountedBase, ThreadSafeRefCountedBase, and IntrusiveRefCntPtr classes.
#define F(x, y, z)
Definition MD5.cpp:54
#define I(x, y, z)
Definition MD5.cpp:57
#define T
if(PassOpts->AAPipeline)
This file defines the SmallVector class.
Value * RHS
Value * LHS
This class is used to gather all the unique data bits of a node.
Definition FoldingSet.h:208
static void Profile(FoldingSetNodeID &ID, const ImmutableSetRef &S)
void Profile(FoldingSetNodeID &ID) const
ImmutableSetRef add(value_type_ref V)
ImutAVLTree< ValInfo > TreeTy
bool contains(value_type_ref V) const
Returns true if the set contains the specified value.
bool operator!=(const ImmutableSetRef &RHS) const
ImmutableSetRef remove(value_type_ref V)
ImutAVLValueIterator< ImmutableSetRef > iterator
bool isSingleton() const
Return true if the set contains exactly one element.
iterator begin() const
bool isEmpty() const
Return true if the set contains no elements.
typename ValInfo::value_type value_type
ImmutableSetRef(TreeTy *R, FactoryTy *F)
Constructs a set from a pointer to a tree root.
typename ValInfo::value_type_ref value_type_ref
iterator end() const
unsigned getHeight() const
ImmutableSet< ValT > asImmutableSet(bool canonicalize=true) const
typename TreeTy::Factory FactoryTy
static ImmutableSetRef getEmptySet(FactoryTy *F)
void validateTree() const
bool operator==(const ImmutableSetRef &RHS) const
TreeTy * getRootWithoutRetain() const
Factory(const Factory &RHS)=delete
void operator=(const Factory &RHS)=delete
TreeTy::Factory * getTreeFactory() const
BumpPtrAllocator & getAllocator()
Factory(BumpPtrAllocator &Alloc, bool canonicalize=true)
ImmutableSet getEmptySet()
Returns an immutable set that contains no elements.
Factory(bool canonicalize=true)
ImmutableSet remove(ImmutableSet Old, value_type_ref V)
Creates a new immutable set that contains all of the values of the original set with the exception of...
ImmutableSet add(ImmutableSet Old, value_type_ref V)
Creates a new immutable set that contains all of the values of the original set with the addition of ...
bool operator!=(const ImmutableSet &RHS) const
typename ValInfo::value_type value_type
bool operator==(const ImmutableSet &RHS) const
iterator end() const
bool isEmpty() const
Return true if the set contains no elements.
ImmutableSet(TreeTy *R)
Constructs a set from a pointer to a tree root.
bool isSingleton() const
Return true if the set contains exactly one element.
TreeTy * getRootWithoutRetain() const
ImutAVLTree< ValInfo > TreeTy
void validateTree() const
bool contains(value_type_ref V) const
Returns true if the set contains the specified value.
void Profile(FoldingSetNodeID &ID) const
iterator begin() const
unsigned getHeight() const
static void Profile(FoldingSetNodeID &ID, const ImmutableSet &S)
ImutAVLValueIterator< ImmutableSet > iterator
typename ValInfo::value_type_ref value_type_ref
static unsigned maskCacheIndex(unsigned I)
TreeTy * balanceTree(TreeTy *L, value_type_ref V, TreeTy *R)
Used by add_internal and remove_internal to balance a newly created tree.
unsigned getHeight(TreeTy *T) const
ImutAVLFactory(BumpPtrAllocator &Alloc)
TreeTy * add_internal(value_type_ref V, TreeTy *T)
add_internal - Creates a new tree that includes the specified data and the data from the original tre...
value_type_ref getValue(TreeTy *T) const
static bool compareTreeWithSection(TreeTy *T, typename TreeTy::iterator &TI, typename TreeTy::iterator &TE)
TreeTy * getLeft(TreeTy *T) const
TreeTy * getCanonicalTree(TreeTy *TNew)
TreeTy * add(TreeTy *T, value_type_ref V)
TreeTy * getRight(TreeTy *T) const
TreeTy * getEmptyTree() const
TreeTy * removeMinBinding(TreeTy *T, TreeTy *&Noderemoved)
TreeTy * createNode(TreeTy *newLeft, TreeTy *oldTree, TreeTy *newRight)
TreeTy * combineTrees(TreeTy *L, TreeTy *R)
TreeTy * remove_internal(key_type_ref K, TreeTy *T)
remove_internal - Creates a new tree that includes all the data from the original tree except the spe...
TreeTy * createNode(TreeTy *L, value_type_ref V, TreeTy *R)
unsigned incrementHeight(TreeTy *L, TreeTy *R) const
TreeTy * remove(TreeTy *T, key_type_ref V)
void markImmutable(TreeTy *T)
Clears the mutable bits of a root and all of its descendants.
bool isEmpty(TreeTy *T) const
ImutAVLTree< ImutInfo > value_type
bool operator==(const ImutAVLTreeGenericIterator &x) const
std::bidirectional_iterator_tag iterator_category
ImutAVLTreeGenericIterator(const TreeTy *Root)
ImutAVLTree< ImutInfo > TreeTy
ImutAVLTreeGenericIterator & operator--()
bool operator!=(const ImutAVLTreeGenericIterator &x) const
ImutAVLTreeGenericIterator & operator++()
bool operator!=(const ImutAVLTreeInOrderIterator &x) const
ImutAVLTreeInOrderIterator & operator++()
ImutAVLTree< ImutInfo > TreeTy
ImutAVLTreeInOrderIterator & operator--()
std::bidirectional_iterator_tag iterator_category
ImutAVLTreeInOrderIterator(const TreeTy *Root)
bool operator==(const ImutAVLTreeInOrderIterator &x) const
ImutAVLTree< ImutInfo > value_type
unsigned size() const
Returns the number of nodes in the tree, which includes both leaves and.
iterator end() const
Returns an iterator for the tree that denotes the end of an inorder traversal.
const value_type & getValue() const
Returns the data value associated with the tree node.
unsigned getHeight() const
Returns the height of the tree. A tree with no subtrees has a height of 1.
typename ValInfo::key_type_ref key_type_ref
ImutAVLFactory< ValInfo > Factory
ImutAVLTree * find(key_type_ref K)
Finds the subtree associated with the specified key value.
typename ValInfo::value_type_ref value_type_ref
unsigned validateTree() const
A utility method that checks that the balancing and ordering invariants of the tree are satisfied.
bool isNotEqual(const ImutAVLTree &RHS) const
Compares two trees for structural inequality.
bool isEqual(const ImutAVLTree &RHS) const
Compares two trees for structural equality and returns true if they are equal.
ImutAVLTree * getLeft() const
Return a pointer to the left subtree.
ImutAVLTreeInOrderIterator< ValInfo > iterator
typename ValInfo::value_type value_type
ImutAVLTree * getRight() const
Return a pointer to the right subtree.
bool isElementEqual(const ImutAVLTree *RHS) const
bool contains(key_type_ref K)
Returns true if this tree contains a subtree (node) that has an data element that matches the specifi...
ImutAVLTree * getMaxElement()
Find the subtree associated with the highest ranged key value.
iterator begin() const
Returns an iterator that iterates over the nodes of the tree in an inorder traversal.
bool isElementEqual(value_type_ref V) const
A smart pointer to a reference-counted object that inherits from RefCountedBase or ThreadSafeRefCount...
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
Definition CallingConv.h:24
This is an optimization pass for GlobalISel generic memory operations.
BumpPtrAllocatorImpl<> BumpPtrAllocator
The standard BumpPtrAllocator which just uses the default template parameters.
Definition Allocator.h:383
#define N
static void Profile(const T &X, FoldingSetNodeID &ID)
Definition FoldingSet.h:117
Generic iterator that wraps a T::TreeTy::iterator and exposes iterator::getValue() on dereference.
ImutAVLValueIterator::reference operator*() const
ImutAVLValueIterator(typename T::TreeTy *Tree)
static bool isDataEqual(data_type_ref, data_type_ref)
static key_type_ref KeyOfValue(value_type_ref D)
static bool isEqual(key_type_ref LHS, key_type_ref RHS)
typename ImutProfileInfo< T * >::value_type_ref value_type_ref
typename ImutProfileInfo< T * >::value_type value_type
static data_type_ref DataOfValue(value_type_ref)
static bool isLess(key_type_ref LHS, key_type_ref RHS)
Generic definition of comparison operations for elements of immutable containers that defaults to usi...
static bool isLess(key_type_ref LHS, key_type_ref RHS)
typename ImutProfileInfo< T >::value_type value_type
static bool isEqual(key_type_ref LHS, key_type_ref RHS)
static bool isDataEqual(data_type_ref, data_type_ref)
static data_type_ref DataOfValue(value_type_ref)
static key_type_ref KeyOfValue(value_type_ref D)
value_type_ref key_type_ref
typename ImutProfileInfo< T >::value_type_ref value_type_ref
static void Profile(FoldingSetNodeID &ID, value_type_ref X)
static void Profile(FoldingSetNodeID &ID, value_type_ref X)
Generic profile template.
static void Profile(FoldingSetNodeID &ID, value_type_ref X)
Profile traits for integers.
static void Profile(FoldingSetNodeID &ID, value_type_ref X)
static void retain(ImutAVLTree< ImutInfo > *Tree)
Class you can specialize to provide custom retain/release functionality for a type.