This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: [PATCH 2/2] optinfo: add diagnostic remarks


On Mon, Jul 2, 2018 at 10:51 PM David Malcolm <dmalcolm@redhat.com> wrote:
>
> This patch adds the first destination for optinfo instances to be
> emitted to: as "remarks" through the diagnostics subsystem.
>
> Examples can be seen at
>   https://dmalcolm.fedorapeople.org/gcc/2018-06-18/test.cc.remarks.html
>
> Remarks look a lot like the output of -fopt-info, with the following
> differences:
>
> * announcing "In function 'blah':" etc when the function changes.
>
> * printing the corresponding source lines (unless
>   "-fno-diagnostics-show-caret"), as per other diagnostics, and
>
> * colorizing the various parts of the message if stderr is at a tty.
>
> * showing extra metadata:
>   * the pass that emitted the remark,
>   * the execution count of the code in question
>   * which file/line/function of GCC emitted the remark
>
> * possibly allowing for remarks to be used in DejaGnu tests to better
>   associate testing of an optimization with the source line in
>   question, rather than relying on a scan of the dumpfile (which is
>   per-source file and thus rather "coarse-grained").*
>
> Successfully bootstrapped & regrtested on x86_64-pc-linux-gnu.
>
> (see the notes in the cover letter about the state of this patch;
> posting for motivation of the optinfo stuff).

As an overall comment I do like this as it is an improvement
over -fopt-info which is currently the user-facing way of
showing remarks about what code is optimized and what
not and why.

But for this very reason I don't like introducing a separate
set of options.  This means the remark stuff should
replace -fopt-info (and re-use that flag as far as possible).
This eventually means some -fXYZ might reduce the
verbosity level (source line / hotness, etc.) to the current
state - but I don't think we have made any guarantees
about the current format.  Given there'll be the JSON stuff
for machine-consumption I am also not worried about
existing machines parsing the stuff.

Anyway, I think the issue outlined in the comment to 1/n
needs to be addressed first.

Thanks for working on this!
Richard.

