Index: include/llvm/Transforms/IPO/FunctionImport.h =================================================================== --- include/llvm/Transforms/IPO/FunctionImport.h +++ include/llvm/Transforms/IPO/FunctionImport.h @@ -70,6 +70,14 @@ const ModuleSummaryIndex &Index, StringMap &ImportLists, StringMap &ExportLists); + +/// Compute all the imports for the given module using the Index. +/// +/// \p ImportList will be populated with a map that can be passed to +/// FunctionImporter::importFunctions() above (see description there). +void ComputeCrossModuleImportForModule( + StringRef ModulePath, const ModuleSummaryIndex &Index, + FunctionImporter::ImportMapTy &ImportList); } #endif // LLVM_FUNCTIONIMPORT_H Index: lib/Transforms/IPO/FunctionImport.cpp =================================================================== --- lib/Transforms/IPO/FunctionImport.cpp +++ lib/Transforms/IPO/FunctionImport.cpp @@ -143,7 +143,7 @@ const std::map &DefinedFunctions, SmallVectorImpl &Worklist, FunctionImporter::ImportMapTy &ImportsForModule, - StringMap &ExportLists) { + StringMap *ExportLists = nullptr) { for (auto &Edge : Summary.calls()) { auto GUID = Edge.first; DEBUG(dbgs() << " edge -> " << GUID << " Threshold:" << Threshold << "\n"); @@ -176,18 +176,21 @@ // Make exports in the source module. auto ExportModulePath = CalleeSummary->modulePath(); - auto ExportList = ExportLists[ExportModulePath]; - ExportList.insert(GUID); - // Mark all functions and globals referenced by this function as exported to - // the outside if they are defined in the same source module. - for (auto &Edge : CalleeSummary->calls()) { - auto CalleeGUID = Edge.first; - if (isGlobalExported(Index, ExportModulePath, CalleeGUID)) - ExportList.insert(CalleeGUID); - } - for (auto &GUID : CalleeSummary->refs()) { - if (isGlobalExported(Index, ExportModulePath, GUID)) - ExportList.insert(GUID); + if (ExportLists) { + auto ExportList = (*ExportLists)[ExportModulePath]; + ExportList.insert(GUID); + // Mark all functions and globals referenced by this function as exported + // to + // the outside if they are defined in the same source module. + for (auto &Edge : CalleeSummary->calls()) { + auto CalleeGUID = Edge.first; + if (isGlobalExported(Index, ExportModulePath, CalleeGUID)) + ExportList.insert(CalleeGUID); + } + for (auto &GUID : CalleeSummary->refs()) { + if (isGlobalExported(Index, ExportModulePath, GUID)) + ExportList.insert(GUID); + } } // Insert the newly imported function to the worklist. @@ -202,7 +205,7 @@ const std::map &DefinedFunctions, const ModuleSummaryIndex &Index, FunctionImporter::ImportMapTy &ImportsForModule, - StringMap &ExportLists) { + StringMap *ExportLists = nullptr) { // Worklist contains the list of function imported in this module, for which // we will analyse the callees and may import further down the callgraph. SmallVector Worklist; @@ -233,7 +236,7 @@ } // anonymous namespace -/// Compute all the import and export for every module in the Index. +/// Compute all the import and export for every module using the Index. void llvm::ComputeCrossModuleImport( const ModuleSummaryIndex &Index, StringMap &ImportLists, @@ -264,7 +267,7 @@ DEBUG(dbgs() << "Computing import for Module '" << DefinedFunctions.first() << "'\n"); ComputeImportForModule(DefinedFunctions.second, Index, ImportsForModule, - ExportLists); + &ExportLists); } #ifndef NDEBUG @@ -285,6 +288,45 @@ #endif } +/// Compute all the imports for the given module in the Index. +void llvm::ComputeCrossModuleImportForModule( + StringRef ModulePath, const ModuleSummaryIndex &Index, + FunctionImporter::ImportMapTy &ImportList) { + + // Collect the list of functions this module defines. + // GUID -> Summary + std::map FunctionInfoMap; + + for (auto &GlobalList : Index) { + auto GUID = GlobalList.first; + for (auto &GlobInfo : GlobalList.second) { + auto *Summary = dyn_cast_or_null(GlobInfo->summary()); + if (!Summary) + /// Ignore global variable, focus on functions + continue; + if (Summary->modulePath() != ModulePath) + continue; + DEBUG(dbgs() << "Adding definition: Module '" << Summary->modulePath() + << "' defines '" << GUID << "'\n"); + FunctionInfoMap[GUID] = Summary; + } + } + + // Compute the import list for this module. + DEBUG(dbgs() << "Computing import for Module '" << ModulePath << "'\n"); + ComputeImportForModule(FunctionInfoMap, Index, ImportList); + +#ifndef NDEBUG + DEBUG(dbgs() << "* Module " << ModulePath << " imports from " + << ImportList.size() << " modules.\n"); + for (auto &Src : ImportList) { + auto SrcModName = Src.first(); + DEBUG(dbgs() << " - " << Src.second.size() << " functions imported from " + << SrcModName << "\n"); + } +#endif +} + // Automatically import functions in Module \p DestModule based on the summaries // index. // @@ -462,13 +504,11 @@ Index = IndexPtr.get(); } - // First step is collecting the import/export lists - // The export list is not used yet, but could limit the amount of renaming - // performed in renameModuleForThinLTO() - StringMap ImportLists; + // First step is collecting the import list. + FunctionImporter::ImportMapTy ImportList; StringMap ExportLists; - ComputeCrossModuleImport(*Index, ImportLists, ExportLists); - auto &ImportList = ImportLists[M.getModuleIdentifier()]; + ComputeCrossModuleImportForModule(M.getModuleIdentifier(), *Index, + ImportList); // Next we need to promote to global scope and rename any local values that // are potentially exported to other modules.