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 1/2] Add "optinfo" framework


On Tue, Jul 10, 2018 at 1:00 PM David Malcolm <dmalcolm@redhat.com> wrote:
>
> On Mon, 2018-07-09 at 15:00 +0200, Richard Biener wrote:
> > On Mon, Jul 2, 2018 at 10:51 PM David Malcolm <dmalcolm@redhat.com>
> > wrote:
> > >
> > > This patch implements a way to consolidate dump_* calls into
> > > optinfo objects, as enabling work towards being able to write out
> > > optimization records to a file, or emit them as diagnostic
> > > "remarks".
> > >
> > > The patch adds the support for building optinfo instances from
> > > dump_*
> > > calls, but leaves implementing any *users* of them to followup
> > > patches.
> > >
> > > Successfully bootstrapped & regrtested on x86_64-pc-linux-gnu.
> > >
> > > OK for trunk?
> >
> > Looks good overall, but ...
> >
> > To "fix" the GC issue you'd need to capture all possibly interesting
> > information from tree/gimple while it is still in flight.  This _may_
> > be
> > necessary anyway since I remember writing code like
> >
> >   fprintf (dump_file, "old: ");
> >   print_gimple_stmt (..., stmt);
> >   gimple_set_rhs1 (stmt, op);
> >   fprintf (dump_file, "new: ");
> >   print_gmple_stmt (..., stmt);
> >   fprintf (dump_file, "\n");
> >
> > capturing interesting information means we know all targeted
> > optinfo channels, right?  And the optinfo consumers
> > need to handle "streams" of input and may not look back.
>
> > I've yet have to look at the 2nd patch but can you comment on
> > this?  How difficult is it to re-wire how the data flows to make
> > stmt re-use like the above possible?
>
> I *think* it's doable: rather than capture, say, a gimple *, the
> optinfo_item would capture the result of pp_gimple_stmt_1, plus some
> metadata.  In fact, it would probably allow for removing the
> optinfo_item subclasses, making optinfo_item concrete, containing
> something like:
>
>   /* Textual form.  */
>   char *m_text;
>   bool m_ownership_of_text;
>
>   /* Metadata for optimization records.  */
>   enum optinfo_item_kind m_kind;
>   location_t m_location;
>
> or somesuch.
>
> I'll have a go at implementing this.

Thanks, that would be much cleaner (if also a bit more fugly
when you need to debug things)

Richard.

