25#include "llvm/Config/config.h"
66#include <system_error>
70 return PACKAGE_NAME
" version " PACKAGE_VERSION;
75 "lto-discard-value-names",
76 cl::desc(
"Strip names from Value during LTO (other than GlobalValue)."),
85 "lto-pass-remarks-with-hotness",
86 cl::desc(
"With PGO, include profile count in optimization remarks"),
91 "lto-pass-remarks-hotness-threshold",
92 cl::desc(
"Minimum profile count required for an "
93 "optimization remark to be output."
94 " Use 'auto' to apply the threshold from profile summary."),
99 cl::desc(
"Output filename for pass remarks"),
104 cl::desc(
"Only record optimization remarks from passes whose "
105 "names match the given regular expression"),
109 "lto-pass-remarks-format",
110 cl::desc(
"The format used for serializing remarks (default: YAML)"),
115 cl::desc(
"Save statistics to the specified file"),
119 "lto-aix-system-assembler",
120 cl::desc(
"Path to a system assembler, picked up on AIX only"),
125 cl::desc(
"Perform context sensitive PGO instrumentation"));
129 cl::desc(
"Context sensitive profile file path"));
134 TheLinker(new
Linker(*MergedModule)) {
151 for (
const StringRef &Undef :
Mod->getAsmUndefinedRefs())
152 AsmUndefinedRefs.
insert(Undef);
156 assert(&
Mod->getModule().getContext() == &Context &&
157 "Expected module in same context");
159 bool ret = TheLinker->linkInModule(
Mod->takeModule());
163 HasVerifiedInput =
false;
169 assert(&
Mod->getModule().getContext() == &Context &&
170 "Expected module in same context");
172 AsmUndefinedRefs.
clear();
174 MergedModule =
Mod->takeModule();
175 TheLinker = std::make_unique<Linker>(*MergedModule);
179 HasVerifiedInput =
false;
189 EmitDwarfDebugInfo =
false;
193 EmitDwarfDebugInfo =
true;
203 std::optional<CodeGenOptLevel> CGOptLevelOrNone =
205 assert(CGOptLevelOrNone &&
"Unknown optimization level!");
210 if (!determineTarget())
214 verifyMergedModuleOnce();
217 applyScopeRestrictions();
223 std::string ErrMsg =
"could not open bitcode file for writing: ";
224 ErrMsg += Path.str() +
": " + EC.message();
234 std::string ErrMsg =
"could not write bitcode file: ";
235 ErrMsg += Path.str() +
": " + Out.
os().
error().message();
245bool LTOCodeGenerator::useAIXSystemAssembler() {
246 const auto &
Triple = TargetMach->getTargetTriple();
251 assert(useAIXSystemAssembler() &&
252 "Runing AIX system assembler when integrated assembler is available!");
260 "Cannot find the assembler specified by lto-aix-system-assembler");
266 std::string LDR_CNTRL_var =
"LDR_CNTRL=MAXDATA32=0xA0000000@DSA";
268 LDR_CNTRL_var += (
"@" + *
V);
271 const auto &
Triple = TargetMach->getTargetTriple();
274 ObjectFileName[ObjectFileName.size() - 1] =
'o';
276 "/bin/env", LDR_CNTRL_var,
286 emitError(
"LTO assembler exited abnormally");
290 emitError(
"Unable to invoke LTO assembler");
294 emitError(
"LTO assembler invocation returned non-zero");
307bool LTOCodeGenerator::compileOptimizedToFile(
const char **
Name) {
308 if (useAIXSystemAssembler())
324 emitError(
EC.message());
326 return std::make_unique<CachedFileStream>(
327 std::make_unique<llvm::raw_fd_ostream>(FD,
true));
344 if (useAIXSystemAssembler())
345 if (!runAIXSystemAssembler(Filename))
348 NativeObjectPath =
Filename.c_str();
349 *
Name = NativeObjectPath.c_str();
353std::unique_ptr<MemoryBuffer>
356 if (!compileOptimizedToFile(&
name))
362 if (std::error_code EC = BufferOrErr.
getError()) {
363 emitError(EC.message());
371 return std::move(*BufferOrErr);
378 return compileOptimizedToFile(
Name);
388bool LTOCodeGenerator::determineTarget() {
392 TripleStr = MergedModule->getTargetTriple();
393 if (TripleStr.empty()) {
395 MergedModule->setTargetTriple(TripleStr);
410 Features.getDefaultSubtargetFeatures(
Triple);
411 FeatureStr = Features.getString();
412 if (Config.
CPU.empty())
420 TargetMach = createTargetMachine();
421 assert(TargetMach &&
"Unable to create target machine");
426std::unique_ptr<TargetMachine> LTOCodeGenerator::createTargetMachine() {
427 assert(MArch &&
"MArch is not set!");
436void LTOCodeGenerator::preserveDiscardableGVs(
439 std::vector<GlobalValue *>
Used;
441 if (!GV.isDiscardableIfUnused() || GV.isDeclaration() ||
444 if (GV.hasAvailableExternallyLinkage())
446 (
Twine(
"Linker asked to preserve available_externally global: '") +
447 GV.getName() +
"'").str());
448 if (GV.hasInternalLinkage())
449 return emitWarning((
Twine(
"Linker asked to preserve internal global: '") +
450 GV.getName() +
"'").str());
453 for (
auto &GV : TheModule)
454 mayPreserveGlobal(GV);
455 for (
auto &GV : TheModule.globals())
456 mayPreserveGlobal(GV);
457 for (
auto &GV : TheModule.aliases())
458 mayPreserveGlobal(GV);
466void LTOCodeGenerator::applyScopeRestrictions() {
467 if (ScopeRestrictionsDone)
483 MangledName.
reserve(GV.getName().size() + 1);
485 return MustPreserveSymbols.
count(MangledName);
491 if (!ShouldInternalize)
494 if (ShouldRestoreGlobalsLinkage) {
499 if (!GV.hasAvailableExternallyLinkage() && !GV.hasLocalLinkage() &&
501 ExternalSymbols.
insert(std::make_pair(GV.getName(), GV.getLinkage()));
503 for (
auto &GV : *MergedModule)
505 for (
auto &GV : MergedModule->globals())
507 for (
auto &GV : MergedModule->aliases())
517 ScopeRestrictionsDone =
true;
521void LTOCodeGenerator::restoreLinkageForExternals() {
522 if (!ShouldInternalize || !ShouldRestoreGlobalsLinkage)
525 assert(ScopeRestrictionsDone &&
526 "Cannot externalize without internalization!");
528 if (ExternalSymbols.
empty())
532 if (!GV.hasLocalLinkage() || !GV.hasName())
535 auto I = ExternalSymbols.
find(GV.getName());
536 if (
I == ExternalSymbols.
end())
539 GV.setLinkage(
I->second);
547void LTOCodeGenerator::verifyMergedModuleOnce() {
549 if (HasVerifiedInput)
551 HasVerifiedInput =
true;
553 bool BrokenDebugInfo =
false;
556 if (BrokenDebugInfo) {
557 emitWarning(
"Invalid debug info found, debug info will be stripped");
562void LTOCodeGenerator::finishOptimizationRemarks() {
563 if (DiagnosticOutputFile) {
564 DiagnosticOutputFile->keep();
566 DiagnosticOutputFile->os().flush();
572 if (!this->determineTarget())
581 if (!DiagFileOrErr) {
582 errs() <<
"Error: " <<
toString(DiagFileOrErr.takeError()) <<
"\n";
585 DiagnosticOutputFile = std::move(*DiagFileOrErr);
589 if (!StatsFileOrErr) {
590 errs() <<
"Error: " <<
toString(StatsFileOrErr.takeError()) <<
"\n";
593 StatsFile = std::move(StatsFileOrErr.get());
612 verifyMergedModuleOnce();
615 this->applyScopeRestrictions();
618 MergedModule->setDataLayout(TargetMach->createDataLayout());
620 if (!SaveIRBeforeOptPath.empty()) {
625 " to save optimized bitcode\n");
631 TargetMach = createTargetMachine();
632 if (!
opt(Config, TargetMach.get(), 0, *MergedModule,
false,
633 &CombinedIndex,
nullptr,
634 std::vector<uint8_t>())) {
635 emitError(
"LTO middle-end optimizations failed");
643 unsigned ParallelismLevel) {
644 if (!this->determineTarget())
649 verifyMergedModuleOnce();
653 restoreLinkageForExternals();
658 Error Err = backend(Config, AddStream, ParallelismLevel, *MergedModule,
660 assert(!Err &&
"unexpected code-generation failure");
672 finishOptimizationRemarks();
679 CodegenOptions.push_back(Option.str());
683 if (!CodegenOptions.empty())
690 std::vector<const char *> CodegenArgv(1,
"libLLVMLTO");
691 for (std::string &Arg :
Options)
692 CodegenArgv.push_back(Arg.c_str());
715 std::string MsgStorage;
723 assert(DiagHandler &&
"Invalid diagnostic handler");
724 (*DiagHandler)(Severity, MsgStorage.c_str(), DiagContext);
731 : CodeGenerator(CodeGenPtr) {}
742 this->DiagHandler = DiagHandler;
743 this->DiagContext = Ctxt;
762void LTOCodeGenerator::emitError(
const std::string &ErrMsg) {
764 (*DiagHandler)(
LTO_DS_ERROR, ErrMsg.c_str(), DiagContext);
766 Context.
diagnose(LTODiagnosticInfo(ErrMsg));
769void 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...
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.
PassManager manages ModulePassManagers.
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()
std::optional< const char * > toString(const std::optional< DWARFFormValue > &V)
Take an optional DWARFFormValue and try to extract a string value from it.
StringLiteral getThinLTODefaultCPU(const Triple &TheTriple)
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)
cl::opt< std::string > LTOStatsFile("lto-stats-file", cl::desc("Save statistics to the specified file"), cl::Hidden)
Pass * createObjCARCContractPass()
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
std::function< void(legacy::PassManager &)> PreCodeGenPassesHook
For adding passes that run right before codegen.
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