Index: include/llvm/IR/ModuleSummaryIndex.h =================================================================== --- include/llvm/IR/ModuleSummaryIndex.h +++ include/llvm/IR/ModuleSummaryIndex.h @@ -241,6 +241,21 @@ /// Return the list of values referenced by this global value definition. ArrayRef refs() const { return RefEdgeList; } + + /// Return true if this global value can be externally referenced, + /// i.e. it does not need renaming (linkage is not local) or renaming + /// is possible (does not have a section for instance). + bool canBeExternallyReferenced() const { + if (!needsRenaming()) + return true; + + if (noRename()) + // Can't externally reference a global that needs renaming if has a + // section or is referenced from inline assembly, for example. + return false; + + return true; + } }; /// \brief Alias summary information. @@ -514,9 +529,10 @@ GVSummaryMapTy &GVSummaryMap) const; /// Collect for each module the list of Summaries it defines (GUID -> - /// Summary). + /// Summary), as well as the set of GUIDs that are not safe to export. void collectDefinedGVSummariesPerModule( - StringMap &ModuleToDefinedGVSummaries) const; + StringMap &ModuleToDefinedGVSummaries, + DenseSet &DoNotExport) const; }; } // End llvm namespace Index: include/llvm/Transforms/IPO/FunctionImport.h =================================================================== --- include/llvm/Transforms/IPO/FunctionImport.h +++ include/llvm/Transforms/IPO/FunctionImport.h @@ -90,7 +90,8 @@ const ModuleSummaryIndex &Index, const StringMap &ModuleToDefinedGVSummaries, StringMap &ImportLists, - StringMap &ExportLists); + StringMap &ExportLists, + DenseSet &DoNotExport); /// Compute all the imports for the given module using the Index. /// @@ -98,7 +99,8 @@ /// FunctionImporter::importFunctions() above (see description there). void ComputeCrossModuleImportForModule( StringRef ModulePath, const ModuleSummaryIndex &Index, - FunctionImporter::ImportMapTy &ImportList); + FunctionImporter::ImportMapTy &ImportList, + DenseSet &DoNotExport); /// Compute the set of summaries needed for a ThinLTO backend compilation of /// \p ModulePath. Index: lib/IR/ModuleSummaryIndex.cpp =================================================================== --- lib/IR/ModuleSummaryIndex.cpp +++ lib/IR/ModuleSummaryIndex.cpp @@ -83,13 +83,17 @@ } } -// Collect for each module the list of function it defines (GUID -> Summary). +// Collect for each module the list of function it defines (GUID -> Summary), +// as well as the set of GUIDs that are not safe to export. void ModuleSummaryIndex::collectDefinedGVSummariesPerModule( - StringMap &ModuleToDefinedGVSummaries) const { + StringMap &ModuleToDefinedGVSummaries, + DenseSet &DoNotExport) const { for (auto &GlobalList : *this) { auto GUID = GlobalList.first; for (auto &Summary : GlobalList.second) { ModuleToDefinedGVSummaries[Summary->modulePath()][GUID] = Summary.get(); + if (!Summary->canBeExternallyReferenced()) + DoNotExport.insert(GUID); } } } Index: lib/LTO/LTO.cpp =================================================================== --- lib/LTO/LTO.cpp +++ lib/LTO/LTO.cpp @@ -835,8 +835,9 @@ // Summary). StringMap> ModuleToDefinedGVSummaries(ThinLTO.ModuleMap.size()); + DenseSet DoNotExport; ThinLTO.CombinedIndex.collectDefinedGVSummariesPerModule( - ModuleToDefinedGVSummaries); + ModuleToDefinedGVSummaries, DoNotExport); // Create entries for any modules that didn't have any GV summaries // (either they didn't have any GVs to start with, or we suppressed // generation of the summaries because they e.g. had inline assembly @@ -856,7 +857,7 @@ if (Conf.OptLevel > 0) { ComputeCrossModuleImport(ThinLTO.CombinedIndex, ModuleToDefinedGVSummaries, - ImportLists, ExportLists); + ImportLists, ExportLists, DoNotExport); std::set ExportedGUIDs; for (auto &Res : GlobalResolutions) { Index: lib/LTO/ThinLTOCodeGenerator.cpp =================================================================== --- lib/LTO/ThinLTOCodeGenerator.cpp +++ lib/LTO/ThinLTOCodeGenerator.cpp @@ -577,13 +577,15 @@ // Collect for each module the list of function it defines (GUID -> Summary). StringMap ModuleToDefinedGVSummaries; - Index.collectDefinedGVSummariesPerModule(ModuleToDefinedGVSummaries); + DenseSet DoNotExport; + Index.collectDefinedGVSummariesPerModule(ModuleToDefinedGVSummaries, + DoNotExport); // Generate import/export list StringMap ImportLists(ModuleCount); StringMap ExportLists(ModuleCount); ComputeCrossModuleImport(Index, ModuleToDefinedGVSummaries, ImportLists, - ExportLists); + ExportLists, DoNotExport); // Resolve LinkOnce/Weak symbols. StringMap> ResolvedODR; @@ -619,13 +621,15 @@ // Collect for each module the list of function it defines (GUID -> Summary). StringMap ModuleToDefinedGVSummaries(ModuleCount); - Index.collectDefinedGVSummariesPerModule(ModuleToDefinedGVSummaries); + DenseSet DoNotExport; + Index.collectDefinedGVSummariesPerModule(ModuleToDefinedGVSummaries, + DoNotExport); // Generate import/export list StringMap ImportLists(ModuleCount); StringMap ExportLists(ModuleCount); ComputeCrossModuleImport(Index, ModuleToDefinedGVSummaries, ImportLists, - ExportLists); + ExportLists, DoNotExport); auto &ImportList = ImportLists[TheModule.getModuleIdentifier()]; crossImportIntoModule(TheModule, Index, ModuleMap, ImportList); @@ -641,13 +645,15 @@ // Collect for each module the list of function it defines (GUID -> Summary). StringMap ModuleToDefinedGVSummaries(ModuleCount); - Index.collectDefinedGVSummariesPerModule(ModuleToDefinedGVSummaries); + DenseSet DoNotExport; + Index.collectDefinedGVSummariesPerModule(ModuleToDefinedGVSummaries, + DoNotExport); // Generate import/export list StringMap ImportLists(ModuleCount); StringMap ExportLists(ModuleCount); ComputeCrossModuleImport(Index, ModuleToDefinedGVSummaries, ImportLists, - ExportLists); + ExportLists, DoNotExport); llvm::gatherImportedSummariesForModule(ModulePath, ModuleToDefinedGVSummaries, ImportLists[ModulePath], @@ -664,13 +670,15 @@ // Collect for each module the list of function it defines (GUID -> Summary). StringMap ModuleToDefinedGVSummaries(ModuleCount); - Index.collectDefinedGVSummariesPerModule(ModuleToDefinedGVSummaries); + DenseSet DoNotExport; + Index.collectDefinedGVSummariesPerModule(ModuleToDefinedGVSummaries, + DoNotExport); // Generate import/export list StringMap ImportLists(ModuleCount); StringMap ExportLists(ModuleCount); ComputeCrossModuleImport(Index, ModuleToDefinedGVSummaries, ImportLists, - ExportLists); + ExportLists, DoNotExport); std::error_code EC; if ((EC = EmitImportsFiles(ModulePath, OutputName, ImportLists[ModulePath]))) @@ -693,13 +701,15 @@ // Collect for each module the list of function it defines (GUID -> Summary). StringMap ModuleToDefinedGVSummaries(ModuleCount); - Index.collectDefinedGVSummariesPerModule(ModuleToDefinedGVSummaries); + DenseSet DoNotExport; + Index.collectDefinedGVSummariesPerModule(ModuleToDefinedGVSummaries, + DoNotExport); // Generate import/export list StringMap ImportLists(ModuleCount); StringMap ExportLists(ModuleCount); ComputeCrossModuleImport(Index, ModuleToDefinedGVSummaries, ImportLists, - ExportLists); + ExportLists, DoNotExport); auto &ExportList = ExportLists[ModuleIdentifier]; // Be friendly and don't nuke totally the module when the client didn't @@ -832,14 +842,16 @@ // Collect for each module the list of function it defines (GUID -> Summary). StringMap ModuleToDefinedGVSummaries(ModuleCount); - Index->collectDefinedGVSummariesPerModule(ModuleToDefinedGVSummaries); + DenseSet DoNotExport; + Index->collectDefinedGVSummariesPerModule(ModuleToDefinedGVSummaries, + DoNotExport); // Collect the import/export lists for all modules from the call-graph in the // combined index. StringMap ImportLists(ModuleCount); StringMap ExportLists(ModuleCount); ComputeCrossModuleImport(*Index, ModuleToDefinedGVSummaries, ImportLists, - ExportLists); + ExportLists, DoNotExport); // Convert the preserved symbols set from string to GUID, this is needed for // computing the caching hash and the internalization. Index: lib/Transforms/IPO/FunctionImport.cpp =================================================================== --- lib/Transforms/IPO/FunctionImport.cpp +++ lib/Transforms/IPO/FunctionImport.cpp @@ -105,45 +105,12 @@ namespace { -// Return true if the Summary describes a GlobalValue that can be externally -// referenced, i.e. it does not need renaming (linkage is not local) or renaming -// is possible (does not have a section for instance). -static bool canBeExternallyReferenced(const GlobalValueSummary &Summary) { - if (!Summary.needsRenaming()) - return true; - - if (Summary.noRename()) - // Can't externally reference a global that needs renaming if has a section - // or is referenced from inline assembly, for example. - return false; - - return true; -} - -// Return true if \p GUID describes a GlobalValue that can be externally -// referenced, i.e. it does not need renaming (linkage is not local) or -// renaming is possible (does not have a section for instance). -static bool canBeExternallyReferenced(const ModuleSummaryIndex &Index, - GlobalValue::GUID GUID) { - auto Summaries = Index.findGlobalValueSummaryList(GUID); - if (Summaries == Index.end()) - return true; - if (Summaries->second.size() != 1) - // If there are multiple globals with this GUID, then we know it is - // not a local symbol, and it is necessarily externally referenced. - return true; - - // We don't need to check for the module path, because if it can't be - // externally referenced and we call it, it is necessarilly in the same - // module - return canBeExternallyReferenced(**Summaries->second.begin()); -} - // Return true if the global described by \p Summary can be imported in another // module. static bool eligibleForImport(const ModuleSummaryIndex &Index, - const GlobalValueSummary &Summary) { - if (!canBeExternallyReferenced(Summary)) + const GlobalValueSummary &Summary, + DenseSet &DoNotExport) { + if (!Summary.canBeExternallyReferenced()) // Can't import a global that needs renaming if has a section for instance. // FIXME: we may be able to import it by copying it without promotion. return false; @@ -161,7 +128,7 @@ return false; bool AllRefsCanBeExternallyReferenced = llvm::all_of(Summary.refs(), [&](const ValueInfo &VI) { - return canBeExternallyReferenced(Index, VI.getGUID()); + return !DoNotExport.count(VI.getGUID()); }); if (!AllRefsCanBeExternallyReferenced) return false; @@ -169,7 +136,7 @@ if (auto *FuncSummary = dyn_cast(&Summary)) { bool AllCallsCanBeExternallyReferenced = llvm::all_of( FuncSummary->calls(), [&](const FunctionSummary::EdgeTy &Edge) { - return canBeExternallyReferenced(Index, Edge.first.getGUID()); + return !DoNotExport.count(Edge.first.getGUID()); }); if (!AllCallsCanBeExternallyReferenced) return false; @@ -190,7 +157,7 @@ static const GlobalValueSummary * selectCallee(const ModuleSummaryIndex &Index, const GlobalValueSummaryList &CalleeSummaryList, - unsigned Threshold) { + unsigned Threshold, DenseSet &DoNotExport) { auto It = llvm::find_if( CalleeSummaryList, [&](const std::unique_ptr &SummaryPtr) { @@ -214,7 +181,7 @@ if (Summary->instCount() > Threshold) return false; - if (!eligibleForImport(Index, *Summary)) + if (!eligibleForImport(Index, *Summary, DoNotExport)) return false; return true; @@ -227,13 +194,14 @@ /// Return the summary for the function \p GUID that fits the \p Threshold, or /// null if there's no match. -static const GlobalValueSummary *selectCallee(GlobalValue::GUID GUID, - unsigned Threshold, - const ModuleSummaryIndex &Index) { +static const GlobalValueSummary * +selectCallee(GlobalValue::GUID GUID, unsigned Threshold, + const ModuleSummaryIndex &Index, + DenseSet &DoNotExport) { auto CalleeSummaryList = Index.findGlobalValueSummaryList(GUID); if (CalleeSummaryList == Index.end()) return nullptr; // This function does not have a summary - return selectCallee(Index, CalleeSummaryList->second, Threshold); + return selectCallee(Index, CalleeSummaryList->second, Threshold, DoNotExport); } using EdgeInfo = std::tuple &Worklist, FunctionImporter::ImportMapTy &ImportList, + DenseSet &DoNotExport, StringMap *ExportLists = nullptr) { for (auto &Edge : Summary.calls()) { auto GUID = Edge.first.getGUID(); @@ -268,7 +237,7 @@ const auto NewThreshold = Threshold * GetBonusMultiplier(Edge.second.Hotness); - auto *CalleeSummary = selectCallee(GUID, NewThreshold, Index); + auto *CalleeSummary = selectCallee(GUID, NewThreshold, Index, DoNotExport); if (!CalleeSummary) { DEBUG(dbgs() << "ignored! No qualifying callee with summary found.\n"); continue; @@ -346,6 +315,7 @@ static void ComputeImportForModule( const GVSummaryMapTy &DefinedGVSummaries, const ModuleSummaryIndex &Index, FunctionImporter::ImportMapTy &ImportList, + DenseSet &DoNotExport, 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. @@ -364,7 +334,7 @@ DEBUG(dbgs() << "Initalize import for " << GVSummary.first << "\n"); computeImportForFunction(*FuncSummary, Index, ImportInstrLimit, DefinedGVSummaries, Worklist, ImportList, - ExportLists); + DoNotExport, ExportLists); } // Process the newly imported functions and add callees to the worklist. @@ -382,7 +352,7 @@ continue; computeImportForFunction(*Summary, Index, Threshold, DefinedGVSummaries, - Worklist, ImportList, ExportLists); + Worklist, ImportList, DoNotExport, ExportLists); } } @@ -393,14 +363,16 @@ const ModuleSummaryIndex &Index, const StringMap &ModuleToDefinedGVSummaries, StringMap &ImportLists, - StringMap &ExportLists) { + StringMap &ExportLists, + DenseSet &DoNotExport) { + // For each module that has function defined, compute the import/export lists. for (auto &DefinedGVSummaries : ModuleToDefinedGVSummaries) { auto &ImportList = ImportLists[DefinedGVSummaries.first()]; DEBUG(dbgs() << "Computing import for Module '" << DefinedGVSummaries.first() << "'\n"); ComputeImportForModule(DefinedGVSummaries.second, Index, ImportList, - &ExportLists); + DoNotExport, &ExportLists); } // When computing imports we added all GUIDs referenced by anything @@ -440,7 +412,8 @@ /// Compute all the imports for the given module in the Index. void llvm::ComputeCrossModuleImportForModule( StringRef ModulePath, const ModuleSummaryIndex &Index, - FunctionImporter::ImportMapTy &ImportList) { + FunctionImporter::ImportMapTy &ImportList, + DenseSet &DoNotExport) { // Collect the list of functions this module defines. // GUID -> Summary @@ -449,7 +422,7 @@ // Compute the import list for this module. DEBUG(dbgs() << "Computing import for Module '" << ModulePath << "'\n"); - ComputeImportForModule(FunctionSummaryMap, Index, ImportList); + ComputeImportForModule(FunctionSummaryMap, Index, ImportList, DoNotExport); #ifndef NDEBUG DEBUG(dbgs() << "* Module " << ModulePath << " imports from " @@ -746,8 +719,13 @@ // First step is collecting the import list. FunctionImporter::ImportMapTy ImportList; - ComputeCrossModuleImportForModule(M.getModuleIdentifier(), *Index, - ImportList); + StringMap> + ModuleToDefinedGVSummaries; + DenseSet DoNotExport; + Index->collectDefinedGVSummariesPerModule(ModuleToDefinedGVSummaries, + DoNotExport); + ComputeCrossModuleImportForModule(M.getModuleIdentifier(), *Index, ImportList, + DoNotExport); // Conservatively mark all internal values as promoted. This interface is // only used when doing importing via the function importing pass. The pass