1 //===-LTOBackend.cpp - LLVM Link Time Optimizer Backend -------------------===//
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
7 //===----------------------------------------------------------------------===//
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.
14 //===----------------------------------------------------------------------===//
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"
53 #define DEBUG_TYPE "lto-backend"
55 enum class LTOBitcodeEmbedding
{
58 EmbedPostMergePreOptimized
= 2
61 static cl::opt
<LTOBitcodeEmbedding
> EmbedBitcode(
62 "lto-embed-bitcode", cl::init(LTOBitcodeEmbedding::DoNotEmbed
),
63 cl::values(clEnumValN(LTOBitcodeEmbedding::DoNotEmbed
, "none",
65 clEnumValN(LTOBitcodeEmbedding::EmbedOptimized
, "optimized",
66 "Embed after all optimization passes"),
67 clEnumValN(LTOBitcodeEmbedding::EmbedPostMergePreOptimized
,
69 "Embed post merge, but before optimizations")),
70 cl::desc("Embed LLVM bitcode in object files produced by LTO"));
72 static cl::opt
<bool> ThinLTOAssumeMerged(
73 "thinlto-assume-merged", cl::init(false),
74 cl::desc("Assume the input has already undergone ThinLTO function "
75 "importing and the other pre-optimization pipeline changes."));
78 extern cl::opt
<bool> NoPGOWarnMismatch
;
81 [[noreturn
]] static void reportOpenError(StringRef Path
, Twine Msg
) {
82 errs() << "failed to open " << Path
<< ": " << Msg
<< '\n';
87 Error
Config::addSaveTemps(std::string OutputFileName
,
88 bool UseInputModulePath
) {
89 ShouldDiscardValueNames
= false;
93 std::make_unique
<raw_fd_ostream
>(OutputFileName
+ "resolution.txt", EC
,
94 sys::fs::OpenFlags::OF_TextWithCRLF
);
96 ResolutionFile
.reset();
97 return errorCodeToError(EC
);
100 auto setHook
= [&](std::string PathSuffix
, ModuleHookFn
&Hook
) {
101 // Keep track of the hook provided by the linker, which also needs to run.
102 ModuleHookFn LinkerHook
= Hook
;
103 Hook
= [=](unsigned Task
, const Module
&M
) {
104 // If the linker's hook returned false, we need to pass that result
106 if (LinkerHook
&& !LinkerHook(Task
, M
))
109 std::string PathPrefix
;
110 // If this is the combined module (not a ThinLTO backend compile) or the
111 // user hasn't requested using the input module's path, emit to a file
112 // named from the provided OutputFileName with the Task ID appended.
113 if (M
.getModuleIdentifier() == "ld-temp.o" || !UseInputModulePath
) {
114 PathPrefix
= OutputFileName
;
115 if (Task
!= (unsigned)-1)
116 PathPrefix
+= utostr(Task
) + ".";
118 PathPrefix
= M
.getModuleIdentifier() + ".";
119 std::string Path
= PathPrefix
+ PathSuffix
+ ".bc";
121 raw_fd_ostream
OS(Path
, EC
, sys::fs::OpenFlags::OF_None
);
122 // Because -save-temps is a debugging feature, we report the error
123 // directly and exit.
125 reportOpenError(Path
, EC
.message());
126 WriteBitcodeToFile(M
, OS
, /*ShouldPreserveUseListOrder=*/false);
131 setHook("0.preopt", PreOptModuleHook
);
132 setHook("1.promote", PostPromoteModuleHook
);
133 setHook("2.internalize", PostInternalizeModuleHook
);
134 setHook("3.import", PostImportModuleHook
);
135 setHook("4.opt", PostOptModuleHook
);
136 setHook("5.precodegen", PreCodeGenModuleHook
);
139 [=](const ModuleSummaryIndex
&Index
,
140 const DenseSet
<GlobalValue::GUID
> &GUIDPreservedSymbols
) {
141 std::string Path
= OutputFileName
+ "index.bc";
143 raw_fd_ostream
OS(Path
, EC
, sys::fs::OpenFlags::OF_None
);
144 // Because -save-temps is a debugging feature, we report the error
145 // directly and exit.
147 reportOpenError(Path
, EC
.message());
148 WriteIndexToFile(Index
, OS
);
150 Path
= OutputFileName
+ "index.dot";
151 raw_fd_ostream
OSDot(Path
, EC
, sys::fs::OpenFlags::OF_None
);
153 reportOpenError(Path
, EC
.message());
154 Index
.exportToDot(OSDot
, GUIDPreservedSymbols
);
158 return Error::success();
161 #define HANDLE_EXTENSION(Ext) \
162 llvm::PassPluginLibraryInfo get##Ext##PluginInfo();
163 #include "llvm/Support/Extension.def"
165 static void RegisterPassPlugins(ArrayRef
<std::string
> PassPlugins
,
167 #define HANDLE_EXTENSION(Ext) \
168 get##Ext##PluginInfo().RegisterPassBuilderCallbacks(PB);
169 #include "llvm/Support/Extension.def"
171 // Load requested pass plugins and let them register pass builder callbacks
172 for (auto &PluginFN
: PassPlugins
) {
173 auto PassPlugin
= PassPlugin::Load(PluginFN
);
175 errs() << "Failed to load passes from '" << PluginFN
176 << "'. Request ignored.\n";
180 PassPlugin
->registerPassBuilderCallbacks(PB
);
184 static std::unique_ptr
<TargetMachine
>
185 createTargetMachine(const Config
&Conf
, const Target
*TheTarget
, Module
&M
) {
186 StringRef TheTriple
= M
.getTargetTriple();
187 SubtargetFeatures Features
;
188 Features
.getDefaultSubtargetFeatures(Triple(TheTriple
));
189 for (const std::string
&A
: Conf
.MAttrs
)
190 Features
.AddFeature(A
);
192 Optional
<Reloc::Model
> RelocModel
= None
;
194 RelocModel
= *Conf
.RelocModel
;
195 else if (M
.getModuleFlag("PIC Level"))
197 M
.getPICLevel() == PICLevel::NotPIC
? Reloc::Static
: Reloc::PIC_
;
199 Optional
<CodeModel::Model
> CodeModel
;
201 CodeModel
= *Conf
.CodeModel
;
203 CodeModel
= M
.getCodeModel();
205 std::unique_ptr
<TargetMachine
> TM(TheTarget
->createTargetMachine(
206 TheTriple
, Conf
.CPU
, Features
.getString(), Conf
.Options
, RelocModel
,
207 CodeModel
, Conf
.CGOptLevel
));
208 assert(TM
&& "Failed to create target machine");
212 static void runNewPMPasses(const Config
&Conf
, Module
&Mod
, TargetMachine
*TM
,
213 unsigned OptLevel
, bool IsThinLTO
,
214 ModuleSummaryIndex
*ExportSummary
,
215 const ModuleSummaryIndex
*ImportSummary
) {
216 Optional
<PGOOptions
> PGOOpt
;
217 if (!Conf
.SampleProfile
.empty())
218 PGOOpt
= PGOOptions(Conf
.SampleProfile
, "", Conf
.ProfileRemapping
,
219 PGOOptions::SampleUse
, PGOOptions::NoCSAction
, true);
220 else if (Conf
.RunCSIRInstr
) {
221 PGOOpt
= PGOOptions("", Conf
.CSIRProfile
, Conf
.ProfileRemapping
,
222 PGOOptions::IRUse
, PGOOptions::CSIRInstr
,
223 Conf
.AddFSDiscriminator
);
224 } else if (!Conf
.CSIRProfile
.empty()) {
225 PGOOpt
= PGOOptions(Conf
.CSIRProfile
, "", Conf
.ProfileRemapping
,
226 PGOOptions::IRUse
, PGOOptions::CSIRUse
,
227 Conf
.AddFSDiscriminator
);
228 NoPGOWarnMismatch
= !Conf
.PGOWarnMismatch
;
229 } else if (Conf
.AddFSDiscriminator
) {
230 PGOOpt
= PGOOptions("", "", "", PGOOptions::NoAction
,
231 PGOOptions::NoCSAction
, true);
234 TM
->setPGOOption(PGOOpt
);
236 LoopAnalysisManager LAM
;
237 FunctionAnalysisManager FAM
;
238 CGSCCAnalysisManager CGAM
;
239 ModuleAnalysisManager MAM
;
241 PassInstrumentationCallbacks PIC
;
242 StandardInstrumentations
SI(Conf
.DebugPassManager
);
243 SI
.registerCallbacks(PIC
, &FAM
);
244 PassBuilder
PB(TM
, Conf
.PTO
, PGOOpt
, &PIC
);
246 RegisterPassPlugins(Conf
.PassPlugins
, PB
);
248 std::unique_ptr
<TargetLibraryInfoImpl
> TLII(
249 new TargetLibraryInfoImpl(Triple(TM
->getTargetTriple())));
250 if (Conf
.Freestanding
)
251 TLII
->disableAllFunctions();
252 FAM
.registerPass([&] { return TargetLibraryAnalysis(*TLII
); });
255 // Parse a custom AA pipeline if asked to.
256 if (!Conf
.AAPipeline
.empty()) {
257 if (auto Err
= PB
.parseAAPipeline(AA
, Conf
.AAPipeline
)) {
258 report_fatal_error("unable to parse AA pipeline description '" +
259 Conf
.AAPipeline
+ "': " + toString(std::move(Err
)));
262 AA
= PB
.buildDefaultAAPipeline();
264 // Register the AA manager first so that our version is the one used.
265 FAM
.registerPass([&] { return std::move(AA
); });
267 // Register all the basic analyses with the managers.
268 PB
.registerModuleAnalyses(MAM
);
269 PB
.registerCGSCCAnalyses(CGAM
);
270 PB
.registerFunctionAnalyses(FAM
);
271 PB
.registerLoopAnalyses(LAM
);
272 PB
.crossRegisterProxies(LAM
, FAM
, CGAM
, MAM
);
274 ModulePassManager MPM
;
276 if (!Conf
.DisableVerify
)
277 MPM
.addPass(VerifierPass());
279 OptimizationLevel OL
;
283 llvm_unreachable("Invalid optimization level");
285 OL
= OptimizationLevel::O0
;
288 OL
= OptimizationLevel::O1
;
291 OL
= OptimizationLevel::O2
;
294 OL
= OptimizationLevel::O3
;
298 // Parse a custom pipeline if asked to.
299 if (!Conf
.OptPipeline
.empty()) {
300 if (auto Err
= PB
.parsePassPipeline(MPM
, Conf
.OptPipeline
)) {
301 report_fatal_error("unable to parse pass pipeline description '" +
302 Conf
.OptPipeline
+ "': " + toString(std::move(Err
)));
304 } else if (IsThinLTO
) {
305 MPM
.addPass(PB
.buildThinLTODefaultPipeline(OL
, ImportSummary
));
307 MPM
.addPass(PB
.buildLTODefaultPipeline(OL
, ExportSummary
));
310 if (!Conf
.DisableVerify
)
311 MPM
.addPass(VerifierPass());
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()));
322 PassManagerBuilder PMB
;
323 PMB
.LibraryInfo
= new TargetLibraryInfoImpl(Triple(TM
->getTargetTriple()));
324 if (Conf
.Freestanding
)
325 PMB
.LibraryInfo
->disableAllFunctions();
326 PMB
.Inliner
= createFunctionInliningPass();
327 PMB
.ExportSummary
= ExportSummary
;
328 PMB
.ImportSummary
= ImportSummary
;
329 // Unconditionally verify input since it is not verified before this
330 // point and has unknown origin.
331 PMB
.VerifyInput
= true;
332 PMB
.VerifyOutput
= !Conf
.DisableVerify
;
333 PMB
.LoopVectorize
= true;
334 PMB
.SLPVectorize
= true;
335 PMB
.OptLevel
= Conf
.OptLevel
;
336 PMB
.PGOSampleUse
= Conf
.SampleProfile
;
337 PMB
.EnablePGOCSInstrGen
= Conf
.RunCSIRInstr
;
338 if (!Conf
.RunCSIRInstr
&& !Conf
.CSIRProfile
.empty()) {
339 PMB
.EnablePGOCSInstrUse
= true;
340 PMB
.PGOInstrUse
= Conf
.CSIRProfile
;
343 PMB
.populateThinLTOPassManager(passes
);
345 PMB
.populateLTOPassManager(passes
);
349 bool lto::opt(const Config
&Conf
, TargetMachine
*TM
, unsigned Task
, Module
&Mod
,
350 bool IsThinLTO
, ModuleSummaryIndex
*ExportSummary
,
351 const ModuleSummaryIndex
*ImportSummary
,
352 const std::vector
<uint8_t> &CmdArgs
) {
353 if (EmbedBitcode
== LTOBitcodeEmbedding::EmbedPostMergePreOptimized
) {
354 // FIXME: the motivation for capturing post-merge bitcode and command line
355 // is replicating the compilation environment from bitcode, without needing
356 // to understand the dependencies (the functions to be imported). This
357 // assumes a clang - based invocation, case in which we have the command
359 // It's not very clear how the above motivation would map in the
360 // linker-based case, so we currently don't plumb the command line args in
364 dbgs() << "Post-(Thin)LTO merge bitcode embedding was requested, but "
365 "command line arguments are not available");
366 llvm::EmbedBitcodeInModule(Mod
, llvm::MemoryBufferRef(),
367 /*EmbedBitcode*/ true, /*EmbedCmdline*/ true,
368 /*Cmdline*/ CmdArgs
);
370 // FIXME: Plumb the combined index into the new pass manager.
371 if (Conf
.UseNewPM
|| !Conf
.OptPipeline
.empty()) {
372 runNewPMPasses(Conf
, Mod
, TM
, Conf
.OptLevel
, IsThinLTO
, ExportSummary
,
375 runOldPMPasses(Conf
, Mod
, TM
, IsThinLTO
, ExportSummary
, ImportSummary
);
377 return !Conf
.PostOptModuleHook
|| Conf
.PostOptModuleHook(Task
, Mod
);
380 static void codegen(const Config
&Conf
, TargetMachine
*TM
,
381 AddStreamFn AddStream
, unsigned Task
, Module
&Mod
,
382 const ModuleSummaryIndex
&CombinedIndex
) {
383 if (Conf
.PreCodeGenModuleHook
&& !Conf
.PreCodeGenModuleHook(Task
, Mod
))
386 if (EmbedBitcode
== LTOBitcodeEmbedding::EmbedOptimized
)
387 llvm::EmbedBitcodeInModule(Mod
, llvm::MemoryBufferRef(),
388 /*EmbedBitcode*/ true,
389 /*EmbedCmdline*/ false,
390 /*CmdArgs*/ std::vector
<uint8_t>());
392 std::unique_ptr
<ToolOutputFile
> DwoOut
;
393 SmallString
<1024> DwoFile(Conf
.SplitDwarfOutput
);
394 if (!Conf
.DwoDir
.empty()) {
396 if (auto EC
= llvm::sys::fs::create_directories(Conf
.DwoDir
))
397 report_fatal_error("Failed to create directory " + Conf
.DwoDir
+ ": " +
400 DwoFile
= Conf
.DwoDir
;
401 sys::path::append(DwoFile
, std::to_string(Task
) + ".dwo");
402 TM
->Options
.MCOptions
.SplitDwarfFile
= std::string(DwoFile
);
404 TM
->Options
.MCOptions
.SplitDwarfFile
= Conf
.SplitDwarfFile
;
406 if (!DwoFile
.empty()) {
408 DwoOut
= std::make_unique
<ToolOutputFile
>(DwoFile
, EC
, sys::fs::OF_None
);
410 report_fatal_error("Failed to open " + DwoFile
+ ": " + EC
.message());
413 auto Stream
= AddStream(Task
);
414 legacy::PassManager CodeGenPasses
;
416 createImmutableModuleSummaryIndexWrapperPass(&CombinedIndex
));
417 if (Conf
.PreCodeGenPassesHook
)
418 Conf
.PreCodeGenPassesHook(CodeGenPasses
);
419 if (TM
->addPassesToEmitFile(CodeGenPasses
, *Stream
->OS
,
420 DwoOut
? &DwoOut
->os() : nullptr,
422 report_fatal_error("Failed to setup codegen");
423 CodeGenPasses
.run(Mod
);
429 static void splitCodeGen(const Config
&C
, TargetMachine
*TM
,
430 AddStreamFn AddStream
,
431 unsigned ParallelCodeGenParallelismLevel
, Module
&Mod
,
432 const ModuleSummaryIndex
&CombinedIndex
) {
433 ThreadPool
CodegenThreadPool(
434 heavyweight_hardware_concurrency(ParallelCodeGenParallelismLevel
));
435 unsigned ThreadCount
= 0;
436 const Target
*T
= &TM
->getTarget();
439 Mod
, ParallelCodeGenParallelismLevel
,
440 [&](std::unique_ptr
<Module
> MPart
) {
441 // We want to clone the module in a new context to multi-thread the
442 // codegen. We do it by serializing partition modules to bitcode
443 // (while still on the main thread, in order to avoid data races) and
444 // spinning up new threads which deserialize the partitions into
445 // separate contexts.
446 // FIXME: Provide a more direct way to do this in LLVM.
448 raw_svector_ostream
BCOS(BC
);
449 WriteBitcodeToFile(*MPart
, BCOS
);
452 CodegenThreadPool
.async(
453 [&](const SmallString
<0> &BC
, unsigned ThreadId
) {
454 LTOLLVMContext
Ctx(C
);
455 Expected
<std::unique_ptr
<Module
>> MOrErr
= parseBitcodeFile(
456 MemoryBufferRef(StringRef(BC
.data(), BC
.size()), "ld-temp.o"),
459 report_fatal_error("Failed to read bitcode");
460 std::unique_ptr
<Module
> MPartInCtx
= std::move(MOrErr
.get());
462 std::unique_ptr
<TargetMachine
> TM
=
463 createTargetMachine(C
, T
, *MPartInCtx
);
465 codegen(C
, TM
.get(), AddStream
, ThreadId
, *MPartInCtx
,
468 // Pass BC using std::move to ensure that it get moved rather than
469 // copied into the thread's context.
470 std::move(BC
), ThreadCount
++);
474 // Because the inner lambda (which runs in a worker thread) captures our local
475 // variables, we need to wait for the worker threads to terminate before we
476 // can leave the function scope.
477 CodegenThreadPool
.wait();
480 static Expected
<const Target
*> initAndLookupTarget(const Config
&C
,
482 if (!C
.OverrideTriple
.empty())
483 Mod
.setTargetTriple(C
.OverrideTriple
);
484 else if (Mod
.getTargetTriple().empty())
485 Mod
.setTargetTriple(C
.DefaultTriple
);
488 const Target
*T
= TargetRegistry::lookupTarget(Mod
.getTargetTriple(), Msg
);
490 return make_error
<StringError
>(Msg
, inconvertibleErrorCode());
494 Error
lto::finalizeOptimizationRemarks(
495 std::unique_ptr
<ToolOutputFile
> DiagOutputFile
) {
496 // Make sure we flush the diagnostic remarks file in case the linker doesn't
497 // call the global destructors before exiting.
499 return Error::success();
500 DiagOutputFile
->keep();
501 DiagOutputFile
->os().flush();
502 return Error::success();
505 Error
lto::backend(const Config
&C
, AddStreamFn AddStream
,
506 unsigned ParallelCodeGenParallelismLevel
, Module
&Mod
,
507 ModuleSummaryIndex
&CombinedIndex
) {
508 Expected
<const Target
*> TOrErr
= initAndLookupTarget(C
, Mod
);
510 return TOrErr
.takeError();
512 std::unique_ptr
<TargetMachine
> TM
= createTargetMachine(C
, *TOrErr
, Mod
);
514 if (!C
.CodeGenOnly
) {
515 if (!opt(C
, TM
.get(), 0, Mod
, /*IsThinLTO=*/false,
516 /*ExportSummary=*/&CombinedIndex
, /*ImportSummary=*/nullptr,
517 /*CmdArgs*/ std::vector
<uint8_t>()))
518 return Error::success();
521 if (ParallelCodeGenParallelismLevel
== 1) {
522 codegen(C
, TM
.get(), AddStream
, 0, Mod
, CombinedIndex
);
524 splitCodeGen(C
, TM
.get(), AddStream
, ParallelCodeGenParallelismLevel
, Mod
,
527 return Error::success();
530 static void dropDeadSymbols(Module
&Mod
, const GVSummaryMapTy
&DefinedGlobals
,
531 const ModuleSummaryIndex
&Index
) {
532 std::vector
<GlobalValue
*> DeadGVs
;
533 for (auto &GV
: Mod
.global_values())
534 if (GlobalValueSummary
*GVS
= DefinedGlobals
.lookup(GV
.getGUID()))
535 if (!Index
.isGlobalValueLive(GVS
)) {
536 DeadGVs
.push_back(&GV
);
537 convertToDeclaration(GV
);
540 // Now that all dead bodies have been dropped, delete the actual objects
541 // themselves when possible.
542 for (GlobalValue
*GV
: DeadGVs
) {
543 GV
->removeDeadConstantUsers();
544 // Might reference something defined in native object (i.e. dropped a
545 // non-prevailing IR def, but we need to keep the declaration).
547 GV
->eraseFromParent();
551 Error
lto::thinBackend(const Config
&Conf
, unsigned Task
, AddStreamFn AddStream
,
552 Module
&Mod
, const ModuleSummaryIndex
&CombinedIndex
,
553 const FunctionImporter::ImportMapTy
&ImportList
,
554 const GVSummaryMapTy
&DefinedGlobals
,
555 MapVector
<StringRef
, BitcodeModule
> *ModuleMap
,
556 const std::vector
<uint8_t> &CmdArgs
) {
557 Expected
<const Target
*> TOrErr
= initAndLookupTarget(Conf
, Mod
);
559 return TOrErr
.takeError();
561 std::unique_ptr
<TargetMachine
> TM
= createTargetMachine(Conf
, *TOrErr
, Mod
);
563 // Setup optimization remarks.
564 auto DiagFileOrErr
= lto::setupLLVMOptimizationRemarks(
565 Mod
.getContext(), Conf
.RemarksFilename
, Conf
.RemarksPasses
,
566 Conf
.RemarksFormat
, Conf
.RemarksWithHotness
, Conf
.RemarksHotnessThreshold
,
569 return DiagFileOrErr
.takeError();
570 auto DiagnosticOutputFile
= std::move(*DiagFileOrErr
);
572 // Set the partial sample profile ratio in the profile summary module flag of
573 // the module, if applicable.
574 Mod
.setPartialSampleProfileRatio(CombinedIndex
);
576 if (Conf
.CodeGenOnly
) {
577 codegen(Conf
, TM
.get(), AddStream
, Task
, Mod
, CombinedIndex
);
578 return finalizeOptimizationRemarks(std::move(DiagnosticOutputFile
));
581 if (Conf
.PreOptModuleHook
&& !Conf
.PreOptModuleHook(Task
, Mod
))
582 return finalizeOptimizationRemarks(std::move(DiagnosticOutputFile
));
584 auto OptimizeAndCodegen
=
585 [&](Module
&Mod
, TargetMachine
*TM
,
586 std::unique_ptr
<ToolOutputFile
> DiagnosticOutputFile
) {
587 if (!opt(Conf
, TM
, Task
, Mod
, /*IsThinLTO=*/true,
588 /*ExportSummary=*/nullptr, /*ImportSummary=*/&CombinedIndex
,
590 return finalizeOptimizationRemarks(std::move(DiagnosticOutputFile
));
592 codegen(Conf
, TM
, AddStream
, Task
, Mod
, CombinedIndex
);
593 return finalizeOptimizationRemarks(std::move(DiagnosticOutputFile
));
596 if (ThinLTOAssumeMerged
)
597 return OptimizeAndCodegen(Mod
, TM
.get(), std::move(DiagnosticOutputFile
));
599 // When linking an ELF shared object, dso_local should be dropped. We
600 // conservatively do this for -fpic.
601 bool ClearDSOLocalOnDeclarations
=
602 TM
->getTargetTriple().isOSBinFormatELF() &&
603 TM
->getRelocationModel() != Reloc::Static
&&
604 Mod
.getPIELevel() == PIELevel::Default
;
605 renameModuleForThinLTO(Mod
, CombinedIndex
, ClearDSOLocalOnDeclarations
);
607 dropDeadSymbols(Mod
, DefinedGlobals
, CombinedIndex
);
609 thinLTOResolvePrevailingInModule(Mod
, DefinedGlobals
);
611 if (Conf
.PostPromoteModuleHook
&& !Conf
.PostPromoteModuleHook(Task
, Mod
))
612 return finalizeOptimizationRemarks(std::move(DiagnosticOutputFile
));
614 if (!DefinedGlobals
.empty())
615 thinLTOInternalizeModule(Mod
, DefinedGlobals
);
617 if (Conf
.PostInternalizeModuleHook
&&
618 !Conf
.PostInternalizeModuleHook(Task
, Mod
))
619 return finalizeOptimizationRemarks(std::move(DiagnosticOutputFile
));
621 auto ModuleLoader
= [&](StringRef Identifier
) {
622 assert(Mod
.getContext().isODRUniquingDebugTypes() &&
623 "ODR Type uniquing should be enabled on the context");
625 auto I
= ModuleMap
->find(Identifier
);
626 assert(I
!= ModuleMap
->end());
627 return I
->second
.getLazyModule(Mod
.getContext(),
628 /*ShouldLazyLoadMetadata=*/true,
629 /*IsImporting*/ true);
632 ErrorOr
<std::unique_ptr
<llvm::MemoryBuffer
>> MBOrErr
=
633 llvm::MemoryBuffer::getFile(Identifier
);
635 return Expected
<std::unique_ptr
<llvm::Module
>>(make_error
<StringError
>(
636 Twine("Error loading imported file ") + Identifier
+ " : ",
637 MBOrErr
.getError()));
639 Expected
<BitcodeModule
> BMOrErr
= findThinLTOModule(**MBOrErr
);
641 return Expected
<std::unique_ptr
<llvm::Module
>>(make_error
<StringError
>(
642 Twine("Error loading imported file ") + Identifier
+ " : " +
643 toString(BMOrErr
.takeError()),
644 inconvertibleErrorCode()));
646 Expected
<std::unique_ptr
<Module
>> MOrErr
=
647 BMOrErr
->getLazyModule(Mod
.getContext(),
648 /*ShouldLazyLoadMetadata=*/true,
649 /*IsImporting*/ true);
651 (*MOrErr
)->setOwnedMemoryBuffer(std::move(*MBOrErr
));
655 FunctionImporter
Importer(CombinedIndex
, ModuleLoader
,
656 ClearDSOLocalOnDeclarations
);
657 if (Error Err
= Importer
.importFunctions(Mod
, ImportList
).takeError())
660 if (Conf
.PostImportModuleHook
&& !Conf
.PostImportModuleHook(Task
, Mod
))
661 return finalizeOptimizationRemarks(std::move(DiagnosticOutputFile
));
663 return OptimizeAndCodegen(Mod
, TM
.get(), std::move(DiagnosticOutputFile
));
666 BitcodeModule
*lto::findThinLTOModule(MutableArrayRef
<BitcodeModule
> BMs
) {
667 if (ThinLTOAssumeMerged
&& BMs
.size() == 1)
670 for (BitcodeModule
&BM
: BMs
) {
671 Expected
<BitcodeLTOInfo
> LTOInfo
= BM
.getLTOInfo();
672 if (LTOInfo
&& LTOInfo
->IsThinLTO
)
678 Expected
<BitcodeModule
> lto::findThinLTOModule(MemoryBufferRef MBRef
) {
679 Expected
<std::vector
<BitcodeModule
>> BMsOrErr
= getBitcodeModuleList(MBRef
);
681 return BMsOrErr
.takeError();
683 // The bitcode file may contain multiple modules, we want the one that is
684 // marked as being the ThinLTO module.
685 if (const BitcodeModule
*Bm
= lto::findThinLTOModule(*BMsOrErr
))
688 return make_error
<StringError
>("Could not find module summary",
689 inconvertibleErrorCode());
692 bool lto::initImportList(const Module
&M
,
693 const ModuleSummaryIndex
&CombinedIndex
,
694 FunctionImporter::ImportMapTy
&ImportList
) {
695 if (ThinLTOAssumeMerged
)
697 // We can simply import the values mentioned in the combined index, since
698 // we should only invoke this using the individual indexes written out
699 // via a WriteIndexesThinBackend.
700 for (const auto &GlobalList
: CombinedIndex
) {
701 // Ignore entries for undefined references.
702 if (GlobalList
.second
.SummaryList
.empty())
705 auto GUID
= GlobalList
.first
;
706 for (const auto &Summary
: GlobalList
.second
.SummaryList
) {
707 // Skip the summaries for the importing module. These are included to
708 // e.g. record required linkage changes.
709 if (Summary
->modulePath() == M
.getModuleIdentifier())
711 // Add an entry to provoke importing by thinBackend.
712 ImportList
[Summary
->modulePath()].insert(GUID
);