From: Chris Lattner Date: Wed, 19 Nov 2003 19:10:23 +0000 (+0000) Subject: *** Significantly speed up type resultion X-Git-Url: http://plrg.eecs.uci.edu/git/?a=commitdiff_plain;h=542d991451c20ab17dc4c3f0b856bb632e546016;p=oota-llvm.git *** 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 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@10088 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/VMCore/Type.cpp b/lib/VMCore/Type.cpp index 2a24a783f13..4796ad2496d 100644 --- a/lib/VMCore/Type.cpp +++ b/lib/VMCore/Type.cpp @@ -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 @@ -495,7 +496,6 @@ static bool TypesEqual(const Type *Ty, const Type *Ty2, std::map &EqTypes) { if (Ty == Ty2) return true; if (Ty->getPrimitiveID() != Ty2->getPrimitiveID()) return false; - if (Ty->isPrimitiveType()) return true; if (isa(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 VisitedTypes; + for (Type::subtype_iterator I = Ty->subtype_begin(), + E = Ty->subtype_end(); I != E; ++I) { + for (df_ext_iterator > + 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!