24#include "llvm/Config/config.h"
65#include <system_error>
69 return PACKAGE_NAME
" version " PACKAGE_VERSION;
74 "lto-discard-value-names",
75 cl::desc(
"Strip names from Value during LTO (other than GlobalValue)."),
84 "lto-pass-remarks-with-hotness",
85 cl::desc(
"With PGO, include profile count in optimization remarks"),
90 "lto-pass-remarks-hotness-threshold",
91 cl::desc(
"Minimum profile count required for an "
92 "optimization remark to be output."
93 " Use 'auto' to apply the threshold from profile summary."),
98 cl::desc(
"Output filename for pass remarks"),
103 cl::desc(
"Only record optimization remarks from passes whose "
104 "names match the given regular expression"),
108 "lto-pass-remarks-format",
109 cl::desc(
"The format used for serializing remarks (default: YAML)"),
114 cl::desc(
"Save statistics to the specified file"),
118 "lto-aix-system-assembler",
119 cl::desc(
"Path to a system assembler, picked up on AIX only"),
124 cl::desc(
"Perform context sensitive PGO instrumentation"));
128 cl::desc(
"Context sensitive profile file path"));
132 : Context(Context), MergedModule(new
Module(
"ld-temp.o", Context)),
133 TheLinker(new
Linker(*MergedModule)) {
146 for (
const StringRef &Undef :
Mod->getAsmUndefinedRefs())
147 AsmUndefinedRefs.
insert(Undef);
151 assert(&
Mod->getModule().getContext() == &Context &&
152 "Expected module in same context");
154 bool ret = TheLinker->linkInModule(
Mod->takeModule());
158 HasVerifiedInput =
false;
164 assert(&
Mod->getModule().getContext() == &Context &&
165 "Expected module in same context");
167 AsmUndefinedRefs.
clear();
169 MergedModule =
Mod->takeModule();
170 TheLinker = std::make_unique<Linker>(*MergedModule);
174 HasVerifiedInput =
false;
184 EmitDwarfDebugInfo =
false;
188 EmitDwarfDebugInfo =
true;
198 std::optional<CodeGenOptLevel> CGOptLevelOrNone =
200 assert(CGOptLevelOrNone &&
"Unknown optimization level!");
205 if (!determineTarget())
209 verifyMergedModuleOnce();
212 applyScopeRestrictions();
218 std::string ErrMsg =
"could not open bitcode file for writing: ";
219 ErrMsg += Path.str() +
": " + EC.message();
229 std::string ErrMsg =
"could not write bitcode file: ";
230 ErrMsg += Path.str() +
": " + Out.
os().
error().message();
240bool LTOCodeGenerator::useAIXSystemAssembler() {
241 const auto &
Triple = TargetMach->getTargetTriple();
246 assert(useAIXSystemAssembler() &&
247 "Runing AIX system assembler when integrated assembler is available!");
255 "Cannot find the assembler specified by lto-aix-system-assembler");
261 std::string LDR_CNTRL_var =
"LDR_CNTRL=MAXDATA32=0xA0000000@DSA";
263 LDR_CNTRL_var += (
"@" + *
V);
266 const auto &
Triple = TargetMach->getTargetTriple();
269 ObjectFileName[ObjectFileName.size() - 1] =
'o';
271 "/bin/env", LDR_CNTRL_var,
281 emitError(
"LTO assembler exited abnormally");
285 emitError(
"Unable to invoke LTO assembler");
289 emitError(
"LTO assembler invocation returned non-zero");
302bool LTOCodeGenerator::compileOptimizedToFile(
const char **
Name) {
303 if (useAIXSystemAssembler())
319 emitError(
EC.message());
321 return std::make_unique<CachedFileStream>(
322 std::make_unique<llvm::raw_fd_ostream>(FD,
true));
339 if (useAIXSystemAssembler())
340 if (!runAIXSystemAssembler(Filename))
343 NativeObjectPath =
Filename.c_str();
344 *
Name = NativeObjectPath.c_str();
348std::unique_ptr<MemoryBuffer>
351 if (!compileOptimizedToFile(&
name))
357 if (std::error_code EC = BufferOrErr.
getError()) {
358 emitError(EC.message());
366 return std::move(*BufferOrErr);
373 return compileOptimizedToFile(
Name);
383bool LTOCodeGenerator::determineTarget() {
387 TripleStr = MergedModule->getTargetTriple();
388 if (TripleStr.empty()) {
390 MergedModule->setTargetTriple(TripleStr);
405 Features.getDefaultSubtargetFeatures(
Triple);
406 FeatureStr = Features.getString();
407 if (Config.
CPU.empty())
415 TargetMach = createTargetMachine();
416 assert(TargetMach &&
"Unable to create target machine");
421std::unique_ptr<TargetMachine> LTOCodeGenerator::createTargetMachine() {
422 assert(MArch &&
"MArch is not set!");
431void LTOCodeGenerator::preserveDiscardableGVs(
434 std::vector<GlobalValue *>
Used;
436 if (!GV.isDiscardableIfUnused() || GV.isDeclaration() ||
439 if (GV.hasAvailableExternallyLinkage())
441 (
Twine(
"Linker asked to preserve available_externally global: '") +
442 GV.getName() +
"'").str());
443 if (GV.hasInternalLinkage())
444 return emitWarning((
Twine(
"Linker asked to preserve internal global: '") +
445 GV.getName() +
"'").str());
448 for (
auto &GV : TheModule)
449 mayPreserveGlobal(GV);
450 for (
auto &GV : TheModule.globals())
451 mayPreserveGlobal(GV);
452 for (
auto &GV : TheModule.aliases())
453 mayPreserveGlobal(GV);
461void LTOCodeGenerator::applyScopeRestrictions() {
462 if (ScopeRestrictionsDone)
478 MangledName.
reserve(GV.getName().size() + 1);
480 return MustPreserveSymbols.
count(MangledName);
486 if (!ShouldInternalize)
489 if (ShouldRestoreGlobalsLinkage) {
494 if (!GV.hasAvailableExternallyLinkage() && !GV.hasLocalLinkage() &&
496 ExternalSymbols.
insert(std::make_pair(GV.getName(), GV.getLinkage()));
498 for (
auto &GV : *MergedModule)
500 for (
auto &GV : MergedModule->globals())
502 for (
auto &GV : MergedModule->aliases())
512 ScopeRestrictionsDone =
true;
516void LTOCodeGenerator::restoreLinkageForExternals() {
517 if (!ShouldInternalize || !ShouldRestoreGlobalsLinkage)
520 assert(ScopeRestrictionsDone &&
521 "Cannot externalize without internalization!");
523 if (ExternalSymbols.
empty())
527 if (!GV.hasLocalLinkage() || !GV.hasName())
530 auto I = ExternalSymbols.
find(GV.getName());
531 if (
I == ExternalSymbols.
end())
534 GV.setLinkage(
I->second);
542void LTOCodeGenerator::verifyMergedModuleOnce() {
544 if (HasVerifiedInput)
546 HasVerifiedInput =
true;
548 bool BrokenDebugInfo =
false;
551 if (BrokenDebugInfo) {
552 emitWarning(
"Invalid debug info found, debug info will be stripped");
557void LTOCodeGenerator::finishOptimizationRemarks() {
558 if (DiagnosticOutputFile) {
559 DiagnosticOutputFile->keep();
561 DiagnosticOutputFile->os().flush();
567 if (!this->determineTarget())
576 if (!DiagFileOrErr) {
577 errs() <<
"Error: " <<
toString(DiagFileOrErr.takeError()) <<
"\n";
580 DiagnosticOutputFile = std::move(*DiagFileOrErr);
584 if (!StatsFileOrErr) {
585 errs() <<
"Error: " <<
toString(StatsFileOrErr.takeError()) <<
"\n";
588 StatsFile = std::move(StatsFileOrErr.get());
607 verifyMergedModuleOnce();
610 this->applyScopeRestrictions();
613 MergedModule->setDataLayout(TargetMach->createDataLayout());
615 if (!SaveIRBeforeOptPath.empty()) {
620 " to save optimized bitcode\n");
626 TargetMach = createTargetMachine();
627 if (!
opt(Config, TargetMach.get(), 0, *MergedModule,
false,
628 &CombinedIndex,
nullptr,
629 std::vector<uint8_t>())) {
630 emitError(
"LTO middle-end optimizations failed");
638 unsigned ParallelismLevel) {
639 if (!this->determineTarget())
644 verifyMergedModuleOnce();
648 restoreLinkageForExternals();
653 Error Err = backend(Config, AddStream, ParallelismLevel, *MergedModule,
655 assert(!Err &&
"unexpected code-generation failure");
667 finishOptimizationRemarks();
674 CodegenOptions.push_back(Option.str());
678 if (!CodegenOptions.empty())
685 std::vector<const char *> CodegenArgv(1,
"libLLVMLTO");
686 for (std::string &Arg :
Options)
687 CodegenArgv.push_back(Arg.c_str());
710 std::string MsgStorage;
718 assert(DiagHandler &&
"Invalid diagnostic handler");
719 (*DiagHandler)(Severity, MsgStorage.c_str(), DiagContext);
726 : CodeGenerator(CodeGenPtr) {}
737 this->DiagHandler = DiagHandler;
738 this->DiagContext = Ctxt;
757void LTOCodeGenerator::emitError(
const std::string &ErrMsg) {
759 (*DiagHandler)(
LTO_DS_ERROR, ErrMsg.c_str(), DiagContext);
761 Context.
diagnose(LTODiagnosticInfo(ErrMsg));
764void LTOCodeGenerator::emitWarning(
const std::string &ErrMsg) {
static bool mustPreserveGV(const GlobalValue &GV)
Predicate for Internalize pass.
static void print(raw_ostream &Out, object::Archive::Kind Kind, T Val)
This file contains the declarations for the subclasses of Constant, which represent the different fla...
static ManagedStatic< cl::opt< bool, true >, CreateDebug > Debug
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.
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 ...
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
static void externalize(GlobalValue *GV)
This file defines the 'Statistic' class, which is designed to be an easy way to expose various metric...
static void DiagHandler(const SMDiagnostic &Diag, void *Context)
ArrayRef - 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.
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).
void setDiagnosticHandler(std::unique_ptr< DiagnosticHandler > &&DH, bool RespectFilters=false)
setDiagnosticHandler - This method sets unique_ptr to object of DiagnosticHandler to provide custom d...
This class provides the core functionality of linking in LLVM.
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.
bool SLPVectorization
Tuning option to enable/disable slp loop vectorization, set based on opt level.
bool LoopVectorization
Tuning option to enable/disable loop vectorization, set based on opt level.
SmallString - A SmallString is just a SmallVector with methods and accessors that make it work better...
void reserve(size_type N)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
iterator find(StringRef Key)
size_type count(StringRef Key) const
count - Return 1 if the element is in the map, 0 otherwise.
bool insert(MapEntryTy *KeyValue)
insert - Insert the specified key/value pair into the map.
StringRef - Represent a constant reference to a string, i.e.
std::pair< typename Base::iterator, bool > insert(StringRef key)
Manages the enabling and disabling of subtarget specific features.
unsigned DataSections
Emit data into separate sections.
unsigned DisableIntegratedAS
Disable the integrated assembler.
TargetMachine * createTargetMachine(StringRef TT, StringRef CPU, StringRef Features, const TargetOptions &Options, std::optional< Reloc::Model > RM, std::optional< CodeModel::Model > CM=std::nullopt, CodeGenOptLevel OL=CodeGenOptLevel::Default, bool JIT=false) const
createTargetMachine - Create a target specific machine implementation for the specified Triple.
Triple - Helper class for working with autoconf configuration names.
bool isOSAIX() const
Tests whether the OS is AIX.
bool isArch64Bit() const
Test whether the architecture is 64-bit.
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.
bool has_error() const
Return the value of the flag in this raw_fd_ostream indicating whether an output error has been encou...
std::error_code error() const
void close()
Manually flush the stream and close the file.
void clear_error()
Set the flag read by has_error() to false.
A raw_ostream that writes to an std::string.
static 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.
bool ParseCommandLineOptions(int argc, const char *const *argv, StringRef Overview="", raw_ostream *Errs=nullptr, const char *EnvVar=nullptr, bool LongOptionsUseDoubleDash=false)
initializer< Ty > init(const Ty &Val)
std::optional< bool > getExplicitDataSections()
StringLiteral getThinLTODefaultCPU(const Triple &TheTriple)
Expected< std::unique_ptr< ToolOutputFile > > setupStatsFile(StringRef StatsFilename)
Setups the output file for saving statistics.
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.
std::error_code real_path(const Twine &path, SmallVectorImpl< char > &output, bool expand_tilde=false)
Collapse all .
std::error_code remove(const Twine &path, bool IgnoreNonExisting=true)
Remove path.
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.
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.
std::string getDefaultTargetTriple()
getDefaultTargetTriple() - Return the default target triple the compiler has been configured to produ...
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)
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.
cl::opt< std::string > LTOCSIRProfile("cs-profile-path", cl::desc("Context sensitive profile file path"))
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"))
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.
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...
void reportAndResetTimings(raw_ostream *OutStream=nullptr)
If -time-passes has been specified, report the timings immediately and then reset the timers to zero.
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"))
void updatePublicTypeTestCalls(Module &M, bool WholeProgramVisibilityEnabledInLTO)
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
void report_fatal_error(Error Err, bool gen_crash_diag=true)
Report a serious error, calling any installed error handler.
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"))
void parseCommandLineOptions(std::vector< std::string > &Options)
A convenience function that calls cl::ParseCommandLineOptions on the given set of options.
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.
@ Mod
The access may modify the value stored in memory.
void PrintStatistics()
Print statistics to the file returned by CreateInfoOutputFile().
void appendToCompilerUsed(Module &M, ArrayRef< GlobalValue * > Values)
Adds global values to the llvm.compiler.used list.
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)
const char * toString(DWARFSectionKind Kind)
cl::opt< std::string > LTOStatsFile("lto-stats-file", cl::desc("Save statistics to the specified file"), cl::Hidden)
void PrintStatisticsJSON(raw_ostream &OS)
Print statistics in JSON format.
cl::opt< bool > LTORunCSIRInstr("cs-profile-generate", cl::desc("Perform context sensitive PGO instrumentation"))
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...
bool verifyModule(const Module &M, raw_ostream *OS=nullptr, bool *BrokenDebugInfo=nullptr)
Check a module for errors.
This is the base class for diagnostic handling in LLVM.
C++ class which implements the opaque lto_code_gen_t type.
bool optimize()
Optimizes the merged module.
std::unique_ptr< MemoryBuffer > compile()
As with compile_to_file(), this function compiles the merged module into single output file.
void setModule(std::unique_ptr< LTOModule > M)
Set the destination module.
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...
void parseCodeGenDebugOptions()
Parse the options set in setCodeGenDebugOptions.
void setOptLevel(unsigned OptLevel)
void setAsmUndefinedRefs(struct LTOModule *)
void setDiagnosticHandler(lto_diagnostic_handler_t, void *)
void setFileType(CodeGenFileType FT)
Set the file type to be emitted (assembly or object code).
void setTargetOptions(const TargetOptions &Options)
void setCodeGenDebugOptions(ArrayRef< StringRef > Opts)
Pass options to the driver and optimization passes.
LTOCodeGenerator(LLVMContext &Context)
std::unique_ptr< MemoryBuffer > compileOptimized()
Compiles the merged optimized module into a single output file.
bool addModule(struct LTOModule *)
Merge given module.
void setDebugInfo(lto_debug_model)
bool writeMergedModules(StringRef Path)
Write the merged module to the file specified by the given path.
void DiagnosticHandler(const DiagnosticInfo &DI)
static const char * getVersionString()
C++ class which implements the opaque lto_module_t type.
static const Target * lookupTarget(StringRef Triple, std::string &Error)
lookupTarget - Lookup a target based on a target triple.
std::string StatsFile
Statistics output file path.
std::optional< CodeModel::Model > CodeModel
bool CodeGenOnly
Disable entirely the optimizer, including importing for ThinLTO.
std::vector< std::string > MAttrs
CodeGenOptLevel CGOptLevel
PipelineTuningOptions PTO
Tunable parameters for passes in the default pipelines.
bool RunCSIRInstr
Run PGO context sensitive IR instrumentation.
std::string CSIRProfile
Context Sensitive PGO profile path.
std::optional< Reloc::Model > RelocModel
CodeGenFileType CGFileType