> Thanks
> Dave
>
> > Thanks,
> > Richard.
> >
> > > gcc/ChangeLog:
> > >         * Makefile.in (OBJS): Add optinfo.o.
> > >         * coretypes.h (class symtab_node): New forward decl.
> > >         (struct cgraph_node): New forward decl.
> > >         (class varpool_node): New forward decl.
> > >         * dump-context.h: New file.
> > >         * dumpfile.c: Include "optinfo.h", "dump-context.h",
> > > "cgraph.h",
> > >         "tree-pass.h", "optinfo-internal.h".
> > >         (refresh_dumps_are_enabled): Use optinfo_enabled_p.
> > >         (set_dump_file): Call
> > > dumpfile_ensure_any_optinfo_are_flushed.
> > >         (set_alt_dump_file): Likewise.
> > >         (dump_context::~dump_context): New dtor.
> > >         (dump_gimple_stmt): Move implementation to...
> > >         (dump_context::dump_gimple_stmt): ...this new member
> > > function.
> > >         Add the stmt to any pending optinfo, creating one if need
> > > be.
> > >         (dump_gimple_stmt_loc): Move implementation to...
> > >         (dump_context::dump_gimple_stmt_loc): ...this new member
> > > function.
> > >         Convert param "loc" from location_t to const
> > > dump_location_t &.
> > >         Start a new optinfo and add the stmt to it.
> > >         (dump_generic_expr): Move implementation to...
> > >         (dump_context::dump_generic_expr): ...this new member
> > > function.
> > >         Add the tree to any pending optinfo, creating one if need
> > > be.
> > >         (dump_generic_expr_loc): Move implementation to...
> > >         (dump_context::dump_generic_expr_loc): ...this new member
> > >         function.  Add the tree to any pending optinfo, creating
> > > one if
> > >         need be.
> > >         (dump_printf): Move implementation to...
> > >         (dump_context::dump_printf_va): ...this new member
> > > function.  Add
> > >         the text to any pending optinfo, creating one if need be.
> > >         (dump_printf_loc): Move implementation to...
> > >         (dump_context::dump_printf_loc_va): ...this new member
> > > function.
> > >         Convert param "loc" from location_t to const
> > > dump_location_t &.
> > >         Start a new optinfo and add the stmt to it.
> > >         (dump_dec): Move implementation to...
> > >         (dump_context::dump_dec): ...this new member function.  Add
> > > the
> > >         value to any pending optinfo, creating one if need be.
> > >         (dump_context::dump_symtab_node): New member function.
> > >         (dump_context::get_scope_depth): New member function.
> > >         (dump_context::begin_scope): New member function.
> > >         (dump_context::end_scope): New member function.
> > >         (dump_context::ensure_pending_optinfo): New member
> > > function.
> > >         (dump_context::begin_next_optinfo): New member function.
> > >         (dump_context::end_any_optinfo): New member function.
> > >         (dump_context::s_current): New global.
> > >         (dump_context::s_default): New global.
> > >         (dump_scope_depth): Delete global.
> > >         (dumpfile_ensure_any_optinfo_are_flushed): New function.
> > >         (dump_symtab_node): New function.
> > >         (get_dump_scope_depth): Reimplement in terms of
> > > dump_context.
> > >         (dump_begin_scope): Likewise.
> > >         (dump_end_scope): Likewise.
> > >         (selftest::temp_dump_context::temp_dump_context): New ctor.
> > >         (selftest::temp_dump_context::~temp_dump_context): New
> > > dtor.
> > >         (selftest::assert_is_text): New support function.
> > >         (selftest::assert_is_tree): New support function.
> > >         (selftest::assert_is_gimple): New support function.
> > >         (selftest::test_capture_of_dump_calls): New test.
> > >         (selftest::dumpfile_c_tests): Call it.
> > >         * dumpfile.h (dump_printf, dump_printf_loc,
> > > dump_basic_block,
> > >         dump_generic_expr_loc, dump_generic_expr,
> > > dump_gimple_stmt_loc,
> > >         dump_gimple_stmt, dump_dec): Gather these related decls and
> > > add a
> > >         descriptive comment.
> > >         (dump_function, print_combine_total_stats,
> > > enable_rtl_dump_file,
> > >         dump_node, dump_bb): Move these unrelated decls.
> > >         (class dump_manager): Add leading comment.
> > >         * ggc-page.c (ggc_collect): Call
> > >         dumpfile_ensure_any_optinfo_are_flushed.
> > >         * optinfo-internal.h: New file.
> > >         * optinfo.cc: New file.
> > >         * optinfo.h: New file.
> > >         * selftest-run-tests.c (selftest::run_tests): Call
> > >         selftest::optinfo_cc_tests.
> > >         * selftest.h (selftest::optinfo_cc_tests): New decl.
> > > ---
> > >  gcc/Makefile.in          |   1 +
> > >  gcc/coretypes.h          |   7 +
> > >  gcc/dump-context.h       | 128 ++++++++++++
> > >  gcc/dumpfile.c           | 498
> > > +++++++++++++++++++++++++++++++++++++++++++----
> > >  gcc/dumpfile.h           |  82 +++++---
> > >  gcc/ggc-page.c           |   2 +
> > >  gcc/optinfo-internal.h   | 148 ++++++++++++++
> > >  gcc/optinfo.cc           | 251 ++++++++++++++++++++++++
> > >  gcc/optinfo.h            | 175 +++++++++++++++++
> > >  gcc/selftest-run-tests.c |   1 +
> > >  gcc/selftest.h           |   1 +
> > >  11 files changed, 1233 insertions(+), 61 deletions(-)
> > >  create mode 100644 gcc/dump-context.h
> > >  create mode 100644 gcc/optinfo-internal.h
> > >  create mode 100644 gcc/optinfo.cc
> > >  create mode 100644 gcc/optinfo.h
> > >
> > > diff --git a/gcc/Makefile.in b/gcc/Makefile.in
> > > index 66c8b6e..7d36a77 100644
> > > --- a/gcc/Makefile.in
> > > +++ b/gcc/Makefile.in
> > > @@ -1426,6 +1426,7 @@ OBJS = \
> > >         optabs-libfuncs.o \
> > >         optabs-query.o \
> > >         optabs-tree.o \
> > > +       optinfo.o \
> > >         options-save.o \
> > >         opts-global.o \
> > >         passes.o \
> > > diff --git a/gcc/coretypes.h b/gcc/coretypes.h
> > > index 283b4eb..ed0e825 100644
> > > --- a/gcc/coretypes.h
> > > +++ b/gcc/coretypes.h
> > > @@ -134,6 +134,13 @@ struct gomp_single;
> > >  struct gomp_target;
> > >  struct gomp_teams;
> > >
> > > +/* Subclasses of symtab_node, using indentation to show the class
> > > +   hierarchy.  */
> > > +
> > > +class symtab_node;
> > > +  struct cgraph_node;
> > > +  class varpool_node;
> > > +
> > >  union section;
> > >  typedef union section section;
> > >  struct gcc_options;
> > > diff --git a/gcc/dump-context.h b/gcc/dump-context.h
> > > new file mode 100644
> > > index 0000000..753f714
> > > --- /dev/null
> > > +++ b/gcc/dump-context.h
> > > @@ -0,0 +1,128 @@
> > > +/* Support code for handling the various dump_* calls in
> > > dumpfile.h
> > > +   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_DUMP_CONTEXT_H
> > > +#define GCC_DUMP_CONTEXT_H 1
> > > +
> > > +/* A class for handling the various dump_* calls.
> > > +
> > > +   In particular, this class has responsibility for consolidating
> > > +   the "dump_*" calls into optinfo instances (delimited by
> > > "dump_*_loc"
> > > +   calls), and emitting them.
> > > +
> > > +   Putting this in a class (rather than as global state) allows
> > > +   for selftesting of this code.  */
> > > +
> > > +class dump_context
> > > +{
> > > +  friend class temp_dump_context;
> > > + public:
> > > +  static dump_context &get () { return *s_current; }
> > > +
> > > +  ~dump_context ();
> > > +
> > > +  void dump_gimple_stmt (dump_flags_t dump_kind, dump_flags_t
> > > extra_dump_flags,
> > > +                        gimple *gs, int spc);
> > > +
> > > +  void dump_gimple_stmt_loc (dump_flags_t dump_kind,
> > > +                            const dump_location_t &loc,
> > > +                            dump_flags_t extra_dump_flags,
> > > +                            gimple *gs, int spc);
> > > +
> > > +  void dump_generic_expr (dump_flags_t dump_kind,
> > > +                         dump_flags_t extra_dump_flags,
> > > +                         tree t);
> > > +
> > > +  void dump_generic_expr_loc (dump_flags_t dump_kind,
> > > +                             const dump_location_t &loc,
> > > +                             dump_flags_t extra_dump_flags,
> > > +                             tree t);
> > > +
> > > +  void dump_printf_va (dump_flags_t dump_kind, const char *format,
> > > +                      va_list ap) ATTRIBUTE_PRINTF (3, 0);
> > > +
> > > +  void dump_printf_loc_va (dump_flags_t dump_kind, const
> > > dump_location_t &loc,
> > > +                          const char *format, va_list ap)
> > > +    ATTRIBUTE_PRINTF (4, 0);
> > > +
> > > +  template<unsigned int N, typename C>
> > > +  void dump_dec (dump_flags_t dump_kind, const poly_int<N, C>
> > > &value);
> > > +
> > > +  void dump_symtab_node (dump_flags_t dump_kind, symtab_node
> > > *node);
> > > +
> > > +  /* Managing nested scopes.  */
> > > +  unsigned int get_scope_depth () const;
> > > +  void begin_scope (const char *name, const dump_location_t &loc);
> > > +  void end_scope ();
> > > +
> > > +  /* For use in selftests; if true then optinfo_enabled_p is
> > > true.  */
> > > +  bool forcibly_enable_optinfo_p () const
> > > +  {
> > > +    return m_forcibly_enable_optinfo;
> > > +  }
> > > +
> > > +  void end_any_optinfo ();
> > > +
> > > + private:
> > > +  optinfo &ensure_pending_optinfo ();
> > > +  optinfo &begin_next_optinfo (const dump_location_t &loc);
> > > +
> > > +  /* For use in selftests; if true then optinfo_enabled_p is
> > > true.  */
> > > +  bool m_forcibly_enable_optinfo;
> > > +
> > > +  /* The current nesting depth of dump scopes, for showing nesting
> > > +     via indentation).  */
> > > +  unsigned int m_scope_depth;
> > > +
> > > +  /* The optinfo currently being accumulated since the last
> > > dump_*_loc call,
> > > +     if any.  */
> > > +  optinfo *m_pending;
> > > +
> > > +  /* The currently active dump_context, for use by the dump_* API
> > > calls.  */
> > > +  static dump_context *s_current;
> > > +
> > > +  /* The default active context.  */
> > > +  static dump_context s_default;
> > > +};
> > > +
> > > +#if CHECKING_P
> > > +
> > > +/* An RAII-style class for use in selftests for temporarily using
> > > a different
> > > +   dump_context.  */
> > > +
> > > +class temp_dump_context
> > > +{
> > > + public:
> > > +  temp_dump_context (bool forcibly_enable_optinfo);
> > > +  ~temp_dump_context ();
> > > +
> > > +  /* Support for selftests.  */
> > > +  optinfo *get_pending_optinfo () const { return
> > > m_context.m_pending; }
> > > +
> > > + private:
> > > +  dump_context m_context;
> > > +  dump_context *m_saved;
> > > +  bool m_saved_flag_remarks;
> > > +};
> > > +
> > > +#endif /* CHECKING_P */
> > > +
> > > +#endif /* GCC_DUMP_CONTEXT_H */
> > > diff --git a/gcc/dumpfile.c b/gcc/dumpfile.c
> > > index 5f69f9b..6e089ef 100644
> > > --- a/gcc/dumpfile.c
> > > +++ b/gcc/dumpfile.c
> > > @@ -33,6 +33,11 @@ along with GCC; see the file COPYING3.  If not
> > > see
> > >  #include "gimple.h" /* for dump_user_location_t ctor.  */
> > >  #include "rtl.h" /* for dump_user_location_t ctor.  */
> > >  #include "selftest.h"
> > > +#include "optinfo.h"
> > > +#include "dump-context.h"
> > > +#include "cgraph.h"
> > > +#include "tree-pass.h" /* for "current_pass".  */
> > > +#include "optinfo-internal.h" /* for selftests.  */
> > >
> > >  /* If non-NULL, return one past-the-end of the matching SUBPART of
> > >     the WHOLE string.  */
> > > @@ -64,7 +69,7 @@ bool dumps_are_enabled = false;
> > >  static void
> > >  refresh_dumps_are_enabled ()
> > >  {
> > > -  dumps_are_enabled = (dump_file || alt_dump_file);
> > > +  dumps_are_enabled = (dump_file || alt_dump_file ||
> > > optinfo_enabled_p ());
> > >  }
> > >
> > >  /* Set global "dump_file" to NEW_DUMP_FILE, refreshing the
> > > "dumps_are_enabled"
> > > @@ -73,6 +78,7 @@ refresh_dumps_are_enabled ()
> > >  void
> > >  set_dump_file (FILE *new_dump_file)
> > >  {
> > > +  dumpfile_ensure_any_optinfo_are_flushed ();
> > >    dump_file = new_dump_file;
> > >    refresh_dumps_are_enabled ();
> > >  }
> > > @@ -83,6 +89,7 @@ set_dump_file (FILE *new_dump_file)
> > >  static void
> > >  set_alt_dump_file (FILE *new_alt_dump_file)
> > >  {
> > > +  dumpfile_ensure_any_optinfo_are_flushed ();
> > >    alt_dump_file = new_alt_dump_file;
> > >    refresh_dumps_are_enabled ();
> > >  }
> > > @@ -458,25 +465,44 @@ dump_loc (dump_flags_t dump_kind, FILE
> > > *dfile, source_location loc)
> > >      }
> > >  }
> > >
> > > +/* Implementation of dump_context member functions.  */
> > > +
> > > +/* dump_context's dtor.  */
> > > +
> > > +dump_context::~dump_context ()
> > > +{
> > > +  delete m_pending;
> > > +}
> > > +
> > >  /* Dump gimple statement GS with SPC indentation spaces and
> > >     EXTRA_DUMP_FLAGS on the dump streams if DUMP_KIND is
> > > enabled.  */
> > >
> > >  void
> > > -dump_gimple_stmt (dump_flags_t dump_kind, dump_flags_t
> > > extra_dump_flags,
> > > -                 gimple *gs, int spc)
> > > +dump_context::dump_gimple_stmt (dump_flags_t dump_kind,
> > > +                               dump_flags_t extra_dump_flags,
> > > +                               gimple *gs, int spc)
> > >  {
> > >    if (dump_file && (dump_kind & pflags))
> > >      print_gimple_stmt (dump_file, gs, spc, dump_flags |
> > > extra_dump_flags);
> > >
> > >    if (alt_dump_file && (dump_kind & alt_flags))
> > >      print_gimple_stmt (alt_dump_file, gs, spc, dump_flags |
> > > extra_dump_flags);
> > > +
> > > +  if (optinfo_enabled_p ())
> > > +    {
> > > +      optinfo &info = ensure_pending_optinfo ();
> > > +      info.handle_dump_file_kind (dump_kind);
> > > +      info.add_stmt (gs, extra_dump_flags);
> > > +    }
> > >  }
> > >
> > >  /* Similar to dump_gimple_stmt, except additionally print source
> > > location.  */
> > >
> > >  void
> > > -dump_gimple_stmt_loc (dump_flags_t dump_kind, const
> > > dump_location_t &loc,
> > > -                     dump_flags_t extra_dump_flags, gimple *gs,
> > > int spc)
> > > +dump_context::dump_gimple_stmt_loc (dump_flags_t dump_kind,
> > > +                                   const dump_location_t &loc,
> > > +                                   dump_flags_t extra_dump_flags,
> > > +                                   gimple *gs, int spc)
> > >  {
> > >    location_t srcloc = loc.get_location_t ();
> > >    if (dump_file && (dump_kind & pflags))
> > > @@ -490,20 +516,35 @@ dump_gimple_stmt_loc (dump_flags_t dump_kind,
> > > const dump_location_t &loc,
> > >        dump_loc (dump_kind, alt_dump_file, srcloc);
> > >        print_gimple_stmt (alt_dump_file, gs, spc, dump_flags |
> > > extra_dump_flags);
> > >      }
> > > +
> > > +  if (optinfo_enabled_p ())
> > > +    {
> > > +      optinfo &info = begin_next_optinfo (loc);
> > > +      info.handle_dump_file_kind (dump_kind);
> > > +      info.add_stmt (gs, extra_dump_flags);
> > > +    }
> > >  }
> > >
> > >  /* Dump expression tree T using EXTRA_DUMP_FLAGS on dump streams
> > > if
> > >     DUMP_KIND is enabled.  */
> > >
> > >  void
> > > -dump_generic_expr (dump_flags_t dump_kind, dump_flags_t
> > > extra_dump_flags,
> > > -                  tree t)
> > > +dump_context::dump_generic_expr (dump_flags_t dump_kind,
> > > +                                dump_flags_t extra_dump_flags,
> > > +                                tree t)
> > >  {
> > >    if (dump_file && (dump_kind & pflags))
> > >        print_generic_expr (dump_file, t, dump_flags |
> > > extra_dump_flags);
> > >
> > >    if (alt_dump_file && (dump_kind & alt_flags))
> > >        print_generic_expr (alt_dump_file, t, dump_flags |
> > > extra_dump_flags);
> > > +
> > > +  if (optinfo_enabled_p ())
> > > +    {
> > > +      optinfo &info = ensure_pending_optinfo ();
> > > +      info.handle_dump_file_kind (dump_kind);
> > > +      info.add_tree (t, extra_dump_flags);
> > > +    }
> > >  }
> > >
> > >
> > > @@ -511,8 +552,10 @@ dump_generic_expr (dump_flags_t dump_kind,
> > > dump_flags_t extra_dump_flags,
> > >     location.  */
> > >
> > >  void
> > > -dump_generic_expr_loc (dump_flags_t dump_kind, const
> > > dump_location_t &loc,
> > > -                      dump_flags_t extra_dump_flags, tree t)
> > > +dump_context::dump_generic_expr_loc (dump_flags_t dump_kind,
> > > +                                    const dump_location_t &loc,
> > > +                                    dump_flags_t extra_dump_flags,
> > > +                                    tree t)
> > >  {
> > >    location_t srcloc = loc.get_location_t ();
> > >    if (dump_file && (dump_kind & pflags))
> > > @@ -526,53 +569,82 @@ dump_generic_expr_loc (dump_flags_t
> > > dump_kind, const dump_location_t &loc,
> > >        dump_loc (dump_kind, alt_dump_file, srcloc);
> > >        print_generic_expr (alt_dump_file, t, dump_flags |
> > > extra_dump_flags);
> > >      }
> > > +
> > > +  if (optinfo_enabled_p ())
> > > +    {
> > > +      optinfo &info = begin_next_optinfo (loc);
> > > +      info.handle_dump_file_kind (dump_kind);
> > > +      info.add_tree (t, extra_dump_flags);
> > > +    }
> > >  }
> > >
> > >  /* Output a formatted message using FORMAT on appropriate dump
> > > streams.  */
> > >
> > >  void
> > > -dump_printf (dump_flags_t dump_kind, const char *format, ...)
> > > +dump_context::dump_printf_va (dump_flags_t dump_kind, const char
> > > *format,
> > > +                             va_list ap)
> > >  {
> > >    if (dump_file && (dump_kind & pflags))
> > >      {
> > > -      va_list ap;
> > > -      va_start (ap, format);
> > > -      vfprintf (dump_file, format, ap);
> > > -      va_end (ap);
> > > +      va_list aq;
> > > +      va_copy (aq, ap);
> > > +      vfprintf (dump_file, format, aq);
> > > +      va_end (aq);
> > >      }
> > >
> > >    if (alt_dump_file && (dump_kind & alt_flags))
> > >      {
> > > -      va_list ap;
> > > -      va_start (ap, format);
> > > -      vfprintf (alt_dump_file, format, ap);
> > > -      va_end (ap);
> > > +      va_list aq;
> > > +      va_copy (aq, ap);
> > > +      vfprintf (alt_dump_file, format, aq);
> > > +      va_end (aq);
> > > +    }
> > > +
> > > +  if (optinfo_enabled_p ())
> > > +    {
> > > +      optinfo &info = ensure_pending_optinfo ();
> > > +      va_list aq;
> > > +      va_copy (aq, ap);
> > > +      info.add_printf_va (format, aq);
> > > +      va_end (aq);
> > >      }
> > >  }
> > >
> > > -/* Similar to dump_printf, except source location is also
> > > printed.  */
> > > +/* Similar to dump_printf, except source location is also printed,
> > > and
> > > +   dump location captured.  */
> > >
> > >  void
> > > -dump_printf_loc (dump_flags_t dump_kind, const dump_location_t
> > > &loc,
> > > -                const char *format, ...)
> > > +dump_context::dump_printf_loc_va (dump_flags_t dump_kind, const
> > > dump_location_t &loc,
> > > +                                 const char *format, va_list ap)
> > >  {
> > >    location_t srcloc = loc.get_location_t ();
> > > +
> > >    if (dump_file && (dump_kind & pflags))
> > >      {
> > > -      va_list ap;
> > >        dump_loc (dump_kind, dump_file, srcloc);
> > > -      va_start (ap, format);
> > > -      vfprintf (dump_file, format, ap);
> > > -      va_end (ap);
> > > +      va_list aq;
> > > +      va_copy (aq, ap);
> > > +      vfprintf (dump_file, format, aq);
> > > +      va_end (aq);
> > >      }
> > >
> > >    if (alt_dump_file && (dump_kind & alt_flags))
> > >      {
> > > -      va_list ap;
> > >        dump_loc (dump_kind, alt_dump_file, srcloc);
> > > -      va_start (ap, format);
> > > -      vfprintf (alt_dump_file, format, ap);
> > > -      va_end (ap);
> > > +      va_list aq;
> > > +      va_copy (aq, ap);
> > > +      vfprintf (alt_dump_file, format, aq);
> > > +      va_end (aq);
> > > +    }
> > > +
> > > +  if (optinfo_enabled_p ())
> > > +    {
> > > +      optinfo &info = begin_next_optinfo (loc);
> > > +      info.handle_dump_file_kind (dump_kind);
> > > +      va_list aq;
> > > +      va_copy (aq, ap);
> > > +      info.add_printf_va (format, aq);
> > > +      va_end (aq);
> > >      }
> > >  }
> > >
> > > @@ -580,7 +652,7 @@ dump_printf_loc (dump_flags_t dump_kind, const
> > > dump_location_t &loc,
> > >
> > >  template<unsigned int N, typename C>
> > >  void
> > > -dump_dec (dump_flags_t dump_kind, const poly_int<N, C> &value)
> > > +dump_context::dump_dec (dump_flags_t dump_kind, const poly_int<N,
> > > C> &value)
> > >  {
> > >    STATIC_ASSERT (poly_coeff_traits<C>::signedness >= 0);
> > >    signop sgn = poly_coeff_traits<C>::signedness ? SIGNED :
> > > UNSIGNED;
> > > @@ -589,6 +661,203 @@ dump_dec (dump_flags_t dump_kind, const
> > > poly_int<N, C> &value)
> > >
> > >    if (alt_dump_file && (dump_kind & alt_flags))
> > >      print_dec (value, alt_dump_file, sgn);
> > > +
> > > +  if (optinfo_enabled_p ())
> > > +    {
> > > +      optinfo &info = ensure_pending_optinfo ();
> > > +      info.handle_dump_file_kind (dump_kind);
> > > +      info.add_poly_int<N,C> (value);
> > > +    }
> > > +}
> > > +
> > > +/* Output the name of NODE on appropriate dump streams.  */
> > > +
> > > +void
> > > +dump_context::dump_symtab_node (dump_flags_t dump_kind,
> > > symtab_node *node)
> > > +{
> > > +  if (dump_file && (dump_kind & pflags))
> > > +    fprintf (dump_file, "%s", node->dump_name ());
> > > +
> > > +  if (alt_dump_file && (dump_kind & alt_flags))
> > > +    fprintf (alt_dump_file, "%s", node->dump_name ());
> > > +
> > > +  if (optinfo_enabled_p ())
> > > +    {
> > > +      optinfo &info = ensure_pending_optinfo ();
> > > +      info.handle_dump_file_kind (dump_kind);
> > > +      info.add_symtab_node (node);
> > > +    }
> > > +}
> > > +
> > > +/* Get the current dump scope-nesting depth.
> > > +   For use by -fopt-info (for showing nesting via
> > > indentation).  */
> > > +
> > > +unsigned int
> > > +dump_context::get_scope_depth () const
> > > +{
> > > +  return m_scope_depth;
> > > +}
> > > +
> > > +/* Push a nested dump scope.
> > > +   Print "=== NAME ===\n" to the dumpfile, if any, and to the
> > > -fopt-info
> > > +   destination, if any.
> > > +   Emit a "scope" optinfo if optinfos are enabled.
> > > +   Increment the scope depth.  */
> > > +
> > > +void
> > > +dump_context::begin_scope (const char *name, const dump_location_t
> > > &loc)
> > > +{
> > > +  /* Specialcase, to avoid going through dump_printf_loc,
> > > +     so that we can create a optinfo of kind
> > > OPTINFO_KIND_SCOPE.  */
> > > +
> > > +  if (dump_file)
> > > +    {
> > > +      dump_loc (MSG_NOTE, dump_file, loc.get_location_t ());
> > > +      fprintf (dump_file, "=== %s ===\n", name);
> > > +    }
> > > +
> > > +  if (alt_dump_file)
> > > +    {
> > > +      dump_loc (MSG_NOTE, alt_dump_file, loc.get_location_t ());
> > > +      fprintf (alt_dump_file, "=== %s ===\n", name);
> > > +    }
> > > +
> > > +  if (optinfo_enabled_p ())
> > > +    {
> > > +      end_any_optinfo ();
> > > +      optinfo info (loc, OPTINFO_KIND_SCOPE, current_pass);
> > > +      info.add_printf ("=== %s ===", name);
> > > +      info.emit ();
> > > +    }
> > > +
> > > +  m_scope_depth++;
> > > +}
> > > +
> > > +/* Pop a nested dump scope.  */
> > > +
> > > +void
> > > +dump_context::end_scope ()
> > > +{
> > > +  end_any_optinfo ();
> > > +  m_scope_depth--;
> > > +}
> > > +
> > > +/* Return the optinfo currently being accumulated, creating one if
> > > +   necessary.  */
> > > +
> > > +optinfo &
> > > +dump_context::ensure_pending_optinfo ()
> > > +{
> > > +  if (!m_pending)
> > > +    return begin_next_optinfo (dump_location_t
> > > (dump_user_location_t ()));
> > > +  return *m_pending;
> > > +}
> > > +
> > > +/* Start a new optinfo and return it, ending any optinfo that was
> > > already
> > > +   accumulated.  */
> > > +
> > > +optinfo &
> > > +dump_context::begin_next_optinfo (const dump_location_t &loc)
> > > +{
> > > +  end_any_optinfo ();
> > > +  gcc_assert (m_pending == NULL);
> > > +  m_pending = new optinfo (loc, OPTINFO_KIND_NOTE, current_pass);
> > > +  return *m_pending;
> > > +}
> > > +
> > > +/* End any optinfo that has been accumulated within this context;
> > > emitting
> > > +   it to any destinations as appropriate - though none have
> > > currently been
> > > +   implemented.  */
> > > +
> > > +void
> > > +dump_context::end_any_optinfo ()
> > > +{
> > > +  if (m_pending)
> > > +    m_pending->emit ();
> > > +  delete m_pending;
> > > +  m_pending = NULL;
> > > +}
> > > +
> > > +/* The current singleton dump_context, and its default.  */
> > > +
> > > +dump_context *dump_context::s_current = &dump_context::s_default;
> > > +dump_context dump_context::s_default;
> > > +
> > > +/* Implementation of dump_* API calls, calling into dump_context
> > > +   member functions.  */
> > > +
> > > +/* Dump gimple statement GS with SPC indentation spaces and
> > > +   EXTRA_DUMP_FLAGS on the dump streams if DUMP_KIND is
> > > enabled.  */
> > > +
> > > +void
> > > +dump_gimple_stmt (dump_flags_t dump_kind, dump_flags_t
> > > extra_dump_flags,
> > > +                 gimple *gs, int spc)
> > > +{
> > > +  dump_context::get ().dump_gimple_stmt (dump_kind,
> > > extra_dump_flags, gs, spc);
> > > +}
> > > +
> > > +/* Similar to dump_gimple_stmt, except additionally print source
> > > location.  */
> > > +
> > > +void
> > > +dump_gimple_stmt_loc (dump_flags_t dump_kind, const
> > > dump_location_t &loc,
> > > +                     dump_flags_t extra_dump_flags, gimple *gs,
> > > int spc)
> > > +{
> > > +  dump_context::get ().dump_gimple_stmt_loc (dump_kind, loc,
> > > extra_dump_flags,
> > > +                                            gs, spc);
> > > +}
> > > +
> > > +/* Dump expression tree T using EXTRA_DUMP_FLAGS on dump streams
> > > if
> > > +   DUMP_KIND is enabled.  */
> > > +
> > > +void
> > > +dump_generic_expr (dump_flags_t dump_kind, dump_flags_t
> > > extra_dump_flags,
> > > +                  tree t)
> > > +{
> > > +  dump_context::get ().dump_generic_expr (dump_kind,
> > > extra_dump_flags, t);
> > > +}
> > > +
> > > +/* Similar to dump_generic_expr, except additionally print the
> > > source
> > > +   location.  */
> > > +
> > > +void
> > > +dump_generic_expr_loc (dump_flags_t dump_kind, const
> > > dump_location_t &loc,
> > > +                      dump_flags_t extra_dump_flags, tree t)
> > > +{
> > > +  dump_context::get ().dump_generic_expr_loc (dump_kind, loc,
> > > extra_dump_flags,
> > > +                                             t);
> > > +}
> > > +
> > > +/* Output a formatted message using FORMAT on appropriate dump
> > > streams.  */
> > > +
> > > +void
> > > +dump_printf (dump_flags_t dump_kind, const char *format, ...)
> > > +{
> > > +  va_list ap;
> > > +  va_start (ap, format);
> > > +  dump_context::get ().dump_printf_va (dump_kind, format, ap);
> > > +  va_end (ap);
> > > +}
> > > +
> > > +/* Similar to dump_printf, except source location is also printed,
> > > and
> > > +   dump location captured.  */
> > > +
> > > +void
> > > +dump_printf_loc (dump_flags_t dump_kind, const dump_location_t
> > > &loc,
> > > +                const char *format, ...)
> > > +{
> > > +  va_list ap;
> > > +  va_start (ap, format);
> > > +  dump_context::get ().dump_printf_loc_va (dump_kind, loc, format,
> > > ap);
> > > +  va_end (ap);
> > > +}
> > > +
> > > +/* Output VALUE in decimal to appropriate dump streams.  */
> > > +
> > > +template<unsigned int N, typename C>
> > > +void
> > > +dump_dec (dump_flags_t dump_kind, const poly_int<N, C> &value)
> > > +{
> > > +  dump_context::get ().dump_dec (dump_kind, value);
> > >  }
> > >
> > >  template void dump_dec (dump_flags_t, const poly_uint16 &);
> > > @@ -597,29 +866,42 @@ template void dump_dec (dump_flags_t, const
> > > poly_uint64 &);
> > >  template void dump_dec (dump_flags_t, const poly_offset_int &);
> > >  template void dump_dec (dump_flags_t, const poly_widest_int &);
> > >
> > > -/* The current dump scope-nesting depth.  */
> > > +/* Emit and delete the currently pending optinfo, if there is one,
> > > +   without the caller needing to know about class
> > > dump_context.  */
> > > +
> > > +void
> > > +dumpfile_ensure_any_optinfo_are_flushed ()
> > > +{
> > > +  dump_context::get().end_any_optinfo ();
> > > +}
> > > +
> > > +/* Output the name of NODE on appropriate dump streams.  */
> > >
> > > -static int dump_scope_depth;
> > > +void
> > > +dump_symtab_node (dump_flags_t dump_kind, symtab_node *node)
> > > +{
> > > +  dump_context::get ().dump_symtab_node (dump_kind, node);
> > > +}
> > >
> > >  /* Get the current dump scope-nesting depth.
> > > -   For use by dump_*_loc (for showing nesting via
> > > indentation).  */
> > > +   For use by -fopt-info (for showing nesting via
> > > indentation).  */
> > >
> > >  unsigned int
> > >  get_dump_scope_depth ()
> > >  {
> > > -  return dump_scope_depth;
> > > +  return dump_context::get ().get_scope_depth ();
> > >  }
> > >
> > >  /* Push a nested dump scope.
> > >     Print "=== NAME ===\n" to the dumpfile, if any, and to the
> > > -fopt-info
> > >     destination, if any.
> > > +   Emit a "scope" opinfo if optinfos are enabled.
> > >     Increment the scope depth.  */
> > >
> > >  void
> > >  dump_begin_scope (const char *name, const dump_location_t &loc)
> > >  {
> > > -  dump_printf_loc (MSG_NOTE, loc, "=== %s ===\n", name);
> > > -  dump_scope_depth++;
> > > +  dump_context::get ().begin_scope (name, loc);
> > >  }
> > >
> > >  /* Pop a nested dump scope.  */
> > > @@ -627,7 +909,7 @@ dump_begin_scope (const char *name, const
> > > dump_location_t &loc)
> > >  void
> > >  dump_end_scope ()
> > >  {
> > > -  dump_scope_depth--;
> > > +  dump_context::get ().end_scope ();
> > >  }
> > >
> > >  /* Start a dump for PHASE. Store user-supplied dump flags in
> > > @@ -1180,6 +1462,24 @@ enable_rtl_dump_file (void)
> > >
> > >  #if CHECKING_P
> > >
> > > +/* temp_dump_context's ctor.  Temporarily override the
> > > dump_context
> > > +   (to forcibly enable optinfo-generation).  */
> > > +
> > > +temp_dump_context::temp_dump_context (bool
> > > forcibly_enable_optinfo)
> > > +: m_context (),
> > > +  m_saved (&dump_context ().get ())
> > > +{
> > > +  dump_context::s_current = &m_context;
> > > +  m_context.m_forcibly_enable_optinfo = forcibly_enable_optinfo;
> > > +}
> > > +
> > > +/* temp_dump_context's dtor.  Restore the saved dump_context.  */
> > > +
> > > +temp_dump_context::~temp_dump_context ()
> > > +{
> > > +  dump_context::s_current = m_saved;
> > > +}
> > > +
> > >  namespace selftest {
> > >
> > >  /* Verify that the dump_location_t constructors capture the source
> > > location
> > > @@ -1216,12 +1516,136 @@ test_impl_location ()
> > >  #endif
> > >  }
> > >
> > > +/* Verify that ITEM is a text item, with EXPECTED_TEXT.  */
> > > +
> > > +static void
> > > +assert_is_text (const optinfo_item *item, const char
> > > *expected_text)
> > > +{
> > > +  ASSERT_EQ (item->get_kind (), OPTINFO_ITEM_KIND_TEXT);
> > > +  const optinfo_item_text * text_item
> > > +    = static_cast <const optinfo_item_text *> (item);
> > > +  ASSERT_STREQ (text_item->get_text (), expected_text);
> > > +}
> > > +
> > > +/* Verify that ITEM is a tree item, with the expected values.  */
> > > +
> > > +static void
> > > +assert_is_tree (const optinfo_item *item, tree expected_tree,
> > > +               dump_flags_t expected_dump_flags)
> > > +{
> > > +  ASSERT_EQ (item->get_kind (), OPTINFO_ITEM_KIND_TREE);
> > > +  const optinfo_item_tree * tree_item
> > > +    = static_cast <const optinfo_item_tree *> (item);
> > > +  ASSERT_EQ (tree_item->get_node (), expected_tree);
> > > +  ASSERT_EQ (tree_item->get_flags (), expected_dump_flags);
> > > +}
> > > +
> > > +/* Verify that ITEM is a gimple item, with the expected
> > > values.  */
> > > +
> > > +static void
> > > +assert_is_gimple (const optinfo_item *item, gimple *expected_stmt,
> > > +                 dump_flags_t expected_dump_flags)
> > > +{
> > > +  ASSERT_EQ (item->get_kind (), OPTINFO_ITEM_KIND_GIMPLE);
> > > +  const optinfo_item_gimple * gimple_item
> > > +    = static_cast <const optinfo_item_gimple *> (item);
> > > +  ASSERT_EQ (gimple_item->get_stmt (), expected_stmt);
> > > +  ASSERT_EQ (gimple_item->get_flags (), expected_dump_flags);
> > > +}
> > > +
> > > +/* Verify that calls to the dump_* API are captured and
> > > consolidated into
> > > +   optimization records. */
> > > +
> > > +static void
> > > +test_capture_of_dump_calls ()
> > > +{
> > > +  dump_location_t loc;
> > > +
> > > +  /* Tree, via dump_generic_expr.  */
> > > +  {
> > > +    temp_dump_context tmp (true);
> > > +    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);
> > > +    ASSERT_EQ (info->get_kind (), OPTINFO_KIND_NOTE);
> > > +    ASSERT_EQ (info->num_items (), 2);
> > > +    assert_is_text (info->get_item (0), "test of tree: ");
> > > +    assert_is_tree (info->get_item (1), integer_zero_node,
> > > TDF_SLIM);
> > > +  }
> > > +
> > > +  /* Tree, via dump_generic_expr_loc.  */
> > > +  {
> > > +    temp_dump_context tmp (true);
> > > +    dump_generic_expr_loc (MSG_NOTE, loc, TDF_SLIM,
> > > integer_one_node);
> > > +
> > > +    optinfo *info = tmp.get_pending_optinfo ();
> > > +    ASSERT_TRUE (info != NULL);
> > > +    ASSERT_EQ (info->get_kind (), OPTINFO_KIND_NOTE);
> > > +    ASSERT_EQ (info->num_items (), 1);
> > > +    assert_is_tree (info->get_item (0), integer_one_node,
> > > TDF_SLIM);
> > > +  }
> > > +
> > > +  /* Gimple.  */
> > > +  {
> > > +    greturn *stmt = gimple_build_return (NULL);
> > > +
> > > +    temp_dump_context tmp (true);
> > > +    dump_gimple_stmt_loc (MSG_NOTE, loc, TDF_SLIM, stmt, 0);
> > > +
> > > +    optinfo *info = tmp.get_pending_optinfo ();
> > > +    ASSERT_TRUE (info != NULL);
> > > +    ASSERT_EQ (info->num_items (), 1);
> > > +    assert_is_gimple (info->get_item (0), stmt, TDF_SLIM);
> > > +
> > > +    /* Verify that optinfo instances are flushed if a GC is about
> > > to
> > > +       happen (and thus don't need to be GTY-marked).
> > > +       We don't want them in the PCH file, but we don't want the
> > > +       items to have their data collected from under them.  */
> > > +    selftest::forcibly_ggc_collect ();
> > > +    ASSERT_TRUE (tmp.get_pending_optinfo () == NULL);
> > > +  }
> > > +
> > > +  /* poly_int.  */
> > > +  {
> > > +    temp_dump_context tmp (true);
> > > +    dump_dec (MSG_NOTE, poly_int64 (42));
> > > +
> > > +    optinfo *info = tmp.get_pending_optinfo ();
> > > +    ASSERT_TRUE (info != NULL);
> > > +    ASSERT_EQ (info->num_items (), 1);
> > > +    assert_is_text (info->get_item (0), "42");
> > > +  }
> > > +
> > > +  /* Verify that MSG_* affects optinfo->get_kind (); we tested
> > > MSG_NOTE
> > > +     above.  */
> > > +  {
> > > +    /* MSG_OPTIMIZED_LOCATIONS.  */
> > > +    {
> > > +      temp_dump_context tmp (true);
> > > +      dump_printf_loc (MSG_OPTIMIZED_LOCATIONS, loc, "test");
> > > +      ASSERT_EQ (tmp.get_pending_optinfo ()->get_kind (),
> > > +                OPTINFO_KIND_SUCCESS);
> > > +    }
> > > +
> > > +    /* MSG_MISSED_OPTIMIZATION.  */
> > > +    {
> > > +      temp_dump_context tmp (true);
> > > +      dump_printf_loc (MSG_MISSED_OPTIMIZATION, loc, "test");
> > > +      ASSERT_EQ (tmp.get_pending_optinfo ()->get_kind (),
> > > +                OPTINFO_KIND_FAILURE);
> > > +    }
> > > +  }
> > > +}
> > > +
> > >  /* Run all of the selftests within this file.  */
> > >
> > >  void
> > >  dumpfile_c_tests ()
> > >  {
> > >    test_impl_location ();
> > > +  test_capture_of_dump_calls ();
> > >  }
> > >
> > >  } // namespace selftest
> > > diff --git a/gcc/dumpfile.h b/gcc/dumpfile.h
> > > index 0e588a6..899bb89 100644
> > > --- a/gcc/dumpfile.h
> > > +++ b/gcc/dumpfile.h
> > > @@ -420,30 +420,6 @@ extern FILE *dump_begin (int, dump_flags_t *);
> > >  extern void dump_end (int, FILE *);
> > >  extern int opt_info_switch_p (const char *);
> > >  extern const char *dump_flag_name (int);
> > > -extern void dump_printf (dump_flags_t, const char *, ...)
> > > ATTRIBUTE_PRINTF_2;
> > > -extern void dump_printf_loc (dump_flags_t, const dump_location_t
> > > &,
> > > -                            const char *, ...) ATTRIBUTE_PRINTF_3;
> > > -extern void dump_function (int phase, tree fn);
> > > -extern void dump_basic_block (dump_flags_t, basic_block, int);
> > > -extern void dump_generic_expr_loc (dump_flags_t, const
> > > dump_location_t &,
> > > -                                  dump_flags_t, tree);
> > > -extern void dump_generic_expr (dump_flags_t, dump_flags_t, tree);
> > > -extern void dump_gimple_stmt_loc (dump_flags_t, const
> > > dump_location_t &,
> > > -                                 dump_flags_t, gimple *, int);
> > > -extern void dump_gimple_stmt (dump_flags_t, dump_flags_t, gimple
> > > *, int);
> > > -extern void print_combine_total_stats (void);
> > > -extern bool enable_rtl_dump_file (void);
> > > -
> > > -template<unsigned int N, typename C>
> > > -void dump_dec (dump_flags_t, const poly_int<N, C> &);
> > > -
> > > -/* In tree-dump.c  */
> > > -extern void dump_node (const_tree, dump_flags_t, FILE *);
> > > -
> > > -/* In combine.c  */
> > > -extern void dump_combine_total_stats (FILE *);
> > > -/* In cfghooks.c  */
> > > -extern void dump_bb (FILE *, basic_block, int, dump_flags_t);
> > >
> > >  /* Global variables used to communicate with passes.  */
> > >  extern FILE *dump_file;
> > > @@ -461,6 +437,49 @@ dump_enabled_p (void)
> > >    return dumps_are_enabled;
> > >  }
> > >
> > > +/* The following API calls (which *don't* take a "FILE *")
> > > +   write the output to zero or more locations:
> > > +   (a) the active dump_file, if any
> > > +   (b) the -fopt-info destination, if any
> > > +   (c) to the "optinfo" destinations, if any:
> > > +
> > > +   dump_* (MSG_*) --> dumpfile.c --+--> (a) dump_file
> > > +                                   |
> > > +                                   +--> (b) alt_dump_file
> > > +                                   |
> > > +                                   `--> (c) optinfo
> > > +                                            `---> optinfo
> > > destinations
> > > +
> > > +   For optinfos, the dump_*_loc mark the beginning of an optinfo
> > > +   instance: all subsequent dump_* calls are consolidated into
> > > +   that optinfo, until the next dump_*_loc call (or a change in
> > > +   dump scope, or a call to
> > > dumpfile_ensure_any_optinfo_are_flushed).
> > > +
> > > +   A group of dump_* calls should be guarded by:
> > > +
> > > +     if (dump_enabled_p ())
> > > +
> > > +   to minimize the work done for the common case where dumps
> > > +   are disabled.  */
> > > +
> > > +extern void dump_printf (dump_flags_t, const char *, ...)
> > > ATTRIBUTE_PRINTF_2;
> > > +extern void dump_printf_loc (dump_flags_t, const dump_location_t
> > > &,
> > > +                            const char *, ...) ATTRIBUTE_PRINTF_3;
> > > +extern void dump_function (int phase, tree fn);
> > > +extern void dump_basic_block (dump_flags_t, basic_block, int);
> > > +extern void dump_generic_expr (dump_flags_t, dump_flags_t, tree);
> > > +extern void dump_generic_expr_loc (dump_flags_t, const
> > > dump_location_t &,
> > > +                                  dump_flags_t, tree);
> > > +extern void dump_gimple_stmt_loc (dump_flags_t, const
> > > dump_location_t &,
> > > +                                 dump_flags_t, gimple *, int);
> > > +extern void dump_gimple_stmt (dump_flags_t, dump_flags_t, gimple
> > > *, int);
> > > +extern void dump_symtab_node (dump_flags_t, symtab_node *);
> > > +
> > > +template<unsigned int N, typename C>
> > > +void dump_dec (dump_flags_t, const poly_int<N, C> &);
> > > +
> > > +extern void dumpfile_ensure_any_optinfo_are_flushed ();
> > > +
> > >  /* Managing nested scopes, so that dumps can express the call
> > > chain
> > >     leading to a dump message.  */
> > >
> > > @@ -500,8 +519,23 @@ class auto_dump_scope
> > >  #define AUTO_DUMP_SCOPE(NAME, LOC) \
> > >    auto_dump_scope scope (NAME, LOC)
> > >
> > > +extern void dump_function (int phase, tree fn);
> > > +extern void print_combine_total_stats (void);
> > > +extern bool enable_rtl_dump_file (void);
> > > +
> > > +/* In tree-dump.c  */
> > > +extern void dump_node (const_tree, dump_flags_t, FILE *);
> > > +
> > > +/* In combine.c  */
> > > +extern void dump_combine_total_stats (FILE *);
> > > +/* In cfghooks.c  */
> > > +extern void dump_bb (FILE *, basic_block, int, dump_flags_t);
> > > +
> > >  namespace gcc {
> > >
> > > +/* A class for managing all of the various dump files used by the
> > > +   optimization passes.  */
> > > +
> > >  class dump_manager
> > >  {
> > >  public:
> > > diff --git a/gcc/ggc-page.c b/gcc/ggc-page.c
> > > index 51783e5..f3a2119 100644
> > > --- a/gcc/ggc-page.c
> > > +++ b/gcc/ggc-page.c
> > > @@ -2177,6 +2177,8 @@ ggc_collect (void)
> > >    if (G.allocated < allocated_last_gc + min_expand &&
> > > !ggc_force_collect)
> > >      return;
> > >
> > > +  dumpfile_ensure_any_optinfo_are_flushed ();
> > > +
> > >    timevar_push (TV_GC);
> > >    if (!quiet_flag)
> > >      fprintf (stderr, " {GC %luk -> ", (unsigned long) G.allocated
> > > / 1024);
> > > diff --git a/gcc/optinfo-internal.h b/gcc/optinfo-internal.h
> > > new file mode 100644
> > > index 0000000..8144174
> > > --- /dev/null
> > > +++ b/gcc/optinfo-internal.h
> > > @@ -0,0 +1,148 @@
> > > +/* Implementation details of optinfo.
> > > +   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_INTERNAL_H
> > > +#define GCC_OPTINFO_INTERNAL_H
> > > +
> > > +/* Multiple dispatch: there are various kinds of items within an
> > > optinfo,
> > > +   and various destinations to send optinfo to.
> > > +
> > > +   Handling this for now by exposing all of the item subclasses,
> > > +   and having the destinations handle them with "switch"
> > > statements.  */
> > > +
> > > +/* An enum for discriminating between optinfo_item subclasses.  */
> > > +
> > > +enum optinfo_item_kind
> > > +{
> > > +  OPTINFO_ITEM_KIND_TEXT,
> > > +  OPTINFO_ITEM_KIND_TREE,
> > > +  OPTINFO_ITEM_KIND_GIMPLE,
> > > +  OPTINFO_ITEM_KIND_SYMTAB_NODE
> > > +};
> > > +
> > > +/* Abstract base class for items within an optinfo.  */
> > > +
> > > +class optinfo_item
> > > +{
> > > + public:
> > > +  virtual ~optinfo_item () {}
> > > +
> > > +  virtual enum optinfo_item_kind get_kind () const = 0;
> > > +};
> > > +
> > > +/* optinfo_item subclasses.  */
> > > +
> > > +/* Item within an optinfo: text, either owned by the item
> > > +   (for optinfo_printf), or borrowed (for string literals).  */
> > > +
> > > +class optinfo_item_text : public optinfo_item
> > > +{
> > > + public:
> > > +  optinfo_item_text (char *text, bool owned)
> > > +  : m_text (text), m_owned (owned)
> > > +  {}
> > > +  ~optinfo_item_text ()
> > > +  {
> > > +    if (m_owned)
> > > +      free (m_text);
> > > +  }
> > > +
> > > +  enum optinfo_item_kind get_kind () const FINAL OVERRIDE
> > > +  {
> > > +    return OPTINFO_ITEM_KIND_TEXT;
> > > +  }
> > > +
> > > +  const char *get_text () const { return m_text; }
> > > +
> > > +  void trim_trailing_whitespace ();
> > > +
> > > + private:
> > > +  char *m_text;
> > > +  bool m_owned;
> > > +};
> > > +
> > > +/* Item within an optinfo: a tree, with dump flags.
> > > +   Note that this is not GTY-marked; see the description of
> > > +   class optinfo for a discussion of the interaction with the
> > > +   garbage-collector.  */
> > > +
> > > +class optinfo_item_tree : public optinfo_item
> > > +{
> > > + public:
> > > +  optinfo_item_tree (tree node, dump_flags_t dump_flags)
> > > +    : m_node (node), m_dump_flags (dump_flags)
> > > +  {}
> > > +  enum optinfo_item_kind get_kind () const FINAL OVERRIDE
> > > +  {
> > > +    return OPTINFO_ITEM_KIND_TREE;
> > > +  }
> > > +
> > > +  tree get_node () const { return m_node; }
> > > +  dump_flags_t get_flags () const { return m_dump_flags; }
> > > +
> > > + private:
> > > +  tree m_node;
> > > +  dump_flags_t m_dump_flags;
> > > +};
> > > +
> > > +/* Item within an optinfo: a gimple statement.
> > > +   Note that this is not GTY-marked; see the description of
> > > +   class optinfo for a discussion of the interaction with the
> > > +   garbage-collector.  */
> > > +
> > > +class optinfo_item_gimple : public optinfo_item
> > > +{
> > > + public:
> > > +  optinfo_item_gimple (gimple *stmt, dump_flags_t dump_flags)
> > > +    : m_stmt (stmt), m_dump_flags (dump_flags) {}
> > > +  enum optinfo_item_kind get_kind () const FINAL OVERRIDE
> > > +  {
> > > +    return OPTINFO_ITEM_KIND_GIMPLE;
> > > +  }
> > > +
> > > +  gimple *get_stmt () const { return m_stmt; }
> > > +  dump_flags_t get_flags () const { return m_dump_flags; }
> > > +
> > > + private:
> > > +  gimple *m_stmt;
> > > +  dump_flags_t m_dump_flags;
> > > +};
> > > +
> > > +/* Item within an optinfo: a symbol table node.
> > > +   Note that this is not GTY-marked; see the description of
> > > +   class optinfo for a discussion of the interaction with the
> > > +   garbage-collector.  */
> > > +
> > > +class optinfo_item_symtab_node : public optinfo_item
> > > +{
> > > + public:
> > > +  optinfo_item_symtab_node (symtab_node *node) : m_node (node) {}
> > > +  enum optinfo_item_kind get_kind () const FINAL OVERRIDE
> > > +  {
> > > +    return OPTINFO_ITEM_KIND_SYMTAB_NODE;
> > > +  }
> > > +
> > > +  symtab_node *get_node () const { return m_node; }
> > > +
> > > + private:
> > > +  symtab_node *m_node;
> > > +};
> > > +
> > > +#endif /* #ifndef GCC_OPTINFO_INTERNAL_H */
> > > diff --git a/gcc/optinfo.cc b/gcc/optinfo.cc
> > > new file mode 100644
> > > index 0000000..1da7d37
> > > --- /dev/null
> > > +++ b/gcc/optinfo.cc
> > > @@ -0,0 +1,251 @@
> > > +/* Optimization information.
> > > +   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 "gimple.h"
> > > +
> > > +#include "optinfo.h"
> > > +#include "optinfo-internal.h"
> > > +#include "dump-context.h"
> > > +#include "selftest.h"
> > > +
> > > +/* Remove any trailing whitespace characters from this text item.
> > > +   Primarily for use in stripping trailing newline characters when
> > > +   emitting remarks (since the diagnostic subsystem doesn't expect
> > > +   trailing newlines in messages).  */
> > > +
> > > +void
> > > +optinfo_item_text::trim_trailing_whitespace ()
> > > +{
> > > +  size_t len = strlen (m_text);
> > > +  if (len == 0)
> > > +    return;
> > > +
> > > +  size_t new_len = len;
> > > +  while (new_len > 0 && ISSPACE (m_text[new_len - 1]))
> > > +    new_len--;
> > > +
> > > +  if (new_len == len)
> > > +    return;
> > > +
> > > +  if (m_owned)
> > > +    m_text[new_len] = '\0';
> > > +  else
> > > +    {
> > > +      m_text = xstrndup (m_text, new_len);
> > > +      m_owned = true;
> > > +    }
> > > +}
> > > +
> > > +/* Get a string from KIND.  */
> > > +
> > > +const char *
> > > +optinfo_kind_to_string (enum optinfo_kind kind)
> > > +{
> > > +  switch (kind)
> > > +    {
> > > +    default:
> > > +      gcc_unreachable ();
> > > +    case OPTINFO_KIND_SUCCESS:
> > > +      return "success";
> > > +    case OPTINFO_KIND_FAILURE:
> > > +      return "failure";
> > > +    case OPTINFO_KIND_NOTE:
> > > +      return "note";
> > > +    case OPTINFO_KIND_SCOPE:
> > > +      return "scope";
> > > +    }
> > > +}
> > > +
> > > +/* optinfo's dtor.  */
> > > +
> > > +optinfo::~optinfo ()
> > > +{
> > > +  /* Cleanup.  */
> > > +  unsigned i;
> > > +  optinfo_item *item;
> > > +  FOR_EACH_VEC_ELT (m_items, i, item)
> > > +    delete item;
> > > +}
> > > +
> > > +/* Emit the optinfo to all of the active destinations.  */
> > > +
> > > +void
> > > +optinfo::emit ()
> > > +{
> > > +  /* Eliminate any trailing whitespace.  */
> > > +  while (m_items.length () > 0)
> > > +    {
> > > +      optinfo_item *last_item = m_items[m_items.length () - 1];
> > > +      if (last_item->get_kind () != OPTINFO_ITEM_KIND_TEXT)
> > > +       break;
> > > +
> > > +      optinfo_item_text *last_text = (optinfo_item_text
> > > *)last_item;
> > > +      last_text->trim_trailing_whitespace ();
> > > +
> > > +      if (strlen (last_text->get_text ()) > 0)
> > > +       break;
> > > +
> > > +      m_items.pop ();
> > > +      delete last_item;
> > > +    }
> > > +
> > > +  /* currently this is a no-op.  */
> > > +}
> > > +
> > > +/* Update the optinfo's kind based on DUMP_KIND.  */
> > > +
> > > +void
> > > +optinfo::handle_dump_file_kind (dump_flags_t dump_kind)
> > > +{
> > > +  if (dump_kind & MSG_OPTIMIZED_LOCATIONS)
> > > +    m_kind = OPTINFO_KIND_SUCCESS;
> > > +  else if (dump_kind & MSG_MISSED_OPTIMIZATION)
> > > +    m_kind = OPTINFO_KIND_FAILURE;
> > > +  else if (dump_kind & MSG_NOTE)
> > > +    m_kind = OPTINFO_KIND_NOTE;
> > > +}
> > > +
> > > +/* Append a string literal to this optinfo.  */
> > > +
> > > +void
> > > +optinfo::add_string (const char *str)
> > > +{
> > > +  optinfo_item *item
> > > +    = new optinfo_item_text (const_cast <char *> (str), false);
> > > +  m_items.safe_push (item);
> > > +}
> > > +
> > > +/* Append printf-formatted text to this optinfo.  */
> > > +
> > > +void
> > > +optinfo::add_printf (const char *format, ...)
> > > +{
> > > +  va_list ap;
> > > +  va_start (ap, format);
> > > +  add_printf_va (format, ap);
> > > +  va_end (ap);
> > > +}
> > > +
> > > +/* Append printf-formatted text to this optinfo.  */
> > > +
> > > +void
> > > +optinfo::add_printf_va (const char *format, va_list ap)
> > > +{
> > > +  char *formatted_text = xvasprintf (format, ap);
> > > +  optinfo_item *item
> > > +    = new optinfo_item_text (formatted_text, true);
> > > +  m_items.safe_push (item);
> > > +}
> > > +
> > > +/* Append a gimple statement to this optinfo.  */
> > > +
> > > +void
> > > +optinfo::add_stmt (gimple *stmt, dump_flags_t dump_flags)
> > > +{
> > > +  m_items.safe_push (new optinfo_item_gimple (stmt, dump_flags));
> > > +}
> > > +
> > > +/* Append a tree node to this optinfo.  */
> > > +
> > > +void
> > > +optinfo::add_tree (tree node, dump_flags_t dump_flags)
> > > +{
> > > +  m_items.safe_push (new optinfo_item_tree (node, dump_flags));
> > > +}
> > > +
> > > +/* Append a symbol table node to this optinfo.  */
> > > +
> > > +void
> > > +optinfo::add_symtab_node (symtab_node *node)
> > > +{
> > > +  m_items.safe_push (new optinfo_item_symtab_node (node));
> > > +}
> > > +
> > > +/* Append the decimal represenation of a wide_int_ref to this
> > > +   optinfo.  */
> > > +
> > > +void
> > > +optinfo::add_dec (const wide_int_ref &wi, signop sgn)
> > > +{
> > > +  char buf[WIDE_INT_PRINT_BUFFER_SIZE];
> > > +  print_dec (wi, buf, sgn);
> > > +  optinfo_item *item
> > > +    = new optinfo_item_text (xstrdup (buf), true);
> > > +  m_items.safe_push (item);
> > > +}
> > > +
> > > +/* Should optinfo instances be created?
> > > +   All creation of optinfos should be guarded by this predicate.
> > > +   Return true if any optinfo destinations are active.  */
> > > +
> > > +bool optinfo_enabled_p ()
> > > +{
> > > +  /* Currently no destinations are implemented, just a hook for
> > > +     selftests.  */
> > > +  return dump_context::get ().forcibly_enable_optinfo_p ();
> > > +}
> > > +
> > > +/* Return true if any of the active optinfo destinations make use
> > > +   of inlining information.
> > > +   (if true, then the information is preserved).  */
> > > +
> > > +bool optinfo_wants_inlining_info_p ()
> > > +{
> > > +  return false;
> > > +}
> > > +
> > > +#if CHECKING_P
> > > +
> > > +namespace selftest {
> > > +
> > > +/* Verify that optinfo_item_text::trim_trailing_whitespace turns
> > > +   INPUT into EXPECTED.  */
> > > +
> > > +static void
> > > +test_trim_trailing_whitespace (const char *input, const char
> > > *expected)
> > > +{
> > > +  optinfo_item_text item (const_cast <char *> (input), false);
> > > +  item.trim_trailing_whitespace ();
> > > +  ASSERT_STREQ (item.get_text (), expected);
> > > +}
> > > +
> > > +/* Run all of the selftests within this file.  */
> > > +
> > > +void
> > > +optinfo_cc_tests ()
> > > +{
> > > +  /* Verify that optinfo_item_text::trim_trailing_whitespace
> > > works.  */
> > > +  test_trim_trailing_whitespace ("", "");
> > > +  test_trim_trailing_whitespace ("\n", "");
> > > +  test_trim_trailing_whitespace ("foo", "foo");
> > > +  test_trim_trailing_whitespace ("foo\n", "foo");
> > > +  test_trim_trailing_whitespace ("foo\n\n", "foo");
> > > +  test_trim_trailing_whitespace ("foo bar \n\n", "foo bar");
> > > +}
> > > +
> > > +} // namespace selftest
> > > +
> > > +#endif /* CHECKING_P */
> > > diff --git a/gcc/optinfo.h b/gcc/optinfo.h
> > > new file mode 100644
> > > index 0000000..0d49823
> > > --- /dev/null
> > > +++ b/gcc/optinfo.h
> > > @@ -0,0 +1,175 @@
> > > +/* Optimization information.
> > > +   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_H
> > > +#define GCC_OPTINFO_H
> > > +
> > > +/* An "optinfo" is a bundle of information describing part of an
> > > +   optimization, which can be emitted to zero or more of several
> > > +   destinations, such as:
> > > +
> > > +   * as a "remark" through the diagnostics subsystem
> > > +
> > > +   * saved to a file as an "optimization record"
> > > +
> > > +   Currently no such destinations are implemented.
> > > +
> > > +   They are generated in response to calls to the "dump_*" API in
> > > +   dumpfile.h; repeated calls to the "dump_*" API are consolidated
> > > +   into a pending optinfo instance, with a "dump_*_loc" starting a
> > > new
> > > +   optinfo instance.
> > > +
> > > +   The data sent to the dump calls are captured within the pending
> > > optinfo
> > > +   instance as a sequence of optinfo_items.  For example, given:
> > > +
> > > +      if (dump_enabled_p ())
> > > +        {
> > > +          dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
> > > +                           "not vectorized: live stmt not
> > > supported: ");
> > > +          dump_gimple_stmt (MSG_MISSED_OPTIMIZATION, TDF_SLIM,
> > > stmt, 0);
> > > +        }
> > > +
> > > +   the "dump_printf_loc" call begins a new optinfo containing two
> > > items:
> > > +   (1) a text item containing "not vectorized: live stmt not
> > > supported: "
> > > +   (2) a gimple item for "stmt"
> > > +
> > > +   Dump destinations are thus able to access rich metadata about
> > > the
> > > +   items when the optinfo is emitted to them, rather than just
> > > having plain
> > > +   text.  For example, when saving the above optinfo to a file as
> > > an
> > > +   "optimization record", the record could capture the source
> > > location of
> > > +   "stmt" above, rather than just its textual form.
> > > +
> > > +   The currently pending optinfo is emitted and deleted:
> > > +   * each time a "dump_*_loc" call occurs (which starts the next
> > > optinfo), or
> > > +   * when the dump files are changed (at the end of a pass), or
> > > +   * when a garbage collection is about to happen.  This safety
> > > measure
> > > +     ensures that no GC happens during the lifetime of an optinfo
> > > instance,
> > > +     and thus that any optinfo_items within the optinfo instances
> > > can refer
> > > +     to GC-allocated objects without needing to be GTY-marked:
> > > they will never
> > > +     refer to collected garbage.  optinfo and optinfo_item are not
> > > GTY-marked
> > > +     as it would make no sense for them to be in PCH files.
> > > +
> > > +   Dumping to an optinfo instance is non-trivial (due to building
> > > optinfo_item
> > > +   instances), so all usage should be guarded by
> > > +
> > > +     if (optinfo_enabled_p ())
> > > +
> > > +   which is off by default.  */
> > > +
> > > +
> > > +/* Forward decls.  */
> > > +struct opt_pass;
> > > +class optinfo_item; /* optinfo-internal.h.  */
> > > +
> > > +/* Should optinfo instances be created?
> > > +   All creation of optinfos should be guarded by this predicate.
> > > +   Return true if any optinfo destinations are active.  */
> > > +
> > > +extern bool optinfo_enabled_p ();
> > > +
> > > +/* Return true if any of the active optinfo destinations make use
> > > +   of inlining information.
> > > +   (if true, then the information is preserved).  */
> > > +
> > > +extern bool optinfo_wants_inlining_info_p ();
> > > +
> > > +/* The various kinds of optinfo.  */
> > > +
> > > +enum optinfo_kind
> > > +{
> > > +  OPTINFO_KIND_SUCCESS,
> > > +  OPTINFO_KIND_FAILURE,
> > > +  OPTINFO_KIND_NOTE,
> > > +  OPTINFO_KIND_SCOPE
> > > +};
> > > +
> > > +extern const char *optinfo_kind_to_string (enum optinfo_kind
> > > kind);
> > > +
> > > +/* A bundle of information describing part of an optimization.  */
> > > +
> > > +class optinfo
> > > +{
> > > +  friend class dump_context;
> > > +
> > > + public:
> > > +  optinfo (const dump_location_t &loc,
> > > +          enum optinfo_kind kind,
> > > +          opt_pass *pass)
> > > +  : m_loc (loc), m_kind (kind), m_pass (pass), m_items ()
> > > +  {}
> > > +  ~optinfo ();
> > > +
> > > +  const dump_user_location_t &
> > > +  get_user_location () const { return m_loc.get_user_location ();
> > > }
> > > +
> > > +  const dump_impl_location_t &
> > > +  get_impl_location () const { return m_loc.get_impl_location ();
> > > }
> > > +
> > > +  enum optinfo_kind get_kind () const { return m_kind; }
> > > +  opt_pass *get_pass () const { return m_pass; }
> > > +  unsigned int num_items () const { return m_items.length (); }
> > > +  const optinfo_item *get_item (unsigned int i) const { return
> > > m_items[i]; }
> > > +
> > > +  location_t get_location_t () const { return m_loc.get_location_t
> > > (); }
> > > +  profile_count get_count () const { return m_loc.get_count (); }
> > > +
> > > + private:
> > > +  void emit ();
> > > +
> > > +  /* Pre-canned ways of manipulating the optinfo, for use by
> > > friend class
> > > +     dump_context.  */
> > > +  void handle_dump_file_kind (dump_flags_t);
> > > +  void add_string (const char *str);
> > > +  void add_printf (const char *format, ...) ATTRIBUTE_PRINTF_2;
> > > +  void add_printf_va (const char *format, va_list ap)
> > > ATTRIBUTE_PRINTF (2, 0);
> > > +  void add_stmt (gimple *stmt, dump_flags_t dump_flags);
> > > +  void add_tree (tree node, dump_flags_t dump_flags);
> > > +  void add_symtab_node (symtab_node *node);
> > > +  void add_dec (const wide_int_ref &wi, signop sgn);
> > > +
> > > +  template<unsigned int N, typename C>
> > > +  void add_poly_int (const poly_int<N, C> &value)
> > > +  {
> > > +    /* Compare with dump_dec (MSG_NOTE, ).  */
> > > +
> > > +    STATIC_ASSERT (poly_coeff_traits<C>::signedness >= 0);
> > > +    signop sgn = poly_coeff_traits<C>::signedness ? SIGNED :
> > > UNSIGNED;
> > > +
> > > +    if (value.is_constant ())
> > > +      add_dec (value.coeffs[0], sgn);
> > > +    else
> > > +      {
> > > +       add_string ("[");
> > > +       for (unsigned int i = 0; i < N; ++i)
> > > +         {
> > > +           add_dec (value.coeffs[i], sgn);
> > > +           add_string (i == N - 1 ? "]" : ",");
> > > +         }
> > > +      }
> > > +  }
> > > +
> > > + private:
> > > +  dump_location_t m_loc;
> > > +  enum optinfo_kind m_kind;
> > > +  opt_pass *m_pass;
> > > +  auto_vec <optinfo_item *> m_items;
> > > +};
> > > +
> > > +#endif /* #ifndef GCC_OPTINFO_H */
> > > diff --git a/gcc/selftest-run-tests.c b/gcc/selftest-run-tests.c
> > > index 7f4d6f3..989c50a 100644
> > > --- a/gcc/selftest-run-tests.c
> > > +++ b/gcc/selftest-run-tests.c
> > > @@ -72,6 +72,7 @@ selftest::run_tests ()
> > >    typed_splay_tree_c_tests ();
> > >    unique_ptr_tests_cc_tests ();
> > >    opt_proposer_c_tests ();
> > > +  optinfo_cc_tests ();
> > >
> > >    /* Mid-level data structures.  */
> > >    input_c_tests ();
> > > diff --git a/gcc/selftest.h b/gcc/selftest.h
> > > index 54fc488..48881c9 100644
> > > --- a/gcc/selftest.h
> > > +++ b/gcc/selftest.h
> > > @@ -228,6 +228,7 @@ extern void gimple_c_tests ();
> > >  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 predict_c_tests ();
> > >  extern void pretty_print_c_tests ();
> > >  extern void read_rtl_function_c_tests ();
> > > --
> > > 1.8.5.3
> > >


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