forked from OSchip/llvm-project
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:
parent
d2a4da09ad
commit
a340eff335
|
@ -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
|
||||
^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
|
|
|
@ -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<
|
||||
|
|
|
@ -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>;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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());
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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
|
||||
|
|
@ -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;
|
||||
}
|
Loading…
Reference in New Issue