[llvm-commits] CVS: llvm/lib/VMCore/Type.cpp

Chris Lattner lattner at cs.uiuc.edu
Wed Nov 19 13:11:01 PST 2003


Changes in directory llvm/lib/VMCore:

Type.cpp updated: 1.81 -> 1.82

---
Log message:

*** Significantly speed up type resultion
  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


---
Diffs of the changes:  (+47 -9)

Index: llvm/lib/VMCore/Type.cpp
diff -u llvm/lib/VMCore/Type.cpp:1.81 llvm/lib/VMCore/Type.cpp:1.82
--- llvm/lib/VMCore/Type.cpp:1.81	Wed Nov 19 00:14:38 2003
+++ llvm/lib/VMCore/Type.cpp	Wed Nov 19 13:10:23 2003
@@ -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 @@
 		       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 @@
     // 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!





More information about the llvm-commits mailing list