diff options
author | Dimitry Andric <dim@FreeBSD.org> | 2020-07-26 19:36:28 +0000 |
---|---|---|
committer | Dimitry Andric <dim@FreeBSD.org> | 2020-07-26 19:36:28 +0000 |
commit | cfca06d7963fa0909f90483b42a6d7d194d01e08 (patch) | |
tree | 209fb2a2d68f8f277793fc8df46c753d31bc853b /llvm/lib/Transforms/IPO/FunctionImport.cpp | |
parent | 706b4fc47bbc608932d3b491ae19a3b9cde9497b (diff) |
Notes
Diffstat (limited to 'llvm/lib/Transforms/IPO/FunctionImport.cpp')
-rw-r--r-- | llvm/lib/Transforms/IPO/FunctionImport.cpp | 133 |
1 files changed, 81 insertions, 52 deletions
diff --git a/llvm/lib/Transforms/IPO/FunctionImport.cpp b/llvm/lib/Transforms/IPO/FunctionImport.cpp index be0446a946ec5..468bf19f2e48a 100644 --- a/llvm/lib/Transforms/IPO/FunctionImport.cpp +++ b/llvm/lib/Transforms/IPO/FunctionImport.cpp @@ -306,28 +306,21 @@ static void computeImportForReferencedGlobals( RefSummary->modulePath() != Summary.modulePath(); }; - auto MarkExported = [&](const ValueInfo &VI, const GlobalValueSummary *S) { - if (ExportLists) - (*ExportLists)[S->modulePath()].insert(VI); - }; - for (auto &RefSummary : VI.getSummaryList()) if (isa<GlobalVarSummary>(RefSummary.get()) && Index.canImportGlobalVar(RefSummary.get(), /* AnalyzeRefs */ true) && !LocalNotInModule(RefSummary.get())) { auto ILI = ImportList[RefSummary->modulePath()].insert(VI.getGUID()); - // Only update stat if we haven't already imported this variable. - if (ILI.second) - NumImportedGlobalVarsThinLink++; - MarkExported(VI, RefSummary.get()); - // Promote referenced functions and variables. We don't promote - // objects referenced by writeonly variable initializer, because - // we convert such variables initializers to "zeroinitializer". - // See processGlobalForThinLTO. - if (!Index.isWriteOnly(cast<GlobalVarSummary>(RefSummary.get()))) - for (const auto &VI : RefSummary->refs()) - for (const auto &RefFn : VI.getSummaryList()) - MarkExported(VI, RefFn.get()); + // Only update stat and exports if we haven't already imported this + // variable. + if (!ILI.second) + break; + NumImportedGlobalVarsThinLink++; + // Any references made by this variable will be marked exported later, + // in ComputeCrossModuleImport, after import decisions are complete, + // which is more efficient than adding them here. + if (ExportLists) + (*ExportLists)[RefSummary->modulePath()].insert(VI); break; } } @@ -494,24 +487,11 @@ static void computeImportForFunction( NumImportedCriticalFunctionsThinLink++; } - // Make exports in the source module. - if (ExportLists) { - auto &ExportList = (*ExportLists)[ExportModulePath]; - ExportList.insert(VI); - if (!PreviouslyImported) { - // This is the first time this function was exported from its source - // module, so mark all functions and globals it references as exported - // to the outside if they are defined in the same source module. - // For efficiency, we unconditionally add all the referenced GUIDs - // to the ExportList for this module, and will prune out any not - // defined in the module later in a single pass. - for (auto &Edge : ResolvedCalleeSummary->calls()) - ExportList.insert(Edge.first); - - for (auto &Ref : ResolvedCalleeSummary->refs()) - ExportList.insert(Ref); - } - } + // Any calls/references made by this function will be marked exported + // later, in ComputeCrossModuleImport, after import decisions are + // complete, which is more efficient than adding them here. + if (ExportLists) + (*ExportLists)[ExportModulePath].insert(VI); } auto GetAdjustedThreshold = [](unsigned Threshold, bool IsHotCallsite) { @@ -678,20 +658,55 @@ void llvm::ComputeCrossModuleImport( &ExportLists); } - // When computing imports we added all GUIDs referenced by anything - // imported from the module to its ExportList. Now we prune each ExportList - // of any not defined in that module. This is more efficient than checking - // while computing imports because some of the summary lists may be long - // due to linkonce (comdat) copies. + // When computing imports we only added the variables and functions being + // imported to the export list. We also need to mark any references and calls + // they make as exported as well. We do this here, as it is more efficient + // since we may import the same values multiple times into different modules + // during the import computation. for (auto &ELI : ExportLists) { + FunctionImporter::ExportSetTy NewExports; const auto &DefinedGVSummaries = ModuleToDefinedGVSummaries.lookup(ELI.first()); - for (auto EI = ELI.second.begin(); EI != ELI.second.end();) { + for (auto &EI : ELI.second) { + // Find the copy defined in the exporting module so that we can mark the + // values it references in that specific definition as exported. + // Below we will add all references and called values, without regard to + // whether they are also defined in this module. We subsequently prune the + // list to only include those defined in the exporting module, see comment + // there as to why. + auto DS = DefinedGVSummaries.find(EI.getGUID()); + // Anything marked exported during the import computation must have been + // defined in the exporting module. + assert(DS != DefinedGVSummaries.end()); + auto *S = DS->getSecond(); + S = S->getBaseObject(); + if (auto *GVS = dyn_cast<GlobalVarSummary>(S)) { + // Export referenced functions and variables. We don't export/promote + // objects referenced by writeonly variable initializer, because + // we convert such variables initializers to "zeroinitializer". + // See processGlobalForThinLTO. + if (!Index.isWriteOnly(GVS)) + for (const auto &VI : GVS->refs()) + NewExports.insert(VI); + } else { + auto *FS = cast<FunctionSummary>(S); + for (auto &Edge : FS->calls()) + NewExports.insert(Edge.first); + for (auto &Ref : FS->refs()) + NewExports.insert(Ref); + } + } + // Prune list computed above to only include values defined in the exporting + // module. We do this after the above insertion since we may hit the same + // ref/call target multiple times in above loop, and it is more efficient to + // avoid a set lookup each time. + for (auto EI = NewExports.begin(); EI != NewExports.end();) { if (!DefinedGVSummaries.count(EI->getGUID())) - ELI.second.erase(EI++); + NewExports.erase(EI++); else ++EI; } + ELI.second.insert(NewExports.begin(), NewExports.end()); } assert(checkVariableImport(Index, ImportLists, ExportLists)); @@ -913,11 +928,12 @@ void llvm::gatherImportedSummariesForModule( const FunctionImporter::ImportMapTy &ImportList, std::map<std::string, GVSummaryMapTy> &ModuleToSummariesForIndex) { // Include all summaries from the importing module. - ModuleToSummariesForIndex[ModulePath] = + ModuleToSummariesForIndex[std::string(ModulePath)] = ModuleToDefinedGVSummaries.lookup(ModulePath); // Include summaries for imports. for (auto &ILI : ImportList) { - auto &SummariesForIndex = ModuleToSummariesForIndex[ILI.first()]; + auto &SummariesForIndex = + ModuleToSummariesForIndex[std::string(ILI.first())]; const auto &DefinedGVSummaries = ModuleToDefinedGVSummaries.lookup(ILI.first()); for (auto &GI : ILI.second) { @@ -976,6 +992,8 @@ bool llvm::convertToDeclaration(GlobalValue &GV) { GV.replaceAllUsesWith(NewGV); return false; } + if (!GV.isImplicitDSOLocal()) + GV.setDSOLocal(false); return true; } @@ -1214,8 +1232,15 @@ Expected<bool> FunctionImporter::importFunctions( // have loaded all the required metadata! UpgradeDebugInfo(*SrcModule); + // Set the partial sample profile ratio in the profile summary module flag + // of the imported source module, if applicable, so that the profile summary + // module flag will match with that of the destination module when it's + // imported. + SrcModule->setPartialSampleProfileRatio(Index); + // Link in the specified functions. - if (renameModuleForThinLTO(*SrcModule, Index, &GlobalsToImport)) + if (renameModuleForThinLTO(*SrcModule, Index, ClearDSOLocalOnDeclarations, + &GlobalsToImport)) return true; if (PrintImports) { @@ -1224,10 +1249,12 @@ Expected<bool> FunctionImporter::importFunctions( << " from " << SrcModule->getSourceFileName() << "\n"; } - if (Mover.move(std::move(SrcModule), GlobalsToImport.getArrayRef(), - [](GlobalValue &, IRMover::ValueAdder) {}, - /*IsPerformingImport=*/true)) - report_fatal_error("Function Import: link error"); + if (Error Err = Mover.move( + std::move(SrcModule), GlobalsToImport.getArrayRef(), + [](GlobalValue &, IRMover::ValueAdder) {}, + /*IsPerformingImport=*/true)) + report_fatal_error("Function Import: link error: " + + toString(std::move(Err))); ImportedCount += GlobalsToImport.size(); NumImportedModules++; @@ -1284,16 +1311,18 @@ static bool doImportingForModule(Module &M) { // Next we need to promote to global scope and rename any local values that // are potentially exported to other modules. - if (renameModuleForThinLTO(M, *Index, nullptr)) { + if (renameModuleForThinLTO(M, *Index, /*clearDSOOnDeclarations=*/false, + /*GlobalsToImport=*/nullptr)) { errs() << "Error renaming module\n"; return false; } // Perform the import now. auto ModuleLoader = [&M](StringRef Identifier) { - return loadFile(Identifier, M.getContext()); + return loadFile(std::string(Identifier), M.getContext()); }; - FunctionImporter Importer(*Index, ModuleLoader); + FunctionImporter Importer(*Index, ModuleLoader, + /*ClearDSOLocalOnDeclarations=*/false); Expected<bool> Result = Importer.importFunctions(M, ImportList); // FIXME: Probably need to propagate Errors through the pass manager. |