ImmutableMap/ImmutableSet: Allow caching of ImutAVLTree digests while the tree
authorTed Kremenek <kremenek@apple.com>
Fri, 10 Jul 2009 00:33:43 +0000 (00:33 +0000)
committerTed Kremenek <kremenek@apple.com>
Fri, 10 Jul 2009 00:33:43 +0000 (00:33 +0000)
is still mutable. My experiments show this reduces the amount of times we
compute a full tree digest by over 50% on very small cases, and potentially much
larger on others.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@75207 91177308-0d34-0410-b5e6-96231b3b80d8

include/llvm/ADT/ImmutableSet.h

index 38816c778675ae36a76f3165dc1224119bbc8649..ef048a94782ad7dd04ca32f58095a27872d02f22 100644 (file)
@@ -283,25 +283,25 @@ private:
   void setLeft(ImutAVLTree* NewLeft) {
     assert(isMutable() &&
            "Only a mutable tree can have its left subtree changed.");
-    assert(!hasCachedDigest() &&
-           "A mutable tree cannot have a cached digest.");
-
     Left = reinterpret_cast<uintptr_t>(NewLeft) | LeftFlags;
   }
 
   /// setRight - Changes the reference of the right subtree.  Used internally
   ///  by ImutAVLFactory.
   void setRight(ImutAVLTree* NewRight) {
-    assert (isMutable() &&
-            "Only a mutable tree can have its right subtree changed.");
+    assert(isMutable() &&
+           "Only a mutable tree can have its right subtree changed.");
 
     Right = NewRight;
+    // Set the NoCachedDigest flag.
+    Left = Left | NoCachedDigest;
+
   }
 
   /// setHeight - Changes the height of the tree.  Used internally by
   ///  ImutAVLFactory.
   void setHeight(unsigned h) {
-    assert (isMutable() && "Only a mutable tree can have its height changed.");
+    assert(isMutable() && "Only a mutable tree can have its height changed.");
     Height = h;
   }
 
@@ -330,12 +330,7 @@ private:
       return Digest;
 
     uint32_t X = ComputeDigest(getLeft(), getRight(), getValue());
-
-    if (!isMutable()) {
-      Digest = X;
-      MarkedCachedDigest();
-    }
-
+    Digest = X;
     return X;
   }
 };
@@ -412,7 +407,6 @@ private:
     return ( hl > hr ? hl : hr ) + 1;
   }
 
-
   static bool CompareTreeWithSection(TreeTy* T,
                                      typename TreeTy::iterator& TI,
                                      typename TreeTy::iterator& TE) {
@@ -454,7 +448,6 @@ private:
 
       // We found a collision.  Perform a comparison of Contents('T')
       // with Contents('L')+'V'+Contents('R').
-
       typename TreeTy::iterator TI = T->begin(), TE = T->end();
 
       // First compare Contents('L') with the (initial) contents of T.
@@ -471,17 +464,15 @@ private:
       if (!CompareTreeWithSection(R, TI, TE))
         continue;
 
-      if (TI != TE) // Contents('R') did not match suffix of 'T'.
-        continue;
+      if (TI != TE)
+        continue; // Contents('R') did not match suffix of 'T'.
 
       // Trees did match!  Return 'T'.
       return T;
     }
 
     // No tree with the contents: Contents('L')+'V'+Contents('R').
-    // Create it.
-
-    // Allocate the new tree node and insert it into the cache.
+    // Create it.  Allocate the new tree node and insert it into the cache.
     BumpPtrAllocator& A = getAllocator();
     TreeTy* T = (TreeTy*) A.Allocate<TreeTy>();
     new (T) TreeTy(L,R,V,IncrementHeight(L,R));
@@ -491,7 +482,6 @@ private:
     // Because our digest is associative and based on the contents of
     // the set, this should hopefully not cause any strange bugs.
     // 'T' is inserted by 'MarkImmutable'.
-
     return T;
   }
 
@@ -504,7 +494,8 @@ private:
       OldTree->setHeight(IncrementHeight(L,R));
       return OldTree;
     }
-    else return CreateNode(L, Value(OldTree), R);
+    else
+      return CreateNode(L, Value(OldTree), R);
   }
 
   /// Balance - Used by Add_internal and Remove_internal to