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.CodeModel = std::nullopt;
140 AsmUndefinedRefs.insert_range(
Mod->getAsmUndefinedRefs());
144 assert(&
Mod->getModule().getContext() == &Context &&
145 "Expected module in same context");
147 bool ret = TheLinker->linkInModule(
Mod->takeModule());
151 HasVerifiedInput =
false;
157 assert(&
Mod->getModule().getContext() == &Context &&
158 "Expected module in same context");
160 AsmUndefinedRefs.clear();
162 MergedModule =
Mod->takeModule();
163 TheLinker = std::make_unique<Linker>(*MergedModule);
167 HasVerifiedInput =
false;
177 EmitDwarfDebugInfo =
false;
181 EmitDwarfDebugInfo =
true;
188 Config.OptLevel = Level;
189 Config.PTO.LoopVectorization = Config.OptLevel > 1;
190 Config.PTO.SLPVectorization = Config.OptLevel > 1;
191 std::optional<CodeGenOptLevel> CGOptLevelOrNone =
193 assert(CGOptLevelOrNone &&
"Unknown optimization level!");
194 Config.CGOptLevel = *CGOptLevelOrNone;
198 if (!determineTarget())
202 verifyMergedModuleOnce();
205 applyScopeRestrictions();
211 std::string ErrMsg =
"could not open bitcode file for writing: ";
212 ErrMsg += Path.str() +
": " + EC.message();
221 if (Out.os().has_error()) {
222 std::string ErrMsg =
"could not write bitcode file: ";
223 ErrMsg += Path.str() +
": " + Out.os().error().message();
225 Out.os().clear_error();
233bool LTOCodeGenerator::useAIXSystemAssembler() {
234 const auto &
Triple = TargetMach->getTargetTriple();
239 assert(useAIXSystemAssembler() &&
240 "Runing AIX system assembler when integrated assembler is available!");
248 "Cannot find the assembler specified by lto-aix-system-assembler");
254 std::string LDR_CNTRL_var =
"LDR_CNTRL=MAXDATA32=0xA0000000@DSA";
256 LDR_CNTRL_var += (
"@" + *
V);
259 const auto &Triple = TargetMach->getTargetTriple();
260 const char *Arch = Triple.isArch64Bit() ?
"-a64" :
"-a32";
262 ObjectFileName[ObjectFileName.size() - 1] =
'o';
264 "/bin/env", LDR_CNTRL_var,
274 emitError(
"LTO assembler exited abnormally");
278 emitError(
"Unable to invoke LTO assembler");
282 emitError(
"LTO assembler invocation returned non-zero");
295bool LTOCodeGenerator::compileOptimizedToFile(
const char **Name) {
296 if (useAIXSystemAssembler())
304 const Twine &ModuleName) -> std::unique_ptr<CachedFileStream> {
312 emitError(
EC.message());
314 return std::make_unique<CachedFileStream>(
315 std::make_unique<llvm::raw_fd_ostream>(FD,
true));
332 if (useAIXSystemAssembler())
333 if (!runAIXSystemAssembler(
Filename))
336 NativeObjectPath =
Filename.c_str();
337 *
Name = NativeObjectPath.c_str();
341std::unique_ptr<MemoryBuffer>
344 if (!compileOptimizedToFile(&
name))
350 if (std::error_code EC = BufferOrErr.
getError()) {
351 emitError(EC.message());
359 return std::move(*BufferOrErr);
366 return compileOptimizedToFile(Name);
376bool LTOCodeGenerator::determineTarget() {
380 if (MergedModule->getTargetTriple().empty())
394 Features.getDefaultSubtargetFeatures(MergedModule->getTargetTriple());
395 FeatureStr = Features.getString();
396 if (Config.
CPU.empty())
405 assert(TargetMach &&
"Unable to create target machine");
410std::unique_ptr<TargetMachine> LTOCodeGenerator::createTargetMachine() {
411 assert(MArch &&
"MArch is not set!");
412 return std::unique_ptr<TargetMachine>(MArch->createTargetMachine(
413 MergedModule->getTargetTriple(), Config.CPU, FeatureStr, Config.Options,
414 Config.RelocModel, std::nullopt, Config.CGOptLevel));
420void LTOCodeGenerator::preserveDiscardableGVs(
423 std::vector<GlobalValue *>
Used;
424 auto mayPreserveGlobal = [&](GlobalValue &GV) {
425 if (!GV.isDiscardableIfUnused() || GV.isDeclaration() ||
428 if (GV.hasAvailableExternallyLinkage())
430 (Twine(
"Linker asked to preserve available_externally global: '") +
431 GV.getName() +
"'").str());
432 if (GV.hasInternalLinkage())
433 return emitWarning((Twine(
"Linker asked to preserve internal global: '") +
434 GV.getName() +
"'").str());
437 for (
auto &GV : TheModule)
438 mayPreserveGlobal(GV);
439 for (
auto &GV : TheModule.globals())
440 mayPreserveGlobal(GV);
441 for (
auto &GV : TheModule.aliases())
442 mayPreserveGlobal(GV);
450void LTOCodeGenerator::applyScopeRestrictions() {
451 if (ScopeRestrictionsDone)
457 SmallString<64> MangledName;
467 MangledName.
reserve(GV.getName().size() + 1);
469 return MustPreserveSymbols.count(MangledName);
475 if (!ShouldInternalize)
478 if (ShouldRestoreGlobalsLinkage) {
483 if (!GV.hasAvailableExternallyLinkage() && !GV.hasLocalLinkage() &&
485 ExternalSymbols.insert(std::make_pair(GV.getName(), GV.getLinkage()));
487 for (
auto &GV : *MergedModule)
489 for (
auto &GV : MergedModule->globals())
491 for (
auto &GV : MergedModule->aliases())
501 ScopeRestrictionsDone =
true;
505void LTOCodeGenerator::restoreLinkageForExternals() {
506 if (!ShouldInternalize || !ShouldRestoreGlobalsLinkage)
509 assert(ScopeRestrictionsDone &&
510 "Cannot externalize without internalization!");
512 if (ExternalSymbols.empty())
515 auto externalize = [
this](GlobalValue &GV) {
516 if (!GV.hasLocalLinkage() || !GV.hasName())
519 auto I = ExternalSymbols.find(GV.getName());
520 if (
I == ExternalSymbols.end())
523 GV.setLinkage(
I->second);
531void LTOCodeGenerator::verifyMergedModuleOnce() {
533 if (HasVerifiedInput)
535 HasVerifiedInput =
true;
537 bool BrokenDebugInfo =
false;
540 if (BrokenDebugInfo) {
541 emitWarning(
"Invalid debug info found, debug info will be stripped");
546void LTOCodeGenerator::finishOptimizationRemarks() {
547 if (DiagnosticOutputFile) {
548 DiagnosticOutputFile->keep();
550 DiagnosticOutputFile.finalize();
551 DiagnosticOutputFile->os().flush();
557 if (!this->determineTarget())
570 if (!DiagFileOrErr) {
571 errs() <<
"Error: " <<
toString(DiagFileOrErr.takeError()) <<
"\n";
574 DiagnosticOutputFile = std::move(*DiagFileOrErr);
578 if (!StatsFileOrErr) {
579 errs() <<
"Error: " <<
toString(StatsFileOrErr.takeError()) <<
"\n";
582 StatsFile = std::move(StatsFileOrErr.get());
601 verifyMergedModuleOnce();
604 this->applyScopeRestrictions();
607 MergedModule->setDataLayout(TargetMach->createDataLayout());
609 if (!SaveIRBeforeOptPath.empty()) {
614 " to save optimized bitcode\n");
620 TargetMach = createTargetMachine();
621 if (!
opt(Config, TargetMach.get(), 0, *MergedModule,
false,
622 &CombinedIndex,
nullptr,
623 std::vector<uint8_t>(), {})) {
624 emitError(
"LTO middle-end optimizations failed");
632 unsigned ParallelismLevel) {
633 if (!this->determineTarget())
638 verifyMergedModuleOnce();
642 restoreLinkageForExternals();
646 Config.CodeGenOnly =
true;
647 Error Err = backend(Config, AddStream, ParallelismLevel, *MergedModule,
649 assert(!Err &&
"unexpected code-generation failure");
661 finishOptimizationRemarks();
668 CodegenOptions.push_back(Option.str());
672 if (!CodegenOptions.empty())
679 std::vector<const char *> CodegenArgv(1,
"libLLVMLTO");
680 for (std::string &Arg :
Options)
681 CodegenArgv.push_back(Arg.c_str());
704 std::string MsgStorage;
711 assert(DiagHandler &&
"Invalid diagnostic handler");
712 (*DiagHandler)(Severity, MsgStorage.c_str(), DiagContext);
719 : CodeGenerator(CodeGenPtr) {}
730 this->DiagHandler = DiagHandler;
731 this->DiagContext = Ctxt;
733 return Context.setDiagnosticHandler(
nullptr);
736 Context.setDiagnosticHandler(std::make_unique<LTODiagnosticHandler>(
this),
751void LTOCodeGenerator::emitError(
const std::string &ErrMsg) {
753 (*DiagHandler)(
LTO_DS_ERROR, ErrMsg.c_str(), DiagContext);
755 Context.diagnose(LTODiagnosticInfo(ErrMsg));
758void LTOCodeGenerator::emitWarning(
const std::string &ErrMsg) {
762 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.
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(int argc, const char *const *argv, StringRef Overview="", raw_ostream *Errs=nullptr, vfs::FileSystem *VFS=nullptr, const char *EnvVar=nullptr, bool LongOptionsUseDoubleDash=false)
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 void parseCommandLineOptions(std::vector< std::string > &Options)
A convenience function that calls cl::ParseCommandLineOptions on the given set of options.
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