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