19ba95f99STeresa Johnson //===-LTOBackend.cpp - LLVM Link Time Optimizer Backend -------------------===//
29ba95f99STeresa Johnson //
32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
69ba95f99STeresa Johnson //
79ba95f99STeresa Johnson //===----------------------------------------------------------------------===//
89ba95f99STeresa Johnson //
99ba95f99STeresa Johnson // This file implements the "backend" phase of LTO, i.e. it performs
109ba95f99STeresa Johnson // optimization and code generation on a loaded module. It is generally used
119ba95f99STeresa Johnson // internally by the LTO class but can also be used independently, for example
129ba95f99STeresa Johnson // to implement a standalone ThinLTO backend.
139ba95f99STeresa Johnson //
149ba95f99STeresa Johnson //===----------------------------------------------------------------------===//
159ba95f99STeresa Johnson
169ba95f99STeresa Johnson #include "llvm/LTO/LTOBackend.h"
179ed8e0caSdfukalov #include "llvm/Analysis/AliasAnalysis.h"
18ec9612daSDavide Italiano #include "llvm/Analysis/CGSCCPassManager.h"
195b1c70a4SVitaly Buka #include "llvm/Analysis/ModuleSummaryAnalysis.h"
209ba95f99STeresa Johnson #include "llvm/Analysis/TargetLibraryInfo.h"
21ad17679aSTeresa Johnson #include "llvm/Bitcode/BitcodeReader.h"
22ad17679aSTeresa Johnson #include "llvm/Bitcode/BitcodeWriter.h"
237531a503SFrancis Visoiu Mistrih #include "llvm/IR/LLVMRemarkStreamer.h"
249ba95f99STeresa Johnson #include "llvm/IR/LegacyPassManager.h"
25ec9612daSDavide Italiano #include "llvm/IR/PassManager.h"
26ec9612daSDavide Italiano #include "llvm/IR/Verifier.h"
27970800e0SMehdi Amini #include "llvm/LTO/LTO.h"
289ba95f99STeresa Johnson #include "llvm/MC/SubtargetFeature.h"
2989b57061SReid Kleckner #include "llvm/MC/TargetRegistry.h"
30192d8520SPeter Collingbourne #include "llvm/Object/ModuleSymbolTable.h"
31ec9612daSDavide Italiano #include "llvm/Passes/PassBuilder.h"
32c285841aSEli Friedman #include "llvm/Passes/PassPlugin.h"
33213d8a9fSTaewook Oh #include "llvm/Passes/StandardInstrumentations.h"
349ba95f99STeresa Johnson #include "llvm/Support/Error.h"
359ba95f99STeresa Johnson #include "llvm/Support/FileSystem.h"
36bd200b9fSYunlian Jiang #include "llvm/Support/MemoryBuffer.h"
37bd200b9fSYunlian Jiang #include "llvm/Support/Path.h"
38bd200b9fSYunlian Jiang #include "llvm/Support/Program.h"
399ba95f99STeresa Johnson #include "llvm/Support/ThreadPool.h"
40e188aae4Sserge-sans-paille #include "llvm/Support/ToolOutputFile.h"
417a21113cSFrancis Visoiu Mistrih #include "llvm/Support/raw_ostream.h"
429ba95f99STeresa Johnson #include "llvm/Target/TargetMachine.h"
43*2eade1dbSArthur Eubanks #include "llvm/Transforms/IPO/WholeProgramDevirt.h"
443bab7e1aSChandler Carruth #include "llvm/Transforms/Scalar/LoopPassManager.h"
459ba95f99STeresa Johnson #include "llvm/Transforms/Utils/FunctionImportUtils.h"
469ba95f99STeresa Johnson #include "llvm/Transforms/Utils/SplitModule.h"
479ba95f99STeresa Johnson
489ba95f99STeresa Johnson using namespace llvm;
499ba95f99STeresa Johnson using namespace lto;
509ba95f99STeresa Johnson
5161fc10d6SMircea Trofin #define DEBUG_TYPE "lto-backend"
5261fc10d6SMircea Trofin
539a2bab5eSMircea Trofin enum class LTOBitcodeEmbedding {
549a2bab5eSMircea Trofin DoNotEmbed = 0,
559a2bab5eSMircea Trofin EmbedOptimized = 1,
5661fc10d6SMircea Trofin EmbedPostMergePreOptimized = 2
579a2bab5eSMircea Trofin };
589a2bab5eSMircea Trofin
599a2bab5eSMircea Trofin static cl::opt<LTOBitcodeEmbedding> EmbedBitcode(
609a2bab5eSMircea Trofin "lto-embed-bitcode", cl::init(LTOBitcodeEmbedding::DoNotEmbed),
619a2bab5eSMircea Trofin cl::values(clEnumValN(LTOBitcodeEmbedding::DoNotEmbed, "none",
629a2bab5eSMircea Trofin "Do not embed"),
639a2bab5eSMircea Trofin clEnumValN(LTOBitcodeEmbedding::EmbedOptimized, "optimized",
6461fc10d6SMircea Trofin "Embed after all optimization passes"),
6561fc10d6SMircea Trofin clEnumValN(LTOBitcodeEmbedding::EmbedPostMergePreOptimized,
6661fc10d6SMircea Trofin "post-merge-pre-opt",
6761fc10d6SMircea Trofin "Embed post merge, but before optimizations")),
689a2bab5eSMircea Trofin cl::desc("Embed LLVM bitcode in object files produced by LTO"));
699a2bab5eSMircea Trofin
70cf112382SMircea Trofin static cl::opt<bool> ThinLTOAssumeMerged(
71cf112382SMircea Trofin "thinlto-assume-merged", cl::init(false),
72cf112382SMircea Trofin cl::desc("Assume the input has already undergone ThinLTO function "
73cf112382SMircea Trofin "importing and the other pre-optimization pipeline changes."));
74cf112382SMircea Trofin
758fa16cc6SYolanda Chen namespace llvm {
768fa16cc6SYolanda Chen extern cl::opt<bool> NoPGOWarnMismatch;
778fa16cc6SYolanda Chen }
788fa16cc6SYolanda Chen
reportOpenError(StringRef Path,Twine Msg)796da3d8b1SFangrui Song [[noreturn]] static void reportOpenError(StringRef Path, Twine Msg) {
80a416d113SDavide Italiano errs() << "failed to open " << Path << ": " << Msg << '\n';
81a416d113SDavide Italiano errs().flush();
82a416d113SDavide Italiano exit(1);
83a416d113SDavide Italiano }
84a416d113SDavide Italiano
addSaveTemps(std::string OutputFileName,bool UseInputModulePath,const DenseSet<StringRef> & SaveTempsArgs)8565001f57SJin Xin Ng Error Config::addSaveTemps(std::string OutputFileName, bool UseInputModulePath,
8665001f57SJin Xin Ng const DenseSet<StringRef> &SaveTempsArgs) {
879ba95f99STeresa Johnson ShouldDiscardValueNames = false;
889ba95f99STeresa Johnson
899ba95f99STeresa Johnson std::error_code EC;
9065001f57SJin Xin Ng if (SaveTempsArgs.empty() || SaveTempsArgs.contains("resolution")) {
9182b3e28eSAbhina Sreeskantharajan ResolutionFile =
9282b3e28eSAbhina Sreeskantharajan std::make_unique<raw_fd_ostream>(OutputFileName + "resolution.txt", EC,
9382b3e28eSAbhina Sreeskantharajan sys::fs::OpenFlags::OF_TextWithCRLF);
9408ff4dc9SFangrui Song if (EC) {
9508ff4dc9SFangrui Song ResolutionFile.reset();
969ba95f99STeresa Johnson return errorCodeToError(EC);
9708ff4dc9SFangrui Song }
9865001f57SJin Xin Ng }
999ba95f99STeresa Johnson
1009ba95f99STeresa Johnson auto setHook = [&](std::string PathSuffix, ModuleHookFn &Hook) {
1019ba95f99STeresa Johnson // Keep track of the hook provided by the linker, which also needs to run.
1029ba95f99STeresa Johnson ModuleHookFn LinkerHook = Hook;
103f8c2f08cSMehdi Amini Hook = [=](unsigned Task, const Module &M) {
1049ba95f99STeresa Johnson // If the linker's hook returned false, we need to pass that result
1059ba95f99STeresa Johnson // through.
1069ba95f99STeresa Johnson if (LinkerHook && !LinkerHook(Task, M))
1079ba95f99STeresa Johnson return false;
1089ba95f99STeresa Johnson
1099ba95f99STeresa Johnson std::string PathPrefix;
1109ba95f99STeresa Johnson // If this is the combined module (not a ThinLTO backend compile) or the
1119ba95f99STeresa Johnson // user hasn't requested using the input module's path, emit to a file
1129ba95f99STeresa Johnson // named from the provided OutputFileName with the Task ID appended.
1139ba95f99STeresa Johnson if (M.getModuleIdentifier() == "ld-temp.o" || !UseInputModulePath) {
11481d92073STeresa Johnson PathPrefix = OutputFileName;
11581d92073STeresa Johnson if (Task != (unsigned)-1)
11681d92073STeresa Johnson PathPrefix += utostr(Task) + ".";
1179ba95f99STeresa Johnson } else
11881d92073STeresa Johnson PathPrefix = M.getModuleIdentifier() + ".";
11981d92073STeresa Johnson std::string Path = PathPrefix + PathSuffix + ".bc";
1209ba95f99STeresa Johnson std::error_code EC;
121d9b948b6SFangrui Song raw_fd_ostream OS(Path, EC, sys::fs::OpenFlags::OF_None);
1229ba95f99STeresa Johnson // Because -save-temps is a debugging feature, we report the error
1239ba95f99STeresa Johnson // directly and exit.
124a416d113SDavide Italiano if (EC)
125a416d113SDavide Italiano reportOpenError(Path, EC.message());
1266a86e25dSRafael Espindola WriteBitcodeToFile(M, OS, /*ShouldPreserveUseListOrder=*/false);
1279ba95f99STeresa Johnson return true;
1289ba95f99STeresa Johnson };
1299ba95f99STeresa Johnson };
1309ba95f99STeresa Johnson
13165001f57SJin Xin Ng auto SaveCombinedIndex =
132ad364956Sevgeny [=](const ModuleSummaryIndex &Index,
133ad364956Sevgeny const DenseSet<GlobalValue::GUID> &GUIDPreservedSymbols) {
134eccffadaSMehdi Amini std::string Path = OutputFileName + "index.bc";
1359ba95f99STeresa Johnson std::error_code EC;
136d9b948b6SFangrui Song raw_fd_ostream OS(Path, EC, sys::fs::OpenFlags::OF_None);
1379ba95f99STeresa Johnson // Because -save-temps is a debugging feature, we report the error
1389ba95f99STeresa Johnson // directly and exit.
139a416d113SDavide Italiano if (EC)
140a416d113SDavide Italiano reportOpenError(Path, EC.message());
1417aaf024dSFangrui Song writeIndexToFile(Index, OS);
14228d8a49fSEugene Leviant
14328d8a49fSEugene Leviant Path = OutputFileName + "index.dot";
144d9b948b6SFangrui Song raw_fd_ostream OSDot(Path, EC, sys::fs::OpenFlags::OF_None);
14528d8a49fSEugene Leviant if (EC)
14628d8a49fSEugene Leviant reportOpenError(Path, EC.message());
147ad364956Sevgeny Index.exportToDot(OSDot, GUIDPreservedSymbols);
1489ba95f99STeresa Johnson return true;
1499ba95f99STeresa Johnson };
1509ba95f99STeresa Johnson
15165001f57SJin Xin Ng if (SaveTempsArgs.empty()) {
15265001f57SJin Xin Ng setHook("0.preopt", PreOptModuleHook);
15365001f57SJin Xin Ng setHook("1.promote", PostPromoteModuleHook);
15465001f57SJin Xin Ng setHook("2.internalize", PostInternalizeModuleHook);
15565001f57SJin Xin Ng setHook("3.import", PostImportModuleHook);
15665001f57SJin Xin Ng setHook("4.opt", PostOptModuleHook);
15765001f57SJin Xin Ng setHook("5.precodegen", PreCodeGenModuleHook);
15865001f57SJin Xin Ng CombinedIndexHook = SaveCombinedIndex;
15965001f57SJin Xin Ng } else {
16065001f57SJin Xin Ng if (SaveTempsArgs.contains("preopt"))
16165001f57SJin Xin Ng setHook("0.preopt", PreOptModuleHook);
16265001f57SJin Xin Ng if (SaveTempsArgs.contains("promote"))
16365001f57SJin Xin Ng setHook("1.promote", PostPromoteModuleHook);
16465001f57SJin Xin Ng if (SaveTempsArgs.contains("internalize"))
16565001f57SJin Xin Ng setHook("2.internalize", PostInternalizeModuleHook);
16665001f57SJin Xin Ng if (SaveTempsArgs.contains("import"))
16765001f57SJin Xin Ng setHook("3.import", PostImportModuleHook);
16865001f57SJin Xin Ng if (SaveTempsArgs.contains("opt"))
16965001f57SJin Xin Ng setHook("4.opt", PostOptModuleHook);
17065001f57SJin Xin Ng if (SaveTempsArgs.contains("precodegen"))
17165001f57SJin Xin Ng setHook("5.precodegen", PreCodeGenModuleHook);
17265001f57SJin Xin Ng if (SaveTempsArgs.contains("combinedindex"))
17365001f57SJin Xin Ng CombinedIndexHook = SaveCombinedIndex;
17465001f57SJin Xin Ng }
17565001f57SJin Xin Ng
17641af4309SMehdi Amini return Error::success();
1779ba95f99STeresa Johnson }
1789ba95f99STeresa Johnson
179c285841aSEli Friedman #define HANDLE_EXTENSION(Ext) \
180c285841aSEli Friedman llvm::PassPluginLibraryInfo get##Ext##PluginInfo();
181c285841aSEli Friedman #include "llvm/Support/Extension.def"
182c285841aSEli Friedman
RegisterPassPlugins(ArrayRef<std::string> PassPlugins,PassBuilder & PB)183c285841aSEli Friedman static void RegisterPassPlugins(ArrayRef<std::string> PassPlugins,
184c285841aSEli Friedman PassBuilder &PB) {
185c285841aSEli Friedman #define HANDLE_EXTENSION(Ext) \
186c285841aSEli Friedman get##Ext##PluginInfo().RegisterPassBuilderCallbacks(PB);
187c285841aSEli Friedman #include "llvm/Support/Extension.def"
188c285841aSEli Friedman
189c285841aSEli Friedman // Load requested pass plugins and let them register pass builder callbacks
190c285841aSEli Friedman for (auto &PluginFN : PassPlugins) {
191c285841aSEli Friedman auto PassPlugin = PassPlugin::Load(PluginFN);
192c285841aSEli Friedman if (!PassPlugin) {
193c285841aSEli Friedman errs() << "Failed to load passes from '" << PluginFN
194c285841aSEli Friedman << "'. Request ignored.\n";
195c285841aSEli Friedman continue;
196c285841aSEli Friedman }
197c285841aSEli Friedman
198c285841aSEli Friedman PassPlugin->registerPassBuilderCallbacks(PB);
199c285841aSEli Friedman }
200c285841aSEli Friedman }
201c285841aSEli Friedman
202f638c2ebSFlorian Hahn static std::unique_ptr<TargetMachine>
createTargetMachine(const Config & Conf,const Target * TheTarget,Module & M)203d0aad9f5STeresa Johnson createTargetMachine(const Config &Conf, const Target *TheTarget, Module &M) {
204b9f1b014SEvgeniy Stepanov StringRef TheTriple = M.getTargetTriple();
2059ba95f99STeresa Johnson SubtargetFeatures Features;
2069ba95f99STeresa Johnson Features.getDefaultSubtargetFeatures(Triple(TheTriple));
20724c29b14SDavide Italiano for (const std::string &A : Conf.MAttrs)
2089ba95f99STeresa Johnson Features.AddFeature(A);
2099ba95f99STeresa Johnson
210be646e31SWael Yehia Optional<Reloc::Model> RelocModel = None;
211b9f1b014SEvgeniy Stepanov if (Conf.RelocModel)
212b9f1b014SEvgeniy Stepanov RelocModel = *Conf.RelocModel;
213be646e31SWael Yehia else if (M.getModuleFlag("PIC Level"))
214b9f1b014SEvgeniy Stepanov RelocModel =
215b9f1b014SEvgeniy Stepanov M.getPICLevel() == PICLevel::NotPIC ? Reloc::Static : Reloc::PIC_;
216b9f1b014SEvgeniy Stepanov
2173dea3f9eSCaroline Tice Optional<CodeModel::Model> CodeModel;
2183dea3f9eSCaroline Tice if (Conf.CodeModel)
2193dea3f9eSCaroline Tice CodeModel = *Conf.CodeModel;
2203dea3f9eSCaroline Tice else
2213dea3f9eSCaroline Tice CodeModel = M.getCodeModel();
2223dea3f9eSCaroline Tice
2231756d679SElla Ma std::unique_ptr<TargetMachine> TM(TheTarget->createTargetMachine(
224b9f1b014SEvgeniy Stepanov TheTriple, Conf.CPU, Features.getString(), Conf.Options, RelocModel,
2253dea3f9eSCaroline Tice CodeModel, Conf.CGOptLevel));
2261756d679SElla Ma assert(TM && "Failed to create target machine");
2271756d679SElla Ma return TM;
2289ba95f99STeresa Johnson }
2299ba95f99STeresa Johnson
runNewPMPasses(const Config & Conf,Module & Mod,TargetMachine * TM,unsigned OptLevel,bool IsThinLTO,ModuleSummaryIndex * ExportSummary,const ModuleSummaryIndex * ImportSummary)230d0aad9f5STeresa Johnson static void runNewPMPasses(const Config &Conf, Module &Mod, TargetMachine *TM,
23128023dbeSTeresa Johnson unsigned OptLevel, bool IsThinLTO,
23228023dbeSTeresa Johnson ModuleSummaryIndex *ExportSummary,
23328023dbeSTeresa Johnson const ModuleSummaryIndex *ImportSummary) {
23489d32260SDehao Chen Optional<PGOOptions> PGOOpt;
23589d32260SDehao Chen if (!Conf.SampleProfile.empty())
236db29a3a4SRong Xu PGOOpt = PGOOptions(Conf.SampleProfile, "", Conf.ProfileRemapping,
237db29a3a4SRong Xu PGOOptions::SampleUse, PGOOptions::NoCSAction, true);
238db29a3a4SRong Xu else if (Conf.RunCSIRInstr) {
239db29a3a4SRong Xu PGOOpt = PGOOptions("", Conf.CSIRProfile, Conf.ProfileRemapping,
240886629a8SRong Xu PGOOptions::IRUse, PGOOptions::CSIRInstr,
241886629a8SRong Xu Conf.AddFSDiscriminator);
242db29a3a4SRong Xu } else if (!Conf.CSIRProfile.empty()) {
243db29a3a4SRong Xu PGOOpt = PGOOptions(Conf.CSIRProfile, "", Conf.ProfileRemapping,
244886629a8SRong Xu PGOOptions::IRUse, PGOOptions::CSIRUse,
245886629a8SRong Xu Conf.AddFSDiscriminator);
2468fa16cc6SYolanda Chen NoPGOWarnMismatch = !Conf.PGOWarnMismatch;
247886629a8SRong Xu } else if (Conf.AddFSDiscriminator) {
248886629a8SRong Xu PGOOpt = PGOOptions("", "", "", PGOOptions::NoAction,
249886629a8SRong Xu PGOOptions::NoCSAction, true);
250db29a3a4SRong Xu }
2515fdaaf7fSRong Xu TM->setPGOOption(PGOOpt);
25289d32260SDehao Chen
2536f713100SArthur Eubanks LoopAnalysisManager LAM;
2546f713100SArthur Eubanks FunctionAnalysisManager FAM;
2556f713100SArthur Eubanks CGSCCAnalysisManager CGAM;
2566f713100SArthur Eubanks ModuleAnalysisManager MAM;
2570dd200e0SDavide Italiano
25839e3e3aaSYevgeny Rouban PassInstrumentationCallbacks PIC;
25939e3e3aaSYevgeny Rouban StandardInstrumentations SI(Conf.DebugPassManager);
26039e3e3aaSYevgeny Rouban SI.registerCallbacks(PIC, &FAM);
26134a8a437SArthur Eubanks PassBuilder PB(TM, Conf.PTO, PGOOpt, &PIC);
26239e3e3aaSYevgeny Rouban
26339e3e3aaSYevgeny Rouban RegisterPassPlugins(Conf.PassPlugins, PB);
26439e3e3aaSYevgeny Rouban
2652a8cbdd8SFlorian Hahn std::unique_ptr<TargetLibraryInfoImpl> TLII(
2662a8cbdd8SFlorian Hahn new TargetLibraryInfoImpl(Triple(TM->getTargetTriple())));
2672a8cbdd8SFlorian Hahn if (Conf.Freestanding)
2682a8cbdd8SFlorian Hahn TLII->disableAllFunctions();
2692a8cbdd8SFlorian Hahn FAM.registerPass([&] { return TargetLibraryAnalysis(*TLII); });
2702a8cbdd8SFlorian Hahn
271964f8103SArthur Eubanks // Parse a custom AA pipeline if asked to.
272964f8103SArthur Eubanks if (!Conf.AAPipeline.empty()) {
27313317286SArthur Eubanks AAManager AA;
274964f8103SArthur Eubanks if (auto Err = PB.parseAAPipeline(AA, Conf.AAPipeline)) {
27521661607SSimon Pilgrim report_fatal_error(Twine("unable to parse AA pipeline description '") +
276964f8103SArthur Eubanks Conf.AAPipeline + "': " + toString(std::move(Err)));
277964f8103SArthur Eubanks }
2780dd200e0SDavide Italiano // Register the AA manager first so that our version is the one used.
2790dd200e0SDavide Italiano FAM.registerPass([&] { return std::move(AA); });
28013317286SArthur Eubanks }
2810dd200e0SDavide Italiano
2820dd200e0SDavide Italiano // Register all the basic analyses with the managers.
2830dd200e0SDavide Italiano PB.registerModuleAnalyses(MAM);
2840dd200e0SDavide Italiano PB.registerCGSCCAnalyses(CGAM);
2850dd200e0SDavide Italiano PB.registerFunctionAnalyses(FAM);
2860dd200e0SDavide Italiano PB.registerLoopAnalyses(LAM);
2870dd200e0SDavide Italiano PB.crossRegisterProxies(LAM, FAM, CGAM, MAM);
2880dd200e0SDavide Italiano
28934a8a437SArthur Eubanks ModulePassManager MPM;
29026d3aaebSArthur Eubanks
29126d3aaebSArthur Eubanks if (!Conf.DisableVerify)
29226d3aaebSArthur Eubanks MPM.addPass(VerifierPass());
2930dd200e0SDavide Italiano
2947a797b29STarindu Jayatilaka OptimizationLevel OL;
2950dd200e0SDavide Italiano
2960dd200e0SDavide Italiano switch (OptLevel) {
2970dd200e0SDavide Italiano default:
2980dd200e0SDavide Italiano llvm_unreachable("Invalid optimization level");
2990dd200e0SDavide Italiano case 0:
3007a797b29STarindu Jayatilaka OL = OptimizationLevel::O0;
3010dd200e0SDavide Italiano break;
3020dd200e0SDavide Italiano case 1:
3037a797b29STarindu Jayatilaka OL = OptimizationLevel::O1;
3040dd200e0SDavide Italiano break;
3050dd200e0SDavide Italiano case 2:
3067a797b29STarindu Jayatilaka OL = OptimizationLevel::O2;
3070dd200e0SDavide Italiano break;
3080dd200e0SDavide Italiano case 3:
3097a797b29STarindu Jayatilaka OL = OptimizationLevel::O3;
3100dd200e0SDavide Italiano break;
3110dd200e0SDavide Italiano }
3120dd200e0SDavide Italiano
313964f8103SArthur Eubanks // Parse a custom pipeline if asked to.
314964f8103SArthur Eubanks if (!Conf.OptPipeline.empty()) {
315964f8103SArthur Eubanks if (auto Err = PB.parsePassPipeline(MPM, Conf.OptPipeline)) {
31621661607SSimon Pilgrim report_fatal_error(Twine("unable to parse pass pipeline description '") +
3178334cddeSArthur Eubanks Conf.OptPipeline + "': " + toString(std::move(Err)));
318964f8103SArthur Eubanks }
3195856f30bSJoseph Huber } else if (Conf.UseDefaultPipeline) {
3205856f30bSJoseph Huber MPM.addPass(PB.buildPerModuleDefaultPipeline(OL));
321964f8103SArthur Eubanks } else if (IsThinLTO) {
322964f8103SArthur Eubanks MPM.addPass(PB.buildThinLTODefaultPipeline(OL, ImportSummary));
323964f8103SArthur Eubanks } else {
324964f8103SArthur Eubanks MPM.addPass(PB.buildLTODefaultPipeline(OL, ExportSummary));
325964f8103SArthur Eubanks }
326ec9612daSDavide Italiano
3278334cddeSArthur Eubanks if (!Conf.DisableVerify)
328ec9612daSDavide Italiano MPM.addPass(VerifierPass());
329964f8103SArthur Eubanks
330ec9612daSDavide Italiano MPM.run(Mod, MAM);
331ec9612daSDavide Italiano }
332ec9612daSDavide Italiano
opt(const Config & Conf,TargetMachine * TM,unsigned Task,Module & Mod,bool IsThinLTO,ModuleSummaryIndex * ExportSummary,const ModuleSummaryIndex * ImportSummary,const std::vector<uint8_t> & CmdArgs)3334bb11b3eSFlorian Hahn bool lto::opt(const Config &Conf, TargetMachine *TM, unsigned Task, Module &Mod,
3344bb11b3eSFlorian Hahn bool IsThinLTO, ModuleSummaryIndex *ExportSummary,
33561fc10d6SMircea Trofin const ModuleSummaryIndex *ImportSummary,
3366fa35541SMircea Trofin const std::vector<uint8_t> &CmdArgs) {
33761fc10d6SMircea Trofin if (EmbedBitcode == LTOBitcodeEmbedding::EmbedPostMergePreOptimized) {
33861fc10d6SMircea Trofin // FIXME: the motivation for capturing post-merge bitcode and command line
33961fc10d6SMircea Trofin // is replicating the compilation environment from bitcode, without needing
34061fc10d6SMircea Trofin // to understand the dependencies (the functions to be imported). This
34161fc10d6SMircea Trofin // assumes a clang - based invocation, case in which we have the command
34261fc10d6SMircea Trofin // line.
34361fc10d6SMircea Trofin // It's not very clear how the above motivation would map in the
34461fc10d6SMircea Trofin // linker-based case, so we currently don't plumb the command line args in
34561fc10d6SMircea Trofin // that case.
3466fa35541SMircea Trofin if (CmdArgs.empty())
34761fc10d6SMircea Trofin LLVM_DEBUG(
34861fc10d6SMircea Trofin dbgs() << "Post-(Thin)LTO merge bitcode embedding was requested, but "
34961fc10d6SMircea Trofin "command line arguments are not available");
3507aaf024dSFangrui Song llvm::embedBitcodeInModule(Mod, llvm::MemoryBufferRef(),
351735ab4beSMircea Trofin /*EmbedBitcode*/ true, /*EmbedCmdline*/ true,
3526fa35541SMircea Trofin /*Cmdline*/ CmdArgs);
35361fc10d6SMircea Trofin }
354e02b74e2SPeter Collingbourne // FIXME: Plumb the combined index into the new pass manager.
35528023dbeSTeresa Johnson runNewPMPasses(Conf, Mod, TM, Conf.OptLevel, IsThinLTO, ExportSummary,
35628023dbeSTeresa Johnson ImportSummary);
35724c29b14SDavide Italiano return !Conf.PostOptModuleHook || Conf.PostOptModuleHook(Task, Mod);
3589ba95f99STeresa Johnson }
3599ba95f99STeresa Johnson
codegen(const Config & Conf,TargetMachine * TM,AddStreamFn AddStream,unsigned Task,Module & Mod,const ModuleSummaryIndex & CombinedIndex)360f638c2ebSFlorian Hahn static void codegen(const Config &Conf, TargetMachine *TM,
361f638c2ebSFlorian Hahn AddStreamFn AddStream, unsigned Task, Module &Mod,
3625b1c70a4SVitaly Buka const ModuleSummaryIndex &CombinedIndex) {
36324c29b14SDavide Italiano if (Conf.PreCodeGenModuleHook && !Conf.PreCodeGenModuleHook(Task, Mod))
3649ba95f99STeresa Johnson return;
3659ba95f99STeresa Johnson
3669a2bab5eSMircea Trofin if (EmbedBitcode == LTOBitcodeEmbedding::EmbedOptimized)
3677aaf024dSFangrui Song llvm::embedBitcodeInModule(Mod, llvm::MemoryBufferRef(),
3689a2bab5eSMircea Trofin /*EmbedBitcode*/ true,
369735ab4beSMircea Trofin /*EmbedCmdline*/ false,
3706fa35541SMircea Trofin /*CmdArgs*/ std::vector<uint8_t>());
371c8e0bb3bSTeresa Johnson
372c5a9765cSPeter Collingbourne std::unique_ptr<ToolOutputFile> DwoOut;
373e1dc495eSAaron Puchert SmallString<1024> DwoFile(Conf.SplitDwarfOutput);
374bd200b9fSYunlian Jiang if (!Conf.DwoDir.empty()) {
375c5a9765cSPeter Collingbourne std::error_code EC;
376c5a9765cSPeter Collingbourne if (auto EC = llvm::sys::fs::create_directories(Conf.DwoDir))
37721661607SSimon Pilgrim report_fatal_error(Twine("Failed to create directory ") + Conf.DwoDir +
37821661607SSimon Pilgrim ": " + EC.message());
379c5a9765cSPeter Collingbourne
3803aa30e80SPeter Collingbourne DwoFile = Conf.DwoDir;
381c5a9765cSPeter Collingbourne sys::path::append(DwoFile, std::to_string(Task) + ".dwo");
382b2924d99SJonas Devlieghere TM->Options.MCOptions.SplitDwarfFile = std::string(DwoFile);
383e1dc495eSAaron Puchert } else
384e1dc495eSAaron Puchert TM->Options.MCOptions.SplitDwarfFile = Conf.SplitDwarfFile;
3853aa30e80SPeter Collingbourne
3863aa30e80SPeter Collingbourne if (!DwoFile.empty()) {
3873aa30e80SPeter Collingbourne std::error_code EC;
3880eaee545SJonas Devlieghere DwoOut = std::make_unique<ToolOutputFile>(DwoFile, EC, sys::fs::OF_None);
389c5a9765cSPeter Collingbourne if (EC)
39021661607SSimon Pilgrim report_fatal_error(Twine("Failed to open ") + DwoFile + ": " +
39121661607SSimon Pilgrim EC.message());
392bd200b9fSYunlian Jiang }
393bd200b9fSYunlian Jiang
394d788c44fSNoah Shutty Expected<std::unique_ptr<CachedFileStream>> StreamOrErr = AddStream(Task);
395d788c44fSNoah Shutty if (Error Err = StreamOrErr.takeError())
396d788c44fSNoah Shutty report_fatal_error(std::move(Err));
397d788c44fSNoah Shutty std::unique_ptr<CachedFileStream> &Stream = *StreamOrErr;
398a282ea48SAlexandre Ganea TM->Options.ObjectFilenameForDebug = Stream->ObjectPathName;
399a282ea48SAlexandre Ganea
4009ba95f99STeresa Johnson legacy::PassManager CodeGenPasses;
4010f5b7180SCraig Topper TargetLibraryInfoImpl TLII(Triple(Mod.getTargetTriple()));
4020f5b7180SCraig Topper CodeGenPasses.add(new TargetLibraryInfoWrapperPass(TLII));
4035b1c70a4SVitaly Buka CodeGenPasses.add(
4045b1c70a4SVitaly Buka createImmutableModuleSummaryIndexWrapperPass(&CombinedIndex));
405697f4e42SJez Ng if (Conf.PreCodeGenPassesHook)
406697f4e42SJez Ng Conf.PreCodeGenPassesHook(CodeGenPasses);
407c5a9765cSPeter Collingbourne if (TM->addPassesToEmitFile(CodeGenPasses, *Stream->OS,
408c5a9765cSPeter Collingbourne DwoOut ? &DwoOut->os() : nullptr,
4099a45114bSPeter Collingbourne Conf.CGFileType))
4109ba95f99STeresa Johnson report_fatal_error("Failed to setup codegen");
41124c29b14SDavide Italiano CodeGenPasses.run(Mod);
412c5a9765cSPeter Collingbourne
413c5a9765cSPeter Collingbourne if (DwoOut)
414c5a9765cSPeter Collingbourne DwoOut->keep();
4159ba95f99STeresa Johnson }
4169ba95f99STeresa Johnson
splitCodeGen(const Config & C,TargetMachine * TM,AddStreamFn AddStream,unsigned ParallelCodeGenParallelismLevel,Module & Mod,const ModuleSummaryIndex & CombinedIndex)417f638c2ebSFlorian Hahn static void splitCodeGen(const Config &C, TargetMachine *TM,
418f638c2ebSFlorian Hahn AddStreamFn AddStream,
419f3a710caSFlorian Hahn unsigned ParallelCodeGenParallelismLevel, Module &Mod,
4205b1c70a4SVitaly Buka const ModuleSummaryIndex &CombinedIndex) {
4218404aeb5SAlexandre Ganea ThreadPool CodegenThreadPool(
4228404aeb5SAlexandre Ganea heavyweight_hardware_concurrency(ParallelCodeGenParallelismLevel));
4239ba95f99STeresa Johnson unsigned ThreadCount = 0;
4249ba95f99STeresa Johnson const Target *T = &TM->getTarget();
4259ba95f99STeresa Johnson
4269ba95f99STeresa Johnson SplitModule(
427f3a710caSFlorian Hahn Mod, ParallelCodeGenParallelismLevel,
4289ba95f99STeresa Johnson [&](std::unique_ptr<Module> MPart) {
4299ba95f99STeresa Johnson // We want to clone the module in a new context to multi-thread the
4309ba95f99STeresa Johnson // codegen. We do it by serializing partition modules to bitcode
4319ba95f99STeresa Johnson // (while still on the main thread, in order to avoid data races) and
4329ba95f99STeresa Johnson // spinning up new threads which deserialize the partitions into
4339ba95f99STeresa Johnson // separate contexts.
4349ba95f99STeresa Johnson // FIXME: Provide a more direct way to do this in LLVM.
4359ba95f99STeresa Johnson SmallString<0> BC;
4369ba95f99STeresa Johnson raw_svector_ostream BCOS(BC);
4376a86e25dSRafael Espindola WriteBitcodeToFile(*MPart, BCOS);
4389ba95f99STeresa Johnson
4399ba95f99STeresa Johnson // Enqueue the task
4409ba95f99STeresa Johnson CodegenThreadPool.async(
4419ba95f99STeresa Johnson [&](const SmallString<0> &BC, unsigned ThreadId) {
4429ba95f99STeresa Johnson LTOLLVMContext Ctx(C);
443d9445c49SPeter Collingbourne Expected<std::unique_ptr<Module>> MOrErr = parseBitcodeFile(
4449ba95f99STeresa Johnson MemoryBufferRef(StringRef(BC.data(), BC.size()), "ld-temp.o"),
4459ba95f99STeresa Johnson Ctx);
4469ba95f99STeresa Johnson if (!MOrErr)
4479ba95f99STeresa Johnson report_fatal_error("Failed to read bitcode");
4489ba95f99STeresa Johnson std::unique_ptr<Module> MPartInCtx = std::move(MOrErr.get());
4499ba95f99STeresa Johnson
4509ba95f99STeresa Johnson std::unique_ptr<TargetMachine> TM =
451b9f1b014SEvgeniy Stepanov createTargetMachine(C, T, *MPartInCtx);
452adc0e26bSMehdi Amini
4535b1c70a4SVitaly Buka codegen(C, TM.get(), AddStream, ThreadId, *MPartInCtx,
4545b1c70a4SVitaly Buka CombinedIndex);
4559ba95f99STeresa Johnson },
4569ba95f99STeresa Johnson // Pass BC using std::move to ensure that it get moved rather than
4579ba95f99STeresa Johnson // copied into the thread's context.
4589ba95f99STeresa Johnson std::move(BC), ThreadCount++);
4599ba95f99STeresa Johnson },
4609ba95f99STeresa Johnson false);
461f75609e0SPeter Collingbourne
462f75609e0SPeter Collingbourne // Because the inner lambda (which runs in a worker thread) captures our local
463f75609e0SPeter Collingbourne // variables, we need to wait for the worker threads to terminate before we
464f75609e0SPeter Collingbourne // can leave the function scope.
4650d5636e5SPeter Collingbourne CodegenThreadPool.wait();
4669ba95f99STeresa Johnson }
4679ba95f99STeresa Johnson
initAndLookupTarget(const Config & C,Module & Mod)468f638c2ebSFlorian Hahn static Expected<const Target *> initAndLookupTarget(const Config &C,
469f638c2ebSFlorian Hahn Module &Mod) {
4709ba95f99STeresa Johnson if (!C.OverrideTriple.empty())
47124c29b14SDavide Italiano Mod.setTargetTriple(C.OverrideTriple);
47224c29b14SDavide Italiano else if (Mod.getTargetTriple().empty())
47324c29b14SDavide Italiano Mod.setTargetTriple(C.DefaultTriple);
4749ba95f99STeresa Johnson
4759ba95f99STeresa Johnson std::string Msg;
47624c29b14SDavide Italiano const Target *T = TargetRegistry::lookupTarget(Mod.getTargetTriple(), Msg);
4779ba95f99STeresa Johnson if (!T)
4789ba95f99STeresa Johnson return make_error<StringError>(Msg, inconvertibleErrorCode());
4799ba95f99STeresa Johnson return T;
4809ba95f99STeresa Johnson }
4819ba95f99STeresa Johnson
finalizeOptimizationRemarks(std::unique_ptr<ToolOutputFile> DiagOutputFile)48231ae0165SGabor Horvath Error lto::finalizeOptimizationRemarks(
48331ae0165SGabor Horvath std::unique_ptr<ToolOutputFile> DiagOutputFile) {
48420a895c4SDavide Italiano // Make sure we flush the diagnostic remarks file in case the linker doesn't
48520a895c4SDavide Italiano // call the global destructors before exiting.
48620a895c4SDavide Italiano if (!DiagOutputFile)
48785cc298cSTeresa Johnson return Error::success();
48820a895c4SDavide Italiano DiagOutputFile->keep();
48920a895c4SDavide Italiano DiagOutputFile->os().flush();
49085cc298cSTeresa Johnson return Error::success();
49120a895c4SDavide Italiano }
49220a895c4SDavide Italiano
backend(const Config & C,AddStreamFn AddStream,unsigned ParallelCodeGenParallelismLevel,Module & Mod,ModuleSummaryIndex & CombinedIndex)493d0aad9f5STeresa Johnson Error lto::backend(const Config &C, AddStreamFn AddStream,
494f3a710caSFlorian Hahn unsigned ParallelCodeGenParallelismLevel, Module &Mod,
495e02b74e2SPeter Collingbourne ModuleSummaryIndex &CombinedIndex) {
496f3a710caSFlorian Hahn Expected<const Target *> TOrErr = initAndLookupTarget(C, Mod);
4979ba95f99STeresa Johnson if (!TOrErr)
4989ba95f99STeresa Johnson return TOrErr.takeError();
4999ba95f99STeresa Johnson
500f3a710caSFlorian Hahn std::unique_ptr<TargetMachine> TM = createTargetMachine(C, *TOrErr, Mod);
5019ba95f99STeresa Johnson
50220a895c4SDavide Italiano if (!C.CodeGenOnly) {
503f3a710caSFlorian Hahn if (!opt(C, TM.get(), 0, Mod, /*IsThinLTO=*/false,
5046fa35541SMircea Trofin /*ExportSummary=*/&CombinedIndex, /*ImportSummary=*/nullptr,
5056fa35541SMircea Trofin /*CmdArgs*/ std::vector<uint8_t>()))
50631ae0165SGabor Horvath return Error::success();
50720a895c4SDavide Italiano }
5089ba95f99STeresa Johnson
509adc0e26bSMehdi Amini if (ParallelCodeGenParallelismLevel == 1) {
510f3a710caSFlorian Hahn codegen(C, TM.get(), AddStream, 0, Mod, CombinedIndex);
511adc0e26bSMehdi Amini } else {
512f3a710caSFlorian Hahn splitCodeGen(C, TM.get(), AddStream, ParallelCodeGenParallelismLevel, Mod,
513f3a710caSFlorian Hahn CombinedIndex);
514adc0e26bSMehdi Amini }
51531ae0165SGabor Horvath return Error::success();
5169ba95f99STeresa Johnson }
5179ba95f99STeresa Johnson
dropDeadSymbols(Module & Mod,const GVSummaryMapTy & DefinedGlobals,const ModuleSummaryIndex & Index)518eaf5172cSGeorge Rimar static void dropDeadSymbols(Module &Mod, const GVSummaryMapTy &DefinedGlobals,
519eaf5172cSGeorge Rimar const ModuleSummaryIndex &Index) {
520791c98e4STeresa Johnson std::vector<GlobalValue*> DeadGVs;
5215a95c477STeresa Johnson for (auto &GV : Mod.global_values())
522f5de271aSGeorge Rimar if (GlobalValueSummary *GVS = DefinedGlobals.lookup(GV.getGUID()))
523791c98e4STeresa Johnson if (!Index.isGlobalValueLive(GVS)) {
524791c98e4STeresa Johnson DeadGVs.push_back(&GV);
525791c98e4STeresa Johnson convertToDeclaration(GV);
526791c98e4STeresa Johnson }
52776c5fae2SGeorge Rimar
528791c98e4STeresa Johnson // Now that all dead bodies have been dropped, delete the actual objects
529791c98e4STeresa Johnson // themselves when possible.
530791c98e4STeresa Johnson for (GlobalValue *GV : DeadGVs) {
531791c98e4STeresa Johnson GV->removeDeadConstantUsers();
532791c98e4STeresa Johnson // Might reference something defined in native object (i.e. dropped a
533791c98e4STeresa Johnson // non-prevailing IR def, but we need to keep the declaration).
534791c98e4STeresa Johnson if (GV->use_empty())
5355a95c477STeresa Johnson GV->eraseFromParent();
536eaf5172cSGeorge Rimar }
537791c98e4STeresa Johnson }
538eaf5172cSGeorge Rimar
thinBackend(const Config & Conf,unsigned Task,AddStreamFn AddStream,Module & Mod,const ModuleSummaryIndex & CombinedIndex,const FunctionImporter::ImportMapTy & ImportList,const GVSummaryMapTy & DefinedGlobals,MapVector<StringRef,BitcodeModule> * ModuleMap,const std::vector<uint8_t> & CmdArgs)539d0aad9f5STeresa Johnson Error lto::thinBackend(const Config &Conf, unsigned Task, AddStreamFn AddStream,
540f7691d8bSPeter Collingbourne Module &Mod, const ModuleSummaryIndex &CombinedIndex,
5419ba95f99STeresa Johnson const FunctionImporter::ImportMapTy &ImportList,
5429ba95f99STeresa Johnson const GVSummaryMapTy &DefinedGlobals,
543d535a05cSWei Mi MapVector<StringRef, BitcodeModule> *ModuleMap,
5446fa35541SMircea Trofin const std::vector<uint8_t> &CmdArgs) {
545acc50c43SMehdi Amini Expected<const Target *> TOrErr = initAndLookupTarget(Conf, Mod);
5469ba95f99STeresa Johnson if (!TOrErr)
5479ba95f99STeresa Johnson return TOrErr.takeError();
5489ba95f99STeresa Johnson
549b9f1b014SEvgeniy Stepanov std::unique_ptr<TargetMachine> TM = createTargetMachine(Conf, *TOrErr, Mod);
5509ba95f99STeresa Johnson
55185cc298cSTeresa Johnson // Setup optimization remarks.
5527531a503SFrancis Visoiu Mistrih auto DiagFileOrErr = lto::setupLLVMOptimizationRemarks(
553dd42236cSFrancis Visoiu Mistrih Mod.getContext(), Conf.RemarksFilename, Conf.RemarksPasses,
5543acda917SWei Wang Conf.RemarksFormat, Conf.RemarksWithHotness, Conf.RemarksHotnessThreshold,
5553acda917SWei Wang Task);
55685cc298cSTeresa Johnson if (!DiagFileOrErr)
55785cc298cSTeresa Johnson return DiagFileOrErr.takeError();
55885cc298cSTeresa Johnson auto DiagnosticOutputFile = std::move(*DiagFileOrErr);
55985cc298cSTeresa Johnson
5606c27c61dSHiroshi Yamauchi // Set the partial sample profile ratio in the profile summary module flag of
5616c27c61dSHiroshi Yamauchi // the module, if applicable.
5626c27c61dSHiroshi Yamauchi Mod.setPartialSampleProfileRatio(CombinedIndex);
5636c27c61dSHiroshi Yamauchi
564*2eade1dbSArthur Eubanks updatePublicTypeTestCalls(Mod, CombinedIndex.withWholeProgramVisibility());
565*2eade1dbSArthur Eubanks
566d310b47cSMehdi Amini if (Conf.CodeGenOnly) {
5675b1c70a4SVitaly Buka codegen(Conf, TM.get(), AddStream, Task, Mod, CombinedIndex);
56885cc298cSTeresa Johnson return finalizeOptimizationRemarks(std::move(DiagnosticOutputFile));
569d310b47cSMehdi Amini }
570d310b47cSMehdi Amini
571acc50c43SMehdi Amini if (Conf.PreOptModuleHook && !Conf.PreOptModuleHook(Task, Mod))
57285cc298cSTeresa Johnson return finalizeOptimizationRemarks(std::move(DiagnosticOutputFile));
5739ba95f99STeresa Johnson
574cf112382SMircea Trofin auto OptimizeAndCodegen =
575cf112382SMircea Trofin [&](Module &Mod, TargetMachine *TM,
576cf112382SMircea Trofin std::unique_ptr<ToolOutputFile> DiagnosticOutputFile) {
577cf112382SMircea Trofin if (!opt(Conf, TM, Task, Mod, /*IsThinLTO=*/true,
578cf112382SMircea Trofin /*ExportSummary=*/nullptr, /*ImportSummary=*/&CombinedIndex,
579cf112382SMircea Trofin CmdArgs))
580cf112382SMircea Trofin return finalizeOptimizationRemarks(std::move(DiagnosticOutputFile));
581cf112382SMircea Trofin
582cf112382SMircea Trofin codegen(Conf, TM, AddStream, Task, Mod, CombinedIndex);
583cf112382SMircea Trofin return finalizeOptimizationRemarks(std::move(DiagnosticOutputFile));
584cf112382SMircea Trofin };
585cf112382SMircea Trofin
586cf112382SMircea Trofin if (ThinLTOAssumeMerged)
587cf112382SMircea Trofin return OptimizeAndCodegen(Mod, TM.get(), std::move(DiagnosticOutputFile));
588cf112382SMircea Trofin
589d2ef8c1fSFangrui Song // When linking an ELF shared object, dso_local should be dropped. We
590d2ef8c1fSFangrui Song // conservatively do this for -fpic.
591d2ef8c1fSFangrui Song bool ClearDSOLocalOnDeclarations =
592d2ef8c1fSFangrui Song TM->getTargetTriple().isOSBinFormatELF() &&
593d2ef8c1fSFangrui Song TM->getRelocationModel() != Reloc::Static &&
594d2ef8c1fSFangrui Song Mod.getPIELevel() == PIELevel::Default;
595d2ef8c1fSFangrui Song renameModuleForThinLTO(Mod, CombinedIndex, ClearDSOLocalOnDeclarations);
5969ba95f99STeresa Johnson
597eaf5172cSGeorge Rimar dropDeadSymbols(Mod, DefinedGlobals, CombinedIndex);
598eaf5172cSGeorge Rimar
59920faf789Smodimo thinLTOFinalizeInModule(Mod, DefinedGlobals, /*PropagateAttrs=*/true);
6008ac7b322SMehdi Amini
601acc50c43SMehdi Amini if (Conf.PostPromoteModuleHook && !Conf.PostPromoteModuleHook(Task, Mod))
60285cc298cSTeresa Johnson return finalizeOptimizationRemarks(std::move(DiagnosticOutputFile));
6039ba95f99STeresa Johnson
6049ba95f99STeresa Johnson if (!DefinedGlobals.empty())
605acc50c43SMehdi Amini thinLTOInternalizeModule(Mod, DefinedGlobals);
6069ba95f99STeresa Johnson
607acc50c43SMehdi Amini if (Conf.PostInternalizeModuleHook &&
608acc50c43SMehdi Amini !Conf.PostInternalizeModuleHook(Task, Mod))
60985cc298cSTeresa Johnson return finalizeOptimizationRemarks(std::move(DiagnosticOutputFile));
6109ba95f99STeresa Johnson
6119ba95f99STeresa Johnson auto ModuleLoader = [&](StringRef Identifier) {
6129ec5a613SMehdi Amini assert(Mod.getContext().isODRUniquingDebugTypes() &&
61363e8f444SDavide Italiano "ODR Type uniquing should be enabled on the context");
614d535a05cSWei Mi if (ModuleMap) {
615d535a05cSWei Mi auto I = ModuleMap->find(Identifier);
616d535a05cSWei Mi assert(I != ModuleMap->end());
6171a0720e8SPeter Collingbourne return I->second.getLazyModule(Mod.getContext(),
618a61f5e37STeresa Johnson /*ShouldLazyLoadMetadata=*/true,
619a61f5e37STeresa Johnson /*IsImporting*/ true);
620d535a05cSWei Mi }
621d535a05cSWei Mi
622d535a05cSWei Mi ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> MBOrErr =
623d535a05cSWei Mi llvm::MemoryBuffer::getFile(Identifier);
624d535a05cSWei Mi if (!MBOrErr)
625d535a05cSWei Mi return Expected<std::unique_ptr<llvm::Module>>(make_error<StringError>(
626d535a05cSWei Mi Twine("Error loading imported file ") + Identifier + " : ",
627d535a05cSWei Mi MBOrErr.getError()));
628d535a05cSWei Mi
629d535a05cSWei Mi Expected<BitcodeModule> BMOrErr = findThinLTOModule(**MBOrErr);
630d535a05cSWei Mi if (!BMOrErr)
631d535a05cSWei Mi return Expected<std::unique_ptr<llvm::Module>>(make_error<StringError>(
632d535a05cSWei Mi Twine("Error loading imported file ") + Identifier + " : " +
633d535a05cSWei Mi toString(BMOrErr.takeError()),
634d535a05cSWei Mi inconvertibleErrorCode()));
635d535a05cSWei Mi
636d535a05cSWei Mi Expected<std::unique_ptr<Module>> MOrErr =
637d535a05cSWei Mi BMOrErr->getLazyModule(Mod.getContext(),
638d535a05cSWei Mi /*ShouldLazyLoadMetadata=*/true,
639d535a05cSWei Mi /*IsImporting*/ true);
640d535a05cSWei Mi if (MOrErr)
641d535a05cSWei Mi (*MOrErr)->setOwnedMemoryBuffer(std::move(*MBOrErr));
642d535a05cSWei Mi return MOrErr;
6439ba95f99STeresa Johnson };
6449ba95f99STeresa Johnson
645d2ef8c1fSFangrui Song FunctionImporter Importer(CombinedIndex, ModuleLoader,
646d2ef8c1fSFangrui Song ClearDSOLocalOnDeclarations);
6477f00d0a1SPeter Collingbourne if (Error Err = Importer.importFunctions(Mod, ImportList).takeError())
6487f00d0a1SPeter Collingbourne return Err;
6499ba95f99STeresa Johnson
650acc50c43SMehdi Amini if (Conf.PostImportModuleHook && !Conf.PostImportModuleHook(Task, Mod))
65185cc298cSTeresa Johnson return finalizeOptimizationRemarks(std::move(DiagnosticOutputFile));
6529ba95f99STeresa Johnson
653cf112382SMircea Trofin return OptimizeAndCodegen(Mod, TM.get(), std::move(DiagnosticOutputFile));
654cf112382SMircea Trofin }
6559ba95f99STeresa Johnson
findThinLTOModule(MutableArrayRef<BitcodeModule> BMs)656cf112382SMircea Trofin BitcodeModule *lto::findThinLTOModule(MutableArrayRef<BitcodeModule> BMs) {
657cf112382SMircea Trofin if (ThinLTOAssumeMerged && BMs.size() == 1)
658cf112382SMircea Trofin return BMs.begin();
659cf112382SMircea Trofin
660cf112382SMircea Trofin for (BitcodeModule &BM : BMs) {
661cf112382SMircea Trofin Expected<BitcodeLTOInfo> LTOInfo = BM.getLTOInfo();
662cf112382SMircea Trofin if (LTOInfo && LTOInfo->IsThinLTO)
663cf112382SMircea Trofin return &BM;
664cf112382SMircea Trofin }
665cf112382SMircea Trofin return nullptr;
666cf112382SMircea Trofin }
667cf112382SMircea Trofin
findThinLTOModule(MemoryBufferRef MBRef)668cf112382SMircea Trofin Expected<BitcodeModule> lto::findThinLTOModule(MemoryBufferRef MBRef) {
669cf112382SMircea Trofin Expected<std::vector<BitcodeModule>> BMsOrErr = getBitcodeModuleList(MBRef);
670cf112382SMircea Trofin if (!BMsOrErr)
671cf112382SMircea Trofin return BMsOrErr.takeError();
672cf112382SMircea Trofin
673cf112382SMircea Trofin // The bitcode file may contain multiple modules, we want the one that is
674cf112382SMircea Trofin // marked as being the ThinLTO module.
675cf112382SMircea Trofin if (const BitcodeModule *Bm = lto::findThinLTOModule(*BMsOrErr))
676cf112382SMircea Trofin return *Bm;
677cf112382SMircea Trofin
678cf112382SMircea Trofin return make_error<StringError>("Could not find module summary",
679cf112382SMircea Trofin inconvertibleErrorCode());
680cf112382SMircea Trofin }
681cf112382SMircea Trofin
initImportList(const Module & M,const ModuleSummaryIndex & CombinedIndex,FunctionImporter::ImportMapTy & ImportList)682d535a05cSWei Mi bool lto::initImportList(const Module &M,
683d535a05cSWei Mi const ModuleSummaryIndex &CombinedIndex,
684d535a05cSWei Mi FunctionImporter::ImportMapTy &ImportList) {
685cf112382SMircea Trofin if (ThinLTOAssumeMerged)
686cf112382SMircea Trofin return true;
687cf112382SMircea Trofin // We can simply import the values mentioned in the combined index, since
688cf112382SMircea Trofin // we should only invoke this using the individual indexes written out
689cf112382SMircea Trofin // via a WriteIndexesThinBackend.
690cf112382SMircea Trofin for (const auto &GlobalList : CombinedIndex) {
691cf112382SMircea Trofin // Ignore entries for undefined references.
692cf112382SMircea Trofin if (GlobalList.second.SummaryList.empty())
693cf112382SMircea Trofin continue;
694cf112382SMircea Trofin
695cf112382SMircea Trofin auto GUID = GlobalList.first;
696cf112382SMircea Trofin for (const auto &Summary : GlobalList.second.SummaryList) {
697cf112382SMircea Trofin // Skip the summaries for the importing module. These are included to
698cf112382SMircea Trofin // e.g. record required linkage changes.
699cf112382SMircea Trofin if (Summary->modulePath() == M.getModuleIdentifier())
700cf112382SMircea Trofin continue;
701cf112382SMircea Trofin // Add an entry to provoke importing by thinBackend.
702cf112382SMircea Trofin ImportList[Summary->modulePath()].insert(GUID);
703cf112382SMircea Trofin }
704cf112382SMircea Trofin }
705cf112382SMircea Trofin return true;
7069ba95f99STeresa Johnson }
707