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