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**
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
------------------------------------
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
^^^^^^^^^^^^^^^^^^^
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<
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">,
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>;
/// 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
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) {
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
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");
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());
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.
--- /dev/null
+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
+
--- /dev/null
+// 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;
+}