Index: docs/UsersManual.rst =================================================================== --- docs/UsersManual.rst +++ docs/UsersManual.rst @@ -315,6 +315,28 @@ 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 + `). 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** @@ -533,6 +555,8 @@ 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 ------------------------------------ @@ -576,6 +600,10 @@ 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 `). + Current limitations ^^^^^^^^^^^^^^^^^^^ Index: include/clang/Basic/DiagnosticDriverKinds.td =================================================================== --- include/clang/Basic/DiagnosticDriverKinds.td +++ include/clang/Basic/DiagnosticDriverKinds.td @@ -189,6 +189,9 @@ def warn_drv_empty_joined_argument : Warning< "joined argument expects additional value: '%0'">, InGroup; +def warn_drv_fdiagnostics_show_hotness_requires_pgo : Warning< + "argument '-fdiagnostics-show-hotness' requires profile-guided optimization information">, + InGroup; def warn_drv_clang_unsupported : Warning< "the clang compiler does not support '%0'">; def warn_drv_deprecated_arg : Warning< Index: include/clang/Driver/Options.td =================================================================== --- include/clang/Driver/Options.td +++ include/clang/Driver/Options.td @@ -583,6 +583,8 @@ def fdiagnostics_print_source_range_info : Flag<["-"], "fdiagnostics-print-source-range-info">, Group, Flags<[CC1Option]>, HelpText<"Print source range spans in numeric form">; +def fdiagnostics_show_hotness : Flag<["-"], "fdiagnostics-show-hotness">, Group, + Flags<[CC1Option]>, HelpText<"Enable profile hotness information in diagnostic line">; def fdiagnostics_show_option : Flag<["-"], "fdiagnostics-show-option">, 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 @@ Flags<[DriverOption]>; def fno_diagnostics_fixit_info : Flag<["-"], "fno-diagnostics-fixit-info">, Group, Flags<[CC1Option]>, HelpText<"Do not include fixit information in diagnostics">; +def fno_diagnostics_show_hotness : Flag<["-"], "fno-diagnostics-show-hotness">, Group; def fno_diagnostics_show_option : Flag<["-"], "fno-diagnostics-show-option">, Group; def fno_diagnostics_show_note_include_stack : Flag<["-"], "fno-diagnostics-show-note-include-stack">, Flags<[CC1Option]>, Group; Index: include/clang/Frontend/CodeGenOptions.def =================================================================== --- include/clang/Frontend/CodeGenOptions.def +++ include/clang/Frontend/CodeGenOptions.def @@ -247,6 +247,9 @@ /// 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 Index: lib/CodeGen/CodeGenAction.cpp =================================================================== --- lib/CodeGen/CodeGenAction.cpp +++ lib/CodeGen/CodeGenAction.cpp @@ -179,6 +179,7 @@ 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 @@ 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 Index: lib/Driver/Tools.cpp =================================================================== --- lib/Driver/Tools.cpp +++ lib/Driver/Tools.cpp @@ -4896,6 +4896,7 @@ 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"); @@ -5898,6 +5899,10 @@ 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()); Index: lib/Frontend/CompilerInvocation.cpp =================================================================== --- lib/Frontend/CompilerInvocation.cpp +++ lib/Frontend/CompilerInvocation.cpp @@ -839,6 +839,12 @@ 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. Index: test/Frontend/Inputs/optimization-remark-with-hotness.proftext =================================================================== --- /dev/null +++ test/Frontend/Inputs/optimization-remark-with-hotness.proftext @@ -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 + Index: test/Frontend/optimization-remark-with-hotness.c =================================================================== --- /dev/null +++ test/Frontend/optimization-remark-with-hotness.c @@ -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; +}