> gcc/ChangeLog:
>         * Makefile.in (OBJS): Add optinfo-emit-diagnostics.o.
>         * common.opt (fremarks): New option.
>         (fdiagnostics-show-remark-hotness): New option.
>         (fdiagnostics-show-remark-origin): New option.
>         (fdiagnostics-show-remark-pass): New option.
>         * diagnostic-color.c (color_dict): Add "remark", as bold green.
>         * diagnostic-core.h (remark): New decl.
>         * diagnostic.c (diagnostic_action_after_output): Handle DK_REMARK.
>         (remark): New function.
>         * diagnostic.def (DK_REMARK): New diagnostic kind.
>         * doc/invoke.texi (Remarks): New section.
>         (-fremarks): New option.
>         (-fno-diagnostics-show-remark-hotness): New option.
>         (-fno-diagnostics-show-remark-origin): New option.
>         (-fno-diagnostics-show-remark-pass): New option.
>         * dumpfile.c (dump_context::get_scope_depth): Update comment.
>         (dump_context::end_any_optinfo): Likewise.
>         * dumpfile.h: Update comment.
>         * opt-functions.awk (function): Handle "Remark" by adding
>         CL_REMARK.
>         * optinfo-emit-diagnostics.cc: New file.
>         * optinfo-emit-diagnostics.h: New file.
>         * optinfo.cc: Include "optinfo-emit-diagnostics.h".
>         (optinfo::emit): Call emit_optinfo_as_diagnostic_remark.
>         (optinfo_enabled_p): Use flag_remarks.
>         * optinfo.h: Update comment.
>         * opts.c (print_specific_help): Handle CL_REMARK.
>         (common_handle_option): Likewise.
>         * opts.h (CL_REMARK): New macro.
>         (CL_MAX_OPTION_CLASS): Update for CL_REMARK.
>         (CL_JOINED, CL_SEPARATE, CL_UNDOCUMENTED, CL_NO_DWARF_RECORD)
>         (CL_PCH_IGNORE): Likewise.
>         * profile-count.c (profile_quality_as_string): New function.
>         * profile-count.h (profile_quality_as_string): New decl.
>         (profile_count::quality): New accessor.
>         * selftest-run-tests.c (selftest::run_tests): Call
>         selftest::optinfo_emit_diagnostics_cc_tests.
>         * selftest.h (selftest::optinfo_emit_diagnostics_cc_tests): New
>         decl.
>
> gcc/fortran/ChangeLog:
>         * gfc-diagnostic.def (DK_REMARK): New diagnostic kind.
>
> gcc/testsuite/ChangeLog:
>         * gcc.dg/plugin/plugin.exp (plugin_test_list): Add
>         remarks_plugin.c.
>         * gcc.dg/plugin/remarks-1.c: New test.
>         * gcc.dg/plugin/remarks_plugin.c: New test plugin.
>         * lib/gcc-dg.exp (dg-remark): New function.
> ---
>  gcc/Makefile.in                              |   1 +
>  gcc/common.opt                               |  17 ++
>  gcc/diagnostic-color.c                       |   2 +
>  gcc/diagnostic-core.h                        |   2 +
>  gcc/diagnostic.c                             |  17 ++
>  gcc/diagnostic.def                           |   1 +
>  gcc/doc/invoke.texi                          |  67 ++++++
>  gcc/dumpfile.c                               |   5 +-
>  gcc/dumpfile.h                               |   2 +
>  gcc/fortran/gfc-diagnostic.def               |   1 +
>  gcc/opt-functions.awk                        |   1 +
>  gcc/optinfo-emit-diagnostics.cc              | 317 +++++++++++++++++++++++++++
>  gcc/optinfo-emit-diagnostics.h               |  26 +++
>  gcc/optinfo.cc                               |   9 +-
>  gcc/optinfo.h                                |   4 +-
>  gcc/opts.c                                   |   4 +
>  gcc/opts.h                                   |  13 +-
>  gcc/profile-count.c                          |  28 +++
>  gcc/profile-count.h                          |   5 +
>  gcc/selftest-run-tests.c                     |   1 +
>  gcc/selftest.h                               |   1 +
>  gcc/testsuite/gcc.dg/plugin/plugin.exp       |   2 +
>  gcc/testsuite/gcc.dg/plugin/remarks-1.c      |  30 +++
>  gcc/testsuite/gcc.dg/plugin/remarks_plugin.c | 152 +++++++++++++
>  gcc/testsuite/lib/gcc-dg.exp                 |   9 +
>  25 files changed, 701 insertions(+), 16 deletions(-)
>  create mode 100644 gcc/optinfo-emit-diagnostics.cc
>  create mode 100644 gcc/optinfo-emit-diagnostics.h
>  create mode 100644 gcc/testsuite/gcc.dg/plugin/remarks-1.c
>  create mode 100644 gcc/testsuite/gcc.dg/plugin/remarks_plugin.c
>
> diff --git a/gcc/Makefile.in b/gcc/Makefile.in
> index 7d36a77..232cae4 100644
> --- a/gcc/Makefile.in
> +++ b/gcc/Makefile.in
> @@ -1427,6 +1427,7 @@ OBJS = \
>         optabs-query.o \
>         optabs-tree.o \
>         optinfo.o \
> +       optinfo-emit-diagnostics.o \
>         options-save.o \
>         opts-global.o \
>         passes.o \
> diff --git a/gcc/common.opt b/gcc/common.opt
> index 5a50bc27..908432e 100644
> --- a/gcc/common.opt
> +++ b/gcc/common.opt
> @@ -510,6 +510,11 @@ Driver Negative(Qn)
>  R
>  Driver Joined Separate
>
> +fremarks
> +Common Remark Var(flag_remarks)
> +Emit diagnostic remarks about optimizations
> +FIXME: should this be -fdiagnostics-foo or somesuch?
> +
>  S
>  Driver
>
> @@ -1281,6 +1286,18 @@ fdiagnostics-show-option
>  Common Var(flag_diagnostics_show_option) Init(1)
>  Amend appropriate diagnostic messages with the command line option that controls them.
>
> +fdiagnostics-show-remark-hotness
> +Common Var(flag_diagnostics_show_remark_hotness) Init(1)
> +When emitting optimization remarks, show the execution count of the code being optimized.
> +
> +fdiagnostics-show-remark-origin
> +Common Var(flag_diagnostics_show_remark_origin) Init(1)
> +When emitting optimization remarks, show which line of GCC code produced the remark.
> +
> +fdiagnostics-show-remark-pass
> +Common Var(flag_diagnostics_show_remark_pass) Init(1)
> +When emitting optimization remarks, show which optimization pass produced the remark.
> +
>  fdisable-
>  Common Joined RejectNegative Var(common_deferred_options) Defer
>  -fdisable-[tree|rtl|ipa]-<pass>=range1+range2 disables an optimization pass.
> diff --git a/gcc/diagnostic-color.c b/gcc/diagnostic-color.c
> index 3ee21bc..bcc3767 100644
> --- a/gcc/diagnostic-color.c
> +++ b/gcc/diagnostic-color.c
> @@ -84,6 +84,8 @@ static struct color_cap color_dict[] =
>    { "error", SGR_SEQ (COLOR_BOLD COLOR_SEPARATOR COLOR_FG_RED), 5, false },
>    { "warning", SGR_SEQ (COLOR_BOLD COLOR_SEPARATOR COLOR_FG_MAGENTA),
>                7, false },
> +  { "remark", SGR_SEQ (COLOR_BOLD COLOR_SEPARATOR COLOR_FG_GREEN),
> +              6, false },
>    { "note", SGR_SEQ (COLOR_BOLD COLOR_SEPARATOR COLOR_FG_CYAN), 4, false },
>    { "range1", SGR_SEQ (COLOR_FG_GREEN), 6, false },
>    { "range2", SGR_SEQ (COLOR_FG_BLUE), 6, false },
> diff --git a/gcc/diagnostic-core.h b/gcc/diagnostic-core.h
> index aa5807e..63166b8 100644
> --- a/gcc/diagnostic-core.h
> +++ b/gcc/diagnostic-core.h
> @@ -69,6 +69,8 @@ extern bool warning_at (location_t, int, const char *, ...)
>      ATTRIBUTE_GCC_DIAG(3,4);
>  extern bool warning_at (rich_location *, int, const char *, ...)
>      ATTRIBUTE_GCC_DIAG(3,4);
> +extern bool remark (location_t, int, const char *, ...)
> +    ATTRIBUTE_GCC_DIAG(3,4);
>  extern void error (const char *, ...) ATTRIBUTE_GCC_DIAG(1,2);
>  extern void error_n (location_t, unsigned HOST_WIDE_INT, const char *,
>                      const char *, ...)
> diff --git a/gcc/diagnostic.c b/gcc/diagnostic.c
> index e22c17b..97ed88b 100644
> --- a/gcc/diagnostic.c
> +++ b/gcc/diagnostic.c
> @@ -492,6 +492,7 @@ diagnostic_action_after_output (diagnostic_context *context,
>      {
>      case DK_DEBUG:
>      case DK_NOTE:
> +    case DK_REMARK:
>      case DK_ANACHRONISM:
>      case DK_WARNING:
>        break;
> @@ -1274,6 +1275,22 @@ warning_n (location_t location, int opt, unsigned HOST_WIDE_INT n,
>    return ret;
>  }
>
> +/* Emit an optimization remark at LOCATION.  This is used by the optinfo
> +   framework.
> +   Return true if the remark was printed, false if it was inhibited.  */
> +// FIXME: we don't yet have a more fine-grained way of inhibiting remarks
> +
> +bool
> +remark (location_t location, int opt, const char *gmsgid, ...)
> +{
> +  va_list ap;
> +  va_start (ap, gmsgid);
> +  rich_location richloc (line_table, location);
> +  bool ret = diagnostic_impl (&richloc, opt, gmsgid, &ap, DK_REMARK);
> +  va_end (ap);
> +  return ret;
> +}
> +
>  /* A "pedantic" warning at LOCATION: issues a warning unless
>     -pedantic-errors was given on the command line, in which case it
>     issues an error.  Use this for diagnostics required by the relevant
> diff --git a/gcc/diagnostic.def b/gcc/diagnostic.def
> index ce3dc56..b58095d 100644
> --- a/gcc/diagnostic.def
> +++ b/gcc/diagnostic.def
> @@ -37,6 +37,7 @@ DEFINE_DIAGNOSTIC_KIND (DK_SORRY, "sorry, unimplemented: ", "error")
>  DEFINE_DIAGNOSTIC_KIND (DK_WARNING, "warning: ", "warning")
>  DEFINE_DIAGNOSTIC_KIND (DK_ANACHRONISM, "anachronism: ", "warning")
>  DEFINE_DIAGNOSTIC_KIND (DK_NOTE, "note: ", "note")
> +DEFINE_DIAGNOSTIC_KIND (DK_REMARK, "remark: ", "remark")
>  DEFINE_DIAGNOSTIC_KIND (DK_DEBUG, "debug: ", "note")
>  /* These two would be re-classified as DK_WARNING or DK_ERROR, so the
>  prefix does not matter.  */
> diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
> index 248e603..1a3c1a6 100644
> --- a/gcc/doc/invoke.texi
> +++ b/gcc/doc/invoke.texi
> @@ -141,6 +141,7 @@ only one of these two forms, whichever one is not the default.
>  * Debugging Options::   Producing debuggable code.
>  * Optimize Options::    How much optimization?
>  * Instrumentation Options:: Enabling profiling and extra run-time error checking.
> +* Remarks::             Details on how your code is being optimized.
>  * Preprocessor Options:: Controlling header files and macro definitions.
>                           Also, getting dependency information for Make.
>  * Assembler Options::   Passing options to the assembler.
> @@ -471,6 +472,11 @@ Objective-C and Objective-C++ Dialects}.
>  -finstrument-functions-exclude-function-list=@var{sym},@var{sym},@dots{} @gol
>  -finstrument-functions-exclude-file-list=@var{file},@var{file},@dots{}}
>
> +@item Remarks
> +@xref{Remarks,,Options to Control Remarks from the Compiler}.
> +@gccoptlist{-fremarks -fno-diagnostics-show-remark-hotness @gol
> +-fno-diagnostics-show-remark-origin -fno-diagnostics-show-remark-pass}
> +
>  @item Preprocessor Options
>  @xref{Preprocessor Options,,Options Controlling the Preprocessor}.
>  @gccoptlist{-A@var{question}=@var{answer} @gol
> @@ -12040,6 +12046,67 @@ The NOP instructions are inserted at---and maybe before, depending on
>  @end table
>
>
> +@node Remarks
> +@section Options to Control Remarks from the Compiler
> +@cindex remarks
> +@cindex options, remarks
> +
> +These options are aimed at advanced users who may be interested
> +in seeing additional diagnostics from the compiler, giving information
> +on the decisions it is making on the code.
> +
> +The precise messages and their format are subject to change.
> +
> +@table @gcctabopt
> +@item -fremarks
> +@opindex fremarks
> +Emit diagnostic remarks about optimizations.
> +
> +Enabling this option leads to GCC emitting diagnostics detailing the
> +optimization decisions it is making.
> +
> +For example, this message:
> +
> +@smallexample
> +test.c:13:3: remark:   Symbolic number of iterations is '(unsigned int) n_8(D)' [pass=vect] [count(precise)=76800000] [../../src/gcc/tree-vect-loop.c:1387:vect_analyze_loop_form]
> +@end smallexample
> +
> +describes an internal detail of the ``vect'' optimization pass, acting at
> +the given source location within ``test.c'', where the remark was emitted
> +by the function ``vect_analyze_loop_form'' at line 1387 of GCC's source
> +file ``tree-vect-loop.c''.
> +
> +@item -fno-diagnostics-show-remark-hotness
> +@opindex fno-diagnostics-show-remark-hotness
> +@opindex fdiagnostics-show-remark-hotness
> +By default, if diagnostic remarks are enabled, they include information
> +on the execution count, or ``hotness'', of the code being optimized:
> +the ``[count(precise)=76800000]'' in the example above.
> +
> +This option suppresses this part of the remark.
> +
> +@item -fno-diagnostics-show-remark-origin
> +@opindex fno-diagnostics-show-remark-origin
> +@opindex fdiagnostics-show-remark-origin
> +By default, if diagnostic remarks are enabled, they include information
> +on where in GCC's own source code (or a plugin's source code) the remark
> +is being emitted from; the
> +``[../../src/gcc/tree-vect-loop.c:1387:vect_analyze_loop_form]''
> +in the example above.
> +
> +This option suppresses this part of the remark.
> +
> +@item -fno-diagnostics-show-remark-pass
> +@opindex fno-diagnostics-show-remark-pass
> +@opindex fdiagnostics-show-remark-pass
> +By default, if diagnostic remarks are enabled, they include information
> +on which optimization pass emitted the remark: the ``[pass=vect]''
> +in the example above.
> +
> +This option suppresses this part of the remark.
> +
> +@end table
> +
>  @node Preprocessor Options
>  @section Options Controlling the Preprocessor
>  @cindex preprocessor options
> diff --git a/gcc/dumpfile.c b/gcc/dumpfile.c
> index 6e089ef..955fd57 100644
> --- a/gcc/dumpfile.c
> +++ b/gcc/dumpfile.c
> @@ -690,7 +690,7 @@ dump_context::dump_symtab_node (dump_flags_t dump_kind, symtab_node *node)
>  }
>
>  /* Get the current dump scope-nesting depth.
> -   For use by -fopt-info (for showing nesting via indentation).  */
> +   For use by remarks and -fopt-info (for showing nesting via indentation).  */
>
>  unsigned int
>  dump_context::get_scope_depth () const
> @@ -766,8 +766,7 @@ dump_context::begin_next_optinfo (const dump_location_t &loc)
>  }
>
>  /* End any optinfo that has been accumulated within this context; emitting
> -   it to any destinations as appropriate - though none have currently been
> -   implemented.  */
> +   it to any destinations as appropriate, such as a diagnostic "remark".  */
>
>  void
>  dump_context::end_any_optinfo ()
> diff --git a/gcc/dumpfile.h b/gcc/dumpfile.h
> index 899bb89..514efe3 100644
> --- a/gcc/dumpfile.h
> +++ b/gcc/dumpfile.h
> @@ -442,6 +442,7 @@ dump_enabled_p (void)
>     (a) the active dump_file, if any
>     (b) the -fopt-info destination, if any
>     (c) to the "optinfo" destinations, if any:
> +       (c.1) as diagnostic "remarks"
>
>     dump_* (MSG_*) --> dumpfile.c --+--> (a) dump_file
>                                     |
> @@ -449,6 +450,7 @@ dump_enabled_p (void)
>                                     |
>                                     `--> (c) optinfo
>                                              `---> optinfo destinations
> +                                                  (c.1) diagnostic "remarks"
>
>     For optinfos, the dump_*_loc mark the beginning of an optinfo
>     instance: all subsequent dump_* calls are consolidated into
> diff --git a/gcc/fortran/gfc-diagnostic.def b/gcc/fortran/gfc-diagnostic.def
> index 565fa83..a10b6aa 100644
> --- a/gcc/fortran/gfc-diagnostic.def
> +++ b/gcc/fortran/gfc-diagnostic.def
> @@ -37,6 +37,7 @@ DEFINE_DIAGNOSTIC_KIND (DK_SORRY, "sorry, unimplemented", "error")
>  DEFINE_DIAGNOSTIC_KIND (DK_WARNING, "Warning", "warning")
>  DEFINE_DIAGNOSTIC_KIND (DK_ANACHRONISM, "anachronism", "warning")
>  DEFINE_DIAGNOSTIC_KIND (DK_NOTE, "note", "note")
> +DEFINE_DIAGNOSTIC_KIND (DK_REMARK, "remark ", "remark")
>  DEFINE_DIAGNOSTIC_KIND (DK_DEBUG, "debug", "note")
>  /* These two would be re-classified as DK_WARNING or DK_ERROR, so the
>  prefix does not matter.  */
> diff --git a/gcc/opt-functions.awk b/gcc/opt-functions.awk
> index 2c371e5..48ecac5 100644
> --- a/gcc/opt-functions.awk
> +++ b/gcc/opt-functions.awk
> @@ -105,6 +105,7 @@ function switch_flags (flags)
>           test_flag("Undocumented", flags,  " | CL_UNDOCUMENTED") \
>           test_flag("NoDWARFRecord", flags,  " | CL_NO_DWARF_RECORD") \
>           test_flag("Warning", flags,  " | CL_WARNING") \
> +         test_flag("Remark", flags,  " | CL_REMARK") \
>           test_flag("(Optimization|PerFunction)", flags,  " | CL_OPTIMIZATION")
>         sub( "^0 \\| ", "", result )
>         return result
> diff --git a/gcc/optinfo-emit-diagnostics.cc b/gcc/optinfo-emit-diagnostics.cc
> new file mode 100644
> index 0000000..5320379
> --- /dev/null
> +++ b/gcc/optinfo-emit-diagnostics.cc
> @@ -0,0 +1,317 @@
> +/* Emit optimization information as "remark" diagnostics.
> +   Copyright (C) 2018 Free Software Foundation, Inc.
> +   Contributed by David Malcolm <dmalcolm@redhat.com>.
> +
> +This file is part of GCC.
> +
> +GCC is free software; you can redistribute it and/or modify it under
> +the terms of the GNU General Public License as published by the Free
> +Software Foundation; either version 3, or (at your option) any later
> +version.
> +
> +GCC is distributed in the hope that it will be useful, but WITHOUT ANY
> +WARRANTY; without even the implied warranty of MERCHANTABILITY or
> +FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
> +for more details.
> +
> +You should have received a copy of the GNU General Public License
> +along with GCC; see the file COPYING3.  If not see
> +<http://www.gnu.org/licenses/>.  */
> +
> +#include "config.h"
> +#include "system.h"
> +#include "coretypes.h"
> +
> +#include "backend.h"
> +#include "tree.h"
> +#include "tree-pass.h"
> +#include "gimple.h"
> +#include "pretty-print.h"
> +#include "tree-pretty-print.h"
> +#include "gimple-pretty-print.h"
> +#include "diagnostic.h"
> +#include "diagnostic-color.h"
> +#include "options.h"
> +#include "cgraph.h"
> +
> +#include "optinfo.h"
> +#include "optinfo-emit-diagnostics.h"
> +#include "optinfo-internal.h"
> +#include "dump-context.h"
> +#include "selftest.h"
> +#include "context.h"
> +#include "pass_manager.h"
> +
> +/* Print the items within OPTINFO to PP (as part of a remark).  */
> +
> +static void
> +print_optinfo_items (pretty_printer *pp, const optinfo *optinfo)
> +{
> +  bool show_color = pp_show_color (pp);
> +
> +  for (unsigned i = 0; i < optinfo->num_items (); i++)
> +    {
> +      const optinfo_item *item = optinfo->get_item (i);
> +      switch (item->get_kind ())
> +       {
> +       default:
> +         gcc_unreachable ();
> +       case OPTINFO_ITEM_KIND_TEXT:
> +         {
> +           const optinfo_item_text *as_text
> +             = (const optinfo_item_text *)item;
> +           pp_string (pp, as_text->get_text ());
> +         }
> +         break;
> +       case OPTINFO_ITEM_KIND_TREE:
> +         {
> +           const optinfo_item_tree *as_tree
> +             = (const optinfo_item_tree *)item;
> +           pp_begin_quote (pp, show_color);
> +           dump_generic_node (pp, as_tree->get_node (), 0, TDF_DETAILS,
> +                              false);
> +           pp_end_quote (pp, show_color);
> +         }
> +         break;
> +       case OPTINFO_ITEM_KIND_GIMPLE:
> +         {
> +           const optinfo_item_gimple *as_gimple
> +             = (const optinfo_item_gimple *)item;
> +           gimple *stmt = as_gimple->get_stmt ();
> +           pp_begin_quote (pp, show_color);
> +           pp_gimple_stmt_1 (pp, stmt, 0, TDF_SLIM);
> +           pp_end_quote (pp, show_color);
> +         }
> +         break;
> +       case OPTINFO_ITEM_KIND_SYMTAB_NODE:
> +         {
> +           const optinfo_item_symtab_node *as_symtab_node
> +             = (const optinfo_item_symtab_node *)item;
> +           symtab_node *node = as_symtab_node->get_node ();
> +           pp_begin_quote (pp, show_color);
> +           pp_string (pp, node->dump_name ());
> +           pp_end_quote (pp, show_color);
> +         }
> +         break;
> +       }
> +    }
> +}
> +
> +/* Print PASS to PP (as part of a remark).  */
> +
> +static void
> +print_pass (pretty_printer *pp, opt_pass *pass)
> +{
> +  if (pass == NULL)
> +    return;
> +
> +  bool show_color = pp_show_color (pp);
> +
> +  pp_string (pp, " [");
> +  pp_string (pp, colorize_start (show_color,
> +                                diagnostic_get_color_for_kind (DK_REMARK)));
> +  pp_string (pp, "pass=");
> +  pp_string (pp, pass->name);
> +  pp_string (pp, colorize_stop (show_color));
> +  pp_string (pp, "]");
> +}
> +
> +/* Print COUNT to PP (as part of a remark).  */
> +
> +static void
> +print_count (pretty_printer *pp, profile_count count)
> +{
> +  if (!count.initialized_p ())
> +    return;
> +
> +  bool show_color = pp_show_color (pp);
> +
> +  pp_string (pp, " [");
> +  pp_string (pp,
> +            colorize_start (show_color,
> +                            diagnostic_get_color_for_kind (DK_NOTE)));
> +  pp_string (pp, "count(");
> +  pp_string (pp, profile_quality_as_string (count.quality ()));
> +  pp_string (pp, ")=");
> +  pp_scalar (pp, "%li", count.to_gcov_type ());
> +  pp_string (pp, colorize_stop (show_color));
> +  pp_string (pp, "]");
> +}
> +
> +/* Print IMPL_LOC to PP (as part of a remark).  */
> +
> +static void
> +print_impl_location (pretty_printer *pp, const dump_impl_location_t &impl_loc)
> +{
> +  bool show_color = pp_show_color (pp);
> +
> +  pp_string (pp, " [");
> +  pp_string (pp,
> +            colorize_start (show_color,
> +                            diagnostic_get_color_for_kind (DK_REMARK)));
> +  pp_printf (pp, "%s:%i", impl_loc.m_file, impl_loc.m_line);
> +  if (impl_loc.m_function)
> +    pp_printf (pp, ":%s", impl_loc.m_function);
> +  pp_string (pp, colorize_stop (show_color));
> +  pp_string (pp, "]");
> +}
> +
> +/* Print OPTINFO to PP.  */
> +
> +static void
> +print_optinfo_as_remark (pretty_printer *pp, const optinfo *optinfo)
> +{
> +  /* Start with scope-based indentation.  */
> +  for (unsigned i = get_dump_scope_depth (); i > 0; i--)
> +    pp_space (pp);
> +
> +  /* Print the items into PP.  */
> +  print_optinfo_items (pp, optinfo);
> +
> +  /* Add metadata: which pass?  */
> +  if (flag_diagnostics_show_remark_pass)
> +    print_pass (pp, optinfo->get_pass ());
> +
> +  /* Add metadata: hotness.  */
> +  if (flag_diagnostics_show_remark_hotness)
> +    print_count (pp, optinfo->get_count ());
> +
> +  /* Add metadata: where was this emitted from.  */
> +  if (flag_diagnostics_show_remark_origin)
> +    print_impl_location (pp, optinfo->get_impl_location ());
> +}
> +
> +/* Subclass of pretty_printer for building up the text of a remark.  */
> +
> +class remark_printer : public pretty_printer
> +{
> +public:
> +  remark_printer (bool show_color_);
> +};
> +
> +/* remark_printer's ctor.  */
> +
> +remark_printer::remark_printer (bool show_color_)
> +{
> +  pp_needs_newline (this) = true;
> +  pp_translate_identifiers (this) = false;
> +  pp_show_color (this) = show_color_;
> +}
> +
> +/* If diagnostic "remarks" are enabled, then emit OPTINFO as a remark.  */
> +
> +void
> +emit_optinfo_as_diagnostic_remark (const optinfo *optinfo)
> +{
> +  if (!flag_remarks)
> +    return;
> +
> +  remark_printer pp (pp_show_color (global_dc->printer));
> +
> +  print_optinfo_as_remark (&pp, optinfo);
> +
> +  const char *msg = pp_formatted_text (&pp);
> +  location_t loc = optinfo->get_location_t ();
> +
> +  remark (loc, 0, "%s", msg);
> +}
> +
> +#if CHECKING_P
> +
> +namespace selftest {
> +
> +/* Verify that print_optinfo_items works.  */
> +
> +static void
> +test_print_optinfo_items ()
> +{
> +  temp_dump_context tmp (true);
> +  dump_location_t loc;
> +  dump_printf_loc (MSG_NOTE, loc, "test of tree: ");
> +  dump_generic_expr (MSG_NOTE, TDF_SLIM, integer_zero_node);
> +  optinfo *info = tmp.get_pending_optinfo ();
> +  ASSERT_TRUE (info != NULL);
> +
> +  /* Avoid introducing locale-specific differences in the results
> +     by hardcoding open_quote and close_quote.  */
> +  auto_fix_quotes fix_quotes;
> +
> +  remark_printer pp (false);
> +  print_optinfo_items (&pp, info);
> +  const char *msg = pp_formatted_text (&pp);
> +  ASSERT_STREQ (msg, "test of tree: `0'");
> +}
> +
> +/* Verify that print_pass works.  */
> +
> +static void
> +test_print_pass ()
> +{
> +  /* NULL pass.  */
> +  {
> +    remark_printer pp (false);
> +    print_pass (&pp, NULL);
> +    const char *msg = pp_formatted_text (&pp);
> +    ASSERT_STREQ (msg, "");
> +  }
> +
> +  /* Non-NULL pass.  */
> +  {
> +    remark_printer pp (false);
> +    opt_pass *pass = make_pass_ipa_increase_alignment (NULL);
> +    print_pass (&pp, pass);
> +    const char *msg = pp_formatted_text (&pp);
> +    ASSERT_STREQ (msg, " [pass=increase_alignment]");
> +    delete pass;
> +  }
> +}
> +
> +/* Verify that print_count works.  */
> +
> +static void
> +test_print_count ()
> +{
> +  remark_printer pp (false);
> +  print_count (&pp, profile_count ());
> +  const char *msg = pp_formatted_text (&pp);
> +  ASSERT_STREQ (msg, " [count(uninitialized)=0]");
> +}
> +
> +/* Verify that print_impl_location works.  */
> +
> +static void
> +test_print_impl_location ()
> +{
> +  /* Non-NULL function.  */
> +  {
> +    remark_printer pp (false);
> +    dump_impl_location_t loc ("foo.c", 42, "funcname");
> +    print_impl_location (&pp, loc);
> +    const char *msg = pp_formatted_text (&pp);
> +    ASSERT_STREQ (msg, " [foo.c:42:funcname]");
> +  }
> +
> +  /* NULL function.  */
> +  {
> +    remark_printer pp (false);
> +    dump_impl_location_t loc ("foo.c", 42, NULL);
> +    print_impl_location (&pp, loc);
> +    const char *msg = pp_formatted_text (&pp);
> +    ASSERT_STREQ (msg, " [foo.c:42]");
> +  }
> +}
> +
> +/* Run all of the selftests within this file.  */
> +
> +void
> +optinfo_emit_diagnostics_cc_tests ()
> +{
> +  test_print_optinfo_items ();
> +  test_print_pass ();
> +  test_print_count ();
> +  test_print_impl_location ();
> +}
> +
> +} // namespace selftest
> +
> +#endif /* CHECKING_P */
> diff --git a/gcc/optinfo-emit-diagnostics.h b/gcc/optinfo-emit-diagnostics.h
> new file mode 100644
> index 0000000..820cefd
> --- /dev/null
> +++ b/gcc/optinfo-emit-diagnostics.h
> @@ -0,0 +1,26 @@
> +/* Emit optimization information as "remark" diagnostics.
> +   Copyright (C) 2018 Free Software Foundation, Inc.
> +   Contributed by David Malcolm <dmalcolm@redhat.com>.
> +
> +This file is part of GCC.
> +
> +GCC is free software; you can redistribute it and/or modify it under
> +the terms of the GNU General Public License as published by the Free
> +Software Foundation; either version 3, or (at your option) any later
> +version.
> +
> +GCC is distributed in the hope that it will be useful, but WITHOUT ANY
> +WARRANTY; without even the implied warranty of MERCHANTABILITY or
> +FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
> +for more details.
> +
> +You should have received a copy of the GNU General Public License
> +along with GCC; see the file COPYING3.  If not see
> +<http://www.gnu.org/licenses/>.  */
> +
> +#ifndef GCC_OPTINFO_EMIT_DIAGNOSTICS_H
> +#define GCC_OPTINFO_EMIT_DIAGNOSTICS_H
> +
> +extern void emit_optinfo_as_diagnostic_remark (const optinfo *);
> +
> +#endif /* #ifndef GCC_OPTINFO_EMIT_DIAGNOSTICS_H */
> diff --git a/gcc/optinfo.cc b/gcc/optinfo.cc
> index 1da7d37..bc86696 100644
> --- a/gcc/optinfo.cc
> +++ b/gcc/optinfo.cc
> @@ -28,6 +28,7 @@ along with GCC; see the file COPYING3.  If not see
>
>  #include "optinfo.h"
>  #include "optinfo-internal.h"
> +#include "optinfo-emit-diagnostics.h"
>  #include "dump-context.h"
>  #include "selftest.h"
>
> @@ -112,7 +113,8 @@ optinfo::emit ()
>        delete last_item;
>      }
>
> -  /* currently this is a no-op.  */
> +  /* -fremarks.  */
> +  emit_optinfo_as_diagnostic_remark (this);
>  }
>
>  /* Update the optinfo's kind based on DUMP_KIND.  */
> @@ -203,9 +205,8 @@ optinfo::add_dec (const wide_int_ref &wi, signop sgn)
>
>  bool optinfo_enabled_p ()
>  {
> -  /* Currently no destinations are implemented, just a hook for
> -     selftests.  */
> -  return dump_context::get ().forcibly_enable_optinfo_p ();
> +  return (dump_context::get ().forcibly_enable_optinfo_p ()
> +         || flag_remarks);
>  }
>
>  /* Return true if any of the active optinfo destinations make use
> diff --git a/gcc/optinfo.h b/gcc/optinfo.h
> index 0d49823..8a8f812 100644
> --- a/gcc/optinfo.h
> +++ b/gcc/optinfo.h
> @@ -27,9 +27,7 @@ along with GCC; see the file COPYING3.  If not see
>
>     * as a "remark" through the diagnostics subsystem
>
> -   * saved to a file as an "optimization record"
> -
> -   Currently no such destinations are implemented.
> +   * saved to a file as an "optimization record" (not yet implemented)
>
>     They are generated in response to calls to the "dump_*" API in
>     dumpfile.h; repeated calls to the "dump_*" API are consolidated
> diff --git a/gcc/opts.c b/gcc/opts.c
> index ed102c0..5cc8801 100644
> --- a/gcc/opts.c
> +++ b/gcc/opts.c
> @@ -1435,6 +1435,9 @@ print_specific_help (unsigned int include_flags,
>         case CL_WARNING:
>           description = _("The following options control compiler warning messages");
>           break;
> +       case CL_REMARK:
> +         description = _("The following options control compiler remarks");
> +         break;
>         case CL_OPTIMIZATION:
>           description = _("The following options control optimizations");
>           break;
> @@ -1875,6 +1878,7 @@ common_handle_option (struct gcc_options *opts,
>               { "optimizers", CL_OPTIMIZATION },
>               { "target", CL_TARGET },
>               { "warnings", CL_WARNING },
> +             { "remarks", CL_REMARK },
>               { "undocumented", CL_UNDOCUMENTED },
>               { "params", CL_PARAMS },
>               { "joined", CL_JOINED },
> diff --git a/gcc/opts.h b/gcc/opts.h
> index 3c4065ea..d9df788 100644
> --- a/gcc/opts.h
> +++ b/gcc/opts.h
> @@ -137,20 +137,21 @@ extern const unsigned int cl_lang_count;
>  #define CL_DRIVER              (1U << 19) /* Driver option.  */
>  #define CL_TARGET              (1U << 20) /* Target-specific option.  */
>  #define CL_COMMON              (1U << 21) /* Language-independent.  */
> +#define CL_REMARK              (1U << 22) /* Enables an (optional) remark.  */
>
>  #define CL_MIN_OPTION_CLASS    CL_PARAMS
> -#define CL_MAX_OPTION_CLASS    CL_COMMON
> +#define CL_MAX_OPTION_CLASS    CL_REMARK
>
>  /* From here on the bits describe attributes of the options.
>     Before this point the bits have described the class of the option.
>     This distinction is important because --help will not list options
>     which only have these higher bits set.  */
>
> -#define CL_JOINED              (1U << 22) /* If takes joined argument.  */
> -#define CL_SEPARATE            (1U << 23) /* If takes a separate argument.  */
> -#define CL_UNDOCUMENTED                (1U << 24) /* Do not output with --help.  */
> -#define CL_NO_DWARF_RECORD     (1U << 25) /* Do not add to producer string.  */
> -#define CL_PCH_IGNORE          (1U << 26) /* Do compare state for pch.  */
> +#define CL_JOINED              (1U << 23) /* If takes joined argument.  */
> +#define CL_SEPARATE            (1U << 24) /* If takes a separate argument.  */
> +#define CL_UNDOCUMENTED                (1U << 25) /* Do not output with --help.  */
> +#define CL_NO_DWARF_RECORD     (1U << 26) /* Do not add to producer string.  */
> +#define CL_PCH_IGNORE          (1U << 27) /* Do compare state for pch.  */
>
>  /* Flags for an enumerated option argument.  */
>  #define CL_ENUM_CANONICAL      (1 << 0) /* Canonical for this value.  */
> diff --git a/gcc/profile-count.c b/gcc/profile-count.c
> index 3d411cf..6a17f5e 100644
> --- a/gcc/profile-count.c
> +++ b/gcc/profile-count.c
> @@ -33,6 +33,34 @@ along with GCC; see the file COPYING3.  If not see
>  #include "wide-int.h"
>  #include "sreal.h"
>
> +/* Get a string describing QUALITY.  */
> +
> +const char *
> +profile_quality_as_string (enum profile_quality quality)
> +{
> +  switch (quality)
> +    {
> +    default:
> +      gcc_unreachable ();
> +    case profile_uninitialized:
> +      return "uninitialized";
> +    case profile_guessed_local:
> +      return "guessed_local";
> +    case profile_guessed_global0:
> +      return "guessed_global0";
> +    case profile_guessed_global0adjusted:
> +      return "guessed_global0adjusted";
> +    case profile_guessed:
> +      return "guessed";
> +    case profile_afdo:
> +      return "afdo";
> +    case profile_adjusted:
> +      return "adjusted";
> +    case profile_precise:
> +      return "precise";
> +    }
> +}
> +
>  /* Dump THIS to F.  */
>
>  void
> diff --git a/gcc/profile-count.h b/gcc/profile-count.h
> index c83fa3b..f4d0c340 100644
> --- a/gcc/profile-count.h
> +++ b/gcc/profile-count.h
> @@ -59,6 +59,8 @@ enum profile_quality {
>    profile_precise
>  };
>
> +extern const char *profile_quality_as_string (enum profile_quality);
> +
>  /* The base value for branch probability notes and edge probabilities.  */
>  #define REG_BR_PROB_BASE  10000
>
> @@ -721,6 +723,9 @@ public:
>        return m_quality == profile_precise;
>      }
>
> +  /* Get the quality of the count.  */
> +  enum profile_quality quality () const { return m_quality; }
> +
>    /* When merging basic blocks, the two different profile counts are unified.
>       Return true if this can be done without losing info about profile.
>       The only case we care about here is when first BB contains something
> diff --git a/gcc/selftest-run-tests.c b/gcc/selftest-run-tests.c
> index 989c50a..c0acf19 100644
> --- a/gcc/selftest-run-tests.c
> +++ b/gcc/selftest-run-tests.c
> @@ -73,6 +73,7 @@ selftest::run_tests ()
>    unique_ptr_tests_cc_tests ();
>    opt_proposer_c_tests ();
>    optinfo_cc_tests ();
> +  optinfo_emit_diagnostics_cc_tests ();
>
>    /* Mid-level data structures.  */
>    input_c_tests ();
> diff --git a/gcc/selftest.h b/gcc/selftest.h
> index 48881c9..1594d1d 100644
> --- a/gcc/selftest.h
> +++ b/gcc/selftest.h
> @@ -229,6 +229,7 @@ extern void hash_map_tests_c_tests ();
>  extern void hash_set_tests_c_tests ();
>  extern void input_c_tests ();
>  extern void optinfo_cc_tests ();
> +extern void optinfo_emit_diagnostics_cc_tests ();
>  extern void predict_c_tests ();
>  extern void pretty_print_c_tests ();
>  extern void read_rtl_function_c_tests ();
> diff --git a/gcc/testsuite/gcc.dg/plugin/plugin.exp b/gcc/testsuite/gcc.dg/plugin/plugin.exp
> index 5a19fc9..1f0a079 100644
> --- a/gcc/testsuite/gcc.dg/plugin/plugin.exp
> +++ b/gcc/testsuite/gcc.dg/plugin/plugin.exp
> @@ -96,6 +96,8 @@ set plugin_test_list [list \
>           must-tail-call-2.c } \
>      { expensive_selftests_plugin.c \
>           expensive-selftests-1.c } \
> +    { remarks_plugin.c \
> +         remarks-1.c } \
>  ]
>
>  foreach plugin_test $plugin_test_list {
> diff --git a/gcc/testsuite/gcc.dg/plugin/remarks-1.c b/gcc/testsuite/gcc.dg/plugin/remarks-1.c
> new file mode 100644
> index 0000000..9139b9d
> --- /dev/null
> +++ b/gcc/testsuite/gcc.dg/plugin/remarks-1.c
> @@ -0,0 +1,30 @@
> +/* { dg-do compile } */
> +/* { dg-options "-fremarks" } */
> +
> +extern void test_string_literal (void);
> +extern void test_tree (void);
> +extern void test_gimple (int);
> +extern void test_cgraph_node (void);
> +extern void test_printf (void);
> +extern void test_wide_int (void);
> +extern void test_poly_int (void);
> +extern void test_scopes (void);
> +
> +void test_remarks (void)
> +{
> +  test_string_literal (); /* { dg-remark "test of remark for test_string_literal" } */
> +  test_tree (); /* { dg-remark "test of tree: '0'" } */
> +  test_gimple (42); /* { dg-remark "test of gimple: 'test_gimple \\(42\\);'" } */
> +  test_cgraph_node (); /* { dg-remark "test of callgraph node: 'test_cgraph_node/.*'" } */
> +  test_printf (); /* { dg-remark "test of optinfo printf: 42" } */
> +  test_wide_int (); /* { dg-remark "test of wide int: 0" } */
> +  test_poly_int (); /* { dg-remark "test of poly int: 42" } */
> +
> +  test_scopes (); /* { dg-line test_scopes_line } */
> +  /* { dg-remark "=== outer scope ===" "" { target *-*-* } test_scopes_line } */
> +  /* { dg-remark " at outer scope" "" { target *-*-* } test_scopes_line } */
> +  /* { dg-remark " === middle scope ===" "" { target *-*-* } test_scopes_line } */
> +  /* { dg-remark "  at middle scope" "" { target *-*-* } test_scopes_line } */
> +  /* { dg-remark "  === innermost scope ===" "" { target *-*-* } test_scopes_line } */
> +  /* { dg-remark "   at innermost scope" "" { target *-*-* } test_scopes_line } */
> +}
> diff --git a/gcc/testsuite/gcc.dg/plugin/remarks_plugin.c b/gcc/testsuite/gcc.dg/plugin/remarks_plugin.c
> new file mode 100644
> index 0000000..332bba6
> --- /dev/null
> +++ b/gcc/testsuite/gcc.dg/plugin/remarks_plugin.c
> @@ -0,0 +1,152 @@
> +/* Test of remark-emission by optinfo.  */
> +
> +#include "gcc-plugin.h"
> +#include "config.h"
> +#include "system.h"
> +#include "coretypes.h"
> +#include "tree.h"
> +#include "tree-pass.h"
> +#include "intl.h"
> +#include "plugin-version.h"
> +#include "diagnostic.h"
> +#include "context.h"
> +#include "optinfo.h"
> +#include "gimple.h"
> +#include "gimple-iterator.h"
> +#include "cgraph.h"
> +
> +int plugin_is_GPL_compatible;
> +
> +const pass_data pass_data_test_remarks =
> +{
> +  GIMPLE_PASS, /* type */
> +  "test_remarks", /* name */
> +  OPTGROUP_NONE, /* optinfo_flags */
> +  TV_NONE, /* tv_id */
> +  PROP_ssa, /* properties_required */
> +  0, /* properties_provided */
> +  0, /* properties_destroyed */
> +  0, /* todo_flags_start */
> +  0, /* todo_flags_finish */
> +};
> +
> +class pass_test_remarks : public gimple_opt_pass
> +{
> +public:
> +  pass_test_remarks(gcc::context *ctxt)
> +    : gimple_opt_pass(pass_data_test_remarks, ctxt)
> +  {}
> +
> +  /* opt_pass methods: */
> +  bool gate (function *) { return true; }
> +  virtual unsigned int execute (function *);
> +
> +}; // class pass_test_remarks
> +
> +unsigned int
> +pass_test_remarks::execute (function *fun)
> +{
> +  basic_block bb;
> +
> +  if (!dump_enabled_p ())
> +    return 0;
> +
> +  FOR_ALL_BB_FN (bb, fun)
> +    for (gimple_stmt_iterator gsi = gsi_start_bb (bb);
> +        !gsi_end_p (gsi); gsi_next (&gsi))
> +      {
> +       gimple *stmt = gsi_stmt (gsi);
> +       gcall *call = dyn_cast <gcall *> (stmt);
> +       if (!call)
> +         continue;
> +       tree callee_decl = gimple_call_fndecl (call);
> +       if (!callee_decl)
> +         continue;
> +       tree callee_name = DECL_NAME (callee_decl);
> +       if (!callee_name)
> +         continue;
> +       const char *callee = IDENTIFIER_POINTER (callee_name);
> +
> +       /* Various optinfo tests, done at callsites,
> +          controlled by the callee name.  */
> +       if (strcmp (callee, "test_string_literal") == 0)
> +         {
> +           dump_printf_loc (MSG_NOTE, stmt, "test of remark for ");
> +           dump_printf (MSG_NOTE, callee);
> +         }
> +       else if (strcmp (callee, "test_tree") == 0)
> +         {
> +           dump_printf_loc (MSG_NOTE, stmt, "test of tree: ");
> +           dump_generic_expr (MSG_NOTE, TDF_SLIM, integer_zero_node);
> +         }
> +       else if (strcmp (callee, "test_gimple") == 0)
> +         {
> +           dump_printf_loc (MSG_NOTE, stmt, "test of gimple: ");
> +           dump_gimple_stmt (MSG_NOTE, TDF_SLIM, stmt, 0);
> +         }
> +       else if (strcmp (callee, "test_cgraph_node") == 0)
> +         {
> +           dump_printf_loc (MSG_NOTE, stmt, "test of callgraph node: ");
> +           dump_symtab_node (MSG_NOTE, cgraph_node::get (callee_decl));
> +         }
> +       else if (strcmp (callee, "test_printf") == 0)
> +         {
> +           dump_printf_loc (MSG_NOTE, stmt, "test of optinfo printf: %d", 42);
> +         }
> +       else if (strcmp (callee, "test_wide_int") == 0)
> +         {
> +           HOST_WIDE_INT val = 0;
> +           dump_printf_loc (MSG_NOTE, stmt,
> +                            "test of wide int: " HOST_WIDE_INT_PRINT_DEC,
> +                            val);
> +         }
> +       else if (strcmp (callee, "test_poly_int") == 0)
> +         {
> +           dump_printf_loc (MSG_NOTE, stmt, "test of poly int: ");
> +           dump_dec (MSG_NOTE, poly_int64 (42));
> +         }
> +       else if (strcmp (callee, "test_scopes") == 0)
> +         {
> +           AUTO_DUMP_SCOPE ("outer scope", stmt);
> +           {
> +             dump_printf_loc (MSG_NOTE, stmt, "at outer scope");
> +             AUTO_DUMP_SCOPE ("middle scope", stmt);
> +             {
> +               dump_printf_loc (MSG_NOTE, stmt, "at middle scope");
> +               AUTO_DUMP_SCOPE ("innermost scope", stmt);
> +               dump_printf_loc (MSG_NOTE, stmt, "at innermost scope");
> +             }
> +           }
> +         }
> +      }
> +
> +  return 0;
> +}
> +
> +static gimple_opt_pass *
> +make_pass_test_remarks (gcc::context *ctxt)
> +{
> +  return new pass_test_remarks (ctxt);
> +}
> +
> +int
> +plugin_init (struct plugin_name_args *plugin_info,
> +            struct plugin_gcc_version *version)
> +{
> +  struct register_pass_info pass_info;
> +  const char *plugin_name = plugin_info->base_name;
> +  int argc = plugin_info->argc;
> +  struct plugin_argument *argv = plugin_info->argv;
> +
> +  if (!plugin_default_version_check (version, &gcc_version))
> +    return 1;
> +
> +  pass_info.pass = make_pass_test_remarks (g);
> +  pass_info.reference_pass_name = "ssa";
> +  pass_info.ref_pass_instance_number = 1;
> +  pass_info.pos_op = PASS_POS_INSERT_AFTER;
> +  register_callback (plugin_name, PLUGIN_PASS_MANAGER_SETUP, NULL,
> +                    &pass_info);
> +
> +  return 0;
> +}
> diff --git a/gcc/testsuite/lib/gcc-dg.exp b/gcc/testsuite/lib/gcc-dg.exp
> index a15c5d5..906ee3b 100644
> --- a/gcc/testsuite/lib/gcc-dg.exp
> +++ b/gcc/testsuite/lib/gcc-dg.exp
> @@ -1154,6 +1154,15 @@ proc dg-locus { args } {
>      verbose "process-message:\n${dg-messages}" 2
>  }
>
> +# Handle remarks.
> +
> +proc dg-remark { args } {
> +    # Make this variable available here and to the saved proc.
> +    upvar dg-messages dg-messages
> +
> +    process-message saved-dg-error "remark: " "$args"
> +}
> +
>  # Check the existence of a gdb in the path, and return true if there
>  # is one.
>  #
> --
> 1.8.5.3
>


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]