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