1 //===-LTOBackend.cpp - LLVM Link Time Optimizer Backend -------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // This file implements the "backend" phase of LTO, i.e. it performs
10 // optimization and code generation on a loaded module. It is generally used
11 // internally by the LTO class but can also be used independently, for example
12 // to implement a standalone ThinLTO backend.
13 //
14 //===----------------------------------------------------------------------===//
15 
16 #include "llvm/LTO/LTOBackend.h"
17 #include "llvm/Analysis/AliasAnalysis.h"
18 #include "llvm/Analysis/CGSCCPassManager.h"
19 #include "llvm/Analysis/ModuleSummaryAnalysis.h"
20 #include "llvm/Analysis/TargetLibraryInfo.h"
21 #include "llvm/Analysis/TargetTransformInfo.h"
22 #include "llvm/Bitcode/BitcodeReader.h"
23 #include "llvm/Bitcode/BitcodeWriter.h"
24 #include "llvm/IR/LLVMRemarkStreamer.h"
25 #include "llvm/IR/LegacyPassManager.h"
26 #include "llvm/IR/PassManager.h"
27 #include "llvm/IR/Verifier.h"
28 #include "llvm/LTO/LTO.h"
29 #include "llvm/MC/SubtargetFeature.h"
30 #include "llvm/Object/ModuleSymbolTable.h"
31 #include "llvm/Passes/PassBuilder.h"
32 #include "llvm/Passes/PassPlugin.h"
33 #include "llvm/Passes/StandardInstrumentations.h"
34 #include "llvm/Support/Error.h"
35 #include "llvm/Support/FileSystem.h"
36 #include "llvm/Support/MemoryBuffer.h"
37 #include "llvm/Support/Path.h"
38 #include "llvm/Support/Program.h"
39 #include "llvm/Support/SmallVectorMemoryBuffer.h"
40 #include "llvm/Support/TargetRegistry.h"
41 #include "llvm/Support/ThreadPool.h"
42 #include "llvm/Support/raw_ostream.h"
43 #include "llvm/Target/TargetMachine.h"
44 #include "llvm/Transforms/IPO.h"
45 #include "llvm/Transforms/IPO/PassManagerBuilder.h"
46 #include "llvm/Transforms/Scalar/LoopPassManager.h"
47 #include "llvm/Transforms/Utils/FunctionImportUtils.h"
48 #include "llvm/Transforms/Utils/SplitModule.h"
49 
50 using namespace llvm;
51 using namespace lto;
52 
53 enum class LTOBitcodeEmbedding {
54   DoNotEmbed = 0,
55   EmbedOptimized = 1,
56 };
57 
58 static cl::opt<LTOBitcodeEmbedding> EmbedBitcode(
59     "lto-embed-bitcode", cl::init(LTOBitcodeEmbedding::DoNotEmbed),
60     cl::values(clEnumValN(LTOBitcodeEmbedding::DoNotEmbed, "none",
61                           "Do not embed"),
62                clEnumValN(LTOBitcodeEmbedding::EmbedOptimized, "optimized",
63                           "Embed after all optimization passes")),
64     cl::desc("Embed LLVM bitcode in object files produced by LTO"));
65 
66 LLVM_ATTRIBUTE_NORETURN static void reportOpenError(StringRef Path, Twine Msg) {
67   errs() << "failed to open " << Path << ": " << Msg << '\n';
68   errs().flush();
69   exit(1);
70 }
71 
72 Error Config::addSaveTemps(std::string OutputFileName,
73                            bool UseInputModulePath) {
74   ShouldDiscardValueNames = false;
75 
76   std::error_code EC;
77   ResolutionFile = std::make_unique<raw_fd_ostream>(
78       OutputFileName + "resolution.txt", EC, sys::fs::OpenFlags::OF_Text);
79   if (EC) {
80     ResolutionFile.reset();
81     return errorCodeToError(EC);
82   }
83 
84   auto setHook = [&](std::string PathSuffix, ModuleHookFn &Hook) {
85     // Keep track of the hook provided by the linker, which also needs to run.
86     ModuleHookFn LinkerHook = Hook;
87     Hook = [=](unsigned Task, const Module &M) {
88       // If the linker's hook returned false, we need to pass that result
89       // through.
90       if (LinkerHook && !LinkerHook(Task, M))
91         return false;
92 
93       std::string PathPrefix;
94       // If this is the combined module (not a ThinLTO backend compile) or the
95       // user hasn't requested using the input module's path, emit to a file
96       // named from the provided OutputFileName with the Task ID appended.
97       if (M.getModuleIdentifier() == "ld-temp.o" || !UseInputModulePath) {
98         PathPrefix = OutputFileName;
99         if (Task != (unsigned)-1)
100           PathPrefix += utostr(Task) + ".";
101       } else
102         PathPrefix = M.getModuleIdentifier() + ".";
103       std::string Path = PathPrefix + PathSuffix + ".bc";
104       std::error_code EC;
105       raw_fd_ostream OS(Path, EC, sys::fs::OpenFlags::OF_None);
106       // Because -save-temps is a debugging feature, we report the error
107       // directly and exit.
108       if (EC)
109         reportOpenError(Path, EC.message());
110       WriteBitcodeToFile(M, OS, /*ShouldPreserveUseListOrder=*/false);
111       return true;
112     };
113   };
114 
115   setHook("0.preopt", PreOptModuleHook);
116   setHook("1.promote", PostPromoteModuleHook);
117   setHook("2.internalize", PostInternalizeModuleHook);
118   setHook("3.import", PostImportModuleHook);
119   setHook("4.opt", PostOptModuleHook);
120   setHook("5.precodegen", PreCodeGenModuleHook);
121 
122   CombinedIndexHook =
123       [=](const ModuleSummaryIndex &Index,
124           const DenseSet<GlobalValue::GUID> &GUIDPreservedSymbols) {
125         std::string Path = OutputFileName + "index.bc";
126         std::error_code EC;
127         raw_fd_ostream OS(Path, EC, sys::fs::OpenFlags::OF_None);
128         // Because -save-temps is a debugging feature, we report the error
129         // directly and exit.
130         if (EC)
131           reportOpenError(Path, EC.message());
132         WriteIndexToFile(Index, OS);
133 
134         Path = OutputFileName + "index.dot";
135         raw_fd_ostream OSDot(Path, EC, sys::fs::OpenFlags::OF_None);
136         if (EC)
137           reportOpenError(Path, EC.message());
138         Index.exportToDot(OSDot, GUIDPreservedSymbols);
139         return true;
140       };
141 
142   return Error::success();
143 }
144 
145 #define HANDLE_EXTENSION(Ext)                                                  \
146   llvm::PassPluginLibraryInfo get##Ext##PluginInfo();
147 #include "llvm/Support/Extension.def"
148 
149 static void RegisterPassPlugins(ArrayRef<std::string> PassPlugins,
150                                 PassBuilder &PB) {
151 #define HANDLE_EXTENSION(Ext)                                                  \
152   get##Ext##PluginInfo().RegisterPassBuilderCallbacks(PB);
153 #include "llvm/Support/Extension.def"
154 
155   // Load requested pass plugins and let them register pass builder callbacks
156   for (auto &PluginFN : PassPlugins) {
157     auto PassPlugin = PassPlugin::Load(PluginFN);
158     if (!PassPlugin) {
159       errs() << "Failed to load passes from '" << PluginFN
160              << "'. Request ignored.\n";
161       continue;
162     }
163 
164     PassPlugin->registerPassBuilderCallbacks(PB);
165   }
166 }
167 
168 namespace {
169 
170 std::unique_ptr<TargetMachine>
171 createTargetMachine(const Config &Conf, const Target *TheTarget, Module &M) {
172   StringRef TheTriple = M.getTargetTriple();
173   SubtargetFeatures Features;
174   Features.getDefaultSubtargetFeatures(Triple(TheTriple));
175   for (const std::string &A : Conf.MAttrs)
176     Features.AddFeature(A);
177 
178   Reloc::Model RelocModel;
179   if (Conf.RelocModel)
180     RelocModel = *Conf.RelocModel;
181   else
182     RelocModel =
183         M.getPICLevel() == PICLevel::NotPIC ? Reloc::Static : Reloc::PIC_;
184 
185   Optional<CodeModel::Model> CodeModel;
186   if (Conf.CodeModel)
187     CodeModel = *Conf.CodeModel;
188   else
189     CodeModel = M.getCodeModel();
190 
191   return std::unique_ptr<TargetMachine>(TheTarget->createTargetMachine(
192       TheTriple, Conf.CPU, Features.getString(), Conf.Options, RelocModel,
193       CodeModel, Conf.CGOptLevel));
194 }
195 
196 static void runNewPMPasses(const Config &Conf, Module &Mod, TargetMachine *TM,
197                            unsigned OptLevel, bool IsThinLTO,
198                            ModuleSummaryIndex *ExportSummary,
199                            const ModuleSummaryIndex *ImportSummary) {
200   Optional<PGOOptions> PGOOpt;
201   if (!Conf.SampleProfile.empty())
202     PGOOpt = PGOOptions(Conf.SampleProfile, "", Conf.ProfileRemapping,
203                         PGOOptions::SampleUse, PGOOptions::NoCSAction, true);
204   else if (Conf.RunCSIRInstr) {
205     PGOOpt = PGOOptions("", Conf.CSIRProfile, Conf.ProfileRemapping,
206                         PGOOptions::IRUse, PGOOptions::CSIRInstr);
207   } else if (!Conf.CSIRProfile.empty()) {
208     PGOOpt = PGOOptions(Conf.CSIRProfile, "", Conf.ProfileRemapping,
209                         PGOOptions::IRUse, PGOOptions::CSIRUse);
210   }
211 
212   PassInstrumentationCallbacks PIC;
213   StandardInstrumentations SI(Conf.DebugPassManager);
214   SI.registerCallbacks(PIC);
215   PassBuilder PB(TM, Conf.PTO, PGOOpt, &PIC);
216   AAManager AA;
217 
218   // Parse a custom AA pipeline if asked to.
219   if (auto Err = PB.parseAAPipeline(AA, "default"))
220     report_fatal_error("Error parsing default AA pipeline");
221 
222   RegisterPassPlugins(Conf.PassPlugins, PB);
223 
224   LoopAnalysisManager LAM(Conf.DebugPassManager);
225   FunctionAnalysisManager FAM(Conf.DebugPassManager);
226   CGSCCAnalysisManager CGAM(Conf.DebugPassManager);
227   ModuleAnalysisManager MAM(Conf.DebugPassManager);
228 
229   // Register the AA manager first so that our version is the one used.
230   FAM.registerPass([&] { return std::move(AA); });
231 
232   // Register all the basic analyses with the managers.
233   PB.registerModuleAnalyses(MAM);
234   PB.registerCGSCCAnalyses(CGAM);
235   PB.registerFunctionAnalyses(FAM);
236   PB.registerLoopAnalyses(LAM);
237   PB.crossRegisterProxies(LAM, FAM, CGAM, MAM);
238 
239   ModulePassManager MPM(Conf.DebugPassManager);
240   // FIXME (davide): verify the input.
241 
242   PassBuilder::OptimizationLevel OL;
243 
244   switch (OptLevel) {
245   default:
246     llvm_unreachable("Invalid optimization level");
247   case 0:
248     OL = PassBuilder::OptimizationLevel::O0;
249     break;
250   case 1:
251     OL = PassBuilder::OptimizationLevel::O1;
252     break;
253   case 2:
254     OL = PassBuilder::OptimizationLevel::O2;
255     break;
256   case 3:
257     OL = PassBuilder::OptimizationLevel::O3;
258     break;
259   }
260 
261   if (IsThinLTO)
262     MPM = PB.buildThinLTODefaultPipeline(OL, Conf.DebugPassManager,
263                                          ImportSummary);
264   else
265     MPM = PB.buildLTODefaultPipeline(OL, Conf.DebugPassManager, ExportSummary);
266   MPM.run(Mod, MAM);
267 
268   // FIXME (davide): verify the output.
269 }
270 
271 static void runNewPMCustomPasses(const Config &Conf, Module &Mod,
272                                  TargetMachine *TM, std::string PipelineDesc,
273                                  std::string AAPipelineDesc,
274                                  bool DisableVerify) {
275   PassBuilder PB(TM);
276   AAManager AA;
277 
278   // Parse a custom AA pipeline if asked to.
279   if (!AAPipelineDesc.empty())
280     if (auto Err = PB.parseAAPipeline(AA, AAPipelineDesc))
281       report_fatal_error("unable to parse AA pipeline description '" +
282                          AAPipelineDesc + "': " + toString(std::move(Err)));
283 
284   RegisterPassPlugins(Conf.PassPlugins, PB);
285 
286   LoopAnalysisManager LAM;
287   FunctionAnalysisManager FAM;
288   CGSCCAnalysisManager CGAM;
289   ModuleAnalysisManager MAM;
290 
291   // Register the AA manager first so that our version is the one used.
292   FAM.registerPass([&] { return std::move(AA); });
293 
294   // Register all the basic analyses with the managers.
295   PB.registerModuleAnalyses(MAM);
296   PB.registerCGSCCAnalyses(CGAM);
297   PB.registerFunctionAnalyses(FAM);
298   PB.registerLoopAnalyses(LAM);
299   PB.crossRegisterProxies(LAM, FAM, CGAM, MAM);
300 
301   ModulePassManager MPM;
302 
303   // Always verify the input.
304   MPM.addPass(VerifierPass());
305 
306   // Now, add all the passes we've been requested to.
307   if (auto Err = PB.parsePassPipeline(MPM, PipelineDesc))
308     report_fatal_error("unable to parse pass pipeline description '" +
309                        PipelineDesc + "': " + toString(std::move(Err)));
310 
311   if (!DisableVerify)
312     MPM.addPass(VerifierPass());
313   MPM.run(Mod, MAM);
314 }
315 
316 static void runOldPMPasses(const Config &Conf, Module &Mod, TargetMachine *TM,
317                            bool IsThinLTO, ModuleSummaryIndex *ExportSummary,
318                            const ModuleSummaryIndex *ImportSummary) {
319   legacy::PassManager passes;
320   passes.add(createTargetTransformInfoWrapperPass(TM->getTargetIRAnalysis()));
321 
322   PassManagerBuilder PMB;
323   PMB.LibraryInfo = new TargetLibraryInfoImpl(Triple(TM->getTargetTriple()));
324   PMB.Inliner = createFunctionInliningPass();
325   PMB.ExportSummary = ExportSummary;
326   PMB.ImportSummary = ImportSummary;
327   // Unconditionally verify input since it is not verified before this
328   // point and has unknown origin.
329   PMB.VerifyInput = true;
330   PMB.VerifyOutput = !Conf.DisableVerify;
331   PMB.LoopVectorize = true;
332   PMB.SLPVectorize = true;
333   PMB.OptLevel = Conf.OptLevel;
334   PMB.PGOSampleUse = Conf.SampleProfile;
335   PMB.EnablePGOCSInstrGen = Conf.RunCSIRInstr;
336   if (!Conf.RunCSIRInstr && !Conf.CSIRProfile.empty()) {
337     PMB.EnablePGOCSInstrUse = true;
338     PMB.PGOInstrUse = Conf.CSIRProfile;
339   }
340   if (IsThinLTO)
341     PMB.populateThinLTOPassManager(passes);
342   else
343     PMB.populateLTOPassManager(passes);
344   passes.run(Mod);
345 }
346 
347 bool opt(const Config &Conf, TargetMachine *TM, unsigned Task, Module &Mod,
348          bool IsThinLTO, ModuleSummaryIndex *ExportSummary,
349          const ModuleSummaryIndex *ImportSummary) {
350   // FIXME: Plumb the combined index into the new pass manager.
351   if (!Conf.OptPipeline.empty())
352     runNewPMCustomPasses(Conf, Mod, TM, Conf.OptPipeline, Conf.AAPipeline,
353                          Conf.DisableVerify);
354   else if (Conf.UseNewPM)
355     runNewPMPasses(Conf, Mod, TM, Conf.OptLevel, IsThinLTO, ExportSummary,
356                    ImportSummary);
357   else
358     runOldPMPasses(Conf, Mod, TM, IsThinLTO, ExportSummary, ImportSummary);
359   return !Conf.PostOptModuleHook || Conf.PostOptModuleHook(Task, Mod);
360 }
361 
362 void codegen(const Config &Conf, TargetMachine *TM, AddStreamFn AddStream,
363              unsigned Task, Module &Mod,
364              const ModuleSummaryIndex &CombinedIndex) {
365   if (Conf.PreCodeGenModuleHook && !Conf.PreCodeGenModuleHook(Task, Mod))
366     return;
367 
368   if (EmbedBitcode == LTOBitcodeEmbedding::EmbedOptimized)
369     llvm::EmbedBitcodeInModule(Mod, llvm::MemoryBufferRef(),
370                                /*EmbedBitcode*/ true,
371                                /*EmbedMarker*/ false, /*CmdArgs*/ nullptr);
372 
373   std::unique_ptr<ToolOutputFile> DwoOut;
374   SmallString<1024> DwoFile(Conf.SplitDwarfOutput);
375   if (!Conf.DwoDir.empty()) {
376     std::error_code EC;
377     if (auto EC = llvm::sys::fs::create_directories(Conf.DwoDir))
378       report_fatal_error("Failed to create directory " + Conf.DwoDir + ": " +
379                          EC.message());
380 
381     DwoFile = Conf.DwoDir;
382     sys::path::append(DwoFile, std::to_string(Task) + ".dwo");
383     TM->Options.MCOptions.SplitDwarfFile = std::string(DwoFile);
384   } else
385     TM->Options.MCOptions.SplitDwarfFile = Conf.SplitDwarfFile;
386 
387   if (!DwoFile.empty()) {
388     std::error_code EC;
389     DwoOut = std::make_unique<ToolOutputFile>(DwoFile, EC, sys::fs::OF_None);
390     if (EC)
391       report_fatal_error("Failed to open " + DwoFile + ": " + EC.message());
392   }
393 
394   auto Stream = AddStream(Task);
395   legacy::PassManager CodeGenPasses;
396   CodeGenPasses.add(
397       createImmutableModuleSummaryIndexWrapperPass(&CombinedIndex));
398   if (TM->addPassesToEmitFile(CodeGenPasses, *Stream->OS,
399                               DwoOut ? &DwoOut->os() : nullptr,
400                               Conf.CGFileType))
401     report_fatal_error("Failed to setup codegen");
402   CodeGenPasses.run(Mod);
403 
404   if (DwoOut)
405     DwoOut->keep();
406 }
407 
408 void splitCodeGen(const Config &C, TargetMachine *TM, AddStreamFn AddStream,
409                   unsigned ParallelCodeGenParallelismLevel,
410                   std::unique_ptr<Module> Mod,
411                   const ModuleSummaryIndex &CombinedIndex) {
412   ThreadPool CodegenThreadPool(
413       heavyweight_hardware_concurrency(ParallelCodeGenParallelismLevel));
414   unsigned ThreadCount = 0;
415   const Target *T = &TM->getTarget();
416 
417   SplitModule(
418       std::move(Mod), ParallelCodeGenParallelismLevel,
419       [&](std::unique_ptr<Module> MPart) {
420         // We want to clone the module in a new context to multi-thread the
421         // codegen. We do it by serializing partition modules to bitcode
422         // (while still on the main thread, in order to avoid data races) and
423         // spinning up new threads which deserialize the partitions into
424         // separate contexts.
425         // FIXME: Provide a more direct way to do this in LLVM.
426         SmallString<0> BC;
427         raw_svector_ostream BCOS(BC);
428         WriteBitcodeToFile(*MPart, BCOS);
429 
430         // Enqueue the task
431         CodegenThreadPool.async(
432             [&](const SmallString<0> &BC, unsigned ThreadId) {
433               LTOLLVMContext Ctx(C);
434               Expected<std::unique_ptr<Module>> MOrErr = parseBitcodeFile(
435                   MemoryBufferRef(StringRef(BC.data(), BC.size()), "ld-temp.o"),
436                   Ctx);
437               if (!MOrErr)
438                 report_fatal_error("Failed to read bitcode");
439               std::unique_ptr<Module> MPartInCtx = std::move(MOrErr.get());
440 
441               std::unique_ptr<TargetMachine> TM =
442                   createTargetMachine(C, T, *MPartInCtx);
443 
444               codegen(C, TM.get(), AddStream, ThreadId, *MPartInCtx,
445                       CombinedIndex);
446             },
447             // Pass BC using std::move to ensure that it get moved rather than
448             // copied into the thread's context.
449             std::move(BC), ThreadCount++);
450       },
451       false);
452 
453   // Because the inner lambda (which runs in a worker thread) captures our local
454   // variables, we need to wait for the worker threads to terminate before we
455   // can leave the function scope.
456   CodegenThreadPool.wait();
457 }
458 
459 Expected<const Target *> initAndLookupTarget(const Config &C, Module &Mod) {
460   if (!C.OverrideTriple.empty())
461     Mod.setTargetTriple(C.OverrideTriple);
462   else if (Mod.getTargetTriple().empty())
463     Mod.setTargetTriple(C.DefaultTriple);
464 
465   std::string Msg;
466   const Target *T = TargetRegistry::lookupTarget(Mod.getTargetTriple(), Msg);
467   if (!T)
468     return make_error<StringError>(Msg, inconvertibleErrorCode());
469   return T;
470 }
471 }
472 
473 Error lto::finalizeOptimizationRemarks(
474     std::unique_ptr<ToolOutputFile> DiagOutputFile) {
475   // Make sure we flush the diagnostic remarks file in case the linker doesn't
476   // call the global destructors before exiting.
477   if (!DiagOutputFile)
478     return Error::success();
479   DiagOutputFile->keep();
480   DiagOutputFile->os().flush();
481   return Error::success();
482 }
483 
484 Error lto::backend(const Config &C, AddStreamFn AddStream,
485                    unsigned ParallelCodeGenParallelismLevel,
486                    std::unique_ptr<Module> Mod,
487                    ModuleSummaryIndex &CombinedIndex) {
488   Expected<const Target *> TOrErr = initAndLookupTarget(C, *Mod);
489   if (!TOrErr)
490     return TOrErr.takeError();
491 
492   std::unique_ptr<TargetMachine> TM = createTargetMachine(C, *TOrErr, *Mod);
493 
494   if (!C.CodeGenOnly) {
495     if (!opt(C, TM.get(), 0, *Mod, /*IsThinLTO=*/false,
496              /*ExportSummary=*/&CombinedIndex, /*ImportSummary=*/nullptr))
497       return Error::success();
498   }
499 
500   if (ParallelCodeGenParallelismLevel == 1) {
501     codegen(C, TM.get(), AddStream, 0, *Mod, CombinedIndex);
502   } else {
503     splitCodeGen(C, TM.get(), AddStream, ParallelCodeGenParallelismLevel,
504                  std::move(Mod), CombinedIndex);
505   }
506   return Error::success();
507 }
508 
509 static void dropDeadSymbols(Module &Mod, const GVSummaryMapTy &DefinedGlobals,
510                             const ModuleSummaryIndex &Index) {
511   std::vector<GlobalValue*> DeadGVs;
512   for (auto &GV : Mod.global_values())
513     if (GlobalValueSummary *GVS = DefinedGlobals.lookup(GV.getGUID()))
514       if (!Index.isGlobalValueLive(GVS)) {
515         DeadGVs.push_back(&GV);
516         convertToDeclaration(GV);
517       }
518 
519   // Now that all dead bodies have been dropped, delete the actual objects
520   // themselves when possible.
521   for (GlobalValue *GV : DeadGVs) {
522     GV->removeDeadConstantUsers();
523     // Might reference something defined in native object (i.e. dropped a
524     // non-prevailing IR def, but we need to keep the declaration).
525     if (GV->use_empty())
526       GV->eraseFromParent();
527   }
528 }
529 
530 Error lto::thinBackend(const Config &Conf, unsigned Task, AddStreamFn AddStream,
531                        Module &Mod, const ModuleSummaryIndex &CombinedIndex,
532                        const FunctionImporter::ImportMapTy &ImportList,
533                        const GVSummaryMapTy &DefinedGlobals,
534                        MapVector<StringRef, BitcodeModule> &ModuleMap) {
535   Expected<const Target *> TOrErr = initAndLookupTarget(Conf, Mod);
536   if (!TOrErr)
537     return TOrErr.takeError();
538 
539   std::unique_ptr<TargetMachine> TM = createTargetMachine(Conf, *TOrErr, Mod);
540 
541   // Setup optimization remarks.
542   auto DiagFileOrErr = lto::setupLLVMOptimizationRemarks(
543       Mod.getContext(), Conf.RemarksFilename, Conf.RemarksPasses,
544       Conf.RemarksFormat, Conf.RemarksWithHotness, Task);
545   if (!DiagFileOrErr)
546     return DiagFileOrErr.takeError();
547   auto DiagnosticOutputFile = std::move(*DiagFileOrErr);
548 
549   // Set the partial sample profile ratio in the profile summary module flag of
550   // the module, if applicable.
551   Mod.setPartialSampleProfileRatio(CombinedIndex);
552 
553   if (Conf.CodeGenOnly) {
554     codegen(Conf, TM.get(), AddStream, Task, Mod, CombinedIndex);
555     return finalizeOptimizationRemarks(std::move(DiagnosticOutputFile));
556   }
557 
558   if (Conf.PreOptModuleHook && !Conf.PreOptModuleHook(Task, Mod))
559     return finalizeOptimizationRemarks(std::move(DiagnosticOutputFile));
560 
561   // When linking an ELF shared object, dso_local should be dropped. We
562   // conservatively do this for -fpic.
563   bool ClearDSOLocalOnDeclarations =
564       TM->getTargetTriple().isOSBinFormatELF() &&
565       TM->getRelocationModel() != Reloc::Static &&
566       Mod.getPIELevel() == PIELevel::Default;
567   renameModuleForThinLTO(Mod, CombinedIndex, ClearDSOLocalOnDeclarations);
568 
569   dropDeadSymbols(Mod, DefinedGlobals, CombinedIndex);
570 
571   thinLTOResolvePrevailingInModule(Mod, DefinedGlobals);
572 
573   if (Conf.PostPromoteModuleHook && !Conf.PostPromoteModuleHook(Task, Mod))
574     return finalizeOptimizationRemarks(std::move(DiagnosticOutputFile));
575 
576   if (!DefinedGlobals.empty())
577     thinLTOInternalizeModule(Mod, DefinedGlobals);
578 
579   if (Conf.PostInternalizeModuleHook &&
580       !Conf.PostInternalizeModuleHook(Task, Mod))
581     return finalizeOptimizationRemarks(std::move(DiagnosticOutputFile));
582 
583   auto ModuleLoader = [&](StringRef Identifier) {
584     assert(Mod.getContext().isODRUniquingDebugTypes() &&
585            "ODR Type uniquing should be enabled on the context");
586     auto I = ModuleMap.find(Identifier);
587     assert(I != ModuleMap.end());
588     return I->second.getLazyModule(Mod.getContext(),
589                                    /*ShouldLazyLoadMetadata=*/true,
590                                    /*IsImporting*/ true);
591   };
592 
593   FunctionImporter Importer(CombinedIndex, ModuleLoader,
594                             ClearDSOLocalOnDeclarations);
595   if (Error Err = Importer.importFunctions(Mod, ImportList).takeError())
596     return Err;
597 
598   if (Conf.PostImportModuleHook && !Conf.PostImportModuleHook(Task, Mod))
599     return finalizeOptimizationRemarks(std::move(DiagnosticOutputFile));
600 
601   if (!opt(Conf, TM.get(), Task, Mod, /*IsThinLTO=*/true,
602            /*ExportSummary=*/nullptr, /*ImportSummary=*/&CombinedIndex))
603     return finalizeOptimizationRemarks(std::move(DiagnosticOutputFile));
604 
605   codegen(Conf, TM.get(), AddStream, Task, Mod, CombinedIndex);
606   return finalizeOptimizationRemarks(std::move(DiagnosticOutputFile));
607 }
608