LLVM 18.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 assert(!ModuleMap.contains(M->getName()) &&
155 "Expect unique Buffer Identifier");
156 ModuleMap[M->getName()] = M.get();
157 }
158 return ModuleMap;
159}
160
161static void promoteModule(Module &TheModule, const ModuleSummaryIndex &Index,
162 bool ClearDSOLocalOnDeclarations) {
163 if (renameModuleForThinLTO(TheModule, Index, ClearDSOLocalOnDeclarations))
164 report_fatal_error("renameModuleForThinLTO failed");
165}
166
167namespace {
168class ThinLTODiagnosticInfo : public DiagnosticInfo {
169 const Twine &Msg;
170public:
171 ThinLTODiagnosticInfo(const Twine &DiagMsg,
172 DiagnosticSeverity Severity = DS_Error)
173 : DiagnosticInfo(DK_Linker, Severity), Msg(DiagMsg) {}
174 void print(DiagnosticPrinter &DP) const override { DP << Msg; }
175};
176}
177
178/// Verify the module and strip broken debug info.
179static void verifyLoadedModule(Module &TheModule) {
180 bool BrokenDebugInfo = false;
181 if (verifyModule(TheModule, &dbgs(), &BrokenDebugInfo))
182 report_fatal_error("Broken module found, compilation aborted!");
183 if (BrokenDebugInfo) {
184 TheModule.getContext().diagnose(ThinLTODiagnosticInfo(
185 "Invalid debug info found, debug info will be stripped", DS_Warning));
186 StripDebugInfo(TheModule);
187 }
188}
189
190static std::unique_ptr<Module> loadModuleFromInput(lto::InputFile *Input,
191 LLVMContext &Context,
192 bool Lazy,
193 bool IsImporting) {
194 auto &Mod = Input->getSingleBitcodeModule();
195 SMDiagnostic Err;
197 Lazy ? Mod.getLazyModule(Context,
198 /* ShouldLazyLoadMetadata */ true, IsImporting)
199 : Mod.parseModule(Context);
200 if (!ModuleOrErr) {
201 handleAllErrors(ModuleOrErr.takeError(), [&](ErrorInfoBase &EIB) {
202 SMDiagnostic Err = SMDiagnostic(Mod.getModuleIdentifier(),
203 SourceMgr::DK_Error, EIB.message());
204 Err.print("ThinLTO", errs());
205 });
206 report_fatal_error("Can't load module, abort.");
207 }
208 if (!Lazy)
209 verifyLoadedModule(*ModuleOrErr.get());
210 return std::move(*ModuleOrErr);
211}
212
213static void
214crossImportIntoModule(Module &TheModule, const ModuleSummaryIndex &Index,
216 const FunctionImporter::ImportMapTy &ImportList,
217 bool ClearDSOLocalOnDeclarations) {
218 auto Loader = [&](StringRef Identifier) {
219 auto &Input = ModuleMap[Identifier];
220 return loadModuleFromInput(Input, TheModule.getContext(),
221 /*Lazy=*/true, /*IsImporting*/ true);
222 };
223
224 FunctionImporter Importer(Index, Loader, ClearDSOLocalOnDeclarations);
225 Expected<bool> Result = Importer.importFunctions(TheModule, ImportList);
226 if (!Result) {
227 handleAllErrors(Result.takeError(), [&](ErrorInfoBase &EIB) {
228 SMDiagnostic Err = SMDiagnostic(TheModule.getModuleIdentifier(),
229 SourceMgr::DK_Error, EIB.message());
230 Err.print("ThinLTO", errs());
231 });
232 report_fatal_error("importFunctions failed");
233 }
234 // Verify again after cross-importing.
235 verifyLoadedModule(TheModule);
236}
237
238static void optimizeModule(Module &TheModule, TargetMachine &TM,
239 unsigned OptLevel, bool Freestanding,
240 bool DebugPassManager, ModuleSummaryIndex *Index) {
241 std::optional<PGOOptions> PGOOpt;
246
248 StandardInstrumentations SI(TheModule.getContext(), DebugPassManager);
249 SI.registerCallbacks(PIC, &MAM);
251 PTO.LoopVectorization = true;
252 PTO.SLPVectorization = true;
253 PassBuilder PB(&TM, PTO, PGOOpt, &PIC);
254
255 std::unique_ptr<TargetLibraryInfoImpl> TLII(
256 new TargetLibraryInfoImpl(Triple(TM.getTargetTriple())));
257 if (Freestanding)
258 TLII->disableAllFunctions();
259 FAM.registerPass([&] { return TargetLibraryAnalysis(*TLII); });
260
261 // Register all the basic analyses with the managers.
267
269
271
272 switch (OptLevel) {
273 default:
274 llvm_unreachable("Invalid optimization level");
275 case 0:
277 break;
278 case 1:
280 break;
281 case 2:
283 break;
284 case 3:
286 break;
287 }
288
290
291 MPM.run(TheModule, MAM);
292}
293
294static void
295addUsedSymbolToPreservedGUID(const lto::InputFile &File,
296 DenseSet<GlobalValue::GUID> &PreservedGUID) {
297 for (const auto &Sym : File.symbols()) {
298 if (Sym.isUsed())
299 PreservedGUID.insert(GlobalValue::getGUID(Sym.getIRName()));
300 }
301}
302
303// Convert the PreservedSymbols map from "Name" based to "GUID" based.
304static void computeGUIDPreservedSymbols(const lto::InputFile &File,
306 const Triple &TheTriple,
308 // Iterate the symbols in the input file and if the input has preserved symbol
309 // compute the GUID for the symbol.
310 for (const auto &Sym : File.symbols()) {
311 if (PreservedSymbols.count(Sym.getName()) && !Sym.getIRName().empty())
313 Sym.getIRName(), GlobalValue::ExternalLinkage, "")));
314 }
315}
316
318computeGUIDPreservedSymbols(const lto::InputFile &File,
320 const Triple &TheTriple) {
321 DenseSet<GlobalValue::GUID> GUIDPreservedSymbols(PreservedSymbols.size());
322 computeGUIDPreservedSymbols(File, PreservedSymbols, TheTriple,
323 GUIDPreservedSymbols);
324 return GUIDPreservedSymbols;
325}
326
327std::unique_ptr<MemoryBuffer> codegenModule(Module &TheModule,
328 TargetMachine &TM) {
330
331 // CodeGen
332 {
335
336 // If the bitcode files contain ARC code and were compiled with optimization,
337 // the ObjCARCContractPass must be run, so do it unconditionally here.
339
340 // Setup the codegen now.
341 if (TM.addPassesToEmitFile(PM, OS, nullptr, CodeGenFileType::ObjectFile,
342 /* DisableVerify */ true))
343 report_fatal_error("Failed to setup codegen");
344
345 // Run codegen now. resulting binary is in OutputBuffer.
346 PM.run(TheModule);
347 }
348 return std::make_unique<SmallVectorMemoryBuffer>(
349 std::move(OutputBuffer), /*RequiresNullTerminator=*/false);
350}
351
352/// Manage caching for a single Module.
353class ModuleCacheEntry {
354 SmallString<128> EntryPath;
355
356public:
357 // Create a cache entry. This compute a unique hash for the Module considering
358 // the current list of export/import, and offer an interface to query to
359 // access the content in the cache.
360 ModuleCacheEntry(
361 StringRef CachePath, const ModuleSummaryIndex &Index, StringRef ModuleID,
362 const FunctionImporter::ImportMapTy &ImportList,
363 const FunctionImporter::ExportSetTy &ExportList,
364 const std::map<GlobalValue::GUID, GlobalValue::LinkageTypes> &ResolvedODR,
365 const GVSummaryMapTy &DefinedGVSummaries, unsigned OptLevel,
366 bool Freestanding, const TargetMachineBuilder &TMBuilder) {
367 if (CachePath.empty())
368 return;
369
370 if (!Index.modulePaths().count(ModuleID))
371 // The module does not have an entry, it can't have a hash at all
372 return;
373
374 if (all_of(Index.getModuleHash(ModuleID),
375 [](uint32_t V) { return V == 0; }))
376 // No hash entry, no caching!
377 return;
378
380 Conf.OptLevel = OptLevel;
381 Conf.Options = TMBuilder.Options;
382 Conf.CPU = TMBuilder.MCpu;
383 Conf.MAttrs.push_back(TMBuilder.MAttr);
384 Conf.RelocModel = TMBuilder.RelocModel;
385 Conf.CGOptLevel = TMBuilder.CGOptLevel;
386 Conf.Freestanding = Freestanding;
388 computeLTOCacheKey(Key, Conf, Index, ModuleID, ImportList, ExportList,
389 ResolvedODR, DefinedGVSummaries);
390
391 // This choice of file name allows the cache to be pruned (see pruneCache()
392 // in include/llvm/Support/CachePruning.h).
393 sys::path::append(EntryPath, CachePath, "llvmcache-" + Key);
394 }
395
396 // Access the path to this entry in the cache.
397 StringRef getEntryPath() { return EntryPath; }
398
399 // Try loading the buffer for this cache entry.
400 ErrorOr<std::unique_ptr<MemoryBuffer>> tryLoadingBuffer() {
401 if (EntryPath.empty())
402 return std::error_code();
403 SmallString<64> ResultPath;
405 Twine(EntryPath), sys::fs::OF_UpdateAtime, &ResultPath);
406 if (!FDOrErr)
407 return errorToErrorCode(FDOrErr.takeError());
409 *FDOrErr, EntryPath, /*FileSize=*/-1, /*RequiresNullTerminator=*/false);
410 sys::fs::closeFile(*FDOrErr);
411 return MBOrErr;
412 }
413
414 // Cache the Produced object file
415 void write(const MemoryBuffer &OutputBuffer) {
416 if (EntryPath.empty())
417 return;
418
419 if (auto Err = llvm::writeToOutput(
420 EntryPath, [&OutputBuffer](llvm::raw_ostream &OS) -> llvm::Error {
422 return llvm::Error::success();
423 }))
424 report_fatal_error(llvm::formatv("ThinLTO: Can't write file {0}: {1}",
425 EntryPath,
426 toString(std::move(Err)).c_str()));
427 }
428};
429
430static std::unique_ptr<MemoryBuffer>
431ProcessThinLTOModule(Module &TheModule, ModuleSummaryIndex &Index,
433 const FunctionImporter::ImportMapTy &ImportList,
434 const FunctionImporter::ExportSetTy &ExportList,
435 const DenseSet<GlobalValue::GUID> &GUIDPreservedSymbols,
436 const GVSummaryMapTy &DefinedGlobals,
437 const ThinLTOCodeGenerator::CachingOptions &CacheOptions,
438 bool DisableCodeGen, StringRef SaveTempsDir,
439 bool Freestanding, unsigned OptLevel, unsigned count,
440 bool DebugPassManager) {
441 // "Benchmark"-like optimization: single-source case
442 bool SingleModule = (ModuleMap.size() == 1);
443
444 // When linking an ELF shared object, dso_local should be dropped. We
445 // conservatively do this for -fpic.
446 bool ClearDSOLocalOnDeclarations =
447 TM.getTargetTriple().isOSBinFormatELF() &&
448 TM.getRelocationModel() != Reloc::Static &&
449 TheModule.getPIELevel() == PIELevel::Default;
450
451 if (!SingleModule) {
452 promoteModule(TheModule, Index, ClearDSOLocalOnDeclarations);
453
454 // Apply summary-based prevailing-symbol resolution decisions.
455 thinLTOFinalizeInModule(TheModule, DefinedGlobals, /*PropagateAttrs=*/true);
456
457 // Save temps: after promotion.
458 saveTempBitcode(TheModule, SaveTempsDir, count, ".1.promoted.bc");
459 }
460
461 // Be friendly and don't nuke totally the module when the client didn't
462 // supply anything to preserve.
463 if (!ExportList.empty() || !GUIDPreservedSymbols.empty()) {
464 // Apply summary-based internalization decisions.
465 thinLTOInternalizeModule(TheModule, DefinedGlobals);
466 }
467
468 // Save internalized bitcode
469 saveTempBitcode(TheModule, SaveTempsDir, count, ".2.internalized.bc");
470
471 if (!SingleModule)
472 crossImportIntoModule(TheModule, Index, ModuleMap, ImportList,
473 ClearDSOLocalOnDeclarations);
474
475 // Do this after any importing so that imported code is updated.
476 // See comment at call to updateVCallVisibilityInIndex() for why
477 // WholeProgramVisibilityEnabledInLTO is false.
479 /* WholeProgramVisibilityEnabledInLTO */ false);
480
481 // Save temps: after cross-module import.
482 saveTempBitcode(TheModule, SaveTempsDir, count, ".3.imported.bc");
483
484 optimizeModule(TheModule, TM, OptLevel, Freestanding, DebugPassManager,
485 &Index);
486
487 saveTempBitcode(TheModule, SaveTempsDir, count, ".4.opt.bc");
488
489 if (DisableCodeGen) {
490 // Configured to stop before CodeGen, serialize the bitcode and return.
492 {
494 ProfileSummaryInfo PSI(TheModule);
495 auto Index = buildModuleSummaryIndex(TheModule, nullptr, &PSI);
496 WriteBitcodeToFile(TheModule, OS, true, &Index);
497 }
498 return std::make_unique<SmallVectorMemoryBuffer>(
499 std::move(OutputBuffer), /*RequiresNullTerminator=*/false);
500 }
501
502 return codegenModule(TheModule, TM);
503}
504
505/// Resolve prevailing symbols. Record resolutions in the \p ResolvedODR map
506/// for caching, and in the \p Index for application during the ThinLTO
507/// backends. This is needed for correctness for exported symbols (ensure
508/// at least one copy kept) and a compile-time optimization (to drop duplicate
509/// copies when possible).
510static void resolvePrevailingInIndex(
512 StringMap<std::map<GlobalValue::GUID, GlobalValue::LinkageTypes>>
513 &ResolvedODR,
514 const DenseSet<GlobalValue::GUID> &GUIDPreservedSymbols,
516 &PrevailingCopy) {
517
518 auto isPrevailing = [&](GlobalValue::GUID GUID, const GlobalValueSummary *S) {
519 const auto &Prevailing = PrevailingCopy.find(GUID);
520 // Not in map means that there was only one copy, which must be prevailing.
521 if (Prevailing == PrevailingCopy.end())
522 return true;
523 return Prevailing->second == S;
524 };
525
526 auto recordNewLinkage = [&](StringRef ModuleIdentifier,
528 GlobalValue::LinkageTypes NewLinkage) {
529 ResolvedODR[ModuleIdentifier][GUID] = NewLinkage;
530 };
531
532 // TODO Conf.VisibilityScheme can be lto::Config::ELF for ELF.
533 lto::Config Conf;
534 thinLTOResolvePrevailingInIndex(Conf, Index, isPrevailing, recordNewLinkage,
535 GUIDPreservedSymbols);
536}
537
538// Initialize the TargetMachine builder for a given Triple
539static void initTMBuilder(TargetMachineBuilder &TMBuilder,
540 const Triple &TheTriple) {
541 // Set a default CPU for Darwin triples (copied from LTOCodeGenerator).
542 // FIXME this looks pretty terrible...
543 if (TMBuilder.MCpu.empty() && TheTriple.isOSDarwin()) {
544 if (TheTriple.getArch() == llvm::Triple::x86_64)
545 TMBuilder.MCpu = "core2";
546 else if (TheTriple.getArch() == llvm::Triple::x86)
547 TMBuilder.MCpu = "yonah";
548 else if (TheTriple.getArch() == llvm::Triple::aarch64 ||
549 TheTriple.getArch() == llvm::Triple::aarch64_32)
550 TMBuilder.MCpu = "cyclone";
551 }
552 TMBuilder.TheTriple = std::move(TheTriple);
553}
554
555} // end anonymous namespace
556
558 MemoryBufferRef Buffer(Data, Identifier);
559
560 auto InputOrError = lto::InputFile::create(Buffer);
561 if (!InputOrError)
562 report_fatal_error(Twine("ThinLTO cannot create input file: ") +
563 toString(InputOrError.takeError()));
564
565 auto TripleStr = (*InputOrError)->getTargetTriple();
566 Triple TheTriple(TripleStr);
567
568 if (Modules.empty())
569 initTMBuilder(TMBuilder, Triple(TheTriple));
570 else if (TMBuilder.TheTriple != TheTriple) {
571 if (!TMBuilder.TheTriple.isCompatibleWith(TheTriple))
572 report_fatal_error("ThinLTO modules with incompatible triples not "
573 "supported");
574 initTMBuilder(TMBuilder, Triple(TMBuilder.TheTriple.merge(TheTriple)));
575 }
576
577 Modules.emplace_back(std::move(*InputOrError));
578}
579
581 PreservedSymbols.insert(Name);
582}
583
585 // FIXME: At the moment, we don't take advantage of this extra information,
586 // we're conservatively considering cross-references as preserved.
587 // CrossReferencedSymbols.insert(Name);
588 PreservedSymbols.insert(Name);
589}
590
591// TargetMachine factory
592std::unique_ptr<TargetMachine> TargetMachineBuilder::create() const {
593 std::string ErrMsg;
594 const Target *TheTarget =
596 if (!TheTarget) {
597 report_fatal_error(Twine("Can't load target for this Triple: ") + ErrMsg);
598 }
599
600 // Use MAttr as the default set of features.
601 SubtargetFeatures Features(MAttr);
603 std::string FeatureStr = Features.getString();
604
605 std::unique_ptr<TargetMachine> TM(
606 TheTarget->createTargetMachine(TheTriple.str(), MCpu, FeatureStr, Options,
607 RelocModel, std::nullopt, CGOptLevel));
608 assert(TM && "Cannot create target machine");
609
610 return TM;
611}
612
613/**
614 * Produce the combined summary index from all the bitcode files:
615 * "thin-link".
616 */
617std::unique_ptr<ModuleSummaryIndex> ThinLTOCodeGenerator::linkCombinedIndex() {
618 std::unique_ptr<ModuleSummaryIndex> CombinedIndex =
619 std::make_unique<ModuleSummaryIndex>(/*HaveGVs=*/false);
620 for (auto &Mod : Modules) {
621 auto &M = Mod->getSingleBitcodeModule();
622 if (Error Err = M.readSummary(*CombinedIndex, Mod->getName())) {
623 // FIXME diagnose
625 std::move(Err), errs(),
626 "error: can't create module summary index for buffer: ");
627 return nullptr;
628 }
629 }
630 return CombinedIndex;
631}
632
633namespace {
634struct IsExported {
636 const DenseSet<GlobalValue::GUID> &GUIDPreservedSymbols;
637
638 IsExported(
640 const DenseSet<GlobalValue::GUID> &GUIDPreservedSymbols)
641 : ExportLists(ExportLists), GUIDPreservedSymbols(GUIDPreservedSymbols) {}
642
643 bool operator()(StringRef ModuleIdentifier, ValueInfo VI) const {
644 const auto &ExportList = ExportLists.find(ModuleIdentifier);
645 return (ExportList != ExportLists.end() && ExportList->second.count(VI)) ||
646 GUIDPreservedSymbols.count(VI.getGUID());
647 }
648};
649
650struct IsPrevailing {
653 &PrevailingCopy)
654 : PrevailingCopy(PrevailingCopy) {}
655
656 bool operator()(GlobalValue::GUID GUID, const GlobalValueSummary *S) const {
657 const auto &Prevailing = PrevailingCopy.find(GUID);
658 // Not in map means that there was only one copy, which must be prevailing.
659 if (Prevailing == PrevailingCopy.end())
660 return true;
661 return Prevailing->second == S;
662 };
663};
664} // namespace
665
668 const DenseSet<GlobalValue::GUID> &GUIDPreservedSymbols) {
669 // We have no symbols resolution available. And can't do any better now in the
670 // case where the prevailing symbol is in a native object. It can be refined
671 // with linker information in the future.
672 auto isPrevailing = [&](GlobalValue::GUID G) {
674 };
675 computeDeadSymbolsWithConstProp(Index, GUIDPreservedSymbols, isPrevailing,
676 /* ImportEnabled = */ true);
677}
678
679/**
680 * Perform promotion and renaming of exported internal functions.
681 * Index is updated to reflect linkage changes from weak resolution.
682 */
684 const lto::InputFile &File) {
685 auto ModuleCount = Index.modulePaths().size();
686 auto ModuleIdentifier = TheModule.getModuleIdentifier();
687
688 // Collect for each module the list of function it defines (GUID -> Summary).
689 DenseMap<StringRef, GVSummaryMapTy> ModuleToDefinedGVSummaries;
690 Index.collectDefinedGVSummariesPerModule(ModuleToDefinedGVSummaries);
691
692 // Convert the preserved symbols set from string to GUID
693 auto GUIDPreservedSymbols = computeGUIDPreservedSymbols(
694 File, PreservedSymbols, Triple(TheModule.getTargetTriple()));
695
696 // Add used symbol to the preserved symbols.
697 addUsedSymbolToPreservedGUID(File, GUIDPreservedSymbols);
698
699 // Compute "dead" symbols, we don't want to import/export these!
700 computeDeadSymbolsInIndex(Index, GUIDPreservedSymbols);
701
702 // Compute prevailing symbols
704 computePrevailingCopies(Index, PrevailingCopy);
705
706 // Generate import/export list
709 ComputeCrossModuleImport(Index, ModuleToDefinedGVSummaries,
710 IsPrevailing(PrevailingCopy), ImportLists,
711 ExportLists);
712
713 // Resolve prevailing symbols
715 resolvePrevailingInIndex(Index, ResolvedODR, GUIDPreservedSymbols,
716 PrevailingCopy);
717
718 thinLTOFinalizeInModule(TheModule,
719 ModuleToDefinedGVSummaries[ModuleIdentifier],
720 /*PropagateAttrs=*/false);
721
722 // Promote the exported values in the index, so that they are promoted
723 // in the module.
725 Index, IsExported(ExportLists, GUIDPreservedSymbols),
726 IsPrevailing(PrevailingCopy));
727
728 // FIXME Set ClearDSOLocalOnDeclarations.
729 promoteModule(TheModule, Index, /*ClearDSOLocalOnDeclarations=*/false);
730}
731
732/**
733 * Perform cross-module importing for the module identified by ModuleIdentifier.
734 */
737 const lto::InputFile &File) {
738 auto ModuleMap = generateModuleMap(Modules);
739 auto ModuleCount = Index.modulePaths().size();
740
741 // Collect for each module the list of function it defines (GUID -> Summary).
742 DenseMap<StringRef, GVSummaryMapTy> ModuleToDefinedGVSummaries(ModuleCount);
743 Index.collectDefinedGVSummariesPerModule(ModuleToDefinedGVSummaries);
744
745 // Convert the preserved symbols set from string to GUID
746 auto GUIDPreservedSymbols = computeGUIDPreservedSymbols(
747 File, PreservedSymbols, Triple(TheModule.getTargetTriple()));
748
749 addUsedSymbolToPreservedGUID(File, GUIDPreservedSymbols);
750
751 // Compute "dead" symbols, we don't want to import/export these!
752 computeDeadSymbolsInIndex(Index, GUIDPreservedSymbols);
753
754 // Compute prevailing symbols
756 computePrevailingCopies(Index, PrevailingCopy);
757
758 // Generate import/export list
761 ComputeCrossModuleImport(Index, ModuleToDefinedGVSummaries,
762 IsPrevailing(PrevailingCopy), ImportLists,
763 ExportLists);
764 auto &ImportList = ImportLists[TheModule.getModuleIdentifier()];
765
766 // FIXME Set ClearDSOLocalOnDeclarations.
767 crossImportIntoModule(TheModule, Index, ModuleMap, ImportList,
768 /*ClearDSOLocalOnDeclarations=*/false);
769}
770
771/**
772 * Compute the list of summaries needed for importing into module.
773 */
775 Module &TheModule, ModuleSummaryIndex &Index,
776 std::map<std::string, GVSummaryMapTy> &ModuleToSummariesForIndex,
777 const lto::InputFile &File) {
778 auto ModuleCount = Index.modulePaths().size();
779 auto ModuleIdentifier = TheModule.getModuleIdentifier();
780
781 // Collect for each module the list of function it defines (GUID -> Summary).
782 DenseMap<StringRef, GVSummaryMapTy> ModuleToDefinedGVSummaries(ModuleCount);
783 Index.collectDefinedGVSummariesPerModule(ModuleToDefinedGVSummaries);
784
785 // Convert the preserved symbols set from string to GUID
786 auto GUIDPreservedSymbols = computeGUIDPreservedSymbols(
787 File, PreservedSymbols, Triple(TheModule.getTargetTriple()));
788
789 addUsedSymbolToPreservedGUID(File, GUIDPreservedSymbols);
790
791 // Compute "dead" symbols, we don't want to import/export these!
792 computeDeadSymbolsInIndex(Index, GUIDPreservedSymbols);
793
794 // Compute prevailing symbols
796 computePrevailingCopies(Index, PrevailingCopy);
797
798 // Generate import/export list
801 ComputeCrossModuleImport(Index, ModuleToDefinedGVSummaries,
802 IsPrevailing(PrevailingCopy), ImportLists,
803 ExportLists);
804
806 ModuleIdentifier, ModuleToDefinedGVSummaries,
807 ImportLists[ModuleIdentifier], ModuleToSummariesForIndex);
808}
809
810/**
811 * Emit the list of files needed for importing into module.
812 */
815 const lto::InputFile &File) {
816 auto ModuleCount = Index.modulePaths().size();
817 auto ModuleIdentifier = TheModule.getModuleIdentifier();
818
819 // Collect for each module the list of function it defines (GUID -> Summary).
820 DenseMap<StringRef, GVSummaryMapTy> ModuleToDefinedGVSummaries(ModuleCount);
821 Index.collectDefinedGVSummariesPerModule(ModuleToDefinedGVSummaries);
822
823 // Convert the preserved symbols set from string to GUID
824 auto GUIDPreservedSymbols = computeGUIDPreservedSymbols(
825 File, PreservedSymbols, Triple(TheModule.getTargetTriple()));
826
827 addUsedSymbolToPreservedGUID(File, GUIDPreservedSymbols);
828
829 // Compute "dead" symbols, we don't want to import/export these!
830 computeDeadSymbolsInIndex(Index, GUIDPreservedSymbols);
831
832 // Compute prevailing symbols
834 computePrevailingCopies(Index, PrevailingCopy);
835
836 // Generate import/export list
839 ComputeCrossModuleImport(Index, ModuleToDefinedGVSummaries,
840 IsPrevailing(PrevailingCopy), ImportLists,
841 ExportLists);
842
843 std::map<std::string, GVSummaryMapTy> ModuleToSummariesForIndex;
845 ModuleIdentifier, ModuleToDefinedGVSummaries,
846 ImportLists[ModuleIdentifier], ModuleToSummariesForIndex);
847
848 std::error_code EC;
849 if ((EC = EmitImportsFiles(ModuleIdentifier, OutputName,
850 ModuleToSummariesForIndex)))
851 report_fatal_error(Twine("Failed to open ") + OutputName +
852 " to save imports lists\n");
853}
854
855/**
856 * Perform internalization. Runs promote and internalization together.
857 * Index is updated to reflect linkage changes.
858 */
861 const lto::InputFile &File) {
862 initTMBuilder(TMBuilder, Triple(TheModule.getTargetTriple()));
863 auto ModuleCount = Index.modulePaths().size();
864 auto ModuleIdentifier = TheModule.getModuleIdentifier();
865
866 // Convert the preserved symbols set from string to GUID
867 auto GUIDPreservedSymbols =
868 computeGUIDPreservedSymbols(File, PreservedSymbols, TMBuilder.TheTriple);
869
870 addUsedSymbolToPreservedGUID(File, GUIDPreservedSymbols);
871
872 // Collect for each module the list of function it defines (GUID -> Summary).
873 DenseMap<StringRef, GVSummaryMapTy> ModuleToDefinedGVSummaries(ModuleCount);
874 Index.collectDefinedGVSummariesPerModule(ModuleToDefinedGVSummaries);
875
876 // Compute "dead" symbols, we don't want to import/export these!
877 computeDeadSymbolsInIndex(Index, GUIDPreservedSymbols);
878
879 // Compute prevailing symbols
881 computePrevailingCopies(Index, PrevailingCopy);
882
883 // Generate import/export list
886 ComputeCrossModuleImport(Index, ModuleToDefinedGVSummaries,
887 IsPrevailing(PrevailingCopy), ImportLists,
888 ExportLists);
889 auto &ExportList = ExportLists[ModuleIdentifier];
890
891 // Be friendly and don't nuke totally the module when the client didn't
892 // supply anything to preserve.
893 if (ExportList.empty() && GUIDPreservedSymbols.empty())
894 return;
895
896 // Resolve prevailing symbols
898 resolvePrevailingInIndex(Index, ResolvedODR, GUIDPreservedSymbols,
899 PrevailingCopy);
900
901 // Promote the exported values in the index, so that they are promoted
902 // in the module.
904 Index, IsExported(ExportLists, GUIDPreservedSymbols),
905 IsPrevailing(PrevailingCopy));
906
907 // FIXME Set ClearDSOLocalOnDeclarations.
908 promoteModule(TheModule, Index, /*ClearDSOLocalOnDeclarations=*/false);
909
910 // Internalization
911 thinLTOFinalizeInModule(TheModule,
912 ModuleToDefinedGVSummaries[ModuleIdentifier],
913 /*PropagateAttrs=*/false);
914
915 thinLTOInternalizeModule(TheModule,
916 ModuleToDefinedGVSummaries[ModuleIdentifier]);
917}
918
919/**
920 * Perform post-importing ThinLTO optimizations.
921 */
923 initTMBuilder(TMBuilder, Triple(TheModule.getTargetTriple()));
924
925 // Optimize now
926 optimizeModule(TheModule, *TMBuilder.create(), OptLevel, Freestanding,
927 DebugPassManager, nullptr);
928}
929
930/// Write out the generated object file, either from CacheEntryPath or from
931/// OutputBuffer, preferring hard-link when possible.
932/// Returns the path to the generated file in SavedObjectsDirectoryPath.
933std::string
935 const MemoryBuffer &OutputBuffer) {
936 auto ArchName = TMBuilder.TheTriple.getArchName();
937 SmallString<128> OutputPath(SavedObjectsDirectoryPath);
938 llvm::sys::path::append(OutputPath,
939 Twine(count) + "." + ArchName + ".thinlto.o");
940 OutputPath.c_str(); // Ensure the string is null terminated.
941 if (sys::fs::exists(OutputPath))
942 sys::fs::remove(OutputPath);
943
944 // We don't return a memory buffer to the linker, just a list of files.
945 if (!CacheEntryPath.empty()) {
946 // Cache is enabled, hard-link the entry (or copy if hard-link fails).
947 auto Err = sys::fs::create_hard_link(CacheEntryPath, OutputPath);
948 if (!Err)
949 return std::string(OutputPath.str());
950 // Hard linking failed, try to copy.
951 Err = sys::fs::copy_file(CacheEntryPath, OutputPath);
952 if (!Err)
953 return std::string(OutputPath.str());
954 // Copy failed (could be because the CacheEntry was removed from the cache
955 // in the meantime by another process), fall back and try to write down the
956 // buffer to the output.
957 errs() << "remark: can't link or copy from cached entry '" << CacheEntryPath
958 << "' to '" << OutputPath << "'\n";
959 }
960 // No cache entry, just write out the buffer.
961 std::error_code Err;
962 raw_fd_ostream OS(OutputPath, Err, sys::fs::OF_None);
963 if (Err)
964 report_fatal_error(Twine("Can't open output '") + OutputPath + "'\n");
965 OS << OutputBuffer.getBuffer();
966 return std::string(OutputPath.str());
967}
968
969// Main entry point for the ThinLTO processing
971 timeTraceProfilerBegin("ThinLink", StringRef(""));
972 auto TimeTraceScopeExit = llvm::make_scope_exit([]() {
975 });
976 // Prepare the resulting object vector
977 assert(ProducedBinaries.empty() && "The generator should not be reused");
978 if (SavedObjectsDirectoryPath.empty())
979 ProducedBinaries.resize(Modules.size());
980 else {
981 sys::fs::create_directories(SavedObjectsDirectoryPath);
982 bool IsDir;
983 sys::fs::is_directory(SavedObjectsDirectoryPath, IsDir);
984 if (!IsDir)
985 report_fatal_error(Twine("Unexistent dir: '") + SavedObjectsDirectoryPath + "'");
986 ProducedBinaryFiles.resize(Modules.size());
987 }
988
989 if (CodeGenOnly) {
990 // Perform only parallel codegen and return.
991 ThreadPool Pool;
992 int count = 0;
993 for (auto &Mod : Modules) {
994 Pool.async([&](int count) {
997
998 // Parse module now
999 auto TheModule = loadModuleFromInput(Mod.get(), Context, false,
1000 /*IsImporting*/ false);
1001
1002 // CodeGen
1003 auto OutputBuffer = codegenModule(*TheModule, *TMBuilder.create());
1004 if (SavedObjectsDirectoryPath.empty())
1005 ProducedBinaries[count] = std::move(OutputBuffer);
1006 else
1007 ProducedBinaryFiles[count] =
1008 writeGeneratedObject(count, "", *OutputBuffer);
1009 }, count++);
1010 }
1011
1012 return;
1013 }
1014
1015 // Sequential linking phase
1016 auto Index = linkCombinedIndex();
1017
1018 // Save temps: index.
1019 if (!SaveTempsDir.empty()) {
1020 auto SaveTempPath = SaveTempsDir + "index.bc";
1021 std::error_code EC;
1022 raw_fd_ostream OS(SaveTempPath, EC, sys::fs::OF_None);
1023 if (EC)
1024 report_fatal_error(Twine("Failed to open ") + SaveTempPath +
1025 " to save optimized bitcode\n");
1027 }
1028
1029
1030 // Prepare the module map.
1031 auto ModuleMap = generateModuleMap(Modules);
1032 auto ModuleCount = Modules.size();
1033
1034 // Collect for each module the list of function it defines (GUID -> Summary).
1035 DenseMap<StringRef, GVSummaryMapTy> ModuleToDefinedGVSummaries(ModuleCount);
1036 Index->collectDefinedGVSummariesPerModule(ModuleToDefinedGVSummaries);
1037
1038 // Convert the preserved symbols set from string to GUID, this is needed for
1039 // computing the caching hash and the internalization.
1040 DenseSet<GlobalValue::GUID> GUIDPreservedSymbols;
1041 for (const auto &M : Modules)
1042 computeGUIDPreservedSymbols(*M, PreservedSymbols, TMBuilder.TheTriple,
1043 GUIDPreservedSymbols);
1044
1045 // Add used symbol from inputs to the preserved symbols.
1046 for (const auto &M : Modules)
1047 addUsedSymbolToPreservedGUID(*M, GUIDPreservedSymbols);
1048
1049 // Compute "dead" symbols, we don't want to import/export these!
1050 computeDeadSymbolsInIndex(*Index, GUIDPreservedSymbols);
1051
1052 // Synthesize entry counts for functions in the combined index.
1054
1055 // Currently there is no support for enabling whole program visibility via a
1056 // linker option in the old LTO API, but this call allows it to be specified
1057 // via the internal option. Must be done before WPD below.
1058 if (hasWholeProgramVisibility(/* WholeProgramVisibilityEnabledInLTO */ false))
1059 Index->setWithWholeProgramVisibility();
1060
1061 // FIXME: This needs linker information via a TBD new interface
1063 /*WholeProgramVisibilityEnabledInLTO=*/false,
1064 // FIXME: These need linker information via a
1065 // TBD new interface.
1066 /*DynamicExportSymbols=*/{},
1067 /*VisibleToRegularObjSymbols=*/{});
1068
1069 // Perform index-based WPD. This will return immediately if there are
1070 // no index entries in the typeIdMetadata map (e.g. if we are instead
1071 // performing IR-based WPD in hybrid regular/thin LTO mode).
1072 std::map<ValueInfo, std::vector<VTableSlotSummary>> LocalWPDTargetsMap;
1073 std::set<GlobalValue::GUID> ExportedGUIDs;
1074 runWholeProgramDevirtOnIndex(*Index, ExportedGUIDs, LocalWPDTargetsMap);
1075 for (auto GUID : ExportedGUIDs)
1076 GUIDPreservedSymbols.insert(GUID);
1077
1078 // Compute prevailing symbols
1080 computePrevailingCopies(*Index, PrevailingCopy);
1081
1082 // Collect the import/export lists for all modules from the call-graph in the
1083 // combined index.
1086 ComputeCrossModuleImport(*Index, ModuleToDefinedGVSummaries,
1087 IsPrevailing(PrevailingCopy), ImportLists,
1088 ExportLists);
1089
1090 // We use a std::map here to be able to have a defined ordering when
1091 // producing a hash for the cache entry.
1092 // FIXME: we should be able to compute the caching hash for the entry based
1093 // on the index, and nuke this map.
1095
1096 // Resolve prevailing symbols, this has to be computed early because it
1097 // impacts the caching.
1098 resolvePrevailingInIndex(*Index, ResolvedODR, GUIDPreservedSymbols,
1099 PrevailingCopy);
1100
1101 // Use global summary-based analysis to identify symbols that can be
1102 // internalized (because they aren't exported or preserved as per callback).
1103 // Changes are made in the index, consumed in the ThinLTO backends.
1105 IsExported(ExportLists, GUIDPreservedSymbols),
1106 LocalWPDTargetsMap);
1108 *Index, IsExported(ExportLists, GUIDPreservedSymbols),
1109 IsPrevailing(PrevailingCopy));
1110
1111 thinLTOPropagateFunctionAttrs(*Index, IsPrevailing(PrevailingCopy));
1112
1113 // Make sure that every module has an entry in the ExportLists, ImportList,
1114 // GVSummary and ResolvedODR maps to enable threaded access to these maps
1115 // below.
1116 for (auto &Module : Modules) {
1117 auto ModuleIdentifier = Module->getName();
1118 ExportLists[ModuleIdentifier];
1119 ImportLists[ModuleIdentifier];
1120 ResolvedODR[ModuleIdentifier];
1121 ModuleToDefinedGVSummaries[ModuleIdentifier];
1122 }
1123
1124 std::vector<BitcodeModule *> ModulesVec;
1125 ModulesVec.reserve(Modules.size());
1126 for (auto &Mod : Modules)
1127 ModulesVec.push_back(&Mod->getSingleBitcodeModule());
1128 std::vector<int> ModulesOrdering = lto::generateModulesOrdering(ModulesVec);
1129
1132
1133 TimeTraceScopeExit.release();
1134
1135 // Parallel optimizer + codegen
1136 {
1138 for (auto IndexCount : ModulesOrdering) {
1139 auto &Mod = Modules[IndexCount];
1140 Pool.async([&](int count) {
1141 auto ModuleIdentifier = Mod->getName();
1142 auto &ExportList = ExportLists[ModuleIdentifier];
1143
1144 auto &DefinedGVSummaries = ModuleToDefinedGVSummaries[ModuleIdentifier];
1145
1146 // The module may be cached, this helps handling it.
1147 ModuleCacheEntry CacheEntry(CacheOptions.Path, *Index, ModuleIdentifier,
1148 ImportLists[ModuleIdentifier], ExportList,
1149 ResolvedODR[ModuleIdentifier],
1150 DefinedGVSummaries, OptLevel, Freestanding,
1151 TMBuilder);
1152 auto CacheEntryPath = CacheEntry.getEntryPath();
1153
1154 {
1155 auto ErrOrBuffer = CacheEntry.tryLoadingBuffer();
1156 LLVM_DEBUG(dbgs() << "Cache " << (ErrOrBuffer ? "hit" : "miss")
1157 << " '" << CacheEntryPath << "' for buffer "
1158 << count << " " << ModuleIdentifier << "\n");
1159
1160 if (ErrOrBuffer) {
1161 // Cache Hit!
1162 if (SavedObjectsDirectoryPath.empty())
1163 ProducedBinaries[count] = std::move(ErrOrBuffer.get());
1164 else
1165 ProducedBinaryFiles[count] = writeGeneratedObject(
1166 count, CacheEntryPath, *ErrOrBuffer.get());
1167 return;
1168 }
1169 }
1170
1174 auto DiagFileOrErr = lto::setupLLVMOptimizationRemarks(
1177 if (!DiagFileOrErr) {
1178 errs() << "Error: " << toString(DiagFileOrErr.takeError()) << "\n";
1179 report_fatal_error("ThinLTO: Can't get an output file for the "
1180 "remarks");
1181 }
1182
1183 // Parse module now
1184 auto TheModule = loadModuleFromInput(Mod.get(), Context, false,
1185 /*IsImporting*/ false);
1186
1187 // Save temps: original file.
1188 saveTempBitcode(*TheModule, SaveTempsDir, count, ".0.original.bc");
1189
1190 auto &ImportList = ImportLists[ModuleIdentifier];
1191 // Run the main process now, and generates a binary
1192 auto OutputBuffer = ProcessThinLTOModule(
1193 *TheModule, *Index, ModuleMap, *TMBuilder.create(), ImportList,
1194 ExportList, GUIDPreservedSymbols,
1195 ModuleToDefinedGVSummaries[ModuleIdentifier], CacheOptions,
1196 DisableCodeGen, SaveTempsDir, Freestanding, OptLevel, count,
1197 DebugPassManager);
1198
1199 // Commit to the cache (if enabled)
1200 CacheEntry.write(*OutputBuffer);
1201
1202 if (SavedObjectsDirectoryPath.empty()) {
1203 // We need to generated a memory buffer for the linker.
1204 if (!CacheEntryPath.empty()) {
1205 // When cache is enabled, reload from the cache if possible.
1206 // Releasing the buffer from the heap and reloading it from the
1207 // cache file with mmap helps us to lower memory pressure.
1208 // The freed memory can be used for the next input file.
1209 // The final binary link will read from the VFS cache (hopefully!)
1210 // or from disk (if the memory pressure was too high).
1211 auto ReloadedBufferOrErr = CacheEntry.tryLoadingBuffer();
1212 if (auto EC = ReloadedBufferOrErr.getError()) {
1213 // On error, keep the preexisting buffer and print a diagnostic.
1214 errs() << "remark: can't reload cached file '" << CacheEntryPath
1215 << "': " << EC.message() << "\n";
1216 } else {
1217 OutputBuffer = std::move(*ReloadedBufferOrErr);
1218 }
1219 }
1220 ProducedBinaries[count] = std::move(OutputBuffer);
1221 return;
1222 }
1223 ProducedBinaryFiles[count] = writeGeneratedObject(
1224 count, CacheEntryPath, *OutputBuffer);
1225 }, IndexCount);
1226 }
1227 }
1228
1229 pruneCache(CacheOptions.Path, CacheOptions.Policy, ProducedBinaries);
1230
1231 // If statistics were requested, print them out now.
1235}
This file provides a bitcode writing pass.
#define LLVM_DEBUG(X)
Definition: Debug.h:101
std::string Name
Symbol * Sym
Definition: ELF_riscv.cpp:468
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:181
A container for analyses that lazily runs them and caches their results.
Definition: PassManager.h:620
bool registerPass(PassBuilderT &&PassBuilder)
Register an analysis pass with the manager.
Definition: PassManager.h:836
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:374
GUID getGUID() const
Return a 64-bit global unique ID constructed from global value name (i.e.
Definition: GlobalValue.h:591
bool isWeakForLinker() const
Definition: GlobalValue.h:547
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:168
LinkageTypes
An enumeration for the kinds of linkage for global values.
Definition: GlobalValue.h:47
@ ExternalLinkage
Externally visible function.
Definition: GlobalValue.h:48
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:262
StringRef getName() const
Get a short "name" for the module.
Definition: Module.h:245
const std::string & getTargetTriple() const
Get the target triple which is a string describing the target host.
Definition: Module.h:258
const std::string & getModuleIdentifier() const
Get the module identifier which is, essentially, the name of the module.
Definition: Module.h:228
PIELevel::Level getPIELevel() const
Returns the PIE level (small or large model)
Definition: Module.cpp:602
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:103
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:544
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:498
Tunable parameters for passes in the default pipelines.
Definition: PassBuilder.h:41
bool SLPVectorization
Tuning option to enable/disable slp loop vectorization, set based on opt level.
Definition: PassBuilder.h:56
bool LoopVectorization
Tuning option to enable/disable loop vectorization, set based on opt level.
Definition: PassBuilder.h:52
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:264
StringRef str() const
Explicit conversion to StringRef.
Definition: SmallString.h:261
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:1200
This class provides an interface to register all the standard pass instrumentations and manages their...
unsigned size() const
Definition: StringMap.h:95
StringMap - This is an unconventional map that is specialized for handling keys that are "strings",...
Definition: StringMap.h:112
bool contains(StringRef Key) const
contains - Return true if the element is in the map, false otherwise.
Definition: StringMap.h:254
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:355
const std::string & str() const
Definition: Triple.h:414
std::string merge(const Triple &Other) const
Merge target triples.
Definition: Triple.cpp:1820
bool isOSDarwin() const
Is this a "Darwin" OS (macOS, iOS, tvOS, watchOS, or DriverKit).
Definition: Triple.h:518
StringRef getArchName() const
Get the architecture (first) component of the triple.
Definition: Triple.cpp:1140
bool isCompatibleWith(const Triple &Other) const
Test whether target triples are compatible.
Definition: Triple.cpp:1796
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:454
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:672
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:445
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:1894
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:1850
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:1727
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.
Error write(MCStreamer &Out, ArrayRef< std::string > Inputs, bool ContinueOnCuIndexOverflow)
Definition: DWP.cpp:585
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)
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:542
@ 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:1919
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:1754
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:6600
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