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 // Set a default CPU for Darwin triples (copied from LTOCodeGenerator).
543 // FIXME this looks pretty terrible...
544 if (TMBuilder.MCpu.empty() && TheTriple.isOSDarwin()) {
545 if (TheTriple.getArch() == llvm::Triple::x86_64)
546 TMBuilder.MCpu = "core2";
547 else if (TheTriple.getArch() == llvm::Triple::x86)
548 TMBuilder.MCpu = "yonah";
549 else if (TheTriple.getArch() == llvm::Triple::aarch64 ||
550 TheTriple.getArch() == llvm::Triple::aarch64_32)
551 TMBuilder.MCpu = "cyclone";
552 }
553 TMBuilder.TheTriple = std::move(TheTriple);
554}
555
556} // end anonymous namespace
557
559 MemoryBufferRef Buffer(Data, Identifier);
560
561 auto InputOrError = lto::InputFile::create(Buffer);
562 if (!InputOrError)
563 report_fatal_error(Twine("ThinLTO cannot create input file: ") +
564 toString(InputOrError.takeError()));
565
566 auto TripleStr = (*InputOrError)->getTargetTriple();
567 Triple TheTriple(TripleStr);
568
569 if (Modules.empty())
570 initTMBuilder(TMBuilder, Triple(TheTriple));
571 else if (TMBuilder.TheTriple != TheTriple) {
572 if (!TMBuilder.TheTriple.isCompatibleWith(TheTriple))
573 report_fatal_error("ThinLTO modules with incompatible triples not "
574 "supported");
575 initTMBuilder(TMBuilder, Triple(TMBuilder.TheTriple.merge(TheTriple)));
576 }
577
578 Modules.emplace_back(std::move(*InputOrError));
579}
580
582 PreservedSymbols.insert(Name);
583}
584
586 // FIXME: At the moment, we don't take advantage of this extra information,
587 // we're conservatively considering cross-references as preserved.
588 // CrossReferencedSymbols.insert(Name);
589 PreservedSymbols.insert(Name);
590}
591
592// TargetMachine factory
593std::unique_ptr<TargetMachine> TargetMachineBuilder::create() const {
594 std::string ErrMsg;
595 const Target *TheTarget =
597 if (!TheTarget) {
598 report_fatal_error(Twine("Can't load target for this Triple: ") + ErrMsg);
599 }
600
601 // Use MAttr as the default set of features.
602 SubtargetFeatures Features(MAttr);
604 std::string FeatureStr = Features.getString();
605
606 std::unique_ptr<TargetMachine> TM(
607 TheTarget->createTargetMachine(TheTriple.str(), MCpu, FeatureStr, Options,
608 RelocModel, std::nullopt, CGOptLevel));
609 assert(TM && "Cannot create target machine");
610
611 return TM;
612}
613
614/**
615 * Produce the combined summary index from all the bitcode files:
616 * "thin-link".
617 */
618std::unique_ptr<ModuleSummaryIndex> ThinLTOCodeGenerator::linkCombinedIndex() {
619 std::unique_ptr<ModuleSummaryIndex> CombinedIndex =
620 std::make_unique<ModuleSummaryIndex>(/*HaveGVs=*/false);
621 for (auto &Mod : Modules) {
622 auto &M = Mod->getSingleBitcodeModule();
623 if (Error Err = M.readSummary(*CombinedIndex, Mod->getName())) {
624 // FIXME diagnose
626 std::move(Err), errs(),
627 "error: can't create module summary index for buffer: ");
628 return nullptr;
629 }
630 }
631 return CombinedIndex;
632}
633
634namespace {
635struct IsExported {
637 const DenseSet<GlobalValue::GUID> &GUIDPreservedSymbols;
638
639 IsExported(
641 const DenseSet<GlobalValue::GUID> &GUIDPreservedSymbols)
642 : ExportLists(ExportLists), GUIDPreservedSymbols(GUIDPreservedSymbols) {}
643
644 bool operator()(StringRef ModuleIdentifier, ValueInfo VI) const {
645 const auto &ExportList = ExportLists.find(ModuleIdentifier);
646 return (ExportList != ExportLists.end() && ExportList->second.count(VI)) ||
647 GUIDPreservedSymbols.count(VI.getGUID());
648 }
649};
650
651struct IsPrevailing {
654 &PrevailingCopy)
655 : PrevailingCopy(PrevailingCopy) {}
656
657 bool operator()(GlobalValue::GUID GUID, const GlobalValueSummary *S) const {
658 const auto &Prevailing = PrevailingCopy.find(GUID);
659 // Not in map means that there was only one copy, which must be prevailing.
660 if (Prevailing == PrevailingCopy.end())
661 return true;
662 return Prevailing->second == S;
663 };
664};
665} // namespace
666
669 const DenseSet<GlobalValue::GUID> &GUIDPreservedSymbols) {
670 // We have no symbols resolution available. And can't do any better now in the
671 // case where the prevailing symbol is in a native object. It can be refined
672 // with linker information in the future.
673 auto isPrevailing = [&](GlobalValue::GUID G) {
675 };
676 computeDeadSymbolsWithConstProp(Index, GUIDPreservedSymbols, isPrevailing,
677 /* ImportEnabled = */ true);
678}
679
680/**
681 * Perform promotion and renaming of exported internal functions.
682 * Index is updated to reflect linkage changes from weak resolution.
683 */
685 const lto::InputFile &File) {
686 auto ModuleCount = Index.modulePaths().size();
687 auto ModuleIdentifier = TheModule.getModuleIdentifier();
688
689 // Collect for each module the list of function it defines (GUID -> Summary).
690 DenseMap<StringRef, GVSummaryMapTy> ModuleToDefinedGVSummaries;
691 Index.collectDefinedGVSummariesPerModule(ModuleToDefinedGVSummaries);
692
693 // Convert the preserved symbols set from string to GUID
694 auto GUIDPreservedSymbols = computeGUIDPreservedSymbols(
695 File, PreservedSymbols, Triple(TheModule.getTargetTriple()));
696
697 // Add used symbol to the preserved symbols.
698 addUsedSymbolToPreservedGUID(File, GUIDPreservedSymbols);
699
700 // Compute "dead" symbols, we don't want to import/export these!
701 computeDeadSymbolsInIndex(Index, GUIDPreservedSymbols);
702
703 // Compute prevailing symbols
705 computePrevailingCopies(Index, PrevailingCopy);
706
707 // Generate import/export list
710 ComputeCrossModuleImport(Index, ModuleToDefinedGVSummaries,
711 IsPrevailing(PrevailingCopy), ImportLists,
712 ExportLists);
713
714 // Resolve prevailing symbols
716 resolvePrevailingInIndex(Index, ResolvedODR, GUIDPreservedSymbols,
717 PrevailingCopy);
718
719 thinLTOFinalizeInModule(TheModule,
720 ModuleToDefinedGVSummaries[ModuleIdentifier],
721 /*PropagateAttrs=*/false);
722
723 // Promote the exported values in the index, so that they are promoted
724 // in the module.
726 Index, IsExported(ExportLists, GUIDPreservedSymbols),
727 IsPrevailing(PrevailingCopy));
728
729 // FIXME Set ClearDSOLocalOnDeclarations.
730 promoteModule(TheModule, Index, /*ClearDSOLocalOnDeclarations=*/false);
731}
732
733/**
734 * Perform cross-module importing for the module identified by ModuleIdentifier.
735 */
738 const lto::InputFile &File) {
739 auto ModuleMap = generateModuleMap(Modules);
740 auto ModuleCount = Index.modulePaths().size();
741
742 // Collect for each module the list of function it defines (GUID -> Summary).
743 DenseMap<StringRef, GVSummaryMapTy> ModuleToDefinedGVSummaries(ModuleCount);
744 Index.collectDefinedGVSummariesPerModule(ModuleToDefinedGVSummaries);
745
746 // Convert the preserved symbols set from string to GUID
747 auto GUIDPreservedSymbols = computeGUIDPreservedSymbols(
748 File, PreservedSymbols, Triple(TheModule.getTargetTriple()));
749
750 addUsedSymbolToPreservedGUID(File, GUIDPreservedSymbols);
751
752 // Compute "dead" symbols, we don't want to import/export these!
753 computeDeadSymbolsInIndex(Index, GUIDPreservedSymbols);
754
755 // Compute prevailing symbols
757 computePrevailingCopies(Index, PrevailingCopy);
758
759 // Generate import/export list
762 ComputeCrossModuleImport(Index, ModuleToDefinedGVSummaries,
763 IsPrevailing(PrevailingCopy), ImportLists,
764 ExportLists);
765 auto &ImportList = ImportLists[TheModule.getModuleIdentifier()];
766
767 // FIXME Set ClearDSOLocalOnDeclarations.
768 crossImportIntoModule(TheModule, Index, ModuleMap, ImportList,
769 /*ClearDSOLocalOnDeclarations=*/false);
770}
771
772/**
773 * Compute the list of summaries needed for importing into module.
774 */
776 Module &TheModule, ModuleSummaryIndex &Index,
777 std::map<std::string, GVSummaryMapTy> &ModuleToSummariesForIndex,
778 const lto::InputFile &File) {
779 auto ModuleCount = Index.modulePaths().size();
780 auto ModuleIdentifier = TheModule.getModuleIdentifier();
781
782 // Collect for each module the list of function it defines (GUID -> Summary).
783 DenseMap<StringRef, GVSummaryMapTy> ModuleToDefinedGVSummaries(ModuleCount);
784 Index.collectDefinedGVSummariesPerModule(ModuleToDefinedGVSummaries);
785
786 // Convert the preserved symbols set from string to GUID
787 auto GUIDPreservedSymbols = computeGUIDPreservedSymbols(
788 File, PreservedSymbols, Triple(TheModule.getTargetTriple()));
789
790 addUsedSymbolToPreservedGUID(File, GUIDPreservedSymbols);
791
792 // Compute "dead" symbols, we don't want to import/export these!
793 computeDeadSymbolsInIndex(Index, GUIDPreservedSymbols);
794
795 // Compute prevailing symbols
797 computePrevailingCopies(Index, PrevailingCopy);
798
799 // Generate import/export list
802 ComputeCrossModuleImport(Index, ModuleToDefinedGVSummaries,
803 IsPrevailing(PrevailingCopy), ImportLists,
804 ExportLists);
805
807 ModuleIdentifier, ModuleToDefinedGVSummaries,
808 ImportLists[ModuleIdentifier], ModuleToSummariesForIndex);
809}
810
811/**
812 * Emit the list of files needed for importing into module.
813 */
816 const lto::InputFile &File) {
817 auto ModuleCount = Index.modulePaths().size();
818 auto ModuleIdentifier = TheModule.getModuleIdentifier();
819
820 // Collect for each module the list of function it defines (GUID -> Summary).
821 DenseMap<StringRef, GVSummaryMapTy> ModuleToDefinedGVSummaries(ModuleCount);
822 Index.collectDefinedGVSummariesPerModule(ModuleToDefinedGVSummaries);
823
824 // Convert the preserved symbols set from string to GUID
825 auto GUIDPreservedSymbols = computeGUIDPreservedSymbols(
826 File, PreservedSymbols, Triple(TheModule.getTargetTriple()));
827
828 addUsedSymbolToPreservedGUID(File, GUIDPreservedSymbols);
829
830 // Compute "dead" symbols, we don't want to import/export these!
831 computeDeadSymbolsInIndex(Index, GUIDPreservedSymbols);
832
833 // Compute prevailing symbols
835 computePrevailingCopies(Index, PrevailingCopy);
836
837 // Generate import/export list
840 ComputeCrossModuleImport(Index, ModuleToDefinedGVSummaries,
841 IsPrevailing(PrevailingCopy), ImportLists,
842 ExportLists);
843
844 std::map<std::string, GVSummaryMapTy> ModuleToSummariesForIndex;
846 ModuleIdentifier, ModuleToDefinedGVSummaries,
847 ImportLists[ModuleIdentifier], ModuleToSummariesForIndex);
848
849 std::error_code EC;
850 if ((EC = EmitImportsFiles(ModuleIdentifier, OutputName,
851 ModuleToSummariesForIndex)))
852 report_fatal_error(Twine("Failed to open ") + OutputName +
853 " to save imports lists\n");
854}
855
856/**
857 * Perform internalization. Runs promote and internalization together.
858 * Index is updated to reflect linkage changes.
859 */
862 const lto::InputFile &File) {
863 initTMBuilder(TMBuilder, Triple(TheModule.getTargetTriple()));
864 auto ModuleCount = Index.modulePaths().size();
865 auto ModuleIdentifier = TheModule.getModuleIdentifier();
866
867 // Convert the preserved symbols set from string to GUID
868 auto GUIDPreservedSymbols =
869 computeGUIDPreservedSymbols(File, PreservedSymbols, TMBuilder.TheTriple);
870
871 addUsedSymbolToPreservedGUID(File, GUIDPreservedSymbols);
872
873 // Collect for each module the list of function it defines (GUID -> Summary).
874 DenseMap<StringRef, GVSummaryMapTy> ModuleToDefinedGVSummaries(ModuleCount);
875 Index.collectDefinedGVSummariesPerModule(ModuleToDefinedGVSummaries);
876
877 // Compute "dead" symbols, we don't want to import/export these!
878 computeDeadSymbolsInIndex(Index, GUIDPreservedSymbols);
879
880 // Compute prevailing symbols
882 computePrevailingCopies(Index, PrevailingCopy);
883
884 // Generate import/export list
887 ComputeCrossModuleImport(Index, ModuleToDefinedGVSummaries,
888 IsPrevailing(PrevailingCopy), ImportLists,
889 ExportLists);
890 auto &ExportList = ExportLists[ModuleIdentifier];
891
892 // Be friendly and don't nuke totally the module when the client didn't
893 // supply anything to preserve.
894 if (ExportList.empty() && GUIDPreservedSymbols.empty())
895 return;
896
897 // Resolve prevailing symbols
899 resolvePrevailingInIndex(Index, ResolvedODR, GUIDPreservedSymbols,
900 PrevailingCopy);
901
902 // Promote the exported values in the index, so that they are promoted
903 // in the module.
905 Index, IsExported(ExportLists, GUIDPreservedSymbols),
906 IsPrevailing(PrevailingCopy));
907
908 // FIXME Set ClearDSOLocalOnDeclarations.
909 promoteModule(TheModule, Index, /*ClearDSOLocalOnDeclarations=*/false);
910
911 // Internalization
912 thinLTOFinalizeInModule(TheModule,
913 ModuleToDefinedGVSummaries[ModuleIdentifier],
914 /*PropagateAttrs=*/false);
915
916 thinLTOInternalizeModule(TheModule,
917 ModuleToDefinedGVSummaries[ModuleIdentifier]);
918}
919
920/**
921 * Perform post-importing ThinLTO optimizations.
922 */
924 initTMBuilder(TMBuilder, Triple(TheModule.getTargetTriple()));
925
926 // Optimize now
927 optimizeModule(TheModule, *TMBuilder.create(), OptLevel, Freestanding,
928 DebugPassManager, nullptr);
929}
930
931/// Write out the generated object file, either from CacheEntryPath or from
932/// OutputBuffer, preferring hard-link when possible.
933/// Returns the path to the generated file in SavedObjectsDirectoryPath.
934std::string
936 const MemoryBuffer &OutputBuffer) {
937 auto ArchName = TMBuilder.TheTriple.getArchName();
938 SmallString<128> OutputPath(SavedObjectsDirectoryPath);
939 llvm::sys::path::append(OutputPath,
940 Twine(count) + "." + ArchName + ".thinlto.o");
941 OutputPath.c_str(); // Ensure the string is null terminated.
942 if (sys::fs::exists(OutputPath))
943 sys::fs::remove(OutputPath);
944
945 // We don't return a memory buffer to the linker, just a list of files.
946 if (!CacheEntryPath.empty()) {
947 // Cache is enabled, hard-link the entry (or copy if hard-link fails).
948 auto Err = sys::fs::create_hard_link(CacheEntryPath, OutputPath);
949 if (!Err)
950 return std::string(OutputPath);
951 // Hard linking failed, try to copy.
952 Err = sys::fs::copy_file(CacheEntryPath, OutputPath);
953 if (!Err)
954 return std::string(OutputPath);
955 // Copy failed (could be because the CacheEntry was removed from the cache
956 // in the meantime by another process), fall back and try to write down the
957 // buffer to the output.
958 errs() << "remark: can't link or copy from cached entry '" << CacheEntryPath
959 << "' to '" << OutputPath << "'\n";
960 }
961 // No cache entry, just write out the buffer.
962 std::error_code Err;
963 raw_fd_ostream OS(OutputPath, Err, sys::fs::OF_None);
964 if (Err)
965 report_fatal_error(Twine("Can't open output '") + OutputPath + "'\n");
966 OS << OutputBuffer.getBuffer();
967 return std::string(OutputPath);
968}
969
970// Main entry point for the ThinLTO processing
972 timeTraceProfilerBegin("ThinLink", StringRef(""));
973 auto TimeTraceScopeExit = llvm::make_scope_exit([]() {
976 });
977 // Prepare the resulting object vector
978 assert(ProducedBinaries.empty() && "The generator should not be reused");
979 if (SavedObjectsDirectoryPath.empty())
980 ProducedBinaries.resize(Modules.size());
981 else {
982 sys::fs::create_directories(SavedObjectsDirectoryPath);
983 bool IsDir;
984 sys::fs::is_directory(SavedObjectsDirectoryPath, IsDir);
985 if (!IsDir)
986 report_fatal_error(Twine("Unexistent dir: '") + SavedObjectsDirectoryPath + "'");
987 ProducedBinaryFiles.resize(Modules.size());
988 }
989
990 if (CodeGenOnly) {
991 // Perform only parallel codegen and return.
992 ThreadPool Pool;
993 int count = 0;
994 for (auto &Mod : Modules) {
995 Pool.async([&](int count) {
998
999 // Parse module now
1000 auto TheModule = loadModuleFromInput(Mod.get(), Context, false,
1001 /*IsImporting*/ false);
1002
1003 // CodeGen
1004 auto OutputBuffer = codegenModule(*TheModule, *TMBuilder.create());
1005 if (SavedObjectsDirectoryPath.empty())
1006 ProducedBinaries[count] = std::move(OutputBuffer);
1007 else
1008 ProducedBinaryFiles[count] =
1009 writeGeneratedObject(count, "", *OutputBuffer);
1010 }, count++);
1011 }
1012
1013 return;
1014 }
1015
1016 // Sequential linking phase
1017 auto Index = linkCombinedIndex();
1018
1019 // Save temps: index.
1020 if (!SaveTempsDir.empty()) {
1021 auto SaveTempPath = SaveTempsDir + "index.bc";
1022 std::error_code EC;
1023 raw_fd_ostream OS(SaveTempPath, EC, sys::fs::OF_None);
1024 if (EC)
1025 report_fatal_error(Twine("Failed to open ") + SaveTempPath +
1026 " to save optimized bitcode\n");
1028 }
1029
1030
1031 // Prepare the module map.
1032 auto ModuleMap = generateModuleMap(Modules);
1033 auto ModuleCount = Modules.size();
1034
1035 // Collect for each module the list of function it defines (GUID -> Summary).
1036 DenseMap<StringRef, GVSummaryMapTy> ModuleToDefinedGVSummaries(ModuleCount);
1037 Index->collectDefinedGVSummariesPerModule(ModuleToDefinedGVSummaries);
1038
1039 // Convert the preserved symbols set from string to GUID, this is needed for
1040 // computing the caching hash and the internalization.
1041 DenseSet<GlobalValue::GUID> GUIDPreservedSymbols;
1042 for (const auto &M : Modules)
1043 computeGUIDPreservedSymbols(*M, PreservedSymbols, TMBuilder.TheTriple,
1044 GUIDPreservedSymbols);
1045
1046 // Add used symbol from inputs to the preserved symbols.
1047 for (const auto &M : Modules)
1048 addUsedSymbolToPreservedGUID(*M, GUIDPreservedSymbols);
1049
1050 // Compute "dead" symbols, we don't want to import/export these!
1051 computeDeadSymbolsInIndex(*Index, GUIDPreservedSymbols);
1052
1053 // Synthesize entry counts for functions in the combined index.
1055
1056 // Currently there is no support for enabling whole program visibility via a
1057 // linker option in the old LTO API, but this call allows it to be specified
1058 // via the internal option. Must be done before WPD below.
1059 if (hasWholeProgramVisibility(/* WholeProgramVisibilityEnabledInLTO */ false))
1060 Index->setWithWholeProgramVisibility();
1061
1062 // FIXME: This needs linker information via a TBD new interface
1064 /*WholeProgramVisibilityEnabledInLTO=*/false,
1065 // FIXME: These need linker information via a
1066 // TBD new interface.
1067 /*DynamicExportSymbols=*/{},
1068 /*VisibleToRegularObjSymbols=*/{});
1069
1070 // Perform index-based WPD. This will return immediately if there are
1071 // no index entries in the typeIdMetadata map (e.g. if we are instead
1072 // performing IR-based WPD in hybrid regular/thin LTO mode).
1073 std::map<ValueInfo, std::vector<VTableSlotSummary>> LocalWPDTargetsMap;
1074 std::set<GlobalValue::GUID> ExportedGUIDs;
1075 runWholeProgramDevirtOnIndex(*Index, ExportedGUIDs, LocalWPDTargetsMap);
1076 for (auto GUID : ExportedGUIDs)
1077 GUIDPreservedSymbols.insert(GUID);
1078
1079 // Compute prevailing symbols
1081 computePrevailingCopies(*Index, PrevailingCopy);
1082
1083 // Collect the import/export lists for all modules from the call-graph in the
1084 // combined index.
1087 ComputeCrossModuleImport(*Index, ModuleToDefinedGVSummaries,
1088 IsPrevailing(PrevailingCopy), ImportLists,
1089 ExportLists);
1090
1091 // We use a std::map here to be able to have a defined ordering when
1092 // producing a hash for the cache entry.
1093 // FIXME: we should be able to compute the caching hash for the entry based
1094 // on the index, and nuke this map.
1096
1097 // Resolve prevailing symbols, this has to be computed early because it
1098 // impacts the caching.
1099 resolvePrevailingInIndex(*Index, ResolvedODR, GUIDPreservedSymbols,
1100 PrevailingCopy);
1101
1102 // Use global summary-based analysis to identify symbols that can be
1103 // internalized (because they aren't exported or preserved as per callback).
1104 // Changes are made in the index, consumed in the ThinLTO backends.
1106 IsExported(ExportLists, GUIDPreservedSymbols),
1107 LocalWPDTargetsMap);
1109 *Index, IsExported(ExportLists, GUIDPreservedSymbols),
1110 IsPrevailing(PrevailingCopy));
1111
1112 thinLTOPropagateFunctionAttrs(*Index, IsPrevailing(PrevailingCopy));
1113
1114 // Make sure that every module has an entry in the ExportLists, ImportList,
1115 // GVSummary and ResolvedODR maps to enable threaded access to these maps
1116 // below.
1117 for (auto &Module : Modules) {
1118 auto ModuleIdentifier = Module->getName();
1119 ExportLists[ModuleIdentifier];
1120 ImportLists[ModuleIdentifier];
1121 ResolvedODR[ModuleIdentifier];
1122 ModuleToDefinedGVSummaries[ModuleIdentifier];
1123 }
1124
1125 std::vector<BitcodeModule *> ModulesVec;
1126 ModulesVec.reserve(Modules.size());
1127 for (auto &Mod : Modules)
1128 ModulesVec.push_back(&Mod->getSingleBitcodeModule());
1129 std::vector<int> ModulesOrdering = lto::generateModulesOrdering(ModulesVec);
1130
1133
1134 TimeTraceScopeExit.release();
1135
1136 // Parallel optimizer + codegen
1137 {
1139 for (auto IndexCount : ModulesOrdering) {
1140 auto &Mod = Modules[IndexCount];
1141 Pool.async([&](int count) {
1142 auto ModuleIdentifier = Mod->getName();
1143 auto &ExportList = ExportLists[ModuleIdentifier];
1144
1145 auto &DefinedGVSummaries = ModuleToDefinedGVSummaries[ModuleIdentifier];
1146
1147 // The module may be cached, this helps handling it.
1148 ModuleCacheEntry CacheEntry(CacheOptions.Path, *Index, ModuleIdentifier,
1149 ImportLists[ModuleIdentifier], ExportList,
1150 ResolvedODR[ModuleIdentifier],
1151 DefinedGVSummaries, OptLevel, Freestanding,
1152 TMBuilder);
1153 auto CacheEntryPath = CacheEntry.getEntryPath();
1154
1155 {
1156 auto ErrOrBuffer = CacheEntry.tryLoadingBuffer();
1157 LLVM_DEBUG(dbgs() << "Cache " << (ErrOrBuffer ? "hit" : "miss")
1158 << " '" << CacheEntryPath << "' for buffer "
1159 << count << " " << ModuleIdentifier << "\n");
1160
1161 if (ErrOrBuffer) {
1162 // Cache Hit!
1163 if (SavedObjectsDirectoryPath.empty())
1164 ProducedBinaries[count] = std::move(ErrOrBuffer.get());
1165 else
1166 ProducedBinaryFiles[count] = writeGeneratedObject(
1167 count, CacheEntryPath, *ErrOrBuffer.get());
1168 return;
1169 }
1170 }
1171
1175 auto DiagFileOrErr = lto::setupLLVMOptimizationRemarks(
1178 if (!DiagFileOrErr) {
1179 errs() << "Error: " << toString(DiagFileOrErr.takeError()) << "\n";
1180 report_fatal_error("ThinLTO: Can't get an output file for the "
1181 "remarks");
1182 }
1183
1184 // Parse module now
1185 auto TheModule = loadModuleFromInput(Mod.get(), Context, false,
1186 /*IsImporting*/ false);
1187
1188 // Save temps: original file.
1189 saveTempBitcode(*TheModule, SaveTempsDir, count, ".0.original.bc");
1190
1191 auto &ImportList = ImportLists[ModuleIdentifier];
1192 // Run the main process now, and generates a binary
1193 auto OutputBuffer = ProcessThinLTOModule(
1194 *TheModule, *Index, ModuleMap, *TMBuilder.create(), ImportList,
1195 ExportList, GUIDPreservedSymbols,
1196 ModuleToDefinedGVSummaries[ModuleIdentifier], CacheOptions,
1197 DisableCodeGen, SaveTempsDir, Freestanding, OptLevel, count,
1198 DebugPassManager);
1199
1200 // Commit to the cache (if enabled)
1201 CacheEntry.write(*OutputBuffer);
1202
1203 if (SavedObjectsDirectoryPath.empty()) {
1204 // We need to generated a memory buffer for the linker.
1205 if (!CacheEntryPath.empty()) {
1206 // When cache is enabled, reload from the cache if possible.
1207 // Releasing the buffer from the heap and reloading it from the
1208 // cache file with mmap helps us to lower memory pressure.
1209 // The freed memory can be used for the next input file.
1210 // The final binary link will read from the VFS cache (hopefully!)
1211 // or from disk (if the memory pressure was too high).
1212 auto ReloadedBufferOrErr = CacheEntry.tryLoadingBuffer();
1213 if (auto EC = ReloadedBufferOrErr.getError()) {
1214 // On error, keep the preexisting buffer and print a diagnostic.
1215 errs() << "remark: can't reload cached file '" << CacheEntryPath
1216 << "': " << EC.message() << "\n";
1217 } else {
1218 OutputBuffer = std::move(*ReloadedBufferOrErr);
1219 }
1220 }
1221 ProducedBinaries[count] = std::move(OutputBuffer);
1222 return;
1223 }
1224 ProducedBinaryFiles[count] = writeGeneratedObject(
1225 count, CacheEntryPath, *OutputBuffer);
1226 }, IndexCount);
1227 }
1228 }
1229
1230 pruneCache(CacheOptions.Path, CacheOptions.Policy, ProducedBinaries);
1231
1232 // If statistics were requested, print them out now.
1236}
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.
LLVMContext & Context
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:348
bool registerPass(PassBuilderT &&PassBuilder)
Register an analysis pass with the manager.
Definition: PassManager.h:562
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:169
LinkageTypes
An enumeration for the kinds of linkage for global values.
Definition: GlobalValue.h:51
@ ExternalLinkage
Externally visible function.
Definition: GlobalValue.h:52
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:283
StringRef getName() const
Get a short "name" for the module.
Definition: Module.h:266
const std::string & getTargetTriple() const
Get the target triple which is a string describing the target host.
Definition: Module.h:279
const std::string & getModuleIdentifier() const
Get the module identifier which is, essentially, the name of the module.
Definition: Module.h:249
PIELevel::Level getPIELevel() const
Returns the PIE level (small or large model)
Definition: Module.cpp:590
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:104
void registerLoopAnalyses(LoopAnalysisManager &LAM)
Registers all available loop analysis passes.
void crossRegisterProxies(LoopAnalysisManager &LAM, FunctionAnalysisManager &FAM, CGSCCAnalysisManager &CGAM, ModuleAnalysisManager &MAM)
Cross register the analysis managers through their proxies.
ModulePassManager buildThinLTODefaultPipeline(OptimizationLevel Level, const ModuleSummaryIndex *ImportSummary)
Build an 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 std::enable_if_t<!std::is_same< PassT, PassManager >::value > addPass(PassT &&Pass)
Definition: PassManager.h:273
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:218
Tunable parameters for passes in the default pipelines.
Definition: PassBuilder.h:42
bool SLPVectorization
Tuning option to enable/disable slp loop vectorization, set based on opt level.
Definition: PassBuilder.h:57
bool LoopVectorization
Tuning option to enable/disable loop vectorization, set based on opt level.
Definition: PassBuilder.h:53
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
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:274
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:34
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:78
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.
A ThreadPool for asynchronous parallel execution on a defined number of threads.
Definition: ThreadPool.h:52
auto async(Function &&F, Args &&...ArgList)
Asynchronous submission of a task to the pool.
Definition: ThreadPool.h:66
Triple - Helper class for working with autoconf configuration names.
Definition: Triple.h:44
@ aarch64_32
Definition: Triple.h:53
ArchType getArch() const
Get the parsed architecture type of this triple.
Definition: Triple.h:361
const std::string & str() const
Definition: Triple.h:424
std::string merge(const Triple &Other) const
Merge target triples.
Definition: Triple.cpp:1895
bool isOSDarwin() const
Is this a "Darwin" OS (macOS, iOS, tvOS, watchOS, XROS, or DriverKit).
Definition: Triple.h:542
StringRef getArchName() const
Get the architecture (first) component of the triple.
Definition: Triple.cpp:1189
bool isCompatibleWith(const Triple &Other) const
Test whether target triples are compatible.
Definition: Triple.cpp:1871
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:109
static Expected< std::unique_ptr< InputFile > > create(MemoryBufferRef Object)
Create an InputFile.
Definition: LTO.cpp:540
BitcodeModule & getSingleBitcodeModule()
Definition: LTO.cpp:573
A raw_ostream that writes to a file descriptor.
Definition: raw_ostream.h:470
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:690
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.
const CustomOperand< const MCSubtargetInfo & > Msg[]
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.
std::vector< int > generateModulesOrdering(ArrayRef< BitcodeModule * > R)
Produces a container ordering for optimal multi-threaded processing.
Definition: LTO.cpp:1898
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:1854
std::error_code closeFile(file_t &F)
Close the file object.
bool exists(const basic_file_status &status)
Does file exist?
Definition: Path.cpp:1079
@ 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:969
std::error_code copy_file(const Twine &From, const Twine &To)
Copy the contents of From to To.
Definition: Path.cpp:1018
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:1094
void append(SmallVectorImpl< char > &path, const Twine &a, const Twine &b="", const Twine &c="", const Twine &d="")
Append to path.
Definition: Path.cpp:458
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
auto formatv(const char *Fmt, Ts &&... Vals) -> formatv_object< decltype(std::make_tuple(detail::build_format_adapter(std::forward< Ts >(Vals))...))>
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:1731
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)
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:527
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 timeTraceProfilerBegin(StringRef Name, StringRef Detail)
Manually begin a time section, with the given Name and Detail.
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:102
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:156
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:426
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:590
@ 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:1923
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:1758
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:6721
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:68