Fix and reapply IR PGO support for Flang (#142892)
This PR resubmits the changes from #136098, which was previously reverted due to a build failure during the linking stage: ``` undefined reference to `llvm::DebugInfoCorrelate' undefined reference to `llvm::ProfileCorrelate' ``` The root cause was that `llvm/lib/Frontend/Driver/CodeGenOptions.cpp` references symbols from the `Instrumentation` component, but the `LINK_COMPONENTS` in the `llvm/lib/Frontend/CMakeLists.txt` for `LLVMFrontendDriver` did not include it. As a result, linking failed in configurations where these components were not transitively linked. ### Fix: This updated patch explicitly adds `Instrumentation` to `LINK_COMPONENTS` in the relevant `llvm/lib/Frontend/CMakeLists.txt` file to ensure the required symbols are properly resolved. --------- Co-authored-by: ict-ql <168183727+ict-ql@users.noreply.github.com> Co-authored-by: Chyaka <52224511+liliumshade@users.noreply.github.com> Co-authored-by: Tarun Prabhu <tarunprabhu@gmail.com>
This commit is contained in:
@@ -223,9 +223,11 @@ AFFECTING_VALUE_CODEGENOPT(OptimizeSize, 2, 0) ///< If -Os (==1) or -Oz (==2) is
|
||||
CODEGENOPT(AtomicProfileUpdate , 1, 0) ///< Set -fprofile-update=atomic
|
||||
CODEGENOPT(ContinuousProfileSync, 1, 0) ///< Enable continuous instrumentation profiling
|
||||
/// Choose profile instrumenation kind or no instrumentation.
|
||||
ENUM_CODEGENOPT(ProfileInstr, ProfileInstrKind, 4, ProfileNone)
|
||||
|
||||
ENUM_CODEGENOPT(ProfileInstr, llvm::driver::ProfileInstrKind, 4, llvm::driver::ProfileInstrKind::ProfileNone)
|
||||
|
||||
/// Choose profile kind for PGO use compilation.
|
||||
ENUM_CODEGENOPT(ProfileUse, ProfileInstrKind, 2, ProfileNone)
|
||||
ENUM_CODEGENOPT(ProfileUse, llvm::driver::ProfileInstrKind, 2, llvm::driver::ProfileInstrKind::ProfileNone)
|
||||
/// Partition functions into N groups and select only functions in group i to be
|
||||
/// instrumented. Selected group numbers can be 0 to N-1 inclusive.
|
||||
VALUE_CODEGENOPT(ProfileTotalFunctionGroups, 32, 1)
|
||||
|
||||
@@ -80,16 +80,6 @@ public:
|
||||
SRCK_InRegs // Small structs in registers (-freg-struct-return).
|
||||
};
|
||||
|
||||
enum ProfileInstrKind {
|
||||
ProfileNone, // Profile instrumentation is turned off.
|
||||
ProfileClangInstr, // Clang instrumentation to generate execution counts
|
||||
// to use with PGO.
|
||||
ProfileIRInstr, // IR level PGO instrumentation in LLVM.
|
||||
ProfileCSIRInstr, // IR level PGO context sensitive instrumentation in LLVM.
|
||||
ProfileIRSampleColdCov, // IR level sample pgo based cold function coverage
|
||||
// instrumentation in LLVM.
|
||||
};
|
||||
|
||||
enum EmbedBitcodeKind {
|
||||
Embed_Off, // No embedded bitcode.
|
||||
Embed_All, // Embed both bitcode and commandline in the output.
|
||||
@@ -522,35 +512,41 @@ public:
|
||||
|
||||
/// Check if Clang profile instrumenation is on.
|
||||
bool hasProfileClangInstr() const {
|
||||
return getProfileInstr() == ProfileClangInstr;
|
||||
return getProfileInstr() ==
|
||||
llvm::driver::ProfileInstrKind::ProfileClangInstr;
|
||||
}
|
||||
|
||||
/// Check if IR level profile instrumentation is on.
|
||||
bool hasProfileIRInstr() const {
|
||||
return getProfileInstr() == ProfileIRInstr;
|
||||
return getProfileInstr() == llvm::driver::ProfileInstrKind::ProfileIRInstr;
|
||||
}
|
||||
|
||||
/// Check if CS IR level profile instrumentation is on.
|
||||
bool hasProfileCSIRInstr() const {
|
||||
return getProfileInstr() == ProfileCSIRInstr;
|
||||
return getProfileInstr() ==
|
||||
llvm::driver::ProfileInstrKind::ProfileCSIRInstr;
|
||||
}
|
||||
|
||||
/// Check if any form of instrumentation is on.
|
||||
bool hasProfileInstr() const { return getProfileInstr() != ProfileNone; }
|
||||
bool hasProfileInstr() const {
|
||||
return getProfileInstr() != llvm::driver::ProfileInstrKind::ProfileNone;
|
||||
}
|
||||
|
||||
/// Check if Clang profile use is on.
|
||||
bool hasProfileClangUse() const {
|
||||
return getProfileUse() == ProfileClangInstr;
|
||||
return getProfileUse() == llvm::driver::ProfileInstrKind::ProfileClangInstr;
|
||||
}
|
||||
|
||||
/// Check if IR level profile use is on.
|
||||
bool hasProfileIRUse() const {
|
||||
return getProfileUse() == ProfileIRInstr ||
|
||||
getProfileUse() == ProfileCSIRInstr;
|
||||
return getProfileUse() == llvm::driver::ProfileInstrKind::ProfileIRInstr ||
|
||||
getProfileUse() == llvm::driver::ProfileInstrKind::ProfileCSIRInstr;
|
||||
}
|
||||
|
||||
/// Check if CSIR profile use is on.
|
||||
bool hasProfileCSIRUse() const { return getProfileUse() == ProfileCSIRInstr; }
|
||||
bool hasProfileCSIRUse() const {
|
||||
return getProfileUse() == llvm::driver::ProfileInstrKind::ProfileCSIRInstr;
|
||||
}
|
||||
|
||||
/// Check if type and variable info should be emitted.
|
||||
bool hasReducedDebugInfo() const {
|
||||
|
||||
@@ -49,17 +49,16 @@ public:
|
||||
~ProfileList();
|
||||
|
||||
bool isEmpty() const { return Empty; }
|
||||
ExclusionType getDefault(CodeGenOptions::ProfileInstrKind Kind) const;
|
||||
ExclusionType getDefault(llvm::driver::ProfileInstrKind Kind) const;
|
||||
|
||||
std::optional<ExclusionType>
|
||||
isFunctionExcluded(StringRef FunctionName,
|
||||
CodeGenOptions::ProfileInstrKind Kind) const;
|
||||
llvm::driver::ProfileInstrKind Kind) const;
|
||||
std::optional<ExclusionType>
|
||||
isLocationExcluded(SourceLocation Loc,
|
||||
CodeGenOptions::ProfileInstrKind Kind) const;
|
||||
llvm::driver::ProfileInstrKind Kind) const;
|
||||
std::optional<ExclusionType>
|
||||
isFileExcluded(StringRef FileName,
|
||||
CodeGenOptions::ProfileInstrKind Kind) const;
|
||||
isFileExcluded(StringRef FileName, llvm::driver::ProfileInstrKind Kind) const;
|
||||
};
|
||||
|
||||
} // namespace clang
|
||||
|
||||
@@ -1772,7 +1772,7 @@ def fmcdc_max_test_vectors_EQ : Joined<["-"], "fmcdc-max-test-vectors=">,
|
||||
HelpText<"Maximum number of test vectors in MC/DC coverage">,
|
||||
MarshallingInfoInt<CodeGenOpts<"MCDCMaxTVs">, "0x7FFFFFFE">;
|
||||
def fprofile_generate : Flag<["-"], "fprofile-generate">,
|
||||
Group<f_Group>, Visibility<[ClangOption, CLOption]>,
|
||||
Group<f_Group>, Visibility<[ClangOption, CLOption, FlangOption, FC1Option]>,
|
||||
HelpText<"Generate instrumented code to collect execution counts into default.profraw (overridden by LLVM_PROFILE_FILE env var)">;
|
||||
def fprofile_generate_EQ : Joined<["-"], "fprofile-generate=">,
|
||||
Group<f_Group>, Visibility<[ClangOption, CLOption]>,
|
||||
@@ -1789,7 +1789,7 @@ def fprofile_use : Flag<["-"], "fprofile-use">, Group<f_Group>,
|
||||
Visibility<[ClangOption, CLOption]>, Alias<fprofile_instr_use>;
|
||||
def fprofile_use_EQ : Joined<["-"], "fprofile-use=">,
|
||||
Group<f_Group>,
|
||||
Visibility<[ClangOption, CLOption]>,
|
||||
Visibility<[ClangOption, CLOption, FlangOption, FC1Option]>,
|
||||
MetaVarName<"<pathname>">,
|
||||
HelpText<"Use instrumentation data for profile-guided optimization. If pathname is a directory, it reads from <pathname>/default.profdata. Otherwise, it reads from file <pathname>.">;
|
||||
def fno_profile_instr_generate : Flag<["-"], "fno-profile-instr-generate">,
|
||||
@@ -7761,7 +7761,7 @@ def fpatchable_function_entry_section_EQ
|
||||
MarshallingInfoString<CodeGenOpts<"PatchableFunctionEntrySection">>;
|
||||
def fprofile_instrument_EQ : Joined<["-"], "fprofile-instrument=">,
|
||||
HelpText<"Enable PGO instrumentation">, Values<"none,clang,llvm,csllvm,sample-coldcov">,
|
||||
NormalizedValuesScope<"CodeGenOptions">,
|
||||
NormalizedValuesScope<"llvm::driver::ProfileInstrKind">,
|
||||
NormalizedValues<["ProfileNone", "ProfileClangInstr", "ProfileIRInstr", "ProfileCSIRInstr", "ProfileIRSampleColdCov"]>,
|
||||
MarshallingInfoEnum<CodeGenOpts<"ProfileInstr">, "ProfileNone">;
|
||||
def fprofile_instrument_path_EQ : Joined<["-"], "fprofile-instrument-path=">,
|
||||
|
||||
@@ -69,24 +69,24 @@ ProfileList::ProfileList(ArrayRef<std::string> Paths, SourceManager &SM)
|
||||
|
||||
ProfileList::~ProfileList() = default;
|
||||
|
||||
static StringRef getSectionName(CodeGenOptions::ProfileInstrKind Kind) {
|
||||
static StringRef getSectionName(llvm::driver::ProfileInstrKind Kind) {
|
||||
switch (Kind) {
|
||||
case CodeGenOptions::ProfileNone:
|
||||
case llvm::driver::ProfileInstrKind::ProfileNone:
|
||||
return "";
|
||||
case CodeGenOptions::ProfileClangInstr:
|
||||
case llvm::driver::ProfileInstrKind::ProfileClangInstr:
|
||||
return "clang";
|
||||
case CodeGenOptions::ProfileIRInstr:
|
||||
case llvm::driver::ProfileInstrKind::ProfileIRInstr:
|
||||
return "llvm";
|
||||
case CodeGenOptions::ProfileCSIRInstr:
|
||||
case llvm::driver::ProfileInstrKind::ProfileCSIRInstr:
|
||||
return "csllvm";
|
||||
case CodeGenOptions::ProfileIRSampleColdCov:
|
||||
case llvm::driver::ProfileInstrKind::ProfileIRSampleColdCov:
|
||||
return "sample-coldcov";
|
||||
}
|
||||
llvm_unreachable("Unhandled CodeGenOptions::ProfileInstrKind enum");
|
||||
llvm_unreachable("Unhandled llvm::driver::ProfileInstrKind enum");
|
||||
}
|
||||
|
||||
ProfileList::ExclusionType
|
||||
ProfileList::getDefault(CodeGenOptions::ProfileInstrKind Kind) const {
|
||||
ProfileList::getDefault(llvm::driver::ProfileInstrKind Kind) const {
|
||||
StringRef Section = getSectionName(Kind);
|
||||
// Check for "default:<type>"
|
||||
if (SCL->inSection(Section, "default", "allow"))
|
||||
@@ -117,7 +117,7 @@ ProfileList::inSection(StringRef Section, StringRef Prefix,
|
||||
|
||||
std::optional<ProfileList::ExclusionType>
|
||||
ProfileList::isFunctionExcluded(StringRef FunctionName,
|
||||
CodeGenOptions::ProfileInstrKind Kind) const {
|
||||
llvm::driver::ProfileInstrKind Kind) const {
|
||||
StringRef Section = getSectionName(Kind);
|
||||
// Check for "function:<regex>=<case>"
|
||||
if (auto V = inSection(Section, "function", FunctionName))
|
||||
@@ -131,13 +131,13 @@ ProfileList::isFunctionExcluded(StringRef FunctionName,
|
||||
|
||||
std::optional<ProfileList::ExclusionType>
|
||||
ProfileList::isLocationExcluded(SourceLocation Loc,
|
||||
CodeGenOptions::ProfileInstrKind Kind) const {
|
||||
llvm::driver::ProfileInstrKind Kind) const {
|
||||
return isFileExcluded(SM.getFilename(SM.getFileLoc(Loc)), Kind);
|
||||
}
|
||||
|
||||
std::optional<ProfileList::ExclusionType>
|
||||
ProfileList::isFileExcluded(StringRef FileName,
|
||||
CodeGenOptions::ProfileInstrKind Kind) const {
|
||||
llvm::driver::ProfileInstrKind Kind) const {
|
||||
StringRef Section = getSectionName(Kind);
|
||||
// Check for "source:<regex>=<case>"
|
||||
if (auto V = inSection(Section, "source", FileName))
|
||||
|
||||
@@ -124,17 +124,10 @@ namespace clang {
|
||||
extern llvm::cl::opt<bool> ClSanitizeGuardChecks;
|
||||
}
|
||||
|
||||
// Default filename used for profile generation.
|
||||
static std::string getDefaultProfileGenName() {
|
||||
return DebugInfoCorrelate || ProfileCorrelate != InstrProfCorrelator::NONE
|
||||
? "default_%m.proflite"
|
||||
: "default_%m.profraw";
|
||||
}
|
||||
|
||||
// Path and name of file used for profile generation
|
||||
static std::string getProfileGenName(const CodeGenOptions &CodeGenOpts) {
|
||||
std::string FileName = CodeGenOpts.InstrProfileOutput.empty()
|
||||
? getDefaultProfileGenName()
|
||||
? llvm::driver::getDefaultProfileGenName()
|
||||
: CodeGenOpts.InstrProfileOutput;
|
||||
if (CodeGenOpts.ContinuousProfileSync)
|
||||
FileName = "%c" + FileName;
|
||||
|
||||
@@ -273,8 +273,8 @@ void BackendConsumer::HandleTranslationUnit(ASTContext &C) {
|
||||
std::unique_ptr<llvm::ToolOutputFile> OptRecordFile =
|
||||
std::move(*OptRecordFileOrErr);
|
||||
|
||||
if (OptRecordFile &&
|
||||
CodeGenOpts.getProfileUse() != CodeGenOptions::ProfileNone)
|
||||
if (OptRecordFile && CodeGenOpts.getProfileUse() !=
|
||||
llvm::driver::ProfileInstrKind::ProfileNone)
|
||||
Ctx.setDiagnosticsHotnessRequested(true);
|
||||
|
||||
if (CodeGenOpts.MisExpect) {
|
||||
|
||||
@@ -943,7 +943,8 @@ void CodeGenFunction::StartFunction(GlobalDecl GD, QualType RetTy,
|
||||
}
|
||||
}
|
||||
|
||||
if (CGM.getCodeGenOpts().getProfileInstr() != CodeGenOptions::ProfileNone) {
|
||||
if (CGM.getCodeGenOpts().getProfileInstr() !=
|
||||
llvm::driver::ProfileInstrKind::ProfileNone) {
|
||||
switch (CGM.isFunctionBlockedFromProfileInstr(Fn, Loc)) {
|
||||
case ProfileList::Skip:
|
||||
Fn->addFnAttr(llvm::Attribute::SkipProfile);
|
||||
|
||||
@@ -3608,7 +3608,7 @@ CodeGenModule::isFunctionBlockedByProfileList(llvm::Function *Fn,
|
||||
// If the profile list is empty, then instrument everything.
|
||||
if (ProfileList.isEmpty())
|
||||
return ProfileList::Allow;
|
||||
CodeGenOptions::ProfileInstrKind Kind = getCodeGenOpts().getProfileInstr();
|
||||
llvm::driver::ProfileInstrKind Kind = getCodeGenOpts().getProfileInstr();
|
||||
// First, check the function name.
|
||||
if (auto V = ProfileList.isFunctionExcluded(Fn->getName(), Kind))
|
||||
return *V;
|
||||
|
||||
@@ -887,6 +887,10 @@ void Flang::ConstructJob(Compilation &C, const JobAction &JA,
|
||||
// TODO: Handle interactions between -w, -pedantic, -Wall, -WOption
|
||||
Args.AddLastArg(CmdArgs, options::OPT_w);
|
||||
|
||||
// recognise options: fprofile-generate -fprofile-use=
|
||||
Args.addAllArgs(
|
||||
CmdArgs, {options::OPT_fprofile_generate, options::OPT_fprofile_use_EQ});
|
||||
|
||||
// Forward flags for OpenMP. We don't do this if the current action is an
|
||||
// device offloading action other than OpenMP.
|
||||
if (Args.hasFlag(options::OPT_fopenmp, options::OPT_fopenmp_EQ,
|
||||
|
||||
@@ -1492,11 +1492,11 @@ static void setPGOUseInstrumentor(CodeGenOptions &Opts,
|
||||
// which is available (might be one or both).
|
||||
if (PGOReader->isIRLevelProfile() || PGOReader->hasMemoryProfile()) {
|
||||
if (PGOReader->hasCSIRLevelProfile())
|
||||
Opts.setProfileUse(CodeGenOptions::ProfileCSIRInstr);
|
||||
Opts.setProfileUse(llvm::driver::ProfileInstrKind::ProfileCSIRInstr);
|
||||
else
|
||||
Opts.setProfileUse(CodeGenOptions::ProfileIRInstr);
|
||||
Opts.setProfileUse(llvm::driver::ProfileInstrKind::ProfileIRInstr);
|
||||
} else
|
||||
Opts.setProfileUse(CodeGenOptions::ProfileClangInstr);
|
||||
Opts.setProfileUse(llvm::driver::ProfileInstrKind::ProfileClangInstr);
|
||||
}
|
||||
|
||||
void CompilerInvocation::setDefaultPointerAuthOptions(
|
||||
|
||||
@@ -24,8 +24,15 @@ CODEGENOPT(OptimizationLevel, 2, 0) ///< The -O[0-3] option specified.
|
||||
CODEGENOPT(DebugPassManager, 1, 0) ///< Prints debug information for the new
|
||||
///< pass manager.
|
||||
|
||||
|
||||
/// Choose profile instrumenation kind or no instrumentation.
|
||||
ENUM_CODEGENOPT(ProfileInstr, llvm::driver::ProfileInstrKind, 2, llvm::driver::ProfileInstrKind::ProfileNone)
|
||||
/// Choose profile kind for PGO use compilation.
|
||||
ENUM_CODEGENOPT(ProfileUse, llvm::driver::ProfileInstrKind, 2, llvm::driver::ProfileInstrKind::ProfileNone)
|
||||
|
||||
CODEGENOPT(InstrumentFunctions, 1, 0) ///< Set when -finstrument_functions is
|
||||
///< enabled on the compile step.
|
||||
|
||||
CODEGENOPT(IsPIE, 1, 0) ///< PIE level is the same as PIC Level.
|
||||
CODEGENOPT(PICLevel, 2, 0) ///< PIC level of the LLVM module.
|
||||
CODEGENOPT(PrepareForFullLTO , 1, 0) ///< Set when -flto is enabled on the
|
||||
|
||||
@@ -154,6 +154,44 @@ public:
|
||||
/// OpenMP is enabled.
|
||||
using DoConcurrentMappingKind = flangomp::DoConcurrentMappingKind;
|
||||
|
||||
/// Name of the profile file to use as output for -fprofile-instr-generate,
|
||||
/// -fprofile-generate, and -fcs-profile-generate.
|
||||
std::string InstrProfileOutput;
|
||||
|
||||
/// Name of the profile file to use as input for -fmemory-profile-use.
|
||||
std::string MemoryProfileUsePath;
|
||||
|
||||
/// Name of the profile file to use as input for -fprofile-instr-use
|
||||
std::string ProfileInstrumentUsePath;
|
||||
|
||||
/// Name of the profile remapping file to apply to the profile data supplied
|
||||
/// by -fprofile-sample-use or -fprofile-instr-use.
|
||||
std::string ProfileRemappingFile;
|
||||
|
||||
/// Check if Clang profile instrumenation is on.
|
||||
bool hasProfileClangInstr() const {
|
||||
return getProfileInstr() == llvm::driver::ProfileClangInstr;
|
||||
}
|
||||
|
||||
/// Check if IR level profile instrumentation is on.
|
||||
bool hasProfileIRInstr() const {
|
||||
return getProfileInstr() == llvm::driver::ProfileIRInstr;
|
||||
}
|
||||
|
||||
/// Check if CS IR level profile instrumentation is on.
|
||||
bool hasProfileCSIRInstr() const {
|
||||
return getProfileInstr() == llvm::driver::ProfileCSIRInstr;
|
||||
}
|
||||
/// Check if IR level profile use is on.
|
||||
bool hasProfileIRUse() const {
|
||||
return getProfileUse() == llvm::driver::ProfileIRInstr ||
|
||||
getProfileUse() == llvm::driver::ProfileCSIRInstr;
|
||||
}
|
||||
/// Check if CSIR profile use is on.
|
||||
bool hasProfileCSIRUse() const {
|
||||
return getProfileUse() == llvm::driver::ProfileCSIRInstr;
|
||||
}
|
||||
|
||||
// Define accessors/mutators for code generation options of enumeration type.
|
||||
#define CODEGENOPT(Name, Bits, Default)
|
||||
#define ENUM_CODEGENOPT(Name, Type, Bits, Default) \
|
||||
|
||||
@@ -29,6 +29,7 @@
|
||||
#include "llvm/ADT/StringRef.h"
|
||||
#include "llvm/ADT/StringSwitch.h"
|
||||
#include "llvm/Frontend/Debug/Options.h"
|
||||
#include "llvm/Frontend/Driver/CodeGenOptions.h"
|
||||
#include "llvm/Option/Arg.h"
|
||||
#include "llvm/Option/ArgList.h"
|
||||
#include "llvm/Option/OptTable.h"
|
||||
@@ -441,6 +442,15 @@ static void parseCodeGenArgs(Fortran::frontend::CodeGenOptions &opts,
|
||||
opts.IsPIE = 1;
|
||||
}
|
||||
|
||||
if (args.hasArg(clang::driver::options::OPT_fprofile_generate)) {
|
||||
opts.setProfileInstr(llvm::driver::ProfileInstrKind::ProfileIRInstr);
|
||||
}
|
||||
|
||||
if (auto A = args.getLastArg(clang::driver::options::OPT_fprofile_use_EQ)) {
|
||||
opts.setProfileUse(llvm::driver::ProfileInstrKind::ProfileIRInstr);
|
||||
opts.ProfileInstrumentUsePath = A->getValue();
|
||||
}
|
||||
|
||||
// -mcmodel option.
|
||||
if (const llvm::opt::Arg *a =
|
||||
args.getLastArg(clang::driver::options::OPT_mcmodel_EQ)) {
|
||||
|
||||
@@ -56,10 +56,12 @@
|
||||
#include "llvm/Passes/PassBuilder.h"
|
||||
#include "llvm/Passes/PassPlugin.h"
|
||||
#include "llvm/Passes/StandardInstrumentations.h"
|
||||
#include "llvm/ProfileData/InstrProfCorrelator.h"
|
||||
#include "llvm/Support/AMDGPUAddrSpace.h"
|
||||
#include "llvm/Support/Error.h"
|
||||
#include "llvm/Support/ErrorHandling.h"
|
||||
#include "llvm/Support/FileSystem.h"
|
||||
#include "llvm/Support/PGOOptions.h"
|
||||
#include "llvm/Support/Path.h"
|
||||
#include "llvm/Support/SourceMgr.h"
|
||||
#include "llvm/Support/ToolOutputFile.h"
|
||||
@@ -67,6 +69,7 @@
|
||||
#include "llvm/TargetParser/RISCVISAInfo.h"
|
||||
#include "llvm/TargetParser/RISCVTargetParser.h"
|
||||
#include "llvm/Transforms/IPO/Internalize.h"
|
||||
#include "llvm/Transforms/Instrumentation/InstrProfiling.h"
|
||||
#include "llvm/Transforms/Utils/ModuleUtils.h"
|
||||
#include <memory>
|
||||
#include <system_error>
|
||||
@@ -919,6 +922,29 @@ void CodeGenAction::runOptimizationPipeline(llvm::raw_pwrite_stream &os) {
|
||||
llvm::PassInstrumentationCallbacks pic;
|
||||
llvm::PipelineTuningOptions pto;
|
||||
std::optional<llvm::PGOOptions> pgoOpt;
|
||||
|
||||
if (opts.hasProfileIRInstr()) {
|
||||
// -fprofile-generate.
|
||||
pgoOpt = llvm::PGOOptions(opts.InstrProfileOutput.empty()
|
||||
? llvm::driver::getDefaultProfileGenName()
|
||||
: opts.InstrProfileOutput,
|
||||
"", "", opts.MemoryProfileUsePath, nullptr,
|
||||
llvm::PGOOptions::IRInstr,
|
||||
llvm::PGOOptions::NoCSAction,
|
||||
llvm::PGOOptions::ColdFuncOpt::Default, false,
|
||||
/*PseudoProbeForProfiling=*/false, false);
|
||||
} else if (opts.hasProfileIRUse()) {
|
||||
llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS =
|
||||
llvm::vfs::getRealFileSystem();
|
||||
// -fprofile-use.
|
||||
auto CSAction = opts.hasProfileCSIRUse() ? llvm::PGOOptions::CSIRUse
|
||||
: llvm::PGOOptions::NoCSAction;
|
||||
pgoOpt = llvm::PGOOptions(
|
||||
opts.ProfileInstrumentUsePath, "", opts.ProfileRemappingFile,
|
||||
opts.MemoryProfileUsePath, VFS, llvm::PGOOptions::IRUse, CSAction,
|
||||
llvm::PGOOptions::ColdFuncOpt::Default, false);
|
||||
}
|
||||
|
||||
llvm::StandardInstrumentations si(llvmModule->getContext(),
|
||||
opts.DebugPassManager);
|
||||
si.registerCallbacks(pic, &mam);
|
||||
|
||||
@@ -8,3 +8,8 @@
|
||||
! CHECK-LABEL: "-fc1"
|
||||
! CHECK: -ffp-contract=off
|
||||
! CHECK: -O3
|
||||
|
||||
! RUN: %flang -### -S -fprofile-generate %s 2>&1 | FileCheck -check-prefix=CHECK-PROFILE-GENERATE-LLVM %s
|
||||
! CHECK-PROFILE-GENERATE-LLVM: "-fprofile-generate"
|
||||
! RUN: %flang -### -S -fprofile-use=%S %s 2>&1 | FileCheck -check-prefix=CHECK-PROFILE-USE-DIR %s
|
||||
! CHECK-PROFILE-USE-DIR: "-fprofile-use={{.*}}"
|
||||
|
||||
18
flang/test/Profile/Inputs/gcc-flag-compatibility_IR.proftext
Normal file
18
flang/test/Profile/Inputs/gcc-flag-compatibility_IR.proftext
Normal file
@@ -0,0 +1,18 @@
|
||||
# IR level Instrumentation Flag
|
||||
:ir
|
||||
_QQmain
|
||||
# Func Hash:
|
||||
146835646621254984
|
||||
# Num Counters:
|
||||
2
|
||||
# Counter Values:
|
||||
100
|
||||
1
|
||||
|
||||
main
|
||||
# Func Hash:
|
||||
742261418966908927
|
||||
# Num Counters:
|
||||
1
|
||||
# Counter Values:
|
||||
1
|
||||
@@ -0,0 +1,11 @@
|
||||
# IR level Instrumentation Flag
|
||||
:ir
|
||||
:entry_first
|
||||
_QQmain
|
||||
# Func Hash:
|
||||
146835646621254984
|
||||
# Num Counters:
|
||||
2
|
||||
# Counter Values:
|
||||
100
|
||||
1
|
||||
32
flang/test/Profile/gcc-flag-compatibility.f90
Normal file
32
flang/test/Profile/gcc-flag-compatibility.f90
Normal file
@@ -0,0 +1,32 @@
|
||||
! Tests for -fprofile-generate and -fprofile-use flag compatibility. These two
|
||||
! flags behave similarly to their GCC counterparts:
|
||||
!
|
||||
! -fprofile-generate Generates the profile file ./default.profraw
|
||||
! -fprofile-use=<dir>/file Uses the profile file <dir>/file
|
||||
|
||||
! On AIX, -flto used to be required with -fprofile-generate. gcc-flag-compatibility-aix.c is used to do the testing on AIX with -flto
|
||||
! RUN: %flang %s -c -S -o - -emit-llvm -fprofile-generate | FileCheck -check-prefix=PROFILE-GEN %s
|
||||
! PROFILE-GEN: @__profc_{{_?}}main = {{(private|internal)}} global [1 x i64] zeroinitializer, section
|
||||
! PROFILE-GEN: @__profd_{{_?}}main =
|
||||
|
||||
! Check that -fprofile-use=some/path/file.prof reads some/path/file.prof
|
||||
! This uses LLVM IR format profile.
|
||||
! RUN: rm -rf %t.dir
|
||||
! RUN: mkdir -p %t.dir/some/path
|
||||
! RUN: llvm-profdata merge %S/Inputs/gcc-flag-compatibility_IR.proftext -o %t.dir/some/path/file.prof
|
||||
! RUN: %flang %s -o - -emit-llvm -S -fprofile-use=%t.dir/some/path/file.prof | FileCheck -check-prefix=PROFILE-USE-IR1 %s
|
||||
! RUN: llvm-profdata merge %S/Inputs/gcc-flag-compatibility_IR_entry.proftext -o %t.dir/some/path/file.prof
|
||||
! RUN: %flang %s -o - -emit-llvm -S -fprofile-use=%t.dir/some/path/file.prof | FileCheck -check-prefix=PROFILE-USE-IR2 %s
|
||||
! PROFILE-USE-IR1: = !{!"branch_weights", i32 100, i32 1}
|
||||
! PROFILE-USE-IR2: = !{!"branch_weights", i32 1, i32 100}
|
||||
|
||||
program main
|
||||
implicit none
|
||||
integer :: i
|
||||
integer :: X = 0
|
||||
|
||||
do i = 0, 99
|
||||
X = X + i
|
||||
end do
|
||||
|
||||
end program main
|
||||
@@ -14,6 +14,7 @@
|
||||
#define LLVM_FRONTEND_DRIVER_CODEGENOPTIONS_H
|
||||
|
||||
#include "llvm/Support/Compiler.h"
|
||||
#include <string>
|
||||
|
||||
namespace llvm {
|
||||
class Triple;
|
||||
@@ -51,6 +52,18 @@ enum class VectorLibrary {
|
||||
LLVM_ABI TargetLibraryInfoImpl *createTLII(const llvm::Triple &TargetTriple,
|
||||
VectorLibrary Veclib);
|
||||
|
||||
enum ProfileInstrKind {
|
||||
ProfileNone, // Profile instrumentation is turned off.
|
||||
ProfileClangInstr, // Clang instrumentation to generate execution counts
|
||||
// to use with PGO.
|
||||
ProfileIRInstr, // IR level PGO instrumentation in LLVM.
|
||||
ProfileCSIRInstr, // IR level PGO context sensitive instrumentation in LLVM.
|
||||
ProfileIRSampleColdCov, // IR level sample pgo based cold function coverage
|
||||
// instrumentation in LLVM.
|
||||
};
|
||||
|
||||
// Default filename used for profile generation.
|
||||
std::string getDefaultProfileGenName();
|
||||
} // end namespace llvm::driver
|
||||
|
||||
#endif
|
||||
|
||||
@@ -12,4 +12,5 @@ add_llvm_component_library(LLVMFrontendDriver
|
||||
Core
|
||||
Support
|
||||
Analysis
|
||||
Instrumentation
|
||||
)
|
||||
|
||||
@@ -8,8 +8,15 @@
|
||||
|
||||
#include "llvm/Frontend/Driver/CodeGenOptions.h"
|
||||
#include "llvm/Analysis/TargetLibraryInfo.h"
|
||||
#include "llvm/ProfileData/InstrProfCorrelator.h"
|
||||
#include "llvm/TargetParser/Triple.h"
|
||||
|
||||
namespace llvm {
|
||||
extern llvm::cl::opt<bool> DebugInfoCorrelate;
|
||||
extern llvm::cl::opt<llvm::InstrProfCorrelator::ProfCorrelatorKind>
|
||||
ProfileCorrelate;
|
||||
} // namespace llvm
|
||||
|
||||
namespace llvm::driver {
|
||||
|
||||
TargetLibraryInfoImpl *createTLII(const llvm::Triple &TargetTriple,
|
||||
@@ -56,4 +63,10 @@ TargetLibraryInfoImpl *createTLII(const llvm::Triple &TargetTriple,
|
||||
return TLII;
|
||||
}
|
||||
|
||||
std::string getDefaultProfileGenName() {
|
||||
return llvm::DebugInfoCorrelate ||
|
||||
llvm::ProfileCorrelate != InstrProfCorrelator::NONE
|
||||
? "default_%m.proflite"
|
||||
: "default_%m.profraw";
|
||||
}
|
||||
} // namespace llvm::driver
|
||||
|
||||
Reference in New Issue
Block a user