Add a cache that protects mergefunc's internals from more surprises in DenseSet.
authorNick Lewycky <nicholas@mxc.ca>
Sat, 15 Jan 2011 10:16:23 +0000 (10:16 +0000)
committerNick Lewycky <nicholas@mxc.ca>
Sat, 15 Jan 2011 10:16:23 +0000 (10:16 +0000)
Also, replace tabs with spaces. Yes, it's 2011.

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

lib/Transforms/IPO/MergeFunctions.cpp

index c678db859001488d9672e662cc15af2fbb4b4bfc..49ebe65fe81324b823e049182942bd3d3d7ffdb3 100644 (file)
@@ -109,10 +109,23 @@ public:
     Func = NULL;
   }
 
+  bool &getOrInsertCachedComparison(const ComparableFunction &Other,
+                                    bool &inserted) const {
+    typedef DenseMap<Function *, bool>::iterator iterator;
+    std::pair<iterator, bool> p =
+        CompareResultCache.insert(std::make_pair(Other.getFunc(), false));
+    inserted = p.second;
+    return p.first->second;
+  }
+
 private:
   explicit ComparableFunction(unsigned Hash)
     : Func(NULL), Hash(Hash), TD(NULL) {}
 
+  // DenseMap::grow() triggers a recomparison of all keys in the map, which is
+  // wildly expensive. This cache tries to preserve known results.
+  mutable DenseMap<Function *, bool> CompareResultCache;
+
   AssertingVH<Function> Func;
   unsigned Hash;
   TargetData *TD;
@@ -708,10 +721,10 @@ void MergeFunctions::RemoveUsers(Value *V) {
       if (Instruction *I = dyn_cast<Instruction>(U.getUser())) {
         Remove(I->getParent()->getParent());
       } else if (isa<GlobalValue>(U.getUser())) {
-       // do nothing
+        // do nothing
       } else if (Constant *C = dyn_cast<Constant>(U.getUser())) {
-       for (Value::use_iterator CUI = C->use_begin(), CUE = C->use_end();
-            CUI != CUE; ++CUI)
+        for (Value::use_iterator CUI = C->use_begin(), CUE = C->use_end();
+             CUI != CUE; ++CUI)
           Worklist.push_back(*CUI);
       }
     }
@@ -777,6 +790,15 @@ bool DenseMapInfo<ComparableFunction>::isEqual(const ComparableFunction &LHS,
     return false;
   assert(LHS.getTD() == RHS.getTD() &&
          "Comparing functions for different targets");
-  return FunctionComparator(LHS.getTD(),
-                            LHS.getFunc(), RHS.getFunc()).Compare();
+
+  bool inserted;
+  bool &result1 = LHS.getOrInsertCachedComparison(RHS, inserted);
+  if (!inserted)
+    return result1;
+  bool &result2 = RHS.getOrInsertCachedComparison(LHS, inserted);
+  if (!inserted)
+    return result1 = result2;
+
+  return result1 = result2 = FunctionComparator(LHS.getTD(), LHS.getFunc(),
+                                                RHS.getFunc()).Compare();
 }