Add -fdiagnostics-show-hotness

Summary:
I've recently added the ability for optimization remarks to include the
hotness of the corresponding code region.  This uses PGO and allows
filtering of the optimization remarks by relevance.  The idea was first
discussed here:
http://thread.gmane.org/gmane.comp.compilers.llvm.devel/98334

The general goal is to produce a YAML file with the remarks.  Then, an
external tool could dynamically filter these by hotness and perhaps by
other things.

That said it makes sense to also expose this at the more basic level
where we just include the hotness info with each optimization remark.
For example, in D22694, the clang flag was pretty useful to measure the
overhead of the additional analyses required to include hotness.
(Without the flag we don't even run the analyses.)

For the record, Hal has already expressed support for the idea of this
patch on IRC.

Differential Revision: https://reviews.llvm.org/D23284

llvm-svn: 281276
This commit is contained in:
Adam Nemet 2016-09-12 23:48:16 +00:00
parent d2a4da09ad
commit a340eff335
9 changed files with 127 additions and 1 deletions

View File

@ -317,6 +317,28 @@ output format of the diagnostics that it generates.
by category, so it should be a high level category. We want dozens
of these, not hundreds or thousands of them.
.. _opt_fdiagnostics-show-hotness:
**-f[no-]diagnostics-show-hotness**
Enable profile hotness information in diagnostic line.
This option, which defaults to off, controls whether Clang prints the
profile hotness associated with a diagnostics in the presence of
profile-guided optimization information. This is currently supported with
optimization remarks (see :ref:`Options to Emit Optimization Reports
<rpass>`). The hotness information allows users to focus on the hot
optimization remarks that are likely to be more relevant for run-time
performance.
For example, in this output, the block containing the callsite of `foo` was
executed 3000 times according to the profile data:
::
s.c:7:10: remark: foo inlined into bar (hotness: 3000) [-Rpass-analysis=inline]
sum += foo(x, x - 2);
^
.. _opt_fdiagnostics-fixit-info:
**-f[no-]diagnostics-fixit-info**
@ -535,6 +557,8 @@ control the crash diagnostics.
The -fno-crash-diagnostics flag can be helpful for speeding the process
of generating a delta reduced test case.
.. _rpass:
Options to Emit Optimization Reports
------------------------------------
@ -578,6 +602,10 @@ outside of the major transformations (e.g., inlining, vectorization,
loop optimizations) and not every optimization pass supports this
feature.
Note that when using profile-guided optimization information, profile hotness
information can be included in the remarks (see
:ref:`-fdiagnostics-show-hotness <opt_fdiagnostics-show-hotness>`).
Current limitations
^^^^^^^^^^^^^^^^^^^

View File

@ -189,6 +189,9 @@ def warn_drv_unused_argument : Warning<
def warn_drv_empty_joined_argument : Warning<
"joined argument expects additional value: '%0'">,
InGroup<UnusedCommandLineArgument>;
def warn_drv_fdiagnostics_show_hotness_requires_pgo : Warning<
"argument '-fdiagnostics-show-hotness' requires profile-guided optimization information">,
InGroup<UnusedCommandLineArgument>;
def warn_drv_clang_unsupported : Warning<
"the clang compiler does not support '%0'">;
def warn_drv_deprecated_arg : Warning<

View File

@ -583,6 +583,8 @@ def fdiagnostics_parseable_fixits : Flag<["-"], "fdiagnostics-parseable-fixits">
def fdiagnostics_print_source_range_info : Flag<["-"], "fdiagnostics-print-source-range-info">,
Group<f_clang_Group>, Flags<[CC1Option]>,
HelpText<"Print source range spans in numeric form">;
def fdiagnostics_show_hotness : Flag<["-"], "fdiagnostics-show-hotness">, Group<f_Group>,
Flags<[CC1Option]>, HelpText<"Enable profile hotness information in diagnostic line">;
def fdiagnostics_show_option : Flag<["-"], "fdiagnostics-show-option">, Group<f_Group>,
Flags<[CC1Option]>, HelpText<"Print option name with mappable diagnostics">;
def fdiagnostics_show_note_include_stack : Flag<["-"], "fdiagnostics-show-note-include-stack">,
@ -939,6 +941,7 @@ def fno_cxx_modules : Flag <["-"], "fno-cxx-modules">, Group<f_Group>,
Flags<[DriverOption]>;
def fno_diagnostics_fixit_info : Flag<["-"], "fno-diagnostics-fixit-info">, Group<f_Group>,
Flags<[CC1Option]>, HelpText<"Do not include fixit information in diagnostics">;
def fno_diagnostics_show_hotness : Flag<["-"], "fno-diagnostics-show-hotness">, Group<f_Group>;
def fno_diagnostics_show_option : Flag<["-"], "fno-diagnostics-show-option">, Group<f_Group>;
def fno_diagnostics_show_note_include_stack : Flag<["-"], "fno-diagnostics-show-note-include-stack">,
Flags<[CC1Option]>, Group<f_Group>;

View File

@ -247,6 +247,9 @@ ENUM_CODEGENOPT(DefaultTLSModel, TLSModel, 2, GeneralDynamicTLSModel)
/// filename)
VALUE_CODEGENOPT(EmitCheckPathComponentsToStrip, 32, 0)
/// Whether to report the hotness of the code region for optimization remarks.
CODEGENOPT(DiagnosticsWithHotness, 1, 0)
#undef CODEGENOPT
#undef ENUM_CODEGENOPT
#undef VALUE_CODEGENOPT

View File

@ -179,6 +179,7 @@ namespace clang {
Ctx.getDiagnosticHandler();
void *OldDiagnosticContext = Ctx.getDiagnosticContext();
Ctx.setDiagnosticHandler(DiagnosticHandler, this);
Ctx.setDiagnosticHotnessRequested(CodeGenOpts.DiagnosticsWithHotness);
// Link LinkModule into this module if present, preserving its validity.
for (auto &I : LinkModules) {
@ -511,9 +512,16 @@ void BackendConsumer::EmitOptimizationMessage(
FullSourceLoc Loc = getBestLocationFromDebugLoc(D, BadDebugInfo, Filename,
Line, Column);
std::string Msg;
raw_string_ostream MsgStream(Msg);
MsgStream << D.getMsg().str();
if (D.getHotness())
MsgStream << " (hotness: " << *D.getHotness() << ")";
Diags.Report(Loc, DiagID)
<< AddFlagValue(D.getPassName() ? D.getPassName() : "")
<< D.getMsg().str();
<< MsgStream.str();
if (BadDebugInfo)
// If we were not able to translate the file:line:col information

View File

@ -4902,6 +4902,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
claimNoWarnArgs(Args);
Args.AddAllArgs(CmdArgs, options::OPT_R_Group);
Args.AddAllArgs(CmdArgs, options::OPT_W_Group);
if (Args.hasFlag(options::OPT_pedantic, options::OPT_no_pedantic, false))
CmdArgs.push_back("-pedantic");
@ -5904,6 +5905,10 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back(A->getValue());
}
if (Args.hasFlag(options::OPT_fdiagnostics_show_hotness,
options::OPT_fno_diagnostics_show_hotness, false))
CmdArgs.push_back("-fdiagnostics-show-hotness");
if (const Arg *A = Args.getLastArg(options::OPT_fdiagnostics_format_EQ)) {
CmdArgs.push_back("-fdiagnostics-format");
CmdArgs.push_back(A->getValue());

View File

@ -839,6 +839,12 @@ static bool ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, InputKind IK,
NeedLocTracking = true;
}
Opts.DiagnosticsWithHotness =
Args.hasArg(options::OPT_fdiagnostics_show_hotness);
if (Opts.DiagnosticsWithHotness &&
Opts.getProfileUse() == CodeGenOptions::ProfileNone)
Diags.Report(diag::warn_drv_fdiagnostics_show_hotness_requires_pgo);
// If the user requested to use a sample profile for PGO, then the
// backend will need to track source location information so the profile
// can be incorporated into the IR.

View File

@ -0,0 +1,25 @@
foo
# Func Hash:
0
# Num Counters:
1
# Counter Values:
30
bar
# Func Hash:
0
# Num Counters:
1
# Counter Values:
30
main
# Func Hash:
4
# Num Counters:
2
# Counter Values:
1
30

View File

@ -0,0 +1,45 @@
// RUN: llvm-profdata merge \
// RUN: %S/Inputs/optimization-remark-with-hotness.proftext \
// RUN: -o %t.profdata
// RUN: %clang_cc1 -triple x86_64-apple-macosx10.9 -main-file-name \
// RUN: optimization-remark-with-hotness.c %s -emit-llvm-only \
// RUN: -fprofile-instrument-use-path=%t.profdata -Rpass=inline \
// RUN: -Rpass-analysis=inline -fdiagnostics-show-hotness -verify
// The clang version of the previous test.
// RUN: %clang -target x86_64-apple-macosx10.9 %s -o /dev/null \
// RUN: -fprofile-instr-use=%t.profdata -Rpass=inline \
// RUN: -Rpass-analysis=inline -fdiagnostics-show-hotness -Xclang -verify
// RUN: %clang_cc1 -triple x86_64-apple-macosx10.9 -main-file-name \
// RUN: optimization-remark-with-hotness.c %s -emit-llvm-only \
// RUN: -fprofile-instrument-use-path=%t.profdata -Rpass=inline \
// RUN: -Rpass-analysis=inline 2>&1 | FileCheck -check-prefix=HOTNESS_OFF %s
// RUN: %clang_cc1 -triple x86_64-apple-macosx10.9 -main-file-name \
// RUN: optimization-remark-with-hotness.c %s -emit-llvm-only \
// RUN: -fprofile-instrument-use-path=%t.profdata -Rpass=inline \
// RUN: -Rpass-analysis=inline -Rno-pass-with-hotness 2>&1 | FileCheck \
// RUN: -check-prefix=HOTNESS_OFF %s
// RUN: %clang_cc1 -triple x86_64-apple-macosx10.9 -main-file-name \
// RUN: optimization-remark-with-hotness.c %s -emit-llvm-only \
// RUN: -Rpass=inline -Rpass-analysis=inline -fdiagnostics-show-hotness 2>&1 \
// RUN: | FileCheck -check-prefix=NO_PGO %s
int foo(int x, int y) __attribute__((always_inline));
int foo(int x, int y) { return x + y; }
int sum = 0;
void bar(int x) {
// HOTNESS_OFF: foo inlined into bar
// HOTNESS_OFF-NOT: hotness:
// NO_PGO: '-fdiagnostics-show-hotness' requires profile-guided optimization information
// expected-remark@+2 {{foo should always be inlined (cost=always) (hotness: 30)}}
// expected-remark@+1 {{foo inlined into bar (hotness: 30)}}
sum += foo(x, x - 2);
}
int main(int argc, const char *argv[]) {
for (int i = 0; i < 30; i++)
// expected-remark@+1 {{bar should never be inlined}}
bar(argc);
return sum;
}