From 3706708edeab5087dd716ccdc3c8e33038731d8d Mon Sep 17 00:00:00 2001 From: Chris Lattner Date: Wed, 4 Aug 2004 07:44:58 +0000 Subject: [PATCH] FindGlobalNamed used to take 2.92s out of 8.39s running a profile build of gccld -disable-opt on 252.eon. This patch deletes it and replaces it with a map. The proper fix for this is to fix PR411, but this will do in the short term. gccld on eon now takes 5.51s, which is 50% faster than before this patch. :) llvm-svn: 15480 --- llvm/lib/VMCore/Linker.cpp | 89 +++++++++++++++----------------------- 1 file changed, 36 insertions(+), 53 deletions(-) diff --git a/llvm/lib/VMCore/Linker.cpp b/llvm/lib/VMCore/Linker.cpp index ffbdb9224c9d..5fa52b60389d 100644 --- a/llvm/lib/VMCore/Linker.cpp +++ b/llvm/lib/VMCore/Linker.cpp @@ -368,41 +368,6 @@ static Value *RemapOperand(const Value *In, return 0; } -/// FindGlobalNamed - Look in the specified symbol table for a global with the -/// specified name and type. If an exactly matching global does not exist, see -/// if there is a global which is "type compatible" with the specified -/// name/type. This allows us to resolve things like '%x = global int*' with -/// '%x = global opaque*'. -/// -static GlobalValue *FindGlobalNamed(const std::string &Name, const Type *Ty, - SymbolTable *ST) { - // See if an exact match exists in the symbol table... - if (Value *V = ST->lookup(Ty, Name)) return cast(V); - - // It doesn't exist exactly, scan through all of the type planes in the symbol - // table, checking each of them for a type-compatible version. - // - for (SymbolTable::plane_iterator PI = ST->plane_begin(), PE = ST->plane_end(); - PI != PE; ++PI) { - // Does this type plane contain an entry with the specified name? - SymbolTable::ValueMap &VM = PI->second; - SymbolTable::value_iterator VI = VM.find(Name); - - if (VI != VM.end()) { - // Ensure that this type if placed correctly into the symbol table. - GlobalValue *ValPtr = cast(VI->second); - assert(ValPtr->getType() == PI->first && "Type conflict!"); - - // Determine whether we can fold the two types together, resolving them. - // If so, we can use this value. - if (!ValPtr->hasInternalLinkage() && - !RecursiveResolveTypes(Ty, PI->first, ST, "")) - return ValPtr; - } - } - return 0; // Otherwise, nothing could be found. -} - /// ForceRenaming - The LLVM SymbolTable class autorenames globals that conflict /// in the symbol table. This is good for all clients except for us. Go /// through the trouble to force this back. @@ -431,6 +396,7 @@ static void ForceRenaming(GlobalValue *GV, const std::string &Name) { static bool LinkGlobals(Module *Dest, const Module *Src, std::map &ValueMap, std::multimap &AppendingVars, + std::map &GlobalsByName, std::string *Err) { // We will need a module level symbol table if the src module has a module // level symbol table... @@ -441,13 +407,12 @@ static bool LinkGlobals(Module *Dest, const Module *Src, for (Module::const_giterator I = Src->gbegin(), E = Src->gend(); I != E; ++I){ const GlobalVariable *SGV = I; GlobalVariable *DGV = 0; + // Check to see if may have to link the global. if (SGV->hasName() && !SGV->hasInternalLinkage()) { - // A same named thing is a global variable, because the only two things - // that may be in a module level symbol table are Global Vars and - // Functions, and they both have distinct, nonoverlapping, possible types. - // - DGV = cast_or_null(FindGlobalNamed(SGV->getName(), - SGV->getType(), ST)); + std::map::iterator EGV = + GlobalsByName.find(SGV->getName()); + if (EGV != GlobalsByName.end()) + DGV = dyn_cast(EGV->second); } assert(SGV->hasInitializer() || SGV->hasExternalLinkage() && @@ -610,6 +575,7 @@ static bool LinkGlobalInits(Module *Dest, const Module *Src, // static bool LinkFunctionProtos(Module *Dest, const Module *Src, std::map &ValueMap, + std::map &GlobalsByName, std::string *Err) { SymbolTable *ST = (SymbolTable*)&Dest->getSymbolTable(); @@ -619,13 +585,13 @@ static bool LinkFunctionProtos(Module *Dest, const Module *Src, for (Module::const_iterator I = Src->begin(), E = Src->end(); I != E; ++I) { const Function *SF = I; // SrcFunction Function *DF = 0; - if (SF->hasName() && !SF->hasInternalLinkage()) - // The same named thing is a Function, because the only two things - // that may be in a module level symbol table are Global Vars and - // Functions, and they both have distinct, nonoverlapping, possible types. - // - DF = cast_or_null(FindGlobalNamed(SF->getName(), SF->getType(), - ST)); + if (SF->hasName() && !SF->hasInternalLinkage()) { + // Check to see if may have to link the function. + std::map::iterator EF = + GlobalsByName.find(SF->getName()); + if (EF != GlobalsByName.end()) + DF = dyn_cast(EF->second); + } if (!DF || SF->hasInternalLinkage() || DF->hasInternalLinkage()) { // Function does not already exist, simply insert an function signature @@ -886,16 +852,32 @@ bool llvm::LinkModules(Module *Dest, const Module *Src, std::string *ErrorMsg) { // std::multimap AppendingVars; - // Add all of the appending globals already in the Dest module to - // AppendingVars. - for (Module::giterator I = Dest->gbegin(), E = Dest->gend(); I != E; ++I) + // GlobalsByName - The LLVM SymbolTable class fights our best efforts at + // linking by separating globals by type. Until PR411 is fixed, we replicate + // it's functionality here. + std::map GlobalsByName; + + for (Module::giterator I = Dest->gbegin(), E = Dest->gend(); I != E; ++I) { + // Add all of the appending globals already in the Dest module to + // AppendingVars. if (I->hasAppendingLinkage()) AppendingVars.insert(std::make_pair(I->getName(), I)); + // Keep track of all globals by name. + if (!I->hasInternalLinkage() && I->hasName()) + GlobalsByName[I->getName()] = I; + } + + // Keep track of all globals by name. + for (Module::iterator I = Dest->begin(), E = Dest->end(); I != E; ++I) + if (!I->hasInternalLinkage() && I->hasName()) + GlobalsByName[I->getName()] = I; + // Insert all of the globals in src into the Dest module... without linking // initializers (which could refer to functions not yet mapped over). // - if (LinkGlobals(Dest, Src, ValueMap, AppendingVars, ErrorMsg)) return true; + if (LinkGlobals(Dest, Src, ValueMap, AppendingVars, GlobalsByName, ErrorMsg)) + return true; // Link the functions together between the two modules, without doing function // bodies... this just adds external function prototypes to the Dest @@ -903,7 +885,8 @@ bool llvm::LinkModules(Module *Dest, const Module *Src, std::string *ErrorMsg) { // all of the global values that may be referenced are available in our // ValueMap. // - if (LinkFunctionProtos(Dest, Src, ValueMap, ErrorMsg)) return true; + if (LinkFunctionProtos(Dest, Src, ValueMap, GlobalsByName, ErrorMsg)) + return true; // Update the initializers in the Dest module now that all globals that may // be referenced are in Dest.