LLVM 17.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"
46#include "llvm/Support/Debug.h"
47#include "llvm/Support/Error.h"
49#include "llvm/Support/Path.h"
50#include "llvm/Support/SHA1.h"
62
63#include <numeric>
64
65#if !defined(_MSC_VER) && !defined(__MINGW32__)
66#include <unistd.h>
67#else
68#include <io.h>
69#endif
70
71using namespace llvm;
72
73#define DEBUG_TYPE "thinlto"
74
75namespace llvm {
76// Flags -discard-value-names, defined in LTOCodeGenerator.cpp
84}
85
86namespace {
87
88// Default to using all available threads in the system, but using only one
89// thred per core, as indicated by the usage of
90// heavyweight_hardware_concurrency() below.
91static cl::opt<int> ThreadCount("threads", cl::init(0));
92
93// Simple helper to save temporary files for debug.
94static void saveTempBitcode(const Module &TheModule, StringRef TempDir,
95 unsigned count, StringRef Suffix) {
96 if (TempDir.empty())
97 return;
98 // User asked to save temps, let dump the bitcode file after import.
99 std::string SaveTempPath = (TempDir + llvm::Twine(count) + Suffix).str();
100 std::error_code EC;
101 raw_fd_ostream OS(SaveTempPath, EC, sys::fs::OF_None);
102 if (EC)
103 report_fatal_error(Twine("Failed to open ") + SaveTempPath +
104 " to save optimized bitcode\n");
105 WriteBitcodeToFile(TheModule, OS, /* ShouldPreserveUseListOrder */ true);
106}
107
108static const GlobalValueSummary *
109getFirstDefinitionForLinker(const GlobalValueSummaryList &GVSummaryList) {
110 // If there is any strong definition anywhere, get it.
111 auto StrongDefForLinker = llvm::find_if(
112 GVSummaryList, [](const std::unique_ptr<GlobalValueSummary> &Summary) {
113 auto Linkage = Summary->linkage();
116 });
117 if (StrongDefForLinker != GVSummaryList.end())
118 return StrongDefForLinker->get();
119 // Get the first *linker visible* definition for this global in the summary
120 // list.
121 auto FirstDefForLinker = llvm::find_if(
122 GVSummaryList, [](const std::unique_ptr<GlobalValueSummary> &Summary) {
123 auto Linkage = Summary->linkage();
125 });
126 // Extern templates can be emitted as available_externally.
127 if (FirstDefForLinker == GVSummaryList.end())
128 return nullptr;
129 return FirstDefForLinker->get();
130}
131
132// Populate map of GUID to the prevailing copy for any multiply defined
133// symbols. Currently assume first copy is prevailing, or any strong
134// definition. Can be refined with Linker information in the future.
135static void computePrevailingCopies(
138 auto HasMultipleCopies = [&](const GlobalValueSummaryList &GVSummaryList) {
139 return GVSummaryList.size() > 1;
140 };
141
142 for (auto &I : Index) {
143 if (HasMultipleCopies(I.second.SummaryList))
144 PrevailingCopy[I.first] =
145 getFirstDefinitionForLinker(I.second.SummaryList);
146 }
147}
148
150generateModuleMap(std::vector<std::unique_ptr<lto::InputFile>> &Modules) {
152 for (auto &M : Modules) {
153 assert(ModuleMap.find(M->getName()) == ModuleMap.end() &&
154 "Expect unique Buffer Identifier");
155 ModuleMap[M->getName()] = M.get();
156 }
157 return ModuleMap;
158}
159
160static void promoteModule(Module &TheModule, const ModuleSummaryIndex &Index,
161 bool ClearDSOLocalOnDeclarations) {
162 if (renameModuleForThinLTO(TheModule, Index, ClearDSOLocalOnDeclarations))
163 report_fatal_error("renameModuleForThinLTO failed");
164}
165
166namespace {
167class ThinLTODiagnosticInfo : public DiagnosticInfo {
168 const Twine &Msg;
169public:
170 ThinLTODiagnosticInfo(const Twine &DiagMsg,
171 DiagnosticSeverity Severity = DS_Error)
172 : DiagnosticInfo(DK_Linker, Severity), Msg(DiagMsg) {}
173 void print(DiagnosticPrinter &DP) const override { DP << Msg; }
174};
175}
176
177/// Verify the module and strip broken debug info.
178static void verifyLoadedModule(Module &TheModule) {
179 bool BrokenDebugInfo = false;
180 if (verifyModule(TheModule, &dbgs(), &BrokenDebugInfo))
181 report_fatal_error("Broken module found, compilation aborted!");
182 if (BrokenDebugInfo) {
183 TheModule.getContext().diagnose(ThinLTODiagnosticInfo(
184 "Invalid debug info found, debug info will be stripped", DS_Warning));
185 StripDebugInfo(TheModule);
186 }
187}
188
189static std::unique_ptr<Module> loadModuleFromInput(lto::InputFile *Input,
190 LLVMContext &Context,
191 bool Lazy,
192 bool IsImporting) {
193 auto &Mod = Input->getSingleBitcodeModule();
194 SMDiagnostic Err;
196 Lazy ? Mod.getLazyModule(Context,
197 /* ShouldLazyLoadMetadata */ true, IsImporting)
198 : Mod.parseModule(Context);
199 if (!ModuleOrErr) {
200 handleAllErrors(ModuleOrErr.takeError(), [&](ErrorInfoBase &EIB) {
201 SMDiagnostic Err = SMDiagnostic(Mod.getModuleIdentifier(),
202 SourceMgr::DK_Error, EIB.message());
203 Err.print("ThinLTO", errs());
204 });
205 report_fatal_error("Can't load module, abort.");
206 }
207 if (!Lazy)
208 verifyLoadedModule(*ModuleOrErr.get());
209 return std::move(*ModuleOrErr);
210}
211
212static void
213crossImportIntoModule(Module &TheModule, const ModuleSummaryIndex &Index,
215 const FunctionImporter::ImportMapTy &ImportList,
216 bool ClearDSOLocalOnDeclarations) {
217 auto Loader = [&](StringRef Identifier) {
218 auto &Input = ModuleMap[Identifier];
219 return loadModuleFromInput(Input, TheModule.getContext(),
220 /*Lazy=*/true, /*IsImporting*/ true);
221 };
222
223 FunctionImporter Importer(Index, Loader, ClearDSOLocalOnDeclarations);
224 Expected<bool> Result = Importer.importFunctions(TheModule, ImportList);
225 if (!Result) {
226 handleAllErrors(Result.takeError(), [&](ErrorInfoBase &EIB) {
227 SMDiagnostic Err = SMDiagnostic(TheModule.getModuleIdentifier(),
228 SourceMgr::DK_Error, EIB.message());
229 Err.print("ThinLTO", errs());
230 });
231 report_fatal_error("importFunctions failed");
232 }
233 // Verify again after cross-importing.
234 verifyLoadedModule(TheModule);
235}
236
237static void optimizeModule(Module &TheModule, TargetMachine &TM,
238 unsigned OptLevel, bool Freestanding,
239 bool DebugPassManager, ModuleSummaryIndex *Index) {
240 std::optional<PGOOptions> PGOOpt;
245
247 StandardInstrumentations SI(TheModule.getContext(), DebugPassManager);
248 SI.registerCallbacks(PIC, &FAM);
250 PTO.LoopVectorization = true;
251 PTO.SLPVectorization = true;
252 PassBuilder PB(&TM, PTO, PGOOpt, &PIC);
253
254 std::unique_ptr<TargetLibraryInfoImpl> TLII(
255 new TargetLibraryInfoImpl(Triple(TM.getTargetTriple())));
256 if (Freestanding)
257 TLII->disableAllFunctions();
258 FAM.registerPass([&] { return TargetLibraryAnalysis(*TLII); });
259
260 // Register all the basic analyses with the managers.
266
268
270
271 switch (OptLevel) {
272 default:
273 llvm_unreachable("Invalid optimization level");
274 case 0:
276 break;
277 case 1:
279 break;
280 case 2:
282 break;
283 case 3:
285 break;
286 }
287
289
290 MPM.run(TheModule, MAM);
291}
292
293static void
294addUsedSymbolToPreservedGUID(const lto::InputFile &File,
295 DenseSet<GlobalValue::GUID> &PreservedGUID) {
296 for (const auto &Sym : File.symbols()) {
297 if (Sym.isUsed())
298 PreservedGUID.insert(GlobalValue::getGUID(Sym.getIRName()));
299 }
300}
301
302// Convert the PreservedSymbols map from "Name" based to "GUID" based.
303static void computeGUIDPreservedSymbols(const lto::InputFile &File,
305 const Triple &TheTriple,
307 // Iterate the symbols in the input file and if the input has preserved symbol
308 // compute the GUID for the symbol.
309 for (const auto &Sym : File.symbols()) {
310 if (PreservedSymbols.count(Sym.getName()) && !Sym.getIRName().empty())
312 Sym.getIRName(), GlobalValue::ExternalLinkage, "")));
313 }
314}
315
317computeGUIDPreservedSymbols(const lto::InputFile &File,
319 const Triple &TheTriple) {
320 DenseSet<GlobalValue::GUID> GUIDPreservedSymbols(PreservedSymbols.size());
321 computeGUIDPreservedSymbols(File, PreservedSymbols, TheTriple,
322 GUIDPreservedSymbols);
323 return GUIDPreservedSymbols;
324}
325
326std::unique_ptr<MemoryBuffer> codegenModule(Module &TheModule,
327 TargetMachine &TM) {
329
330 // CodeGen
331 {
334
335 // If the bitcode files contain ARC code and were compiled with optimization,
336 // the ObjCARCContractPass must be run, so do it unconditionally here.
338
339 // Setup the codegen now.
340 if (TM.addPassesToEmitFile(PM, OS, nullptr, CGFT_ObjectFile,
341 /* DisableVerify */ true))
342 report_fatal_error("Failed to setup codegen");
343
344 // Run codegen now. resulting binary is in OutputBuffer.
345 PM.run(TheModule);
346 }
347 return std::make_unique<SmallVectorMemoryBuffer>(
348 std::move(OutputBuffer), /*RequiresNullTerminator=*/false);
349}
350
351/// Manage caching for a single Module.
352class ModuleCacheEntry {
353 SmallString<128> EntryPath;
354
355public:
356 // Create a cache entry. This compute a unique hash for the Module considering
357 // the current list of export/import, and offer an interface to query to
358 // access the content in the cache.
359 ModuleCacheEntry(
360 StringRef CachePath, const ModuleSummaryIndex &Index, StringRef ModuleID,
361 const FunctionImporter::ImportMapTy &ImportList,
362 const FunctionImporter::ExportSetTy &ExportList,
363 const std::map<GlobalValue::GUID, GlobalValue::LinkageTypes> &ResolvedODR,
364 const GVSummaryMapTy &DefinedGVSummaries, unsigned OptLevel,
365 bool Freestanding, const TargetMachineBuilder &TMBuilder) {
366 if (CachePath.empty())
367 return;
368
369 if (!Index.modulePaths().count(ModuleID))
370 // The module does not have an entry, it can't have a hash at all
371 return;
372
373 if (all_of(Index.getModuleHash(ModuleID),
374 [](uint32_t V) { return V == 0; }))
375 // No hash entry, no caching!
376 return;
377
379 Conf.OptLevel = OptLevel;
380 Conf.Options = TMBuilder.Options;
381 Conf.CPU = TMBuilder.MCpu;
382 Conf.MAttrs.push_back(TMBuilder.MAttr);
383 Conf.RelocModel = TMBuilder.RelocModel;
384 Conf.CGOptLevel = TMBuilder.CGOptLevel;
385 Conf.Freestanding = Freestanding;
387 computeLTOCacheKey(Key, Conf, Index, ModuleID, ImportList, ExportList,
388 ResolvedODR, DefinedGVSummaries);
389
390 // This choice of file name allows the cache to be pruned (see pruneCache()
391 // in include/llvm/Support/CachePruning.h).
392 sys::path::append(EntryPath, CachePath, "llvmcache-" + Key);
393 }
394
395 // Access the path to this entry in the cache.
396 StringRef getEntryPath() { return EntryPath; }
397
398 // Try loading the buffer for this cache entry.
399 ErrorOr<std::unique_ptr<MemoryBuffer>> tryLoadingBuffer() {
400 if (EntryPath.empty())
401 return std::error_code();
402 SmallString<64> ResultPath;
404 Twine(EntryPath), sys::fs::OF_UpdateAtime, &ResultPath);
405 if (!FDOrErr)
406 return errorToErrorCode(FDOrErr.takeError());
408 *FDOrErr, EntryPath, /*FileSize=*/-1, /*RequiresNullTerminator=*/false);
409 sys::fs::closeFile(*FDOrErr);
410 return MBOrErr;
411 }
412
413 // Cache the Produced object file
414 void write(const MemoryBuffer &OutputBuffer) {
415 if (EntryPath.empty())
416 return;
417
418 // Write to a temporary to avoid race condition
419 SmallString<128> TempFilename;
420 SmallString<128> CachePath(EntryPath);
422 sys::path::append(TempFilename, CachePath, "Thin-%%%%%%.tmp.o");
423
424 if (auto Err = handleErrors(
425 llvm::writeFileAtomically(TempFilename, EntryPath,
427 [](const llvm::AtomicFileWriteError &E) {
428 std::string ErrorMsgBuffer;
429 llvm::raw_string_ostream S(ErrorMsgBuffer);
430 E.log(S);
431
432 if (E.Error ==
433 llvm::atomic_write_error::failed_to_create_uniq_file) {
434 errs() << "Error: " << ErrorMsgBuffer << "\n";
435 report_fatal_error("ThinLTO: Can't get a temporary file");
436 }
437 })) {
438 // FIXME
439 consumeError(std::move(Err));
440 }
441 }
442};
443
444static std::unique_ptr<MemoryBuffer>
445ProcessThinLTOModule(Module &TheModule, ModuleSummaryIndex &Index,
447 const FunctionImporter::ImportMapTy &ImportList,
448 const FunctionImporter::ExportSetTy &ExportList,
449 const DenseSet<GlobalValue::GUID> &GUIDPreservedSymbols,
450 const GVSummaryMapTy &DefinedGlobals,
451 const ThinLTOCodeGenerator::CachingOptions &CacheOptions,
452 bool DisableCodeGen, StringRef SaveTempsDir,
453 bool Freestanding, unsigned OptLevel, unsigned count,
454 bool DebugPassManager) {
455 // See comment at call to updateVCallVisibilityInIndex() for why
456 // WholeProgramVisibilityEnabledInLTO is false.
458 /* WholeProgramVisibilityEnabledInLTO */ false);
459
460 // "Benchmark"-like optimization: single-source case
461 bool SingleModule = (ModuleMap.size() == 1);
462
463 // When linking an ELF shared object, dso_local should be dropped. We
464 // conservatively do this for -fpic.
465 bool ClearDSOLocalOnDeclarations =
466 TM.getTargetTriple().isOSBinFormatELF() &&
467 TM.getRelocationModel() != Reloc::Static &&
468 TheModule.getPIELevel() == PIELevel::Default;
469
470 if (!SingleModule) {
471 promoteModule(TheModule, Index, ClearDSOLocalOnDeclarations);
472
473 // Apply summary-based prevailing-symbol resolution decisions.
474 thinLTOFinalizeInModule(TheModule, DefinedGlobals, /*PropagateAttrs=*/true);
475
476 // Save temps: after promotion.
477 saveTempBitcode(TheModule, SaveTempsDir, count, ".1.promoted.bc");
478 }
479
480 // Be friendly and don't nuke totally the module when the client didn't
481 // supply anything to preserve.
482 if (!ExportList.empty() || !GUIDPreservedSymbols.empty()) {
483 // Apply summary-based internalization decisions.
484 thinLTOInternalizeModule(TheModule, DefinedGlobals);
485 }
486
487 // Save internalized bitcode
488 saveTempBitcode(TheModule, SaveTempsDir, count, ".2.internalized.bc");
489
490 if (!SingleModule) {
491 crossImportIntoModule(TheModule, Index, ModuleMap, ImportList,
492 ClearDSOLocalOnDeclarations);
493
494 // Save temps: after cross-module import.
495 saveTempBitcode(TheModule, SaveTempsDir, count, ".3.imported.bc");
496 }
497
498 optimizeModule(TheModule, TM, OptLevel, Freestanding, DebugPassManager,
499 &Index);
500
501 saveTempBitcode(TheModule, SaveTempsDir, count, ".4.opt.bc");
502
503 if (DisableCodeGen) {
504 // Configured to stop before CodeGen, serialize the bitcode and return.
506 {
508 ProfileSummaryInfo PSI(TheModule);
509 auto Index = buildModuleSummaryIndex(TheModule, nullptr, &PSI);
510 WriteBitcodeToFile(TheModule, OS, true, &Index);
511 }
512 return std::make_unique<SmallVectorMemoryBuffer>(
513 std::move(OutputBuffer), /*RequiresNullTerminator=*/false);
514 }
515
516 return codegenModule(TheModule, TM);
517}
518
519/// Resolve prevailing symbols. Record resolutions in the \p ResolvedODR map
520/// for caching, and in the \p Index for application during the ThinLTO
521/// backends. This is needed for correctness for exported symbols (ensure
522/// at least one copy kept) and a compile-time optimization (to drop duplicate
523/// copies when possible).
524static void resolvePrevailingInIndex(
526 StringMap<std::map<GlobalValue::GUID, GlobalValue::LinkageTypes>>
527 &ResolvedODR,
528 const DenseSet<GlobalValue::GUID> &GUIDPreservedSymbols,
530 &PrevailingCopy) {
531
532 auto isPrevailing = [&](GlobalValue::GUID GUID, const GlobalValueSummary *S) {
533 const auto &Prevailing = PrevailingCopy.find(GUID);
534 // Not in map means that there was only one copy, which must be prevailing.
535 if (Prevailing == PrevailingCopy.end())
536 return true;
537 return Prevailing->second == S;
538 };
539
540 auto recordNewLinkage = [&](StringRef ModuleIdentifier,
542 GlobalValue::LinkageTypes NewLinkage) {
543 ResolvedODR[ModuleIdentifier][GUID] = NewLinkage;
544 };
545
546 // TODO Conf.VisibilityScheme can be lto::Config::ELF for ELF.
547 lto::Config Conf;
548 thinLTOResolvePrevailingInIndex(Conf, Index, isPrevailing, recordNewLinkage,
549 GUIDPreservedSymbols);
550}
551
552// Initialize the TargetMachine builder for a given Triple
553static void initTMBuilder(TargetMachineBuilder &TMBuilder,
554 const Triple &TheTriple) {
555 // Set a default CPU for Darwin triples (copied from LTOCodeGenerator).
556 // FIXME this looks pretty terrible...
557 if (TMBuilder.MCpu.empty() && TheTriple.isOSDarwin()) {
558 if (TheTriple.getArch() == llvm::Triple::x86_64)
559 TMBuilder.MCpu = "core2";
560 else if (TheTriple.getArch() == llvm::Triple::x86)
561 TMBuilder.MCpu = "yonah";
562 else if (TheTriple.getArch() == llvm::Triple::aarch64 ||
563 TheTriple.getArch() == llvm::Triple::aarch64_32)
564 TMBuilder.MCpu = "cyclone";
565 }
566 TMBuilder.TheTriple = std::move(TheTriple);
567}
568
569} // end anonymous namespace
570
572 MemoryBufferRef Buffer(Data, Identifier);
573
574 auto InputOrError = lto::InputFile::create(Buffer);
575 if (!InputOrError)
576 report_fatal_error(Twine("ThinLTO cannot create input file: ") +
577 toString(InputOrError.takeError()));
578
579 auto TripleStr = (*InputOrError)->getTargetTriple();
580 Triple TheTriple(TripleStr);
581
582 if (Modules.empty())
583 initTMBuilder(TMBuilder, Triple(TheTriple));
584 else if (TMBuilder.TheTriple != TheTriple) {
585 if (!TMBuilder.TheTriple.isCompatibleWith(TheTriple))
586 report_fatal_error("ThinLTO modules with incompatible triples not "
587 "supported");
588 initTMBuilder(TMBuilder, Triple(TMBuilder.TheTriple.merge(TheTriple)));
589 }
590
591 Modules.emplace_back(std::move(*InputOrError));
592}
593
595 PreservedSymbols.insert(Name);
596}
597
599 // FIXME: At the moment, we don't take advantage of this extra information,
600 // we're conservatively considering cross-references as preserved.
601 // CrossReferencedSymbols.insert(Name);
602 PreservedSymbols.insert(Name);
603}
604
605// TargetMachine factory
606std::unique_ptr<TargetMachine> TargetMachineBuilder::create() const {
607 std::string ErrMsg;
608 const Target *TheTarget =
610 if (!TheTarget) {
611 report_fatal_error(Twine("Can't load target for this Triple: ") + ErrMsg);
612 }
613
614 // Use MAttr as the default set of features.
615 SubtargetFeatures Features(MAttr);
617 std::string FeatureStr = Features.getString();
618
619 std::unique_ptr<TargetMachine> TM(
620 TheTarget->createTargetMachine(TheTriple.str(), MCpu, FeatureStr, Options,
621 RelocModel, std::nullopt, CGOptLevel));
622 assert(TM && "Cannot create target machine");
623
624 return TM;
625}
626
627/**
628 * Produce the combined summary index from all the bitcode files:
629 * "thin-link".
630 */
631std::unique_ptr<ModuleSummaryIndex> ThinLTOCodeGenerator::linkCombinedIndex() {
632 std::unique_ptr<ModuleSummaryIndex> CombinedIndex =
633 std::make_unique<ModuleSummaryIndex>(/*HaveGVs=*/false);
634 uint64_t NextModuleId = 0;
635 for (auto &Mod : Modules) {
636 auto &M = Mod->getSingleBitcodeModule();
637 if (Error Err =
638 M.readSummary(*CombinedIndex, Mod->getName(), NextModuleId++)) {
639 // FIXME diagnose
641 std::move(Err), errs(),
642 "error: can't create module summary index for buffer: ");
643 return nullptr;
644 }
645 }
646 return CombinedIndex;
647}
648
649namespace {
650struct IsExported {
652 const DenseSet<GlobalValue::GUID> &GUIDPreservedSymbols;
653
654 IsExported(const StringMap<FunctionImporter::ExportSetTy> &ExportLists,
655 const DenseSet<GlobalValue::GUID> &GUIDPreservedSymbols)
656 : ExportLists(ExportLists), GUIDPreservedSymbols(GUIDPreservedSymbols) {}
657
658 bool operator()(StringRef ModuleIdentifier, ValueInfo VI) const {
659 const auto &ExportList = ExportLists.find(ModuleIdentifier);
660 return (ExportList != ExportLists.end() && ExportList->second.count(VI)) ||
661 GUIDPreservedSymbols.count(VI.getGUID());
662 }
663};
664
665struct IsPrevailing {
668 &PrevailingCopy)
669 : PrevailingCopy(PrevailingCopy) {}
670
671 bool operator()(GlobalValue::GUID GUID, const GlobalValueSummary *S) const {
672 const auto &Prevailing = PrevailingCopy.find(GUID);
673 // Not in map means that there was only one copy, which must be prevailing.
674 if (Prevailing == PrevailingCopy.end())
675 return true;
676 return Prevailing->second == S;
677 };
678};
679} // namespace
680
683 const DenseSet<GlobalValue::GUID> &GUIDPreservedSymbols) {
684 // We have no symbols resolution available. And can't do any better now in the
685 // case where the prevailing symbol is in a native object. It can be refined
686 // with linker information in the future.
687 auto isPrevailing = [&](GlobalValue::GUID G) {
689 };
690 computeDeadSymbolsWithConstProp(Index, GUIDPreservedSymbols, isPrevailing,
691 /* ImportEnabled = */ true);
692}
693
694/**
695 * Perform promotion and renaming of exported internal functions.
696 * Index is updated to reflect linkage changes from weak resolution.
697 */
699 const lto::InputFile &File) {
700 auto ModuleCount = Index.modulePaths().size();
701 auto ModuleIdentifier = TheModule.getModuleIdentifier();
702
703 // Collect for each module the list of function it defines (GUID -> Summary).
704 StringMap<GVSummaryMapTy> ModuleToDefinedGVSummaries;
705 Index.collectDefinedGVSummariesPerModule(ModuleToDefinedGVSummaries);
706
707 // Convert the preserved symbols set from string to GUID
708 auto GUIDPreservedSymbols = computeGUIDPreservedSymbols(
709 File, PreservedSymbols, Triple(TheModule.getTargetTriple()));
710
711 // Add used symbol to the preserved symbols.
712 addUsedSymbolToPreservedGUID(File, GUIDPreservedSymbols);
713
714 // Compute "dead" symbols, we don't want to import/export these!
715 computeDeadSymbolsInIndex(Index, GUIDPreservedSymbols);
716
717 // Generate import/export list
718 StringMap<FunctionImporter::ImportMapTy> ImportLists(ModuleCount);
719 StringMap<FunctionImporter::ExportSetTy> ExportLists(ModuleCount);
720 ComputeCrossModuleImport(Index, ModuleToDefinedGVSummaries, ImportLists,
721 ExportLists);
722
724 computePrevailingCopies(Index, PrevailingCopy);
725
726 // Resolve prevailing symbols
728 resolvePrevailingInIndex(Index, ResolvedODR, GUIDPreservedSymbols,
729 PrevailingCopy);
730
731 thinLTOFinalizeInModule(TheModule,
732 ModuleToDefinedGVSummaries[ModuleIdentifier],
733 /*PropagateAttrs=*/false);
734
735 // Promote the exported values in the index, so that they are promoted
736 // in the module.
738 Index, IsExported(ExportLists, GUIDPreservedSymbols),
739 IsPrevailing(PrevailingCopy));
740
741 // FIXME Set ClearDSOLocalOnDeclarations.
742 promoteModule(TheModule, Index, /*ClearDSOLocalOnDeclarations=*/false);
743}
744
745/**
746 * Perform cross-module importing for the module identified by ModuleIdentifier.
747 */
750 const lto::InputFile &File) {
751 auto ModuleMap = generateModuleMap(Modules);
752 auto ModuleCount = Index.modulePaths().size();
753
754 // Collect for each module the list of function it defines (GUID -> Summary).
755 StringMap<GVSummaryMapTy> ModuleToDefinedGVSummaries(ModuleCount);
756 Index.collectDefinedGVSummariesPerModule(ModuleToDefinedGVSummaries);
757
758 // Convert the preserved symbols set from string to GUID
759 auto GUIDPreservedSymbols = computeGUIDPreservedSymbols(
760 File, PreservedSymbols, Triple(TheModule.getTargetTriple()));
761
762 addUsedSymbolToPreservedGUID(File, GUIDPreservedSymbols);
763
764 // Compute "dead" symbols, we don't want to import/export these!
765 computeDeadSymbolsInIndex(Index, GUIDPreservedSymbols);
766
767 // Generate import/export list
768 StringMap<FunctionImporter::ImportMapTy> ImportLists(ModuleCount);
769 StringMap<FunctionImporter::ExportSetTy> ExportLists(ModuleCount);
770 ComputeCrossModuleImport(Index, ModuleToDefinedGVSummaries, ImportLists,
771 ExportLists);
772 auto &ImportList = ImportLists[TheModule.getModuleIdentifier()];
773
774 // FIXME Set ClearDSOLocalOnDeclarations.
775 crossImportIntoModule(TheModule, Index, ModuleMap, ImportList,
776 /*ClearDSOLocalOnDeclarations=*/false);
777}
778
779/**
780 * Compute the list of summaries needed for importing into module.
781 */
783 Module &TheModule, ModuleSummaryIndex &Index,
784 std::map<std::string, GVSummaryMapTy> &ModuleToSummariesForIndex,
785 const lto::InputFile &File) {
786 auto ModuleCount = Index.modulePaths().size();
787 auto ModuleIdentifier = TheModule.getModuleIdentifier();
788
789 // Collect for each module the list of function it defines (GUID -> Summary).
790 StringMap<GVSummaryMapTy> ModuleToDefinedGVSummaries(ModuleCount);
791 Index.collectDefinedGVSummariesPerModule(ModuleToDefinedGVSummaries);
792
793 // Convert the preserved symbols set from string to GUID
794 auto GUIDPreservedSymbols = computeGUIDPreservedSymbols(
795 File, PreservedSymbols, Triple(TheModule.getTargetTriple()));
796
797 addUsedSymbolToPreservedGUID(File, GUIDPreservedSymbols);
798
799 // Compute "dead" symbols, we don't want to import/export these!
800 computeDeadSymbolsInIndex(Index, GUIDPreservedSymbols);
801
802 // Generate import/export list
803 StringMap<FunctionImporter::ImportMapTy> ImportLists(ModuleCount);
804 StringMap<FunctionImporter::ExportSetTy> ExportLists(ModuleCount);
805 ComputeCrossModuleImport(Index, ModuleToDefinedGVSummaries, ImportLists,
806 ExportLists);
807
809 ModuleIdentifier, ModuleToDefinedGVSummaries,
810 ImportLists[ModuleIdentifier], ModuleToSummariesForIndex);
811}
812
813/**
814 * Emit the list of files needed for importing into module.
815 */
818 const lto::InputFile &File) {
819 auto ModuleCount = Index.modulePaths().size();
820 auto ModuleIdentifier = TheModule.getModuleIdentifier();
821
822 // Collect for each module the list of function it defines (GUID -> Summary).
823 StringMap<GVSummaryMapTy> ModuleToDefinedGVSummaries(ModuleCount);
824 Index.collectDefinedGVSummariesPerModule(ModuleToDefinedGVSummaries);
825
826 // Convert the preserved symbols set from string to GUID
827 auto GUIDPreservedSymbols = computeGUIDPreservedSymbols(
828 File, PreservedSymbols, Triple(TheModule.getTargetTriple()));
829
830 addUsedSymbolToPreservedGUID(File, GUIDPreservedSymbols);
831
832 // Compute "dead" symbols, we don't want to import/export these!
833 computeDeadSymbolsInIndex(Index, GUIDPreservedSymbols);
834
835 // Generate import/export list
836 StringMap<FunctionImporter::ImportMapTy> ImportLists(ModuleCount);
837 StringMap<FunctionImporter::ExportSetTy> ExportLists(ModuleCount);
838 ComputeCrossModuleImport(Index, ModuleToDefinedGVSummaries, ImportLists,
839 ExportLists);
840
841 std::map<std::string, GVSummaryMapTy> ModuleToSummariesForIndex;
843 ModuleIdentifier, ModuleToDefinedGVSummaries,
844 ImportLists[ModuleIdentifier], ModuleToSummariesForIndex);
845
846 std::error_code EC;
847 if ((EC = EmitImportsFiles(ModuleIdentifier, OutputName,
848 ModuleToSummariesForIndex)))
849 report_fatal_error(Twine("Failed to open ") + OutputName +
850 " to save imports lists\n");
851}
852
853/**
854 * Perform internalization. Runs promote and internalization together.
855 * Index is updated to reflect linkage changes.
856 */
859 const lto::InputFile &File) {
860 initTMBuilder(TMBuilder, Triple(TheModule.getTargetTriple()));
861 auto ModuleCount = Index.modulePaths().size();
862 auto ModuleIdentifier = TheModule.getModuleIdentifier();
863
864 // Convert the preserved symbols set from string to GUID
865 auto GUIDPreservedSymbols =
866 computeGUIDPreservedSymbols(File, PreservedSymbols, TMBuilder.TheTriple);
867
868 addUsedSymbolToPreservedGUID(File, GUIDPreservedSymbols);
869
870 // Collect for each module the list of function it defines (GUID -> Summary).
871 StringMap<GVSummaryMapTy> ModuleToDefinedGVSummaries(ModuleCount);
872 Index.collectDefinedGVSummariesPerModule(ModuleToDefinedGVSummaries);
873
874 // Compute "dead" symbols, we don't want to import/export these!
875 computeDeadSymbolsInIndex(Index, GUIDPreservedSymbols);
876
877 // Generate import/export list
878 StringMap<FunctionImporter::ImportMapTy> ImportLists(ModuleCount);
879 StringMap<FunctionImporter::ExportSetTy> ExportLists(ModuleCount);
880 ComputeCrossModuleImport(Index, ModuleToDefinedGVSummaries, 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
890 computePrevailingCopies(Index, PrevailingCopy);
891
892 // Resolve prevailing symbols
894 resolvePrevailingInIndex(Index, ResolvedODR, GUIDPreservedSymbols,
895 PrevailingCopy);
896
897 // Promote the exported values in the index, so that they are promoted
898 // in the module.
900 Index, IsExported(ExportLists, GUIDPreservedSymbols),
901 IsPrevailing(PrevailingCopy));
902
903 // FIXME Set ClearDSOLocalOnDeclarations.
904 promoteModule(TheModule, Index, /*ClearDSOLocalOnDeclarations=*/false);
905
906 // Internalization
907 thinLTOFinalizeInModule(TheModule,
908 ModuleToDefinedGVSummaries[ModuleIdentifier],
909 /*PropagateAttrs=*/false);
910
911 thinLTOInternalizeModule(TheModule,
912 ModuleToDefinedGVSummaries[ModuleIdentifier]);
913}
914
915/**
916 * Perform post-importing ThinLTO optimizations.
917 */
919 initTMBuilder(TMBuilder, Triple(TheModule.getTargetTriple()));
920
921 // Optimize now
922 optimizeModule(TheModule, *TMBuilder.create(), OptLevel, Freestanding,
923 DebugPassManager, nullptr);
924}
925
926/// Write out the generated object file, either from CacheEntryPath or from
927/// OutputBuffer, preferring hard-link when possible.
928/// Returns the path to the generated file in SavedObjectsDirectoryPath.
929std::string
931 const MemoryBuffer &OutputBuffer) {
932 auto ArchName = TMBuilder.TheTriple.getArchName();
933 SmallString<128> OutputPath(SavedObjectsDirectoryPath);
934 llvm::sys::path::append(OutputPath,
935 Twine(count) + "." + ArchName + ".thinlto.o");
936 OutputPath.c_str(); // Ensure the string is null terminated.
937 if (sys::fs::exists(OutputPath))
938 sys::fs::remove(OutputPath);
939
940 // We don't return a memory buffer to the linker, just a list of files.
941 if (!CacheEntryPath.empty()) {
942 // Cache is enabled, hard-link the entry (or copy if hard-link fails).
943 auto Err = sys::fs::create_hard_link(CacheEntryPath, OutputPath);
944 if (!Err)
945 return std::string(OutputPath.str());
946 // Hard linking failed, try to copy.
947 Err = sys::fs::copy_file(CacheEntryPath, OutputPath);
948 if (!Err)
949 return std::string(OutputPath.str());
950 // Copy failed (could be because the CacheEntry was removed from the cache
951 // in the meantime by another process), fall back and try to write down the
952 // buffer to the output.
953 errs() << "remark: can't link or copy from cached entry '" << CacheEntryPath
954 << "' to '" << OutputPath << "'\n";
955 }
956 // No cache entry, just write out the buffer.
957 std::error_code Err;
958 raw_fd_ostream OS(OutputPath, Err, sys::fs::OF_None);
959 if (Err)
960 report_fatal_error(Twine("Can't open output '") + OutputPath + "'\n");
961 OS << OutputBuffer.getBuffer();
962 return std::string(OutputPath.str());
963}
964
965// Main entry point for the ThinLTO processing
967 timeTraceProfilerBegin("ThinLink", StringRef(""));
968 auto TimeTraceScopeExit = llvm::make_scope_exit([]() {
971 });
972 // Prepare the resulting object vector
973 assert(ProducedBinaries.empty() && "The generator should not be reused");
974 if (SavedObjectsDirectoryPath.empty())
975 ProducedBinaries.resize(Modules.size());
976 else {
977 sys::fs::create_directories(SavedObjectsDirectoryPath);
978 bool IsDir;
979 sys::fs::is_directory(SavedObjectsDirectoryPath, IsDir);
980 if (!IsDir)
981 report_fatal_error(Twine("Unexistent dir: '") + SavedObjectsDirectoryPath + "'");
982 ProducedBinaryFiles.resize(Modules.size());
983 }
984
985 if (CodeGenOnly) {
986 // Perform only parallel codegen and return.
987 ThreadPool Pool;
988 int count = 0;
989 for (auto &Mod : Modules) {
990 Pool.async([&](int count) {
993
994 // Parse module now
995 auto TheModule = loadModuleFromInput(Mod.get(), Context, false,
996 /*IsImporting*/ false);
997
998 // CodeGen
999 auto OutputBuffer = codegenModule(*TheModule, *TMBuilder.create());
1000 if (SavedObjectsDirectoryPath.empty())
1001 ProducedBinaries[count] = std::move(OutputBuffer);
1002 else
1003 ProducedBinaryFiles[count] =
1004 writeGeneratedObject(count, "", *OutputBuffer);
1005 }, count++);
1006 }
1007
1008 return;
1009 }
1010
1011 // Sequential linking phase
1012 auto Index = linkCombinedIndex();
1013
1014 // Save temps: index.
1015 if (!SaveTempsDir.empty()) {
1016 auto SaveTempPath = SaveTempsDir + "index.bc";
1017 std::error_code EC;
1018 raw_fd_ostream OS(SaveTempPath, EC, sys::fs::OF_None);
1019 if (EC)
1020 report_fatal_error(Twine("Failed to open ") + SaveTempPath +
1021 " to save optimized bitcode\n");
1022 writeIndexToFile(*Index, OS);
1023 }
1024
1025
1026 // Prepare the module map.
1027 auto ModuleMap = generateModuleMap(Modules);
1028 auto ModuleCount = Modules.size();
1029
1030 // Collect for each module the list of function it defines (GUID -> Summary).
1031 StringMap<GVSummaryMapTy> ModuleToDefinedGVSummaries(ModuleCount);
1032 Index->collectDefinedGVSummariesPerModule(ModuleToDefinedGVSummaries);
1033
1034 // Convert the preserved symbols set from string to GUID, this is needed for
1035 // computing the caching hash and the internalization.
1036 DenseSet<GlobalValue::GUID> GUIDPreservedSymbols;
1037 for (const auto &M : Modules)
1038 computeGUIDPreservedSymbols(*M, PreservedSymbols, TMBuilder.TheTriple,
1039 GUIDPreservedSymbols);
1040
1041 // Add used symbol from inputs to the preserved symbols.
1042 for (const auto &M : Modules)
1043 addUsedSymbolToPreservedGUID(*M, GUIDPreservedSymbols);
1044
1045 // Compute "dead" symbols, we don't want to import/export these!
1046 computeDeadSymbolsInIndex(*Index, GUIDPreservedSymbols);
1047
1048 // Synthesize entry counts for functions in the combined index.
1050
1051 // Currently there is no support for enabling whole program visibility via a
1052 // linker option in the old LTO API, but this call allows it to be specified
1053 // via the internal option. Must be done before WPD below.
1054 if (hasWholeProgramVisibility(/* WholeProgramVisibilityEnabledInLTO */ false))
1055 Index->setWithWholeProgramVisibility();
1057 /* WholeProgramVisibilityEnabledInLTO */ false,
1058 // FIXME: This needs linker information via a
1059 // TBD new interface.
1060 /* DynamicExportSymbols */ {});
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 // Collect the import/export lists for all modules from the call-graph in the
1072 // combined index.
1073 StringMap<FunctionImporter::ImportMapTy> ImportLists(ModuleCount);
1074 StringMap<FunctionImporter::ExportSetTy> ExportLists(ModuleCount);
1075 ComputeCrossModuleImport(*Index, ModuleToDefinedGVSummaries, ImportLists,
1076 ExportLists);
1077
1078 // We use a std::map here to be able to have a defined ordering when
1079 // producing a hash for the cache entry.
1080 // FIXME: we should be able to compute the caching hash for the entry based
1081 // on the index, and nuke this map.
1083
1085 computePrevailingCopies(*Index, PrevailingCopy);
1086
1087 // Resolve prevailing symbols, this has to be computed early because it
1088 // impacts the caching.
1089 resolvePrevailingInIndex(*Index, ResolvedODR, GUIDPreservedSymbols,
1090 PrevailingCopy);
1091
1092 // Use global summary-based analysis to identify symbols that can be
1093 // internalized (because they aren't exported or preserved as per callback).
1094 // Changes are made in the index, consumed in the ThinLTO backends.
1096 IsExported(ExportLists, GUIDPreservedSymbols),
1097 LocalWPDTargetsMap);
1099 *Index, IsExported(ExportLists, GUIDPreservedSymbols),
1100 IsPrevailing(PrevailingCopy));
1101
1102 thinLTOPropagateFunctionAttrs(*Index, IsPrevailing(PrevailingCopy));
1103
1104 // Make sure that every module has an entry in the ExportLists, ImportList,
1105 // GVSummary and ResolvedODR maps to enable threaded access to these maps
1106 // below.
1107 for (auto &Module : Modules) {
1108 auto ModuleIdentifier = Module->getName();
1109 ExportLists[ModuleIdentifier];
1110 ImportLists[ModuleIdentifier];
1111 ResolvedODR[ModuleIdentifier];
1112 ModuleToDefinedGVSummaries[ModuleIdentifier];
1113 }
1114
1115 std::vector<BitcodeModule *> ModulesVec;
1116 ModulesVec.reserve(Modules.size());
1117 for (auto &Mod : Modules)
1118 ModulesVec.push_back(&Mod->getSingleBitcodeModule());
1119 std::vector<int> ModulesOrdering = lto::generateModulesOrdering(ModulesVec);
1120
1123
1124 TimeTraceScopeExit.release();
1125
1126 // Parallel optimizer + codegen
1127 {
1129 for (auto IndexCount : ModulesOrdering) {
1130 auto &Mod = Modules[IndexCount];
1131 Pool.async([&](int count) {
1132 auto ModuleIdentifier = Mod->getName();
1133 auto &ExportList = ExportLists[ModuleIdentifier];
1134
1135 auto &DefinedGVSummaries = ModuleToDefinedGVSummaries[ModuleIdentifier];
1136
1137 // The module may be cached, this helps handling it.
1138 ModuleCacheEntry CacheEntry(CacheOptions.Path, *Index, ModuleIdentifier,
1139 ImportLists[ModuleIdentifier], ExportList,
1140 ResolvedODR[ModuleIdentifier],
1141 DefinedGVSummaries, OptLevel, Freestanding,
1142 TMBuilder);
1143 auto CacheEntryPath = CacheEntry.getEntryPath();
1144
1145 {
1146 auto ErrOrBuffer = CacheEntry.tryLoadingBuffer();
1147 LLVM_DEBUG(dbgs() << "Cache " << (ErrOrBuffer ? "hit" : "miss")
1148 << " '" << CacheEntryPath << "' for buffer "
1149 << count << " " << ModuleIdentifier << "\n");
1150
1151 if (ErrOrBuffer) {
1152 // Cache Hit!
1153 if (SavedObjectsDirectoryPath.empty())
1154 ProducedBinaries[count] = std::move(ErrOrBuffer.get());
1155 else
1156 ProducedBinaryFiles[count] = writeGeneratedObject(
1157 count, CacheEntryPath, *ErrOrBuffer.get());
1158 return;
1159 }
1160 }
1161
1165 auto DiagFileOrErr = lto::setupLLVMOptimizationRemarks(
1168 if (!DiagFileOrErr) {
1169 errs() << "Error: " << toString(DiagFileOrErr.takeError()) << "\n";
1170 report_fatal_error("ThinLTO: Can't get an output file for the "
1171 "remarks");
1172 }
1173
1174 // Parse module now
1175 auto TheModule = loadModuleFromInput(Mod.get(), Context, false,
1176 /*IsImporting*/ false);
1177
1178 // Save temps: original file.
1179 saveTempBitcode(*TheModule, SaveTempsDir, count, ".0.original.bc");
1180
1181 auto &ImportList = ImportLists[ModuleIdentifier];
1182 // Run the main process now, and generates a binary
1183 auto OutputBuffer = ProcessThinLTOModule(
1184 *TheModule, *Index, ModuleMap, *TMBuilder.create(), ImportList,
1185 ExportList, GUIDPreservedSymbols,
1186 ModuleToDefinedGVSummaries[ModuleIdentifier], CacheOptions,
1187 DisableCodeGen, SaveTempsDir, Freestanding, OptLevel, count,
1188 DebugPassManager);
1189
1190 // Commit to the cache (if enabled)
1191 CacheEntry.write(*OutputBuffer);
1192
1193 if (SavedObjectsDirectoryPath.empty()) {
1194 // We need to generated a memory buffer for the linker.
1195 if (!CacheEntryPath.empty()) {
1196 // When cache is enabled, reload from the cache if possible.
1197 // Releasing the buffer from the heap and reloading it from the
1198 // cache file with mmap helps us to lower memory pressure.
1199 // The freed memory can be used for the next input file.
1200 // The final binary link will read from the VFS cache (hopefully!)
1201 // or from disk (if the memory pressure was too high).
1202 auto ReloadedBufferOrErr = CacheEntry.tryLoadingBuffer();
1203 if (auto EC = ReloadedBufferOrErr.getError()) {
1204 // On error, keep the preexisting buffer and print a diagnostic.
1205 errs() << "remark: can't reload cached file '" << CacheEntryPath
1206 << "': " << EC.message() << "\n";
1207 } else {
1208 OutputBuffer = std::move(*ReloadedBufferOrErr);
1209 }
1210 }
1211 ProducedBinaries[count] = std::move(OutputBuffer);
1212 return;
1213 }
1214 ProducedBinaryFiles[count] = writeGeneratedObject(
1215 count, CacheEntryPath, *OutputBuffer);
1216 }, IndexCount);
1217 }
1218 }
1219
1220 pruneCache(CacheOptions.Path, CacheOptions.Policy, ProducedBinaries);
1221
1222 // If statistics were requested, print them out now.
1226}
This file provides a bitcode writing pass.
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
#define LLVM_DEBUG(X)
Definition: Debug.h:101
std::string Name
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...
@ SI
@ VI
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
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:176
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:150
iterator end()
Definition: DenseMap.h:84
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:47
Represents either an error or a value T.
Definition: ErrorOr.h:56
Lightweight error class with error context and mandatory checking.
Definition: Error.h:156
Tagged union holding either a T or a Error.
Definition: Error.h:470
Error takeError()
Take ownership of the stored error.
Definition: Error.h:597
reference get()
Returns a reference to the stored T value.
Definition: Error.h:567
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:170
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:604
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:100
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:111
iterator end()
Definition: StringMap.h:204
iterator find(StringRef Key)
Definition: StringMap.h:217
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, CodeGenOpt::Level OL=CodeGenOpt::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:1822
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:1147
bool isCompatibleWith(const Triple &Other) const
Test whether target triples are compatible.
Definition: Triple.cpp:1798
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:105
static Expected< std::unique_ptr< InputFile > > create(MemoryBufferRef Object)
Create an InputFile.
Definition: LTO.cpp:475
BitcodeModule & getSingleBitcodeModule()
Definition: LTO.cpp:508
A raw_ostream that writes to a file descriptor.
Definition: raw_ostream.h:454
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:1689
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:1645
std::error_code closeFile(file_t &F)
Close the file object.
bool exists(const basic_file_status &status)
Does file exist?
Definition: Path.cpp:1077
@ OF_UpdateAtime
Force files Atime to be updated on access.
Definition: FileSystem.h:785
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:967
std::error_code copy_file(const Twine &From, const Twine &To)
Copy the contents of From to To.
Definition: Path.cpp:1016
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:1092
void remove_filename(SmallVectorImpl< char > &path, Style style=Style::native)
Remove the last component from path unless it is the root dir.
Definition: Path.cpp:474
void append(SmallVectorImpl< char > &path, const Twine &a, const Twine &b="", const Twine &c="", const Twine &d="")
Append to path.
Definition: Path.cpp:456
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
llvm::Error writeFileAtomically(StringRef TempPathModel, StringRef FinalPath, StringRef Buffer)
Creates a unique file with name according to the given TempPathModel, writes content of Buffer to the...
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:63
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"))
Error write(MCStreamer &Out, ArrayRef< std::string > Inputs)
Definition: DWP.cpp:551
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:1735
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:966
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 ...
void gatherImportedSummariesForModule(StringRef ModulePath, const StringMap< 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.
Error handleErrors(Error E, HandlerTs &&... Hs)
Pass the ErrorInfo(s) contained in E to their respective handlers.
Definition: Error.h:943
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:462
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:81
void timeTraceProfilerBegin(StringRef Name, StringRef Detail)
Manually begin a time section, with the given Name and Detail.
void updatePublicTypeTestCalls(Module &M, bool WholeProgramVisibilityEnabledInLTO)
@ CGFT_ObjectFile
Definition: CodeGen.h:86
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:145
void ComputeCrossModuleImport(const ModuleSummaryIndex &Index, const StringMap< GVSummaryMapTy > &ModuleToDefinedGVSummaries, StringMap< FunctionImporter::ImportMapTy > &ImportLists, StringMap< FunctionImporter::ExportSetTy > &ExportLists)
Compute all the imports and exports for every module in the Index.
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:402
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:557
@ 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 updateVCallVisibilityInIndex(ModuleSummaryIndex &Index, bool WholeProgramVisibilityEnabledInLTO, const DenseSet< GlobalValue::GUID > &DynamicExportSymbols)
If whole program visibility asserted, then upgrade all public vcall visibility metadata on vtable def...
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:1896
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:1762
Pass * createObjCARCContractPass()
std::error_code errorToErrorCode(Error Err)
Helper for converting an ECError to a std::error_code.
Definition: Error.cpp:98
void consumeError(Error Err)
Consume a Error without doing anything.
Definition: Error.h:1043
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:6439
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(const std::string &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
std::string CPU
Definition: Config.h:48
TargetOptions Options
Definition: Config.h:49
CodeGenOpt::Level CGOptLevel
Definition: Config.h:57
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:67