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

Chris Lattner lattner at cs.uiuc.edu
Wed Aug 4 00:45:11 PDT 2004



Changes in directory llvm/lib/VMCore:

Linker.cpp updated: 1.78 -> 1.79
---
Log message:

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: http://llvm.cs.uiuc.edu/PR411 , but this will do in the short term.

gccld on eon now takes 5.51s, which is 50% faster than before this patch. :)


---
Diffs of the changes:  (+36 -53)

Index: llvm/lib/VMCore/Linker.cpp
diff -u llvm/lib/VMCore/Linker.cpp:1.78 llvm/lib/VMCore/Linker.cpp:1.79
--- llvm/lib/VMCore/Linker.cpp:1.78	Wed Aug  4 02:28:06 2004
+++ llvm/lib/VMCore/Linker.cpp	Wed Aug  4 02:44:58 2004
@@ -368,41 +368,6 @@
   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<GlobalValue>(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<GlobalValue>(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 bool LinkGlobals(Module *Dest, const Module *Src,
                         std::map<const Value*, Value*> &ValueMap,
                     std::multimap<std::string, GlobalVariable *> &AppendingVars,
+                        std::map<std::string, GlobalValue*> &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 @@
   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<GlobalVariable>(FindGlobalNamed(SGV->getName(), 
-                                                         SGV->getType(), ST));
+      std::map<std::string, GlobalValue*>::iterator EGV =
+        GlobalsByName.find(SGV->getName());
+      if (EGV != GlobalsByName.end())
+        DGV = dyn_cast<GlobalVariable>(EGV->second);
     }
 
     assert(SGV->hasInitializer() || SGV->hasExternalLinkage() &&
@@ -610,6 +575,7 @@
 //
 static bool LinkFunctionProtos(Module *Dest, const Module *Src,
                                std::map<const Value*, Value*> &ValueMap,
+                             std::map<std::string, GlobalValue*> &GlobalsByName,
                                std::string *Err) {
   SymbolTable *ST = (SymbolTable*)&Dest->getSymbolTable();
   
@@ -619,13 +585,13 @@
   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<Function>(FindGlobalNamed(SF->getName(), SF->getType(),
-                                                  ST));
+    if (SF->hasName() && !SF->hasInternalLinkage()) {
+      // Check to see if may have to link the function.
+      std::map<std::string, GlobalValue*>::iterator EF =
+        GlobalsByName.find(SF->getName());
+      if (EF != GlobalsByName.end())
+        DF = dyn_cast<Function>(EF->second);
+    }
 
     if (!DF || SF->hasInternalLinkage() || DF->hasInternalLinkage()) {
       // Function does not already exist, simply insert an function signature
@@ -886,16 +852,32 @@
   //
   std::multimap<std::string, GlobalVariable *> 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<std::string, GlobalValue*> 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 @@
   // 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.






More information about the llvm-commits mailing list