Skip to content

Commit

Permalink
[CSSPGO] A Clang switch -fpseudo-probe-for-profiling for pseudo-probe…
Browse files Browse the repository at this point in the history
… instrumentation.

This change introduces a new clang switch `-fpseudo-probe-for-profiling` to enable AutoFDO with pseudo instrumentation. Please refer to https://reviews.llvm.org/D86193 for the whole story.

One implication from pseudo-probe instrumentation is that the profile is now sensitive to CFG changes. We perform the pseudo instrumentation very early in the pre-LTO pipeline, before any CFG transformation. This ensures that the CFG instrumented and annotated is stable and optimization-resilient.

The early instrumentation also allows the inliner to duplicate probes for inlined instances. When a probe along with the other instructions of a callee function are inlined into its caller function, the GUID of the callee function goes with the probe. This allows samples collected on inlined probes to be reported for the original callee function.

Reviewed By: wmi

Differential Revision: https://reviews.llvm.org/D86502
  • Loading branch information
htyu committed Nov 30, 2020
1 parent 64fa8cc commit c083fed
Show file tree
Hide file tree
Showing 8 changed files with 61 additions and 11 deletions.
3 changes: 3 additions & 0 deletions clang/include/clang/Basic/CodeGenOptions.def
Expand Up @@ -380,6 +380,9 @@ CODEGENOPT(StrictReturn, 1, 1)
/// Whether emit extra debug info for sample pgo profile collection.
CODEGENOPT(DebugInfoForProfiling, 1, 0)

/// Whether emit pseudo probes for sample pgo profile collection.
CODEGENOPT(PseudoProbeForProfiling, 1, 0)

/// Whether 3-component vector type is preserved.
CODEGENOPT(PreserveVec3Type, 1, 0)

Expand Down
6 changes: 6 additions & 0 deletions clang/include/clang/Driver/Options.td
Expand Up @@ -903,6 +903,12 @@ def fprofile_exclude_files_EQ : Joined<["-"], "fprofile-exclude-files=">,
def fprofile_update_EQ : Joined<["-"], "fprofile-update=">,
Group<f_Group>, Flags<[CC1Option, CoreOption]>, Values<"atomic,prefer-atomic,single">,
MetaVarName<"<method>">, HelpText<"Set update method of profile counters (atomic,prefer-atomic,single)">;
def fpseudo_probe_for_profiling : Flag<["-"], "fpseudo-probe-for-profiling">,
Group<f_Group>, Flags<[NoXarchOption, CC1Option]>,
HelpText<"Emit pseudo probes for sample profiler">;
def fno_pseudo_probe_for_profiling : Flag<["-"], "fno-pseudo-probe-for-profiling">,
Group<f_Group>, Flags<[NoXarchOption, CC1Option]>,
HelpText<"Do not emit pseudo probes for sample profiler.">;
def forder_file_instrumentation : Flag<["-"], "forder-file-instrumentation">,
Group<f_Group>, Flags<[CC1Option, CoreOption]>,
HelpText<"Generate instrumented code to collect order file into default.profraw file (overridden by '=' form of option or LLVM_PROFILE_FILE env var)">;
Expand Down
11 changes: 8 additions & 3 deletions clang/lib/CodeGen/BackendUtil.cpp
Expand Up @@ -1094,10 +1094,15 @@ void EmitAssemblyHelper::EmitAssemblyWithNewPassManager(
CSAction, CodeGenOpts.DebugInfoForProfiling);
} else if (!CodeGenOpts.SampleProfileFile.empty())
// -fprofile-sample-use
PGOOpt = PGOOptions(
CodeGenOpts.SampleProfileFile, "", CodeGenOpts.ProfileRemappingFile,
PGOOptions::SampleUse, PGOOptions::NoCSAction,
CodeGenOpts.DebugInfoForProfiling, CodeGenOpts.PseudoProbeForProfiling);
else if (CodeGenOpts.PseudoProbeForProfiling)
// -fpseudo-probe-for-profiling
PGOOpt =
PGOOptions(CodeGenOpts.SampleProfileFile, "",
CodeGenOpts.ProfileRemappingFile, PGOOptions::SampleUse,
PGOOptions::NoCSAction, CodeGenOpts.DebugInfoForProfiling);
PGOOptions("", "", "", PGOOptions::NoAction, PGOOptions::NoCSAction,
CodeGenOpts.DebugInfoForProfiling, true);
else if (CodeGenOpts.DebugInfoForProfiling)
// -fdebug-info-for-profiling
PGOOpt = PGOOptions("", "", "", PGOOptions::NoAction,
Expand Down
4 changes: 4 additions & 0 deletions clang/lib/Driver/ToolChains/Clang.cpp
Expand Up @@ -5636,6 +5636,10 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
}
Args.AddLastArg(CmdArgs, options::OPT_fprofile_remapping_file_EQ);

if (Args.hasFlag(options::OPT_fpseudo_probe_for_profiling,
options::OPT_fno_pseudo_probe_for_profiling, false))
CmdArgs.push_back("-fpseudo-probe-for-profiling");

RenderBuiltinOptions(TC, RawTriple, Args, CmdArgs);

