*** Significantly speed up type resultion
authorChris Lattner <sabre@nondot.org>
Wed, 19 Nov 2003 19:10:23 +0000 (19:10 +0000)
committerChris Lattner <sabre@nondot.org>
Wed, 19 Nov 2003 19:10:23 +0000 (19:10 +0000)
  This change speeds up type resolution by checking to see if a type is
  recursive, and if it's not, using a more efficient algorithm.

  This dramatically reduces bytecode loading time of kc++, reducing time-to-jit
  kc++ --version to 17s from 33s

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

lib/VMCore/Type.cpp

index 2a24a783f13ffc872dce9df6ea03ed62c6ee61dc..4796ad2496da0dfdad650e194436a7b2356ca6c7 100644 (file)
@@ -14,6 +14,7 @@
 #include "llvm/DerivedTypes.h"
 #include "llvm/SymbolTable.h"
 #include "llvm/Constants.h"
+#include "Support/DepthFirstIterator.h"
 #include "Support/StringExtras.h"
 #include "Support/STLExtras.h"
 #include <algorithm>
@@ -495,7 +496,6 @@ static bool TypesEqual(const Type *Ty, const Type *Ty2,
                       std::map<const Type *, const Type *> &EqTypes) {
   if (Ty == Ty2) return true;
   if (Ty->getPrimitiveID() != Ty2->getPrimitiveID()) return false;
-  if (Ty->isPrimitiveType()) return true;
   if (isa<OpaqueType>(Ty))
     return false;  // Two unequal opaque types are never equal
 
@@ -595,23 +595,61 @@ public:
     // updated.  Remove the obsolete entry from the map.
     Map.erase(TyIt);
 
-    // Now we check to see if there is an existing entry in the table which is
-    // structurally identical to the newly refined type.  If so, this type gets
-    // refined to the pre-existing type.
-    //
-    for (iterator I = Map.begin(), E = Map.end(); I != E; ++I)
-      if (TypesEqual(Ty, I->second)) {
+    // Determine whether there is a cycle through the type graph which passes
+    // back through this type.  Other cycles are ok, 
+    bool HasTypeCycle = false;
+    {
+      std::set<const Type*> VisitedTypes;
+      for (Type::subtype_iterator I = Ty->subtype_begin(),
+             E = Ty->subtype_end(); I != E; ++I) {
+        for (df_ext_iterator<const Type *, std::set<const Type*> > 
+               DFI = df_ext_begin(*I, VisitedTypes),
+               E = df_ext_end(*I, VisitedTypes); DFI != E; ++DFI)
+          if (*DFI == Ty) {
+            HasTypeCycle = true;
+            goto FoundCycle;
+          }
+      }
+    }
+  FoundCycle:
+
+    ValType Key = ValType::get(Ty);
+
+    // If there are no cycles going through this node, we can do a simple,
+    // efficient lookup in the map, instead of an inefficient nasty linear
+    // lookup.
+    if (!HasTypeCycle) {
+      iterator I = Map.find(ValType::get(Ty));
+      if (I != Map.end()) {
+        // We already have this type in the table.  Get rid of the newly refined
+        // type.
         assert(Ty->isAbstract() && "Replacing a non-abstract type?");
         TypeClass *NewTy = I->second;
-
+        
         // Refined to a different type altogether?
         Ty->refineAbstractTypeTo(NewTy);
         return;
       }
+      
+    } else {
+      // Now we check to see if there is an existing entry in the table which is
+      // structurally identical to the newly refined type.  If so, this type
+      // gets refined to the pre-existing type.
+      //
+      for (iterator I = Map.begin(), E = Map.end(); I != E; ++I)
+        if (TypesEqual(Ty, I->second)) {
+          assert(Ty->isAbstract() && "Replacing a non-abstract type?");
+          TypeClass *NewTy = I->second;
+          
+          // Refined to a different type altogether?
+          Ty->refineAbstractTypeTo(NewTy);
+          return;
+        }
+    }
 
     // If there is no existing type of the same structure, we reinsert an
     // updated record into the map.
-    Map.insert(std::make_pair(ValType::get(Ty), Ty));
+    Map.insert(std::make_pair(Key, Ty));
 
     // If the type is currently thought to be abstract, rescan all of our
     // subtypes to see if the type has just become concrete!