Index: lib/Transforms/IPO/FunctionImport.cpp =================================================================== --- lib/Transforms/IPO/FunctionImport.cpp +++ lib/Transforms/IPO/FunctionImport.cpp @@ -24,6 +24,7 @@ #include "llvm/Support/CommandLine.h" #include "llvm/Support/Debug.h" #include "llvm/Support/SourceMgr.h" + using namespace llvm; #define DEBUG_TYPE "function-import" @@ -81,12 +82,11 @@ } // Helper function: given a worklist and an index, will process all the worklist -// and import them based on the summary information -static unsigned ProcessImportWorklist( - Module &DestModule, SmallVector &Worklist, - StringSet<> &CalledFunctions, Linker &TheLinker, - const FunctionInfoIndex &Index, - std::function &LazyModuleLoader) { +// and decide which function to add to the import list +static unsigned GetImportList(SmallVector &Worklist, + StringMap> + &ModuleToFunctionsToImportMap, + const FunctionInfoIndex &Index) { unsigned ImportCount = 0; while (!Worklist.empty()) { auto CalledFunctionName = Worklist.pop_back_val(); @@ -121,40 +121,53 @@ } // Get the module path from the summary. - auto FileName = Summary->modulePath(); - DEBUG(dbgs() << "Importing " << CalledFunctionName << " from " << FileName - << "\n"); + auto ModuleIdentifier = Summary->modulePath(); + DEBUG(dbgs() << "Importing " << CalledFunctionName << " from " + << ModuleIdentifier << "\n"); + + // Add the function name to the list of import for this module + ModuleToFunctionsToImportMap[ModuleIdentifier].insert(CalledFunctionName); - // Get the module for the import (potentially from the cache). - auto &Module = LazyModuleLoader(FileName); - assert(&Module.getContext() == &DestModule.getContext()); + ++ImportCount; + } + return ImportCount; +} +static unsigned ImportFunctions(Module &SrcModule, + DenseSet FunctionNamesToImport, + Linker &TheLinker, + const FunctionInfoIndex &Index) { + // Set of functions to import + DenseSet FunctionsToImport; + + for (auto ImportFunctionName : FunctionNamesToImport) { // The function that we will import! - GlobalValue *SGV = Module.getNamedValue(CalledFunctionName); - StringRef ImportFunctionName = CalledFunctionName; + GlobalValue *SGV = SrcModule.getNamedValue(ImportFunctionName); + if (!SGV) { - // Might be local in source Module, promoted/renamed in DestModule. + // The destination module is referencing function using their renamed name + // when importing a function that was originally local in the source + // module. The source module we have might not have been renamed so we try + // to remove the suffix added during the renaming to recover the original + // name in the source module. std::pair Split = - CalledFunctionName.split(".llvm."); - SGV = Module.getNamedValue(Split.first); -#ifndef NDEBUG - // Assert that Split.second is module id - uint64_t ModuleId; - assert(!Split.second.getAsInteger(10, ModuleId)); - assert(ModuleId == Index.getModuleId(FileName)); -#endif + ImportFunctionName.split(".llvm."); + SGV = SrcModule.getNamedValue(Split.first); + assert(SGV && "Can't find function to import in source module"); } + if (!SGV) { + report_fatal_error(Twine("Can't load function '") + ImportFunctionName + + "' in Module '" + SrcModule.getModuleIdentifier() + + "', error in the summary?\n"); + } + Function *F = dyn_cast(SGV); if (!F && isa(SGV)) { auto *SGA = dyn_cast(SGV); F = dyn_cast(SGA->getBaseObject()); ImportFunctionName = F->getName(); } - if (!F) { - errs() << "Can't load function '" << CalledFunctionName << "' in Module '" - << FileName << "', error in the summary?\n"; - llvm_unreachable("Can't load function in Module"); - } + assert(F && "Imported Function is ... not a Function"); // We cannot import weak_any functions/aliases without possibly affecting // the order they are seen and selected by the linker, changing program @@ -162,26 +175,24 @@ if (SGV->hasWeakAnyLinkage()) { DEBUG(dbgs() << "Ignoring import request for weak-any " << (isa(SGV) ? "function " : "alias ") - << CalledFunctionName << " from " << FileName << "\n"); + << ImportFunctionName << " from " + << SrcModule.getModuleIdentifier() << "\n"); continue; } - // Link in the specified function. - DenseSet FunctionsToImport; + // Add the function to the import list FunctionsToImport.insert(F); - if (TheLinker.linkInModule(Module, Linker::Flags::None, &Index, - &FunctionsToImport)) - report_fatal_error("Function Import: link error"); - - // Process the newly imported function and add callees to the worklist. - GlobalValue *NewGV = DestModule.getNamedValue(ImportFunctionName); - assert(NewGV); - Function *NewF = dyn_cast(NewGV); - assert(NewF); - findExternalCalls(*NewF, CalledFunctions, Worklist); - ++ImportCount; } - return ImportCount; + + if (FunctionsToImport.empty()) + return 0; + + // Link in the specified functions. + if (TheLinker.linkInModule(SrcModule, Linker::Flags::None, &Index, + &FunctionsToImport)) + report_fatal_error("Function Import: link error"); + + return FunctionsToImport.size(); } // Automatically import functions in Module \p DestModule based on the summaries @@ -210,9 +221,50 @@ // Linker that will be used for importing function Linker TheLinker(DestModule, DiagnosticHandler); - ImportedCount += ProcessImportWorklist(DestModule, Worklist, CalledFunctions, - TheLinker, Index, getLazyModule); - + // For each iteration, GetImportList() will flush the Worklist and + // populate ModuleToFunctionsToImportMap with the function we really want + // to import. + // Then we'll process one module at a time, importing the list of functions + // for this module. + // Finally, the imported function will be analyzed and the worklist will be + // populated with the set of candidates. + while (!Worklist.empty()) { + // Map of Module -> List of Function to import from the Module + StringMap> ModuleToFunctionsToImportMap; + + // Analyze the summaries and get the list of functions to import by + // populating ModuleToFunctionsToImportMap + GetImportList(Worklist, ModuleToFunctionsToImportMap, Index); + assert(Worklist.empty() && "Worklist hasn't been flushed in GetImportList"); + + // Do the actual import of functions now, one Module at a time + for (auto &FunctionsToImportPerModule : ModuleToFunctionsToImportMap) { + // Get the module for the import + // Can't cache it for now because the linker mess it up. + auto &FunctionsToImport = FunctionsToImportPerModule.second; + const auto &ModuleName = FunctionsToImportPerModule.first(); + auto &SrcModule = getLazyModule(ModuleName); + assert(&DestModule.getContext() == &SrcModule.getContext() && + "Context mismatch"); + + ImportedCount += + ImportFunctions(SrcModule, FunctionsToImport, TheLinker, Index); + + /// Make functions as processed so we don't try to reimport them + CalledFunctions.insert(FunctionsToImport.begin(), + FunctionsToImport.end()); + + // Process the newly imported functions and add callees to the worklist. + for (const auto &ImportedFunction : FunctionsToImport) { + GlobalValue *NewGV = + DestModule.getNamedValue(ImportedFunction); + assert(NewGV && "Can't locate newly imported function"); + Function *NewF = dyn_cast(NewGV); + assert(NewF && "Imported Function is ... not a Function?"); + findExternalCalls(*NewF, CalledFunctions, Worklist); + } + } + } DEBUG(errs() << "Imported " << ImportedCount << " functions for Module " << DestModule.getModuleIdentifier() << "\n"); return ImportedCount;