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