LLVM 19.0.0git
ThinLTOCodeGenerator.cpp
Go to the documentation of this file.
1//===-ThinLTOCodeGenerator.cpp - LLVM Link Time Optimizer -----------------===//
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 Thin Link Time Optimization library. This library is
10// intended to be used by linker to optimize code at link time.
11//
12//===----------------------------------------------------------------------===//
13
16
17#include "llvm/ADT/ScopeExit.h"
18#include "llvm/ADT/Statistic.h"
27#include "llvm/Config/llvm-config.h"
28#include "llvm/IR/DebugInfo.h"
31#include "llvm/IR/LLVMContext.h"
33#include "llvm/IR/Mangler.h"
35#include "llvm/IR/Verifier.h"
37#include "llvm/LTO/LTO.h"
45#include "llvm/Support/Debug.h"
46#include "llvm/Support/Error.h"
48#include "llvm/Support/Path.h"
49#include "llvm/Support/SHA1.h"
63
64#include <numeric>
65
66#if !defined(_MSC_VER) && !defined(__MINGW32__)
67#include <unistd.h>
68#else
69#include <io.h>
70#endif
71
72using namespace llvm;
73
74#define DEBUG_TYPE "thinlto"
75
76namespace llvm {
77// Flags -discard-value-names, defined in LTOCodeGenerator.cpp
85}
86
87namespace {
88
89// Default to using all available threads in the system, but using only one
90// thred per core, as indicated by the usage of
91// heavyweight_hardware_concurrency() below.
92static cl::opt<int> ThreadCount("threads", cl::init(0));
93
94// Simple helper to save temporary files for debug.
95static void saveTempBitcode(const Module &TheModule, StringRef TempDir,
96 unsigned count, StringRef Suffix) {
97 if (TempDir.empty())
98 return;
99 // User asked to save temps, let dump the bitcode file after import.
100 std::string SaveTempPath = (TempDir + llvm::Twine(count) + Suffix).str();
101 std::error_code EC;
102 raw_fd_ostream OS(SaveTempPath, EC, sys::fs::OF_None);
103 if (EC)
104 report_fatal_error(Twine("Failed to open ") + SaveTempPath +
105 " to save optimized bitcode\n");
106 WriteBitcodeToFile(TheModule, OS, /* ShouldPreserveUseListOrder */ true);
107}
108
109static const GlobalValueSummary *
110getFirstDefinitionForLinker(const GlobalValueSummaryList &GVSummaryList) {
111 // If there is any strong definition anywhere, get it.
112 auto StrongDefForLinker = llvm::find_if(
113 GVSummaryList, [](const std::unique_ptr<GlobalValueSummary> &Summary) {
114 auto Linkage = Summary->linkage();
117 });
118 if (StrongDefForLinker != GVSummaryList.end())
119 return StrongDefForLinker->get();
120 // Get the first *linker visible* definition for this global in the summary
121 // list.
122 auto FirstDefForLinker = llvm::find_if(
123 GVSummaryList, [](const std::unique_ptr<GlobalValueSummary> &Summary) {
124 auto Linkage = Summary->linkage();
126 });
127 // Extern templates can be emitted as available_externally.
128 if (FirstDefForLinker == GVSummaryList.end())
129 return nullptr;
130 return FirstDefForLinker->get();
131}
132
133// Populate map of GUID to the prevailing copy for any multiply defined
134// symbols. Currently assume first copy is prevailing, or any strong
135// definition. Can be refined with Linker information in the future.
136static void computePrevailingCopies(
139 auto HasMultipleCopies = [&](const GlobalValueSummaryList &GVSummaryList) {
140 return GVSummaryList.size() > 1;
141 };
142
143 for (auto &I : Index) {
144 if (HasMultipleCopies(I.second.SummaryList))
145 PrevailingCopy[I.first] =
146 getFirstDefinitionForLinker(I.second.SummaryList);
147 }
148}
149
151generateModuleMap(std::vector<std::unique_ptr<lto::InputFile>> &Modules) {
153 for (auto &M : Modules) {
154 LLVM_DEBUG(dbgs() << "Adding module " << M->getName() << " to ModuleMap\n");
155 assert(!ModuleMap.contains(M->getName()) &&
156 "Expect unique Buffer Identifier");
157 ModuleMap[M->getName()] = M.get();
158 }
159 return ModuleMap;
160}
161
162static void promoteModule(Module &TheModule, const ModuleSummaryIndex &Index,
163 bool ClearDSOLocalOnDeclarations) {
164 if (renameModuleForThinLTO(TheModule, Index, ClearDSOLocalOnDeclarations))
165 report_fatal_error("renameModuleForThinLTO failed");
166}
167
168namespace {
169class ThinLTODiagnosticInfo : public DiagnosticInfo {
170 const Twine &Msg;
171public:
172 ThinLTODiagnosticInfo(const Twine &DiagMsg,
173 DiagnosticSeverity Severity = DS_Error)
174 : DiagnosticInfo(DK_Linker, Severity), Msg(DiagMsg) {}
175 void print(DiagnosticPrinter &DP) const override { DP << Msg; }
176};
177}
178
179/// Verify the module and strip broken debug info.
180static void verifyLoadedModule(Module &TheModule) {
181 bool BrokenDebugInfo = false;
182 if (verifyModule(TheModule, &dbgs(), &BrokenDebugInfo))
183 report_fatal_error("Broken module found, compilation aborted!");
184 if (BrokenDebugInfo) {
185 TheModule.getContext().diagnose(ThinLTODiagnosticInfo(
186 "Invalid debug info found, debug info will be stripped", DS_Warning));
187 StripDebugInfo(TheModule);
188 }
189}
190
191static std::unique_ptr<Module> loadModuleFromInput(lto::InputFile *Input,
192 LLVMContext &Context,
193 bool Lazy,
194 bool IsImporting) {
195 auto &Mod = Input->getSingleBitcodeModule();
196 SMDiagnostic Err;
198 Lazy ? Mod.getLazyModule(Context,
199 /* ShouldLazyLoadMetadata */ true, IsImporting)
200 : Mod.parseModule(Context);
201 if (!ModuleOrErr) {
202 handleAllErrors(ModuleOrErr.takeError(), [&](ErrorInfoBase &EIB) {
203 SMDiagnostic Err = SMDiagnostic(Mod.getModuleIdentifier(),
204 SourceMgr::DK_Error, EIB.message());
205 Err.print("ThinLTO", errs());
206 });
207 report_fatal_error("Can't load module, abort.");
208 }
209 if (!Lazy)
210 verifyLoadedModule(*ModuleOrErr.get());
211 return std::move(*ModuleOrErr);
212}
213
214static void
215crossImportIntoModule(Module &TheModule, const ModuleSummaryIndex &Index,
217 const FunctionImporter::ImportMapTy &ImportList,
218 bool ClearDSOLocalOnDeclarations) {
219 auto Loader = [&](StringRef Identifier) {
220 auto &Input = ModuleMap[Identifier];
221 return loadModuleFromInput(Input, TheModule.getContext(),
222 /*Lazy=*/true, /*IsImporting*/ true);
223 };
224
225 FunctionImporter Importer(Index, Loader, ClearDSOLocalOnDeclarations);
226 Expected<bool> Result = Importer.importFunctions(TheModule, ImportList);
227 if (!Result) {
228 handleAllErrors(Result.takeError(), [&](ErrorInfoBase &EIB) {
229 SMDiagnostic Err = SMDiagnostic(TheModule.getModuleIdentifier(),
230 SourceMgr::DK_Error, EIB.message());
231 Err.print("ThinLTO", errs());
232 });
233 report_fatal_error("importFunctions failed");
234 }
235 // Verify again after cross-importing.
236 verifyLoadedModule(TheModule);
237}
238
239static void optimizeModule(Module &TheModule, TargetMachine &TM,
240 unsigned OptLevel, bool Freestanding,
241 bool DebugPassManager, ModuleSummaryIndex *Index) {
242 std::optional<PGOOptions> PGOOpt;
247
249 StandardInstrumentations SI(TheModule.getContext(), DebugPassManager);
250 SI.registerCallbacks(PIC, &MAM);
252 PTO.LoopVectorization = true;
253 PTO.SLPVectorization = true;
254 PassBuilder PB(&TM, PTO, PGOOpt, &PIC);
255
256 std::unique_ptr<TargetLibraryInfoImpl> TLII(
257 new TargetLibraryInfoImpl(Triple(TM.getTargetTriple())));
258 if (Freestanding)
259 TLII->disableAllFunctions();
260 FAM.registerPass([&] { return TargetLibraryAnalysis(*TLII); });
261
262 // Register all the basic analyses with the managers.
268
270
272
273 switch (OptLevel) {
274 default:
275 llvm_unreachable("Invalid optimization level");
276 case 0:
278 break;
279 case 1:
281 break;
282 case 2:
284 break;
285 case 3:
287 break;
288 }
289
291
292 MPM.run(TheModule, MAM);
293}
294
295static void
296addUsedSymbolToPreservedGUID(const lto::InputFile &File,
297 DenseSet<GlobalValue::GUID> &PreservedGUID) {
298 for (const auto &Sym : File.symbols()) {
299 if (Sym.isUsed())
300 PreservedGUID.insert(GlobalValue::getGUID(Sym.getIRName()));
301 }
302}
303
304// Convert the PreservedSymbols map from "Name" based to "GUID" based.
305static void computeGUIDPreservedSymbols(const lto::InputFile &File,
307 const Triple &TheTriple,
309 // Iterate the symbols in the input file and if the input has preserved symbol
310 // compute the GUID for the symbol.
311 for (const auto &Sym : File.symbols()) {
312 if (PreservedSymbols.count(Sym.getName()) && !Sym.getIRName().empty())
314 Sym.getIRName(), GlobalValue::ExternalLinkage, "")));
315 }
316}
317
319computeGUIDPreservedSymbols(const lto::InputFile &File,
321 const Triple &TheTriple) {
322 DenseSet<GlobalValue::GUID> GUIDPreservedSymbols(PreservedSymbols.size());
323 computeGUIDPreservedSymbols(File, PreservedSymbols, TheTriple,
324 GUIDPreservedSymbols);
325 return GUIDPreservedSymbols;
326}
327
328std::unique_ptr<MemoryBuffer> codegenModule(Module &TheModule,
329 TargetMachine &TM) {
331
332 // CodeGen
333 {
336
337 // If the bitcode files contain ARC code and were compiled with optimization,
338 // the ObjCARCContractPass must be run, so do it unconditionally here.
340
341 // Setup the codegen now.
342 if (TM.addPassesToEmitFile(PM, OS, nullptr, CodeGenFileType::ObjectFile,
343 /* DisableVerify */ true))
344 report_fatal_error("Failed to setup codegen");
345
346 // Run codegen now. resulting binary is in OutputBuffer.
347 PM.run(TheModule);
348 }
349 return std::make_unique<SmallVectorMemoryBuffer>(
350 std::move(OutputBuffer), /*RequiresNullTerminator=*/false);
351}
352
353/// Manage caching for a single Module.
354class ModuleCacheEntry {
355 SmallString<128> EntryPath;
356
357public:
358 // Create a cache entry. This compute a unique hash for the Module considering
359 // the current list of export/import, and offer an interface to query to
360 // access the content in the cache.
361 ModuleCacheEntry(
362 StringRef CachePath, const ModuleSummaryIndex &Index, StringRef ModuleID,
363 const FunctionImporter::ImportMapTy &ImportList,
364 const FunctionImporter::ExportSetTy &ExportList,
365 const std::map<GlobalValue::GUID, GlobalValue::LinkageTypes> &ResolvedODR,
366 const GVSummaryMapTy &DefinedGVSummaries, unsigned OptLevel,
367 bool Freestanding, const TargetMachineBuilder &TMBuilder) {
368 if (CachePath.empty())
369 return;
370
371 if (!Index.modulePaths().count(ModuleID))
372 // The module does not have an entry, it can't have a hash at all
373 return;
374
375 if (all_of(Index.getModuleHash(ModuleID),
376 [](uint32_t V) { return V == 0; }))
377 // No hash entry, no caching!
378 return;
379
381 Conf.OptLevel = OptLevel;
382 Conf.Options = TMBuilder.Options;
383 Conf.CPU = TMBuilder.MCpu;
384 Conf.MAttrs.push_back(TMBuilder.MAttr);
385 Conf.RelocModel = TMBuilder.RelocModel;
386 Conf.CGOptLevel = TMBuilder.CGOptLevel;
387 Conf.Freestanding = Freestanding;
389 computeLTOCacheKey(Key, Conf, Index, ModuleID, ImportList, ExportList,
390 ResolvedODR, DefinedGVSummaries);
391
392 // This choice of file name allows the cache to be pruned (see pruneCache()
393 // in include/llvm/Support/CachePruning.h).
394 sys::path::append(EntryPath, CachePath, "llvmcache-" + Key);
395 }
396
397 // Access the path to this entry in the cache.
398 StringRef getEntryPath() { return EntryPath; }
399
400 // Try loading the buffer for this cache entry.
401 ErrorOr<std::unique_ptr<MemoryBuffer>> tryLoadingBuffer() {
402 if (EntryPath.empty())
403 return std::error_code();
404 SmallString<64> ResultPath;
406 Twine(EntryPath), sys::fs::OF_UpdateAtime, &ResultPath);
407 if (!FDOrErr)
408 return errorToErrorCode(FDOrErr.takeError());
410 *FDOrErr, EntryPath, /*FileSize=*/-1, /*RequiresNullTerminator=*/false);
411 sys::fs::closeFile(*FDOrErr);
412 return MBOrErr;
413 }
414
415 // Cache the Produced object file
416 void write(const MemoryBuffer &OutputBuffer) {
417 if (EntryPath.empty())
418 return;
419
420 if (auto Err = llvm::writeToOutput(
421 EntryPath, [&OutputBuffer](llvm::raw_ostream &OS) -> llvm::Error {
423 return llvm::Error::success();
424 }))
425 report_fatal_error(llvm::formatv("ThinLTO: Can't write file {0}: {1}",
426 EntryPath,
427 toString(std::move(Err)).c_str()));
428 }
429};
430
431static std::unique_ptr<MemoryBuffer>
432ProcessThinLTOModule(Module &TheModule, ModuleSummaryIndex &Index,
434 const FunctionImporter::ImportMapTy &ImportList,
435 const FunctionImporter::ExportSetTy &ExportList,
436 const DenseSet<GlobalValue::GUID> &GUIDPreservedSymbols,
437 const GVSummaryMapTy &DefinedGlobals,
438 const ThinLTOCodeGenerator::CachingOptions &CacheOptions,
439 bool DisableCodeGen, StringRef SaveTempsDir,
440 bool Freestanding, unsigned OptLevel, unsigned count,
441 bool DebugPassManager) {
442 // "Benchmark"-like optimization: single-source case
443 bool SingleModule = (ModuleMap.size() == 1);
444
445 // When linking an ELF shared object, dso_local should be dropped. We
446 // conservatively do this for -fpic.
447 bool ClearDSOLocalOnDeclarations =
448 TM.getTargetTriple().isOSBinFormatELF() &&
449 TM.getRelocationModel() != Reloc::Static &&
450 TheModule.getPIELevel() == PIELevel::Default;
451
452 if (!SingleModule) {
453 promoteModule(TheModule, Index, ClearDSOLocalOnDeclarations);
454
455 // Apply summary-based prevailing-symbol resolution decisions.
456 thinLTOFinalizeInModule(TheModule, DefinedGlobals, /*PropagateAttrs=*/true);
457
458 // Save temps: after promotion.
459 saveTempBitcode(TheModule, SaveTempsDir, count, ".1.promoted.bc");
460 }
461
462 // Be friendly and don't nuke totally the module when the client didn't
463 // supply anything to preserve.
464 if (!ExportList.empty() || !GUIDPreservedSymbols.empty()) {
465 // Apply summary-based internalization decisions.
466 thinLTOInternalizeModule(TheModule, DefinedGlobals);
467 }
468
469 // Save internalized bitcode
470 saveTempBitcode(TheModule, SaveTempsDir, count, ".2.internalized.bc");
471
472 if (!SingleModule)
473 crossImportIntoModule(TheModule, Index, ModuleMap, ImportList,
474 ClearDSOLocalOnDeclarations);
475
476 // Do this after any importing so that imported code is updated.
477 // See comment at call to updateVCallVisibilityInIndex() for why
478 // WholeProgramVisibilityEnabledInLTO is false.
480 /* WholeProgramVisibilityEnabledInLTO */ false);
481
482 // Save temps: after cross-module import.
483 saveTempBitcode(TheModule, SaveTempsDir, count, ".3.imported.bc");
484
485 optimizeModule(TheModule, TM, OptLevel, Freestanding, DebugPassManager,
486 &Index);
487
488 saveTempBitcode(TheModule, SaveTempsDir, count, ".4.opt.bc");
489
490 if (DisableCodeGen) {
491 // Configured to stop before CodeGen, serialize the bitcode and return.
493 {
495 ProfileSummaryInfo PSI(TheModule);
496 auto Index = buildModuleSummaryIndex(TheModule, nullptr, &PSI);
497 WriteBitcodeToFile(TheModule, OS, true, &Index);
498 }
499 return std::make_unique<SmallVectorMemoryBuffer>(
500 std::move(OutputBuffer), /*RequiresNullTerminator=*/false);
501 }
502
503 return codegenModule(TheModule, TM);
504}
505
506/// Resolve prevailing symbols. Record resolutions in the \p ResolvedODR map
507/// for caching, and in the \p Index for application during the ThinLTO
508/// backends. This is needed for correctness for exported symbols (ensure
509/// at least one copy kept) and a compile-time optimization (to drop duplicate
510/// copies when possible).
511static void resolvePrevailingInIndex(
513 StringMap<std::map<GlobalValue::GUID, GlobalValue::LinkageTypes>>
514 &ResolvedODR,
515 const DenseSet<GlobalValue::GUID> &GUIDPreservedSymbols,
517 &PrevailingCopy) {
518
519 auto isPrevailing = [&](GlobalValue::GUID GUID, const GlobalValueSummary *S) {
520 const auto &Prevailing = PrevailingCopy.find(GUID);
521 // Not in map means that there was only one copy, which must be prevailing.
522 if (Prevailing == PrevailingCopy.end())
523 return true;
524 return Prevailing->second == S;
525 };
526
527 auto recordNewLinkage = [&](StringRef ModuleIdentifier,
529 GlobalValue::LinkageTypes NewLinkage) {
530 ResolvedODR[ModuleIdentifier][GUID] = NewLinkage;
531 };
532
533 // TODO Conf.VisibilityScheme can be lto::Config::ELF for ELF.
534 lto::Config Conf;
535 thinLTOResolvePrevailingInIndex(Conf, Index, isPrevailing, recordNewLinkage,
536 GUIDPreservedSymbols);
537}
538
539// Initialize the TargetMachine builder for a given Triple
540static void initTMBuilder(TargetMachineBuilder &TMBuilder,
541 const Triple &TheTriple) {
542 if (TMBuilder.MCpu.empty())
543 TMBuilder.MCpu = lto::getThinLTODefaultCPU(TheTriple);
544 TMBuilder.TheTriple = std::move(TheTriple);
545}
546
547} // end anonymous namespace
548
550 MemoryBufferRef Buffer(Data, Identifier);
551
552 auto InputOrError = lto::InputFile::create(Buffer);
553 if (!InputOrError)
554 report_fatal_error(Twine("ThinLTO cannot create input file: ") +
555 toString(InputOrError.takeError()));
556
557 auto TripleStr = (*InputOrError)->getTargetTriple();
558 Triple TheTriple(TripleStr);
559
560 if (Modules.empty())
561 initTMBuilder(TMBuilder, Triple(TheTriple));
562 else if (TMBuilder.TheTriple != TheTriple) {
563 if (!TMBuilder.TheTriple.isCompatibleWith(TheTriple))
564 report_fatal_error("ThinLTO modules with incompatible triples not "
565 "supported");
566 initTMBuilder(TMBuilder, Triple(TMBuilder.TheTriple.merge(TheTriple)));
567 }
568
569 Modules.emplace_back(std::move(*InputOrError));
570}
571
573 PreservedSymbols.insert(Name);
574}
575
577 // FIXME: At the moment, we don't take advantage of this extra information,
578 // we're conservatively considering cross-references as preserved.
579 // CrossReferencedSymbols.insert(Name);
580 PreservedSymbols.insert(Name);
581}
582
583// TargetMachine factory
584std::unique_ptr<TargetMachine> TargetMachineBuilder::create() const {
585 std::string ErrMsg;
586 const Target *TheTarget =
588 if (!TheTarget) {
589 report_fatal_error(Twine("Can't load target for this Triple: ") + ErrMsg);
590 }
591
592 // Use MAttr as the default set of features.
593 SubtargetFeatures Features(MAttr);
595 std::string FeatureStr = Features.getString();
596
597 std::unique_ptr<TargetMachine> TM(
598 TheTarget->createTargetMachine(TheTriple.str(), MCpu, FeatureStr, Options,
599 RelocModel, std::nullopt, CGOptLevel));
600 assert(TM && "Cannot create target machine");
601
602 return TM;
603}
604
605/**
606 * Produce the combined summary index from all the bitcode files:
607 * "thin-link".
608 */
609std::unique_ptr<ModuleSummaryIndex> ThinLTOCodeGenerator::linkCombinedIndex() {
610 std::unique_ptr<ModuleSummaryIndex> CombinedIndex =
611 std::make_unique<ModuleSummaryIndex>(/*HaveGVs=*/false);
612 for (auto &Mod : Modules) {
613 auto &M = Mod->getSingleBitcodeModule();
614 if (Error Err = M.readSummary(*CombinedIndex, Mod->getName())) {
615 // FIXME diagnose
617 std::move(Err), errs(),
618 "error: can't create module summary index for buffer: ");
619 return nullptr;
620 }
621 }
622 return CombinedIndex;
623}
624
625namespace {
626struct IsExported {
628 const DenseSet<GlobalValue::GUID> &GUIDPreservedSymbols;
629
630 IsExported(
632 const DenseSet<GlobalValue::GUID> &GUIDPreservedSymbols)
633 : ExportLists(ExportLists), GUIDPreservedSymbols(GUIDPreservedSymbols) {}
634
635 bool operator()(StringRef ModuleIdentifier, ValueInfo VI) const {
636 const auto &ExportList = ExportLists.find(ModuleIdentifier);
637 return (ExportList != ExportLists.end() && ExportList->second.count(VI)) ||
638 GUIDPreservedSymbols.count(VI.getGUID());
639 }
640};
641
642struct IsPrevailing {
645 &PrevailingCopy)
646 : PrevailingCopy(PrevailingCopy) {}
647
648 bool operator()(GlobalValue::GUID GUID, const GlobalValueSummary *S) const {
649 const auto &Prevailing = PrevailingCopy.find(GUID);
650 // Not in map means that there was only one copy, which must be prevailing.
651 if (Prevailing == PrevailingCopy.end())
652 return true;
653 return Prevailing->second == S;
654 };
655};
656} // namespace
657
660 const DenseSet<GlobalValue::GUID> &GUIDPreservedSymbols) {
661 // We have no symbols resolution available. And can't do any better now in the
662 // case where the prevailing symbol is in a native object. It can be refined
663 // with linker information in the future.
664 auto isPrevailing = [&](GlobalValue::GUID G) {
666 };
667 computeDeadSymbolsWithConstProp(Index, GUIDPreservedSymbols, isPrevailing,
668 /* ImportEnabled = */ true);
669}
670
671/**
672 * Perform promotion and renaming of exported internal functions.
673 * Index is updated to reflect linkage changes from weak resolution.
674 */
676 const lto::InputFile &File) {
677 auto ModuleCount = Index.modulePaths().size();
678 auto ModuleIdentifier = TheModule.getModuleIdentifier();
679
680 // Collect for each module the list of function it defines (GUID -> Summary).
681 DenseMap<StringRef, GVSummaryMapTy> ModuleToDefinedGVSummaries;
682 Index.collectDefinedGVSummariesPerModule(ModuleToDefinedGVSummaries);
683
684 // Convert the preserved symbols set from string to GUID
685 auto GUIDPreservedSymbols = computeGUIDPreservedSymbols(
686 File, PreservedSymbols, Triple(TheModule.getTargetTriple()));
687
688 // Add used symbol to the preserved symbols.
689 addUsedSymbolToPreservedGUID(File, GUIDPreservedSymbols);
690
691 // Compute "dead" symbols, we don't want to import/export these!
692 computeDeadSymbolsInIndex(Index, GUIDPreservedSymbols);
693
694 // Compute prevailing symbols
696 computePrevailingCopies(Index, PrevailingCopy);
697
698 // Generate import/export list
701 ComputeCrossModuleImport(Index, ModuleToDefinedGVSummaries,
702 IsPrevailing(PrevailingCopy), ImportLists,
703 ExportLists);
704
705 // Resolve prevailing symbols
707 resolvePrevailingInIndex(Index, ResolvedODR, GUIDPreservedSymbols,
708 PrevailingCopy);
709
710 thinLTOFinalizeInModule(TheModule,
711 ModuleToDefinedGVSummaries[ModuleIdentifier],
712 /*PropagateAttrs=*/false);
713
714 // Promote the exported values in the index, so that they are promoted
715 // in the module.
717 Index, IsExported(ExportLists, GUIDPreservedSymbols),
718 IsPrevailing(PrevailingCopy));
719
720 // FIXME Set ClearDSOLocalOnDeclarations.
721 promoteModule(TheModule, Index, /*ClearDSOLocalOnDeclarations=*/false);
722}
723
724/**
725 * Perform cross-module importing for the module identified by ModuleIdentifier.
726 */
729 const lto::InputFile &File) {
730 auto ModuleMap = generateModuleMap(Modules);
731 auto ModuleCount = Index.modulePaths().size();
732
733 // Collect for each module the list of function it defines (GUID -> Summary).
734 DenseMap<StringRef, GVSummaryMapTy> ModuleToDefinedGVSummaries(ModuleCount);
735 Index.collectDefinedGVSummariesPerModule(ModuleToDefinedGVSummaries);
736
737 // Convert the preserved symbols set from string to GUID
738 auto GUIDPreservedSymbols = computeGUIDPreservedSymbols(
739 File, PreservedSymbols, Triple(TheModule.getTargetTriple()));
740
741 addUsedSymbolToPreservedGUID(File, GUIDPreservedSymbols);
742
743 // Compute "dead" symbols, we don't want to import/export these!
744 computeDeadSymbolsInIndex(Index, GUIDPreservedSymbols);
745
746 // Compute prevailing symbols
748 computePrevailingCopies(Index, PrevailingCopy);
749
750 // Generate import/export list
753 ComputeCrossModuleImport(Index, ModuleToDefinedGVSummaries,
754 IsPrevailing(PrevailingCopy), ImportLists,
755 ExportLists);
756 auto &ImportList = ImportLists[TheModule.getModuleIdentifier()];
757
758 // FIXME Set ClearDSOLocalOnDeclarations.
759 crossImportIntoModule(TheModule, Index, ModuleMap, ImportList,
760 /*ClearDSOLocalOnDeclarations=*/false);
761}
762
763/**
764 * Compute the list of summaries needed for importing into module.
765 */
767 Module &TheModule, ModuleSummaryIndex &Index,
768 std::map<std::string, GVSummaryMapTy> &ModuleToSummariesForIndex,
769 const lto::InputFile &File) {
770 auto ModuleCount = Index.modulePaths().size();
771 auto ModuleIdentifier = TheModule.getModuleIdentifier();
772
773 // Collect for each module the list of function it defines (GUID -> Summary).
774 DenseMap<StringRef, GVSummaryMapTy> ModuleToDefinedGVSummaries(ModuleCount);
775 Index.collectDefinedGVSummariesPerModule(ModuleToDefinedGVSummaries);
776
777 // Convert the preserved symbols set from string to GUID
778 auto GUIDPreservedSymbols = computeGUIDPreservedSymbols(
779 File, PreservedSymbols, Triple(TheModule.getTargetTriple()));
780
781 addUsedSymbolToPreservedGUID(File, GUIDPreservedSymbols);
782
783 // Compute "dead" symbols, we don't want to import/export these!
784 computeDeadSymbolsInIndex(Index, GUIDPreservedSymbols);
785
786 // Compute prevailing symbols
788 computePrevailingCopies(Index, PrevailingCopy);
789
790 // Generate import/export list
793 ComputeCrossModuleImport(Index, ModuleToDefinedGVSummaries,
794 IsPrevailing(PrevailingCopy), ImportLists,
795 ExportLists);
796
798 ModuleIdentifier, ModuleToDefinedGVSummaries,
799 ImportLists[ModuleIdentifier], ModuleToSummariesForIndex);
800}
801
802/**
803 * Emit the list of files needed for importing into module.
804 */
807 const lto::InputFile &File) {
808 auto ModuleCount = Index.modulePaths().size();
809 auto ModuleIdentifier = TheModule.getModuleIdentifier();
810
811 // Collect for each module the list of function it defines (GUID -> Summary).
812 DenseMap<StringRef, GVSummaryMapTy> ModuleToDefinedGVSummaries(ModuleCount);
813 Index.collectDefinedGVSummariesPerModule(ModuleToDefinedGVSummaries);
814
815 // Convert the preserved symbols set from string to GUID
816 auto GUIDPreservedSymbols = computeGUIDPreservedSymbols(
817 File, PreservedSymbols, Triple(TheModule.getTargetTriple()));
818
819 addUsedSymbolToPreservedGUID(File, GUIDPreservedSymbols);
820
821 // Compute "dead" symbols, we don't want to import/export these!
822 computeDeadSymbolsInIndex(Index, GUIDPreservedSymbols);
823
824 // Compute prevailing symbols
826 computePrevailingCopies(Index, PrevailingCopy);
827
828 // Generate import/export list
831 ComputeCrossModuleImport(Index, ModuleToDefinedGVSummaries,
832 IsPrevailing(PrevailingCopy), ImportLists,
833 ExportLists);
834
835 std::map<std::string, GVSummaryMapTy> ModuleToSummariesForIndex;
837 ModuleIdentifier, ModuleToDefinedGVSummaries,
838 ImportLists[ModuleIdentifier], ModuleToSummariesForIndex);
839
840 std::error_code EC;
841 if ((EC = EmitImportsFiles(ModuleIdentifier, OutputName,
842 ModuleToSummariesForIndex)))
843 report_fatal_error(Twine("Failed to open ") + OutputName +
844 " to save imports lists\n");
845}
846
847/**
848 * Perform internalization. Runs promote and internalization together.
849 * Index is updated to reflect linkage changes.
850 */
853 const lto::InputFile &File) {
854 initTMBuilder(TMBuilder, Triple(TheModule.getTargetTriple()));
855 auto ModuleCount = Index.modulePaths().size();
856 auto ModuleIdentifier = TheModule.getModuleIdentifier();
857
858 // Convert the preserved symbols set from string to GUID
859 auto GUIDPreservedSymbols =
860 computeGUIDPreservedSymbols(File, PreservedSymbols, TMBuilder.TheTriple);
861
862 addUsedSymbolToPreservedGUID(File, GUIDPreservedSymbols);
863
864 // Collect for each module the list of function it defines (GUID -> Summary).
865 DenseMap<StringRef, GVSummaryMapTy> ModuleToDefinedGVSummaries(ModuleCount);
866 Index.collectDefinedGVSummariesPerModule(ModuleToDefinedGVSummaries);
867
868 // Compute "dead" symbols, we don't want to import/export these!
869 computeDeadSymbolsInIndex(Index, GUIDPreservedSymbols);
870
871 // Compute prevailing symbols
873 computePrevailingCopies(Index, PrevailingCopy);
874
875 // Generate import/export list
878 ComputeCrossModuleImport(Index, ModuleToDefinedGVSummaries,
879 IsPrevailing(PrevailingCopy), ImportLists,
880 ExportLists);
881 auto &ExportList = ExportLists[ModuleIdentifier];
882
883 // Be friendly and don't nuke totally the module when the client didn't
884 // supply anything to preserve.
885 if (ExportList.empty() && GUIDPreservedSymbols.empty())
886 return;
887
888 // Resolve prevailing symbols
890 resolvePrevailingInIndex(Index, ResolvedODR, GUIDPreservedSymbols,
891 PrevailingCopy);
892
893 // Promote the exported values in the index, so that they are promoted
894 // in the module.
896 Index, IsExported(ExportLists, GUIDPreservedSymbols),
897 IsPrevailing(PrevailingCopy));
898
899 // FIXME Set ClearDSOLocalOnDeclarations.
900 promoteModule(TheModule, Index, /*ClearDSOLocalOnDeclarations=*/false);
901
902 // Internalization
903 thinLTOFinalizeInModule(TheModule,
904 ModuleToDefinedGVSummaries[ModuleIdentifier],
905 /*PropagateAttrs=*/false);
906
907 thinLTOInternalizeModule(TheModule,
908 ModuleToDefinedGVSummaries[ModuleIdentifier]);
909}
910
911/**
912 * Perform post-importing ThinLTO optimizations.
913 */
915 initTMBuilder(TMBuilder, Triple(TheModule.getTargetTriple()));
916
917 // Optimize now
918 optimizeModule(TheModule, *TMBuilder.create(), OptLevel, Freestanding,
919 DebugPassManager, nullptr);
920}
921
922/// Write out the generated object file, either from CacheEntryPath or from
923/// OutputBuffer, preferring hard-link when possible.
924/// Returns the path to the generated file in SavedObjectsDirectoryPath.
925std::string
927 const MemoryBuffer &OutputBuffer) {
928 auto ArchName = TMBuilder.TheTriple.getArchName();
929 SmallString<128> OutputPath(SavedObjectsDirectoryPath);
930 llvm::sys::path::append(OutputPath,
931 Twine(count) + "." + ArchName + ".thinlto.o");
932 OutputPath.c_str(); // Ensure the string is null terminated.
933 if (sys::fs::exists(OutputPath))
934 sys::fs::remove(OutputPath);
935
936 // We don't return a memory buffer to the linker, just a list of files.
937 if (!CacheEntryPath.empty()) {
938 // Cache is enabled, hard-link the entry (or copy if hard-link fails).
939 auto Err = sys::fs::create_hard_link(CacheEntryPath, OutputPath);
940 if (!Err)
941 return std::string(OutputPath);
942 // Hard linking failed, try to copy.
943 Err = sys::fs::copy_file(CacheEntryPath, OutputPath);
944 if (!Err)
945 return std::string(OutputPath);
946 // Copy failed (could be because the CacheEntry was removed from the cache
947 // in the meantime by another process), fall back and try to write down the
948 // buffer to the output.
949 errs() << "remark: can't link or copy from cached entry '" << CacheEntryPath
950 << "' to '" << OutputPath << "'\n";
951 }
952 // No cache entry, just write out the buffer.
953 std::error_code Err;
954 raw_fd_ostream OS(OutputPath, Err, sys::fs::OF_None);
955 if (Err)
956 report_fatal_error(Twine("Can't open output '") + OutputPath + "'\n");
957 OS << OutputBuffer.getBuffer();
958 return std::string(OutputPath);
959}
960
961// Main entry point for the ThinLTO processing
963 timeTraceProfilerBegin("ThinLink", StringRef(""));
964 auto TimeTraceScopeExit = llvm::make_scope_exit([]() {
967 });
968 // Prepare the resulting object vector
969 assert(ProducedBinaries.empty() && "The generator should not be reused");
970 if (SavedObjectsDirectoryPath.empty())
971 ProducedBinaries.resize(Modules.size());
972 else {
973 sys::fs::create_directories(SavedObjectsDirectoryPath);
974 bool IsDir;
975 sys::fs::is_directory(SavedObjectsDirectoryPath, IsDir);
976 if (!IsDir)
977 report_fatal_error(Twine("Unexistent dir: '") + SavedObjectsDirectoryPath + "'");
978 ProducedBinaryFiles.resize(Modules.size());
979 }
980
981 if (CodeGenOnly) {
982 // Perform only parallel codegen and return.
984 int count = 0;
985 for (auto &Mod : Modules) {
986 Pool.async([&](int count) {
987 LLVMContext Context;
989
990 // Parse module now
991 auto TheModule = loadModuleFromInput(Mod.get(), Context, false,
992 /*IsImporting*/ false);
993
994 // CodeGen
995 auto OutputBuffer = codegenModule(*TheModule, *TMBuilder.create());
996 if (SavedObjectsDirectoryPath.empty())
997 ProducedBinaries[count] = std::move(OutputBuffer);
998 else
999 ProducedBinaryFiles[count] =
1000 writeGeneratedObject(count, "", *OutputBuffer);
1001 }, count++);
1002 }
1003
1004 return;
1005 }
1006
1007 // Sequential linking phase
1008 auto Index = linkCombinedIndex();
1009
1010 // Save temps: index.
1011 if (!SaveTempsDir.empty()) {
1012 auto SaveTempPath = SaveTempsDir + "index.bc";
1013 std::error_code EC;
1014 raw_fd_ostream OS(SaveTempPath, EC, sys::fs::OF_None);
1015 if (EC)
1016 report_fatal_error(Twine("Failed to open ") + SaveTempPath +
1017 " to save optimized bitcode\n");
1019 }
1020
1021
1022 // Prepare the module map.
1023 auto ModuleMap = generateModuleMap(Modules);
1024 auto ModuleCount = Modules.size();
1025
1026 // Collect for each module the list of function it defines (GUID -> Summary).
1027 DenseMap<StringRef, GVSummaryMapTy> ModuleToDefinedGVSummaries(ModuleCount);
1028 Index->collectDefinedGVSummariesPerModule(ModuleToDefinedGVSummaries);
1029
1030 // Convert the preserved symbols set from string to GUID, this is needed for
1031 // computing the caching hash and the internalization.
1032 DenseSet<GlobalValue::GUID> GUIDPreservedSymbols;
1033 for (const auto &M : Modules)
1034 computeGUIDPreservedSymbols(*M, PreservedSymbols, TMBuilder.TheTriple,
1035 GUIDPreservedSymbols);
1036
1037 // Add used symbol from inputs to the preserved symbols.
1038 for (const auto &M : Modules)
1039 addUsedSymbolToPreservedGUID(*M, GUIDPreservedSymbols);
1040
1041 // Compute "dead" symbols, we don't want to import/export these!
1042 computeDeadSymbolsInIndex(*Index, GUIDPreservedSymbols);
1043
1044 // Synthesize entry counts for functions in the combined index.
1046
1047 // Currently there is no support for enabling whole program visibility via a
1048 // linker option in the old LTO API, but this call allows it to be specified
1049 // via the internal option. Must be done before WPD below.
1050 if (hasWholeProgramVisibility(/* WholeProgramVisibilityEnabledInLTO */ false))
1051 Index->setWithWholeProgramVisibility();
1052
1053 // FIXME: This needs linker information via a TBD new interface
1055 /*WholeProgramVisibilityEnabledInLTO=*/false,
1056 // FIXME: These need linker information via a
1057 // TBD new interface.
1058 /*DynamicExportSymbols=*/{},
1059 /*VisibleToRegularObjSymbols=*/{});
1060
1061 // Perform index-based WPD. This will return immediately if there are
1062 // no index entries in the typeIdMetadata map (e.g. if we are instead
1063 // performing IR-based WPD in hybrid regular/thin LTO mode).
1064 std::map<ValueInfo, std::vector<VTableSlotSummary>> LocalWPDTargetsMap;
1065 std::set<GlobalValue::GUID> ExportedGUIDs;
1066 runWholeProgramDevirtOnIndex(*Index, ExportedGUIDs, LocalWPDTargetsMap);
1067 for (auto GUID : ExportedGUIDs)
1068 GUIDPreservedSymbols.insert(GUID);
1069
1070 // Compute prevailing symbols
1072 computePrevailingCopies(*Index, PrevailingCopy);
1073
1074 // Collect the import/export lists for all modules from the call-graph in the
1075 // combined index.
1078 ComputeCrossModuleImport(*Index, ModuleToDefinedGVSummaries,
1079 IsPrevailing(PrevailingCopy), ImportLists,
1080 ExportLists);
1081
1082 // We use a std::map here to be able to have a defined ordering when
1083 // producing a hash for the cache entry.
1084 // FIXME: we should be able to compute the caching hash for the entry based
1085 // on the index, and nuke this map.
1087
1088 // Resolve prevailing symbols, this has to be computed early because it
1089 // impacts the caching.
1090 resolvePrevailingInIndex(*Index, ResolvedODR, GUIDPreservedSymbols,
1091 PrevailingCopy);
1092
1093 // Use global summary-based analysis to identify symbols that can be
1094 // internalized (because they aren't exported or preserved as per callback).
1095 // Changes are made in the index, consumed in the ThinLTO backends.
1097 IsExported(ExportLists, GUIDPreservedSymbols),
1098 LocalWPDTargetsMap);
1100 *Index, IsExported(ExportLists, GUIDPreservedSymbols),
1101 IsPrevailing(PrevailingCopy));
1102
1103 thinLTOPropagateFunctionAttrs(*Index, IsPrevailing(PrevailingCopy));
1104
1105 // Make sure that every module has an entry in the ExportLists, ImportList,
1106 // GVSummary and ResolvedODR maps to enable threaded access to these maps
1107 // below.
1108 for (auto &Module : Modules) {
1109 auto ModuleIdentifier = Module->getName();
1110 ExportLists[ModuleIdentifier];
1111 ImportLists[ModuleIdentifier];
1112 ResolvedODR[ModuleIdentifier];
1113 ModuleToDefinedGVSummaries[ModuleIdentifier];
1114 }
1115
1116 std::vector<BitcodeModule *> ModulesVec;
1117 ModulesVec.reserve(Modules.size());
1118 for (auto &Mod : Modules)
1119 ModulesVec.push_back(&Mod->getSingleBitcodeModule());
1120 std::vector<int> ModulesOrdering = lto::generateModulesOrdering(ModulesVec);
1121
1124
1125 TimeTraceScopeExit.release();
1126
1127 // Parallel optimizer + codegen
1128 {
1130 for (auto IndexCount : ModulesOrdering) {
1131 auto &Mod = Modules[IndexCount];
1132 Pool.async([&](int count) {
1133 auto ModuleIdentifier = Mod->getName();
1134 auto &ExportList = ExportLists[ModuleIdentifier];
1135
1136 auto &DefinedGVSummaries = ModuleToDefinedGVSummaries[ModuleIdentifier];
1137
1138 // The module may be cached, this helps handling it.
1139 ModuleCacheEntry CacheEntry(CacheOptions.Path, *Index, ModuleIdentifier,
1140 ImportLists[ModuleIdentifier], ExportList,
1141 ResolvedODR[ModuleIdentifier],
1142 DefinedGVSummaries, OptLevel, Freestanding,
1143 TMBuilder);
1144 auto CacheEntryPath = CacheEntry.getEntryPath();
1145
1146 {
1147 auto ErrOrBuffer = CacheEntry.tryLoadingBuffer();
1148 LLVM_DEBUG(dbgs() << "Cache " << (ErrOrBuffer ? "hit" : "miss")
1149 << " '" << CacheEntryPath << "' for buffer "
1150 << count << " " << ModuleIdentifier << "\n");
1151
1152 if (ErrOrBuffer) {
1153 // Cache Hit!
1154 if (SavedObjectsDirectoryPath.empty())
1155 ProducedBinaries[count] = std::move(ErrOrBuffer.get());
1156 else
1157 ProducedBinaryFiles[count] = writeGeneratedObject(
1158 count, CacheEntryPath, *ErrOrBuffer.get());
1159 return;
1160 }
1161 }
1162
1163 LLVMContext Context;
1166 auto DiagFileOrErr = lto::setupLLVMOptimizationRemarks(
1169 if (!DiagFileOrErr) {
1170 errs() << "Error: " << toString(DiagFileOrErr.takeError()) << "\n";
1171 report_fatal_error("ThinLTO: Can't get an output file for the "
1172 "remarks");
1173 }
1174
1175 // Parse module now
1176 auto TheModule = loadModuleFromInput(Mod.get(), Context, false,
1177 /*IsImporting*/ false);
1178
1179 // Save temps: original file.
1180 saveTempBitcode(*TheModule, SaveTempsDir, count, ".0.original.bc");
1181
1182 auto &ImportList = ImportLists[ModuleIdentifier];
1183 // Run the main process now, and generates a binary
1184 auto OutputBuffer = ProcessThinLTOModule(
1185 *TheModule, *Index, ModuleMap, *TMBuilder.create(), ImportList,
1186 ExportList, GUIDPreservedSymbols,
1187 ModuleToDefinedGVSummaries[ModuleIdentifier], CacheOptions,
1188 DisableCodeGen, SaveTempsDir, Freestanding, OptLevel, count,
1189 DebugPassManager);
1190
1191 // Commit to the cache (if enabled)
1192 CacheEntry.write(*OutputBuffer);
1193
1194 if (SavedObjectsDirectoryPath.empty()) {
1195 // We need to generated a memory buffer for the linker.
1196 if (!CacheEntryPath.empty()) {
1197 // When cache is enabled, reload from the cache if possible.
1198 // Releasing the buffer from the heap and reloading it from the
1199 // cache file with mmap helps us to lower memory pressure.
1200 // The freed memory can be used for the next input file.
1201 // The final binary link will read from the VFS cache (hopefully!)
1202 // or from disk (if the memory pressure was too high).
1203 auto ReloadedBufferOrErr = CacheEntry.tryLoadingBuffer();
1204 if (auto EC = ReloadedBufferOrErr.getError()) {
1205 // On error, keep the preexisting buffer and print a diagnostic.
1206 errs() << "remark: can't reload cached file '" << CacheEntryPath
1207 << "': " << EC.message() << "\n";
1208 } else {
1209 OutputBuffer = std::move(*ReloadedBufferOrErr);
1210 }
1211 }
1212 ProducedBinaries[count] = std::move(OutputBuffer);
1213 return;
1214 }
1215 ProducedBinaryFiles[count] = writeGeneratedObject(
1216 count, CacheEntryPath, *OutputBuffer);
1217 }, IndexCount);
1218 }
1219 }
1220
1221 pruneCache(CacheOptions.Path, CacheOptions.Policy, ProducedBinaries);
1222
1223 // If statistics were requested, print them out now.
1227}
This file provides a bitcode writing pass.
#define LLVM_DEBUG(X)
Definition: Debug.h:101
std::string Name
Symbol * Sym
Definition: ELF_riscv.cpp:479
Provides passes for computing function attributes based on interprocedural analyses.
This file implements a simple parser to decode commandline option for remarks hotness threshold that ...
static const char * PreservedSymbols[]
Definition: IRSymtab.cpp:48
#define I(x, y, z)
Definition: MD5.cpp:58
#define G(x, y, z)
Definition: MD5.cpp:56
This is the interface to build a ModuleSummaryIndex for a module.
CGSCCAnalysisManager CGAM
ModulePassManager MPM
Module * Mod
LoopAnalysisManager LAM
FunctionAnalysisManager FAM
ModuleAnalysisManager MAM
const char LLVMTargetMachineRef TM
PassInstrumentationCallbacks PIC
PassBuilder PB(Machine, PassOpts->PTO, std::nullopt, &PIC)
This header defines classes/functions to handle pass execution timing information with interfaces for...
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
raw_pwrite_stream & OS
This file defines the make_scope_exit function, which executes user-defined cleanup logic at scope ex...
This header defines a class that provides bookkeeping for all standard (i.e in-tree) pass instrumenta...
This file defines the 'Statistic' class, which is designed to be an easy way to expose various metric...
This file contains some functions that are useful when dealing with strings.
static void computeDeadSymbolsInIndex(ModuleSummaryIndex &Index, const DenseSet< GlobalValue::GUID > &GUIDPreservedSymbols)
char * getBuffer()
Definition: Utility.h:180
A container for analyses that lazily runs them and caches their results.
Definition: PassManager.h:321
bool registerPass(PassBuilderT &&PassBuilder)
Register an analysis pass with the manager.
Definition: PassManager.h:535
iterator find(const_arg_type_t< KeyT > Val)
Definition: DenseMap.h:155
iterator end()
Definition: DenseMap.h:84
void reserve(size_type NumEntries)
Grow the densemap so that it can contain at least NumEntries items before resizing again.
Definition: DenseMap.h:103
Implements a dense probed hash-table based set.
Definition: DenseSet.h:271
This is the base abstract class for diagnostic reporting in the backend.
virtual void print(DiagnosticPrinter &DP) const =0
Print using the given DP a user-friendly message.
Interface for custom diagnostic printing.
Base class for error info classes.
Definition: Error.h:45
Represents either an error or a value T.
Definition: ErrorOr.h:56
Lightweight error class with error context and mandatory checking.
Definition: Error.h:160
static ErrorSuccess success()
Create a success value.
Definition: Error.h:334
Tagged union holding either a T or a Error.
Definition: Error.h:474
Error takeError()
Take ownership of the stored error.
Definition: Error.h:601
reference get()
Returns a reference to the stored T value.
Definition: Error.h:571
The function importer is automatically importing function from other modules based on the provided su...
Function and variable summary information to aid decisions and implementation of importing.
static bool isAvailableExternallyLinkage(LinkageTypes Linkage)
Definition: GlobalValue.h:378
GUID getGUID() const
Return a 64-bit global unique ID constructed from global value name (i.e.
Definition: GlobalValue.h:594
bool isWeakForLinker() const
Definition: GlobalValue.h:551
std::string getGlobalIdentifier() const
Return the modified name for this global value suitable to be used as the key for a global lookup (e....
Definition: Globals.cpp:174
LinkageTypes
An enumeration for the kinds of linkage for global values.
Definition: GlobalValue.h:50
@ ExternalLinkage
Externally visible function.
Definition: GlobalValue.h:51
This is an important class for using LLVM in a threaded context.
Definition: LLVMContext.h:67
void enableDebugTypeODRUniquing()
void diagnose(const DiagnosticInfo &DI)
Report a message to the currently installed diagnostic handler.
void setDiscardValueNames(bool Discard)
Set the Context runtime configuration to discard all value name (but GlobalValue).
This interface provides simple read-only access to a block of memory, and provides simple methods for...
Definition: MemoryBuffer.h:51
static ErrorOr< std::unique_ptr< MemoryBuffer > > getOpenFile(sys::fs::file_t FD, const Twine &Filename, uint64_t FileSize, bool RequiresNullTerminator=true, bool IsVolatile=false, std::optional< Align > Alignment=std::nullopt)
Given an already-open file descriptor, read the file and return a MemoryBuffer.
StringRef getBuffer() const
Definition: MemoryBuffer.h:70
Class to hold module path string table and global value map, and encapsulate methods for operating on...
A Module instance is used to store all the information related to an LLVM module.
Definition: Module.h:65
LLVMContext & getContext() const
Get the global data context.
Definition: Module.h:301
StringRef getName() const
Get a short "name" for the module.
Definition: Module.h:284
const std::string & getTargetTriple() const
Get the target triple which is a string describing the target host.
Definition: Module.h:297
const std::string & getModuleIdentifier() const
Get the module identifier which is, essentially, the name of the module.
Definition: Module.h:267
PIELevel::Level getPIELevel() const
Returns the PIE level (small or large model)
Definition: Module.cpp:611
static const OptimizationLevel O3
Optimize for fast execution as much as possible.
static const OptimizationLevel O0
Disable as many optimizations as possible.
static const OptimizationLevel O2
Optimize for fast execution as much as possible without triggering significant incremental compile ti...
static const OptimizationLevel O1
Optimize quickly without destroying debuggability.
This class provides access to building LLVM's passes.
Definition: PassBuilder.h:105
void registerLoopAnalyses(LoopAnalysisManager &LAM)
Registers all available loop analysis passes.
void crossRegisterProxies(LoopAnalysisManager &LAM, FunctionAnalysisManager &FAM, CGSCCAnalysisManager &CGAM, ModuleAnalysisManager &MAM, MachineFunctionAnalysisManager *MFAM=nullptr)
Cross register the analysis managers through their proxies.
ModulePassManager buildThinLTODefaultPipeline(OptimizationLevel Level, const ModuleSummaryIndex *ImportSummary)
Build a ThinLTO default optimization pipeline to a pass manager.
void registerModuleAnalyses(ModuleAnalysisManager &MAM)
Registers all available module analysis passes.
void registerCGSCCAnalyses(CGSCCAnalysisManager &CGAM)
Registers all available CGSCC analysis passes.
void registerFunctionAnalyses(FunctionAnalysisManager &FAM)
Registers all available function analysis passes.
This class manages callbacks registration, as well as provides a way for PassInstrumentation to pass ...
LLVM_ATTRIBUTE_MINSIZE void addPass(PassT &&Pass)
Definition: PassManager.h:249
PreservedAnalyses run(IRUnitT &IR, AnalysisManagerT &AM, ExtraArgTs... ExtraArgs)
Run all of the passes in this manager over the given unit of IR.
Definition: PassManager.h:201
Tunable parameters for passes in the default pipelines.
Definition: PassBuilder.h:43
bool SLPVectorization
Tuning option to enable/disable slp loop vectorization, set based on opt level.
Definition: PassBuilder.h:58
bool LoopVectorization
Tuning option to enable/disable loop vectorization, set based on opt level.
Definition: PassBuilder.h:54
Analysis providing profile information.
Instances of this class encapsulate one diagnostic report, allowing printing to a raw_ostream as a ca...
Definition: SourceMgr.h:281
A non-threaded implementation.
Definition: ThreadPool.h:218
SmallString - A SmallString is just a SmallVector with methods and accessors that make it work better...
Definition: SmallString.h:26
const char * c_str()
Definition: SmallString.h:259
bool empty() const
Definition: SmallVector.h:94
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Definition: SmallVector.h:1209
This class provides an interface to register all the standard pass instrumentations and manages their...
unsigned size() const
Definition: StringMap.h:104
StringMap - This is an unconventional map that is specialized for handling keys that are "strings",...
Definition: StringMap.h:128
bool contains(StringRef Key) const
contains - Return true if the element is in the map, false otherwise.
Definition: StringMap.h:273
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:50
constexpr bool empty() const
empty - Check if the string is empty.
Definition: StringRef.h:134
StringSet - A wrapper for StringMap that provides set-like functionality.
Definition: StringSet.h:23
std::pair< typename Base::iterator, bool > insert(StringRef key)
Definition: StringSet.h:38
Manages the enabling and disabling of subtarget specific features.
void getDefaultSubtargetFeatures(const Triple &Triple)
Adds the default features for the specified target triple.
std::string getString() const
Returns features as a string.
Analysis pass providing the TargetLibraryInfo.
Implementation of the target library information.
Primary interface to the complete machine description for the target machine.
Definition: TargetMachine.h:76
Target - Wrapper for Target specific information.
TargetMachine * createTargetMachine(StringRef TT, StringRef CPU, StringRef Features, const TargetOptions &Options, std::optional< Reloc::Model > RM, std::optional< CodeModel::Model > CM=std::nullopt, CodeGenOptLevel OL=CodeGenOptLevel::Default, bool JIT=false) const
createTargetMachine - Create a target specific machine implementation for the specified Triple.
void preserveSymbol(StringRef Name)
Adds to a list of all global symbols that must exist in the final generated code.
void run()
Process all the modules that were added to the code generator in parallel.
void crossReferenceSymbol(StringRef Name)
Adds to a list of all global symbols that are cross-referenced between ThinLTO files.
void addModule(StringRef Identifier, StringRef Data)
Add given module to the code generator.
auto async(Function &&F, Args &&...ArgList)
Asynchronous submission of a task to the pool.
Definition: ThreadPool.h:78
Triple - Helper class for working with autoconf configuration names.
Definition: Triple.h:44
const std::string & str() const
Definition: Triple.h:440
std::string merge(const Triple &Other) const
Merge target triples.
Definition: Triple.cpp:2018
StringRef getArchName() const
Get the architecture (first) component of the triple.
Definition: Triple.cpp:1299
bool isCompatibleWith(const Triple &Other) const
Test whether target triples are compatible.
Definition: Triple.cpp:1994
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
Definition: Twine.h:81
std::pair< iterator, bool > insert(const ValueT &V)
Definition: DenseSet.h:206
size_type count(const_arg_type_t< ValueT > V) const
Return 1 if the specified key is in the set, 0 otherwise.
Definition: DenseSet.h:97
PassManager manages ModulePassManagers.
void add(Pass *P) override
Add a pass to the queue of passes to run.
bool run(Module &M)
run - Execute all of the passes scheduled for execution.
An input file.
Definition: LTO.h:111
static Expected< std::unique_ptr< InputFile > > create(MemoryBufferRef Object)
Create an InputFile.
Definition: LTO.cpp:546
BitcodeModule & getSingleBitcodeModule()
Definition: LTO.cpp:579
A raw_ostream that writes to a file descriptor.
Definition: raw_ostream.h:471
This class implements an extremely fast bulk output stream that can only output to a stream.
Definition: raw_ostream.h:52
A raw_ostream that writes to an SmallVector or SmallString.
Definition: raw_ostream.h:691
void optimize(Module &Module)
Perform post-importing ThinLTO optimizations.
std::unique_ptr< ModuleSummaryIndex > linkCombinedIndex()
Produce the combined summary index from all the bitcode files: "thin-link".
void crossModuleImport(Module &Module, ModuleSummaryIndex &Index, const lto::InputFile &File)
Perform cross-module importing for the module identified by ModuleIdentifier.
void emitImports(Module &Module, StringRef OutputName, ModuleSummaryIndex &Index, const lto::InputFile &File)
Compute and emit the imported files for module at ModulePath.
void gatherImportedSummariesForModule(Module &Module, ModuleSummaryIndex &Index, std::map< std::string, GVSummaryMapTy > &ModuleToSummariesForIndex, const lto::InputFile &File)
Compute the list of summaries needed for importing into module.
void internalize(Module &Module, ModuleSummaryIndex &Index, const lto::InputFile &File)
Perform internalization.
void promote(Module &Module, ModuleSummaryIndex &Index, const lto::InputFile &File)
Perform promotion and renaming of exported internal functions, and additionally resolve weak and link...
std::string writeGeneratedObject(int count, StringRef CacheEntryPath, const MemoryBuffer &OutputBuffer)
Write temporary object file to SavedObjectDirectoryPath, write symlink to Cache directory if needed.
Interfaces for registering analysis passes, producing common pass manager configurations,...
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
Key
PAL metadata keys.
initializer< Ty > init(const Ty &Val)
Definition: CommandLine.h:450
std::optional< const char * > toString(const std::optional< DWARFFormValue > &V)
Take an optional DWARFFormValue and try to extract a string value from it.
StringLiteral getThinLTODefaultCPU(const Triple &TheTriple)
Definition: LTO.cpp:1568
std::vector< int > generateModulesOrdering(ArrayRef< BitcodeModule * > R)
Produces a container ordering for optimal multi-threaded processing.
Definition: LTO.cpp:1921
Expected< std::unique_ptr< ToolOutputFile > > setupLLVMOptimizationRemarks(LLVMContext &Context, StringRef RemarksFilename, StringRef RemarksPasses, StringRef RemarksFormat, bool RemarksWithHotness, std::optional< uint64_t > RemarksHotnessThreshold=0, int Count=-1)
Setup optimization remarks.
Definition: LTO.cpp:1877
std::error_code closeFile(file_t &F)
Close the file object.
bool exists(const basic_file_status &status)
Does file exist?
Definition: Path.cpp:1078
@ OF_UpdateAtime
Force files Atime to be updated on access.
Definition: FileSystem.h:783
std::error_code create_hard_link(const Twine &to, const Twine &from)
Create a hard link from from to to, or return an error.
std::error_code remove(const Twine &path, bool IgnoreNonExisting=true)
Remove path.
std::error_code create_directories(const Twine &path, bool IgnoreExisting=true, perms Perms=owner_all|group_all)
Create all the non-existent directories in path.
Definition: Path.cpp:968
std::error_code copy_file(const Twine &From, const Twine &To)
Copy the contents of From to To.
Definition: Path.cpp:1017
Expected< file_t > openNativeFileForRead(const Twine &Name, OpenFlags Flags=OF_None, SmallVectorImpl< char > *RealPath=nullptr)
Opens the file with the given name in a read-only mode, returning its open file descriptor.
bool is_directory(const basic_file_status &status)
Does status represent a directory?
Definition: Path.cpp:1093
void append(SmallVectorImpl< char > &path, const Twine &a, const Twine &b="", const Twine &c="", const Twine &d="")
Append to path.
Definition: Path.cpp:457
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
ThreadPoolStrategy heavyweight_hardware_concurrency(unsigned ThreadCount=0)
Returns a thread strategy for tasks requiring significant memory or other resources.
Definition: Threading.h:162
void logAllUnhandledErrors(Error E, raw_ostream &OS, Twine ErrorBanner={})
Log all errors (if any) in E to OS.
Definition: Error.cpp:65
cl::opt< std::string > RemarksFormat("lto-pass-remarks-format", cl::desc("The format used for serializing remarks (default: YAML)"), cl::value_desc("format"), cl::init("yaml"))
bool all_of(R &&range, UnaryPredicate P)
Provide wrappers to std::all_of which take ranges instead of having to pass begin/end explicitly.
Definition: STLExtras.h:1722
void ComputeCrossModuleImport(const ModuleSummaryIndex &Index, const DenseMap< StringRef, GVSummaryMapTy > &ModuleToDefinedGVSummaries, function_ref< bool(GlobalValue::GUID, const GlobalValueSummary *)> isPrevailing, DenseMap< StringRef, FunctionImporter::ImportMapTy > &ImportLists, DenseMap< StringRef, FunctionImporter::ExportSetTy > &ExportLists)
Compute all the imports and exports for every module in the Index.
cl::opt< bool > LTODiscardValueNames("lto-discard-value-names", cl::desc("Strip names from Value during LTO (other than GlobalValue)."), cl::init(false), cl::Hidden)
void WriteBitcodeToFile(const Module &M, raw_ostream &Out, bool ShouldPreserveUseListOrder=false, const ModuleSummaryIndex *Index=nullptr, bool GenerateHash=false, ModuleHash *ModHash=nullptr)
Write the specified module to the specified raw output stream.
detail::scope_exit< std::decay_t< Callable > > make_scope_exit(Callable &&F)
Definition: ScopeExit.h:59
cl::opt< std::string > RemarksPasses("lto-pass-remarks-filter", cl::desc("Only record optimization remarks from passes whose " "names match the given regular expression"), cl::value_desc("regex"))
void handleAllErrors(Error E, HandlerTs &&... Handlers)
Behaves the same as handleErrors, except that by contract all errors must be handled by the given han...
Definition: Error.h:970
void writeIndexToFile(const ModuleSummaryIndex &Index, raw_ostream &Out, const std::map< std::string, GVSummaryMapTy > *ModuleToSummariesForIndex=nullptr)
Write the specified module summary index to the given raw output stream, where it will be written in ...
SmallVectorImpl< T >::const_pointer c_str(SmallVectorImpl< T > &str)
auto formatv(const char *Fmt, Ts &&...Vals) -> formatv_object< decltype(std::make_tuple(support::detail::build_format_adapter(std::forward< Ts >(Vals))...))>
std::error_code EmitImportsFiles(StringRef ModulePath, StringRef OutputFilename, const std::map< std::string, GVSummaryMapTy > &ModuleToSummariesForIndex)
Emit into OutputFilename the files module ModulePath will import from.
bool thinLTOPropagateFunctionAttrs(ModuleSummaryIndex &Index, function_ref< bool(GlobalValue::GUID, const GlobalValueSummary *)> isPrevailing)
Propagate function attributes for function summaries along the index's callgraph during thinlink.
ModuleSummaryIndex buildModuleSummaryIndex(const Module &M, std::function< BlockFrequencyInfo *(const Function &F)> GetBFICallback, ProfileSummaryInfo *PSI, std::function< const StackSafetyInfo *(const Function &F)> GetSSICallback=[](const Function &F) -> const StackSafetyInfo *{ return nullptr;})
Direct function to compute a ModuleSummaryIndex from a given module.
void reportAndResetTimings(raw_ostream *OutStream=nullptr)
If -time-passes has been specified, report the timings immediately and then reset the timers to zero.
@ DK_Linker
bool hasWholeProgramVisibility(bool WholeProgramVisibilityEnabledInLTO)
bool renameModuleForThinLTO(Module &M, const ModuleSummaryIndex &Index, bool ClearDSOLocalOnDeclarations, SetVector< GlobalValue * > *GlobalsToImport=nullptr)
Perform in-place global value handling on the given Module for exported local functions renamed and p...
void thinLTOInternalizeAndPromoteInIndex(ModuleSummaryIndex &Index, function_ref< bool(StringRef, ValueInfo)> isExported, function_ref< bool(GlobalValue::GUID, const GlobalValueSummary *)> isPrevailing)
Update the linkages in the given Index to mark exported values as external and non-exported values as...
Definition: LTO.cpp:533
void computeLTOCacheKey(SmallString< 40 > &Key, const lto::Config &Conf, const ModuleSummaryIndex &Index, StringRef ModuleID, const FunctionImporter::ImportMapTy &ImportList, const FunctionImporter::ExportSetTy &ExportList, const std::map< GlobalValue::GUID, GlobalValue::LinkageTypes > &ResolvedODR, const GVSummaryMapTy &DefinedGlobals, const std::set< GlobalValue::GUID > &CfiFunctionDefs={}, const std::set< GlobalValue::GUID > &CfiFunctionDecls={})
Computes a unique hash for the Module considering the current list of export/import and other global ...
Definition: LTO.cpp:89
void updatePublicTypeTestCalls(Module &M, bool WholeProgramVisibilityEnabledInLTO)
Error write(MCStreamer &Out, ArrayRef< std::string > Inputs, OnCuIndexOverflow OverflowOptValue)
Definition: DWP.cpp:601
bool timeTraceProfilerEnabled()
Is the time trace profiler enabled, i.e. initialized?
Definition: TimeProfiler.h:104
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition: Debug.cpp:163
void report_fatal_error(Error Err, bool gen_crash_diag=true)
Report a serious error, calling any installed error handler.
Definition: Error.cpp:159
Error writeToOutput(StringRef OutputFileName, std::function< Error(raw_ostream &)> Write)
This helper creates an output stream and then passes it to Write.
bool AreStatisticsEnabled()
Check if statistics are enabled.
Definition: Statistic.cpp:139
cl::opt< bool > RemarksWithHotness("lto-pass-remarks-with-hotness", cl::desc("With PGO, include profile count in optimization remarks"), cl::Hidden)
void computeSyntheticCounts(ModuleSummaryIndex &Index)
Compute synthetic function entry counts.
void timeTraceProfilerEnd()
Manually end the last time section.
cl::opt< std::string > RemarksFilename("lto-pass-remarks-output", cl::desc("Output filename for pass remarks"), cl::value_desc("filename"))
void updateIndexWPDForExports(ModuleSummaryIndex &Summary, function_ref< bool(StringRef, ValueInfo)> isExported, std::map< ValueInfo, std::vector< VTableSlotSummary > > &LocalWPDTargetsMap)
Call after cross-module importing to update the recorded single impl devirt target names for any loca...
void thinLTOResolvePrevailingInIndex(const lto::Config &C, ModuleSummaryIndex &Index, function_ref< bool(GlobalValue::GUID, const GlobalValueSummary *)> isPrevailing, function_ref< void(StringRef, GlobalValue::GUID, GlobalValue::LinkageTypes)> recordNewLinkage, const DenseSet< GlobalValue::GUID > &GUIDPreservedSymbols)
Resolve linkage for prevailing symbols in the Index.
Definition: LTO.cpp:432
std::vector< std::unique_ptr< GlobalValueSummary > > GlobalValueSummaryList
void gatherImportedSummariesForModule(StringRef ModulePath, const DenseMap< StringRef, GVSummaryMapTy > &ModuleToDefinedGVSummaries, const FunctionImporter::ImportMapTy &ImportList, std::map< std::string, GVSummaryMapTy > &ModuleToSummariesForIndex)
Compute the set of summaries needed for a ThinLTO backend compilation of ModulePath.
raw_fd_ostream & errs()
This returns a reference to a raw_ostream for standard error.
bool StripDebugInfo(Module &M)
Strip debug info in the module if it exists.
Definition: DebugInfo.cpp:591
@ Mod
The access may modify the value stored in memory.
void PrintStatistics()
Print statistics to the file returned by CreateInfoOutputFile().
Definition: Statistic.cpp:229
void runWholeProgramDevirtOnIndex(ModuleSummaryIndex &Summary, std::set< GlobalValue::GUID > &ExportedGUIDs, std::map< ValueInfo, std::vector< VTableSlotSummary > > &LocalWPDTargetsMap)
Perform index-based whole program devirtualization on the Summary index.
bool pruneCache(StringRef Path, CachePruningPolicy Policy, const std::vector< std::unique_ptr< MemoryBuffer > > &Files={})
Peform pruning using the supplied policy, returns true if pruning occurred, i.e.
void thinLTOInternalizeModule(Module &TheModule, const GVSummaryMapTy &DefinedGlobals)
Internalize TheModule based on the information recorded in the summaries during global summary-based ...
auto count(R &&Range, const E &Element)
Wrapper function around std::count to count the number of times an element Element occurs in the give...
Definition: STLExtras.h:1914
DiagnosticSeverity
Defines the different supported severity of a diagnostic.
@ DS_Warning
@ DS_Error
cl::opt< std::optional< uint64_t >, false, remarks::HotnessThresholdParser > RemarksHotnessThreshold("lto-pass-remarks-hotness-threshold", cl::desc("Minimum profile count required for an " "optimization remark to be output." " Use 'auto' to apply the threshold from profile summary."), cl::value_desc("uint or 'auto'"), cl::init(0), cl::Hidden)
auto find_if(R &&Range, UnaryPredicate P)
Provide wrappers to std::find_if which take ranges instead of having to pass begin/end explicitly.
Definition: STLExtras.h:1749
Pass * createObjCARCContractPass()
std::error_code errorToErrorCode(Error Err)
Helper for converting an ECError to a std::error_code.
Definition: Error.cpp:109
void computeDeadSymbolsWithConstProp(ModuleSummaryIndex &Index, const DenseSet< GlobalValue::GUID > &GUIDPreservedSymbols, function_ref< PrevailingType(GlobalValue::GUID)> isPrevailing, bool ImportEnabled)
Compute dead symbols and run constant propagation in combined index after that.
bool verifyModule(const Module &M, raw_ostream *OS=nullptr, bool *BrokenDebugInfo=nullptr)
Check a module for errors.
Definition: Verifier.cpp:7097
TimeTraceProfilerEntry * timeTraceProfilerBegin(StringRef Name, StringRef Detail)
Manually begin a time section, with the given Name and Detail.
void updateVCallVisibilityInIndex(ModuleSummaryIndex &Index, bool WholeProgramVisibilityEnabledInLTO, const DenseSet< GlobalValue::GUID > &DynamicExportSymbols, const DenseSet< GlobalValue::GUID > &VisibleToRegularObjSymbols)
If whole program visibility asserted, then upgrade all public vcall visibility metadata on vtable def...
void thinLTOFinalizeInModule(Module &TheModule, const GVSummaryMapTy &DefinedGlobals, bool PropagateAttrs)
Based on the information recorded in the summaries during global summary-based analysis:
Helper to gather options relevant to the target machine creation.
std::unique_ptr< TargetMachine > create() const
std::optional< Reloc::Model > RelocModel
static const Target * lookupTarget(StringRef Triple, std::string &Error)
lookupTarget - Lookup a target based on a target triple.
Struct that holds a reference to a particular GUID in a global value summary.
LTO configuration.
Definition: Config.h:41
std::vector< std::string > MAttrs
Definition: Config.h:50
CodeGenOptLevel CGOptLevel
Definition: Config.h:57
std::string CPU
Definition: Config.h:48
TargetOptions Options
Definition: Config.h:49
unsigned OptLevel
Definition: Config.h:59
std::optional< Reloc::Model > RelocModel
Definition: Config.h:55
bool Freestanding
Flag to indicate that the optimizer should not assume builtins are present on the target.
Definition: Config.h:65