23#include "llvm/Config/config.h"
58#include <system_error>
62 return PACKAGE_NAME
" version " PACKAGE_VERSION;
67 "lto-discard-value-names",
68 cl::desc(
"Strip names from Value during LTO (other than GlobalValue)."),
77 "lto-pass-remarks-with-hotness",
78 cl::desc(
"With PGO, include profile count in optimization remarks"),
83 "lto-pass-remarks-hotness-threshold",
84 cl::desc(
"Minimum profile count required for an "
85 "optimization remark to be output."
86 " Use 'auto' to apply the threshold from profile summary."),
91 cl::desc(
"Output filename for pass remarks"),
96 cl::desc(
"Only record optimization remarks from passes whose "
97 "names match the given regular expression"),
101 "lto-pass-remarks-format",
102 cl::desc(
"The format used for serializing remarks (default: YAML)"),
110 "lto-aix-system-assembler",
111 cl::desc(
"Path to a system assembler, picked up on AIX only"),
116 cl::desc(
"Perform context sensitive PGO instrumentation"));
120 cl::desc(
"Context sensitive profile file path"));
126 : Context(Context), MergedModule(new
Module(
"ld-temp.o", Context)),
127 TheLinker(new
Linker(*MergedModule)) {
129 Context.enableDebugTypeODRUniquing();
131 Config.LibraryOptions = &Context.getLibraryOptions();
132 Config.CodeModel = std::nullopt;
141 AsmUndefinedRefs.insert_range(
Mod->getAsmUndefinedRefs());
145 assert(&
Mod->getModule().getContext() == &Context &&
146 "Expected module in same context");
148 bool ret = TheLinker->linkInModule(
Mod->takeModule());
152 HasVerifiedInput =
false;
158 assert(&
Mod->getModule().getContext() == &Context &&
159 "Expected module in same context");
161 AsmUndefinedRefs.clear();
163 MergedModule =
Mod->takeModule();
164 TheLinker = std::make_unique<Linker>(*MergedModule);
168 HasVerifiedInput =
false;
178 EmitDwarfDebugInfo =
false;
182 EmitDwarfDebugInfo =
true;
189 Config.OptLevel = Level;
190 std::optional<CodeGenOptLevel> CGOptLevelOrNone =
192 assert(CGOptLevelOrNone &&
"Unknown optimization level!");
193 Config.CGOptLevel = *CGOptLevelOrNone;
197 if (!determineTarget())
201 verifyMergedModuleOnce();
204 applyScopeRestrictions();
210 std::string ErrMsg =
"could not open bitcode file for writing: ";
211 ErrMsg += Path.str() +
": " + EC.message();
220 if (Out.os().has_error()) {
221 std::string ErrMsg =
"could not write bitcode file: ";
222 ErrMsg += Path.str() +
": " + Out.os().error().message();
224 Out.os().clear_error();
232bool LTOCodeGenerator::useAIXSystemAssembler() {
233 const auto &
Triple = TargetMach->getTargetTriple();
238 assert(useAIXSystemAssembler() &&
239 "Runing AIX system assembler when integrated assembler is available!");
247 "Cannot find the assembler specified by lto-aix-system-assembler");
253 std::string LDR_CNTRL_var =
"LDR_CNTRL=MAXDATA32=0xA0000000@DSA";
255 LDR_CNTRL_var += (
"@" + *
V);
258 const auto &Triple = TargetMach->getTargetTriple();
259 const char *Arch = Triple.isArch64Bit() ?
"-a64" :
"-a32";
261 ObjectFileName[ObjectFileName.size() - 1] =
'o';
263 "/bin/env", LDR_CNTRL_var,
273 emitError(
"LTO assembler exited abnormally");
277 emitError(
"Unable to invoke LTO assembler");
281 emitError(
"LTO assembler invocation returned non-zero");
294bool LTOCodeGenerator::compileOptimizedToFile(
const char **Name) {
295 if (useAIXSystemAssembler())
303 const Twine &ModuleName) -> std::unique_ptr<CachedFileStream> {
311 emitError(
EC.message());
313 return std::make_unique<CachedFileStream>(
314 std::make_unique<llvm::raw_fd_ostream>(FD,
true));
331 if (useAIXSystemAssembler())
332 if (!runAIXSystemAssembler(
Filename))
335 NativeObjectPath =
Filename.c_str();
336 *
Name = NativeObjectPath.c_str();
340std::unique_ptr<MemoryBuffer>
343 if (!compileOptimizedToFile(&
name))
349 if (std::error_code EC = BufferOrErr.
getError()) {
350 emitError(EC.message());
358 return std::move(*BufferOrErr);
365 return compileOptimizedToFile(Name);
375bool LTOCodeGenerator::determineTarget() {
379 if (MergedModule->getTargetTriple().empty())
393 Features.getDefaultSubtargetFeatures(MergedModule->getTargetTriple());
394 FeatureStr = Features.getString();
395 if (Config.
CPU.empty())
404 assert(TargetMach &&
"Unable to create target machine");
409std::unique_ptr<TargetMachine> LTOCodeGenerator::createTargetMachine() {
410 assert(MArch &&
"MArch is not set!");
411 TargetOptions
Options = Config.Options;
412 Options.MCOptions.LibraryOptions = Config.LibraryOptions;
413 return std::unique_ptr<TargetMachine>(MArch->createTargetMachine(
414 MergedModule->getTargetTriple(), Config.CPU, FeatureStr,
Options,
415 Config.RelocModel, std::nullopt, Config.CGOptLevel));
421void LTOCodeGenerator::preserveDiscardableGVs(
424 std::vector<GlobalValue *>
Used;
425 auto mayPreserveGlobal = [&](GlobalValue &GV) {
426 if (!GV.isDiscardableIfUnused() || GV.isDeclaration() ||
429 if (GV.hasAvailableExternallyLinkage())
431 (Twine(
"Linker asked to preserve available_externally global: '") +
432 GV.getName() +
"'").str());
433 if (GV.hasInternalLinkage())
434 return emitWarning((Twine(
"Linker asked to preserve internal global: '") +
435 GV.getName() +
"'").str());
438 for (
auto &GV : TheModule)
439 mayPreserveGlobal(GV);
440 for (
auto &GV : TheModule.globals())
441 mayPreserveGlobal(GV);
442 for (
auto &GV : TheModule.aliases())
443 mayPreserveGlobal(GV);
451void LTOCodeGenerator::applyScopeRestrictions() {
452 if (ScopeRestrictionsDone)
458 SmallString<64> MangledName;
468 MangledName.
reserve(GV.getName().size() + 1);
470 return MustPreserveSymbols.count(MangledName);
476 if (!ShouldInternalize)
479 if (ShouldRestoreGlobalsLinkage) {
484 if (!GV.hasAvailableExternallyLinkage() && !GV.hasLocalLinkage() &&
486 ExternalSymbols.insert(std::make_pair(GV.getName(), GV.getLinkage()));
488 for (
auto &GV : *MergedModule)
490 for (
auto &GV : MergedModule->globals())
492 for (
auto &GV : MergedModule->aliases())
502 ScopeRestrictionsDone =
true;
506void LTOCodeGenerator::restoreLinkageForExternals() {
507 if (!ShouldInternalize || !ShouldRestoreGlobalsLinkage)
510 assert(ScopeRestrictionsDone &&
511 "Cannot externalize without internalization!");
513 if (ExternalSymbols.empty())
516 auto externalize = [
this](GlobalValue &GV) {
517 if (!GV.hasLocalLinkage() || !GV.hasName())
520 auto I = ExternalSymbols.find(GV.getName());
521 if (
I == ExternalSymbols.end())
524 GV.setLinkage(
I->second);
532void LTOCodeGenerator::verifyMergedModuleOnce() {
534 if (HasVerifiedInput)
536 HasVerifiedInput =
true;
538 bool BrokenDebugInfo =
false;
541 if (BrokenDebugInfo) {
542 emitWarning(
"Invalid debug info found, debug info will be stripped");
547void LTOCodeGenerator::finishOptimizationRemarks() {
548 if (DiagnosticOutputFile) {
549 DiagnosticOutputFile->keep();
551 DiagnosticOutputFile.finalize();
552 DiagnosticOutputFile->os().flush();
558 if (!this->determineTarget())
568 Config.PTO.LoopVectorization = Config.OptLevel > 1;
569 Config.PTO.SLPVectorization = Config.OptLevel > 1;
574 if (!DiagFileOrErr) {
575 errs() <<
"Error: " <<
toString(DiagFileOrErr.takeError()) <<
"\n";
578 DiagnosticOutputFile = std::move(*DiagFileOrErr);
582 if (!StatsFileOrErr) {
583 errs() <<
"Error: " <<
toString(StatsFileOrErr.takeError()) <<
"\n";
586 StatsFile = std::move(StatsFileOrErr.get());
605 verifyMergedModuleOnce();
608 this->applyScopeRestrictions();
613 if (MergedModule->getDataLayout().isDefault()) {
614 MergedModule->setDataLayout(
615 MergedModule->getTargetTriple().computeDataLayout(
616 TargetMach->getTargetABIName(*MergedModule)));
619 if (!SaveIRBeforeOptPath.empty()) {
624 " to save optimized bitcode\n");
630 TargetMach = createTargetMachine();
631 if (!
opt(Config, TargetMach.get(), 0, *MergedModule,
false,
632 &CombinedIndex,
nullptr,
633 std::vector<uint8_t>(), {})) {
634 emitError(
"LTO middle-end optimizations failed");
642 unsigned ParallelismLevel) {
643 if (!this->determineTarget())
648 verifyMergedModuleOnce();
652 restoreLinkageForExternals();
656 Config.CodeGenOnly =
true;
657 Error Err = backend(Config, AddStream, ParallelismLevel, *MergedModule,
659 assert(!Err &&
"unexpected code-generation failure");
671 finishOptimizationRemarks();
678 CodegenOptions.push_back(Option.str());
682 if (!CodegenOptions.empty()) {
684 std::vector<const char *> CodegenArgv(1,
"libLLVMLTO");
685 for (std::string &Arg : CodegenOptions)
686 CodegenArgv.push_back(Arg.c_str());
709 std::string MsgStorage;
716 assert(DiagHandler &&
"Invalid diagnostic handler");
717 (*DiagHandler)(Severity, MsgStorage.c_str(), DiagContext);
724 : CodeGenerator(CodeGenPtr) {}
735 this->DiagHandler = DiagHandler;
736 this->DiagContext = Ctxt;
738 return Context.setDiagnosticHandler(
nullptr);
741 Context.setDiagnosticHandler(std::make_unique<LTODiagnosticHandler>(
this),
756void LTOCodeGenerator::emitError(
const std::string &ErrMsg) {
758 (*DiagHandler)(
LTO_DS_ERROR, ErrMsg.c_str(), DiagContext);
760 Context.diagnose(LTODiagnosticInfo(ErrMsg));
763void LTOCodeGenerator::emitWarning(
const std::string &ErrMsg) {
767 Context.diagnose(LTODiagnosticInfo(ErrMsg,
DS_Warning));
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static bool mustPreserveGV(const GlobalValue &GV)
Predicate for Internalize pass.
static void print(raw_ostream &Out, object::Archive::Kind Kind, T Val)
#define LLVM_LIFETIME_BOUND
This file implements a simple parser to decode commandline option for remarks hotness threshold that ...
Module.h This file contains the declarations for the Module class.
static std::unique_ptr< TargetMachine > createTargetMachine(Function *F, CodeGenOptLevel OptLevel)
Create the TargetMachine object to query the backend for optimization preferences.
static constexpr StringLiteral Filename
This header defines classes/functions to handle pass execution timing information with interfaces for...
Provides a library for accessing information about this process and other processes on the operating ...
This file defines the 'Statistic' class, which is designed to be an easy way to expose various metric...
Represent a constant reference to an array (0 or more elements consecutively in memory),...
This is the base abstract class for diagnostic reporting in the backend.
DiagnosticSeverity getSeverity() const
virtual void print(DiagnosticPrinter &DP) const =0
Print using the given DP a user-friendly message.
Basic diagnostic printer that uses an underlying raw_ostream.
Interface for custom diagnostic printing.
Represents either an error or a value T.
std::error_code getError() const
Lightweight error class with error context and mandatory checking.
This is an important class for using LLVM in a threaded context.
This class provides the core functionality of linking in LLVM.
LLVM_ABI void getNameWithPrefix(raw_ostream &OS, const GlobalValue *GV, bool CannotUsePrivateLabel) const
Print the appropriate prefix and the specified global variable's name.
static ErrorOr< std::unique_ptr< MemoryBuffer > > getFile(const Twine &Filename, bool IsText=false, bool RequiresNullTerminator=true, bool IsVolatile=false, std::optional< Align > Alignment=std::nullopt)
Open the specified file as a MemoryBuffer, returning a new MemoryBuffer if successful,...
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.
Tunable parameters for passes in the default pipelines.
SmallString - A SmallString is just a SmallVector with methods and accessors that make it work better...
void reserve(size_type N)
Represent a constant reference to a string, i.e.
Manages the enabling and disabling of subtarget specific features.
MCTargetOptions MCOptions
Machine level options.
unsigned DataSections
Emit data into separate sections.
Triple - Helper class for working with autoconf configuration names.
bool isOSAIX() const
Tests whether the OS is AIX.
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
An efficient, type-erasing, non-owning reference to a callable.
A raw_ostream that writes to a file descriptor.
A raw_ostream that writes to an std::string.
static LLVM_ABI std::optional< std::string > GetEnv(StringRef name)
lto_codegen_diagnostic_severity_t
Diagnostic severity.
void(* lto_diagnostic_handler_t)(lto_codegen_diagnostic_severity_t severity, const char *diag, void *ctxt)
Diagnostic handler type.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
constexpr char Args[]
Key for Kernel::Metadata::mArgs.
std::optional< CodeGenOptLevel > getLevel(int OL)
Get the Level identified by the integer OL.
initializer< Ty > init(const Ty &Val)
LLVM_ABI bool parseCommandLineOptions(LibraryOptionsContext &Context, ArrayRef< const char * > Args, StringRef Overview="", raw_ostream *Errs=nullptr, vfs::FileSystem *VFS=nullptr, const char *EnvVar=nullptr)
LLVM_ABI std::optional< bool > getExplicitDataSections()
LLVM_ABI StringLiteral getThinLTODefaultCPU(const Triple &TheTriple)
LLVM_ABI Expected< std::unique_ptr< ToolOutputFile > > setupStatsFile(StringRef StatsFilename)
Setups the output file for saving statistics.
LLVM_ABI Expected< LLVMRemarkFileHandle > setupLLVMOptimizationRemarks(LLVMContext &Context, StringRef RemarksFilename, StringRef RemarksPasses, StringRef RemarksFormat, bool RemarksWithHotness, std::optional< uint64_t > RemarksHotnessThreshold=0, int Count=-1)
Setup optimization remarks.
LLVM_ABI std::error_code remove(const Twine &path, bool IgnoreNonExisting=true)
Remove path.
LLVM_ABI std::error_code real_path(const Twine &path, SmallVectorImpl< char > &output, bool expand_tilde=false)
Collapse all .
LLVM_ABI std::error_code createTemporaryFile(const Twine &Prefix, StringRef Suffix, int &ResultFD, SmallVectorImpl< char > &ResultPath, OpenFlags Flags=OF_None)
Create a file in the system temporary directory.
LLVM_ABI std::string getDefaultTargetTriple()
getDefaultTargetTriple() - Return the default target triple the compiler has been configured to produ...
LLVM_ABI int ExecuteAndWait(StringRef Program, ArrayRef< StringRef > Args, std::optional< ArrayRef< StringRef > > Env=std::nullopt, ArrayRef< std::optional< StringRef > > Redirects={}, unsigned SecondsToWait=0, unsigned MemoryLimit=0, std::string *ErrMsg=nullptr, bool *ExecutionFailed=nullptr, std::optional< ProcessStatistics > *ProcStat=nullptr, BitVector *AffinityMask=nullptr)
This function executes the program using the arguments provided.
This is an optimization pass for GlobalISel generic memory operations.
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"))
UnaryFunction for_each(R &&Range, UnaryFunction F)
Provide wrappers to std::for_each which take ranges instead of having to pass begin/end explicitly.
cl::opt< bool > LTODiscardValueNames("lto-discard-value-names", cl::desc("Strip names from Value during LTO (other than GlobalValue)."), cl::init(false), cl::Hidden)
LLVM_ABI 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.
bool internalizeModule(Module &TheModule, std::function< bool(const GlobalValue &)> MustPreserveGV)
Helper function to internalize functions and variables in a Module.
@ Debug
Register 'use' is for debugging purpose.
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"))
LLVM_ABI void updateCompilerUsed(Module &TheModule, const TargetMachine &TM, const StringSet<> &AsmUndefinedRefs)
Find all globals in TheModule that are referenced in AsmUndefinedRefs, as well as the user-supplied f...
LLVM_ABI void reportAndResetTimings(raw_ostream *OutStream=nullptr)
If -time-passes has been specified, report the timings immediately and then reset the timers to zero.
static cl::opt< std::string > AIXSystemAssemblerPath("lto-aix-system-assembler", cl::desc("Path to a system assembler, picked up on AIX only"), cl::value_desc("path"))
LLVM_ABI void updatePublicTypeTestCalls(Module &M, bool WholeProgramVisibilityEnabledInLTO)
cl::opt< std::string > LTOCSIRProfile("cs-profile-path", cl::desc("Context sensitive profile file path"))
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
LLVM_ABI void report_fatal_error(Error Err, bool gen_crash_diag=true)
LLVM_ABI bool AreStatisticsEnabled()
Check if statistics are enabled.
cl::opt< bool > RemarksWithHotness("lto-pass-remarks-with-hotness", cl::desc("With PGO, include profile count in optimization remarks"), cl::Hidden)
cl::opt< std::string > RemarksFilename("lto-pass-remarks-output", cl::desc("Output filename for pass remarks"), cl::value_desc("filename"))
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
cl::opt< bool > LTORunCSIRInstr("cs-profile-generate", cl::desc("Perform context sensitive PGO instrumentation"))
LLVM_ABI raw_fd_ostream & errs()
This returns a reference to a raw_ostream for standard error.
LLVM_ABI bool StripDebugInfo(Module &M)
Strip debug info in the module if it exists.
@ Mod
The access may modify the value stored in memory.
std::string join(IteratorT Begin, IteratorT End, StringRef Separator)
Joins the strings in the range [Begin, End), adding Separator between the elements.
LLVM_ABI void PrintStatistics()
Print statistics to the file returned by CreateInfoOutputFile().
LLVM_ABI void appendToCompilerUsed(Module &M, ArrayRef< GlobalValue * > Values)
Adds global values to the llvm.compiler.used list.
std::string toString(const APInt &I, unsigned Radix, bool Signed, bool formatAsCLiteral=false, bool UpperCase=true, bool InsertSeparators=false)
DiagnosticSeverity
Defines the different supported severity of a diagnostic.
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)
static cl::opt< std::string > LTOStatsFile("lto-stats-file", cl::desc("Save statistics to the specified file"), cl::Hidden)
std::function< Expected< std::unique_ptr< CachedFileStream > >( unsigned Task, const Twine &ModuleName)> AddStreamFn
This type defines the callback to add a file that is generated on the fly.
LLVM_ABI void PrintStatisticsJSON(raw_ostream &OS)
Print statistics in JSON format.
LLVM_ABI void updateVCallVisibilityInModule(Module &M, bool WholeProgramVisibilityEnabledInLTO, const DenseSet< GlobalValue::GUID > &DynamicExportSymbols, bool ValidateAllVtablesHaveTypeInfos, function_ref< bool(StringRef)> IsVisibleToRegularObj)
If whole program visibility asserted, then upgrade all public vcall visibility metadata on vtable def...
LLVM_ABI bool verifyModule(const Module &M, raw_ostream *OS=nullptr, bool *BrokenDebugInfo=nullptr)
Check a module for errors.
cl::opt< std::string > SampleProfileFile
This is the base class for diagnostic handling in LLVM.
C++ class which implements the opaque lto_code_gen_t type.
LLVM_ABI bool optimize()
Optimizes the merged module.
LLVM_ABI std::unique_ptr< MemoryBuffer > compile()
As with compile_to_file(), this function compiles the merged module into single output file.
LLVM_ABI void setModule(std::unique_ptr< LTOModule > M)
Set the destination module.
LLVM_ABI bool compile_to_file(const char **Name)
Compile the merged module into a single output file; the path to output file is returned to the calle...
LLVM_ABI void parseCodeGenDebugOptions()
Parse the options set in setCodeGenDebugOptions.
LLVM_ABI void setOptLevel(unsigned OptLevel)
LLVM_ABI void setAsmUndefinedRefs(struct LTOModule *)
LLVM_ABI void setDiagnosticHandler(lto_diagnostic_handler_t, void *)
void setFileType(CodeGenFileType FT)
Set the file type to be emitted (assembly or object code).
LLVM_ABI void setTargetOptions(const TargetOptions &Options)
LLVM_ABI void setCodeGenDebugOptions(ArrayRef< StringRef > Opts)
Pass options to the driver and optimization passes.
LLVM_ABI LTOCodeGenerator(LLVMContext &Context)
LLVM_ABI std::unique_ptr< MemoryBuffer > compileOptimized()
Compiles the merged optimized module into a single output file.
LLVM_ABI bool addModule(struct LTOModule *)
Merge given module.
LLVM_ABI void setDebugInfo(lto_debug_model)
LLVM_ABI ~LTOCodeGenerator()
LLVM_ABI bool writeMergedModules(StringRef Path)
Write the merged module to the file specified by the given path.
LLVM_ABI void DiagnosticHandler(const DiagnosticInfo &DI)
static LLVM_ABI const char * getVersionString()
C++ class which implements the opaque lto_module_t type.
static LLVM_ABI const Target * lookupTarget(const Triple &TheTriple, std::string &Error)
lookupTarget - Lookup a target based on a target triple.
std::vector< std::string > MAttrs