Index: llvm/trunk/include/llvm/IR/ModuleSummaryIndex.h =================================================================== --- llvm/trunk/include/llvm/IR/ModuleSummaryIndex.h +++ llvm/trunk/include/llvm/IR/ModuleSummaryIndex.h @@ -434,6 +434,12 @@ /// but if there was only one module or this was the first module we might /// not invoke mergeFrom. void removeEmptySummaryEntries(); + + /// Collect for the given module the list of function it defines + /// (GUID -> Summary). + void collectDefinedFunctionsForModule( + StringRef ModulePath, + std::map &FunctionInfoMap) const; }; } // End llvm namespace Index: llvm/trunk/include/llvm/Transforms/IPO/FunctionImport.h =================================================================== --- llvm/trunk/include/llvm/Transforms/IPO/FunctionImport.h +++ llvm/trunk/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: llvm/trunk/lib/IR/ModuleSummaryIndex.cpp =================================================================== --- llvm/trunk/lib/IR/ModuleSummaryIndex.cpp +++ llvm/trunk/lib/IR/ModuleSummaryIndex.cpp @@ -69,6 +69,26 @@ } } +// Collect for the given module the list of function it defines +// (GUID -> Summary). +void ModuleSummaryIndex::collectDefinedFunctionsForModule( + StringRef ModulePath, + std::map &FunctionInfoMap) const { + for (auto &GlobalList : *this) { + 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; + // Ignore summaries from other modules. + if (Summary->modulePath() != ModulePath) + continue; + FunctionInfoMap[GUID] = Summary; + } + } +} + GlobalValueInfo * ModuleSummaryIndex::getGlobalValueInfo(uint64_t ValueGUID, bool PerModuleIndex) const { Index: llvm/trunk/lib/Transforms/IPO/FunctionImport.cpp =================================================================== --- llvm/trunk/lib/Transforms/IPO/FunctionImport.cpp +++ llvm/trunk/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.getGUID(); DEBUG(dbgs() << " edge -> " << GUID << " Threshold:" << Threshold << "\n"); @@ -176,19 +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.getGUID(); - if (isGlobalExported(Index, ExportModulePath, CalleeGUID)) - ExportList.insert(CalleeGUID); - } - for (auto &Ref : CalleeSummary->refs()) { - auto GUID = Ref.getGUID(); - 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.getGUID(); + if (isGlobalExported(Index, ExportModulePath, CalleeGUID)) + ExportList.insert(CalleeGUID); + } + for (auto &Ref : CalleeSummary->refs()) { + auto GUID = Ref.getGUID(); + if (isGlobalExported(Index, ExportModulePath, GUID)) + ExportList.insert(GUID); + } } // Insert the newly imported function to the worklist. @@ -203,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; @@ -234,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, @@ -265,7 +267,7 @@ DEBUG(dbgs() << "Computing import for Module '" << DefinedFunctions.first() << "'\n"); ComputeImportForModule(DefinedFunctions.second, Index, ImportsForModule, - ExportLists); + &ExportLists); } #ifndef NDEBUG @@ -286,6 +288,31 @@ #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; + Index.collectDefinedFunctionsForModule(ModulePath, FunctionInfoMap); + + // 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. // @@ -463,13 +490,10 @@ 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; - StringMap ExportLists; - ComputeCrossModuleImport(*Index, ImportLists, ExportLists); - auto &ImportList = ImportLists[M.getModuleIdentifier()]; + // First step is collecting the import list. + FunctionImporter::ImportMapTy ImportList; + 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.