if (!Args.hasFlag(options::OPT_fassume_sane_operator_new,
Expand Down
3 changes: 3 additions & 0 deletions clang/lib/Frontend/CompilerInvocation.cpp
Expand Up @@ -952,6 +952,9 @@ static bool ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, InputKind IK,
std::string(Args.getLastArgValue(OPT_fprofile_sample_use_EQ));
Opts.DebugInfoForProfiling = Args.hasFlag(
OPT_fdebug_info_for_profiling, OPT_fno_debug_info_for_profiling, false);
Opts.PseudoProbeForProfiling =
Args.hasFlag(OPT_fpseudo_probe_for_profiling,
OPT_fno_pseudo_probe_for_profiling, false);
Opts.DebugNameTable = static_cast<unsigned>(
Args.hasArg(OPT_ggnu_pubnames)
? llvm::DICompileUnit::DebugNameTableKind::GNU
Expand Down
17 changes: 17 additions & 0 deletions clang/test/CodeGen/pseudo-probe-emit.c
@@ -0,0 +1,17 @@
// RUN: %clang -O2 -fexperimental-new-pass-manager -fpseudo-probe-for-profiling -g -emit-llvm -S -o - %s | FileCheck %s

// Check the generation of pseudoprobe intrinsic call

void bar();
void go();

void foo(int x) {
// CHECK: call void @llvm.pseudoprobe(i64 [[#GUID:]], i64 1, i32 0)
if (x == 0)
// CHECK: call void @llvm.pseudoprobe(i64 [[#GUID]], i64 2, i32 0)
bar();
else
// CHECK: call void @llvm.pseudoprobe(i64 [[#GUID]], i64 3, i32 0)
go();
// CHECK: call void @llvm.pseudoprobe(i64 [[#GUID]], i64 4, i32 0)
}
18 changes: 12 additions & 6 deletions llvm/include/llvm/Passes/PassBuilder.h
Expand Up @@ -36,11 +36,15 @@ struct PGOOptions {
enum CSPGOAction { NoCSAction, CSIRInstr, CSIRUse };
PGOOptions(std::string ProfileFile = "", std::string CSProfileGenFile = "",
std::string ProfileRemappingFile = "", PGOAction Action = NoAction,
CSPGOAction CSAction = NoCSAction, bool SamplePGOSupport = false)
CSPGOAction CSAction = NoCSAction,
bool DebugInfoForProfiling = false,
bool PseudoProbeForProfiling = false)
: ProfileFile(ProfileFile), CSProfileGenFile(CSProfileGenFile),
ProfileRemappingFile(ProfileRemappingFile), Action(Action),
CSAction(CSAction),
SamplePGOSupport(SamplePGOSupport || Action == SampleUse) {
CSAction(CSAction), DebugInfoForProfiling(DebugInfoForProfiling ||
(Action == SampleUse &&
!PseudoProbeForProfiling)),
PseudoProbeForProfiling(PseudoProbeForProfiling) {
// Note, we do allow ProfileFile.empty() for Action=IRUse LTO can
// callback with IRUse action without ProfileFile.

Expand All @@ -55,16 +59,18 @@ struct PGOOptions {
// a profile.
assert(this->CSAction != CSIRUse || this->Action == IRUse);

// If neither Action nor CSAction, SamplePGOSupport needs to be true.
// If neither Action nor CSAction, DebugInfoForProfiling or
// PseudoProbeForProfiling needs to be true.
assert(this->Action != NoAction || this->CSAction != NoCSAction ||
this->SamplePGOSupport);
this->DebugInfoForProfiling || this->PseudoProbeForProfiling);
}
std::string ProfileFile;
std::string CSProfileGenFile;
std::string ProfileRemappingFile;
PGOAction Action;
CSPGOAction CSAction;
bool SamplePGOSupport;
bool DebugInfoForProfiling;
bool PseudoProbeForProfiling;
};

/// Tunable parameters for passes in the default pipelines.
Expand Down
10 changes: 8 additions & 2 deletions llvm/lib/Passes/PassBuilder.cpp
Expand Up @@ -952,6 +952,12 @@ PassBuilder::buildModuleSimplificationPipeline(OptimizationLevel Level,
ThinLTOPhase Phase) {
ModulePassManager MPM(DebugLogging);

// Place pseudo probe instrumentation as the first pass of the pipeline to
// minimize the impact of optimization changes.
if (PGOOpt && PGOOpt->PseudoProbeForProfiling &&
Phase != ThinLTOPhase::PostLink)
MPM.addPass(SampleProfileProbePass(TM));

bool HasSampleProfile = PGOOpt && (PGOOpt->Action == PGOOptions::SampleUse);

// In ThinLTO mode, when flattened profile is used, all the available
Expand Down Expand Up @@ -1320,7 +1326,7 @@ PassBuilder::buildPerModuleDefaultPipeline(OptimizationLevel Level,
for (auto &C : PipelineStartEPCallbacks)
C(MPM, Level);

if (PGOOpt && PGOOpt->SamplePGOSupport)
if (PGOOpt && PGOOpt->DebugInfoForProfiling)
MPM.addPass(createModuleToFunctionPassAdaptor(AddDiscriminatorsPass()));

// Add the core simplification pipeline.
Expand Down Expand Up @@ -1351,7 +1357,7 @@ PassBuilder::buildThinLTOPreLinkDefaultPipeline(OptimizationLevel Level) {
// Force any function attributes we want the rest of the pipeline to observe.
MPM.addPass(ForceFunctionAttrsPass());

if (PGOOpt && PGOOpt->SamplePGOSupport)
if (PGOOpt && PGOOpt->DebugInfoForProfiling)
MPM.addPass(createModuleToFunctionPassAdaptor(AddDiscriminatorsPass()));

// Apply module pipeline start EP callback.
Expand Down

0 comments on commit c083fed

Please sign in to comment.