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] v3 of optinfo, remarks and optimization records


On Wed, Jun 20, 2018 at 6:34 PM David Malcolm <dmalcolm@redhat.com> wrote:
>
> Here's v3 of the patch (one big patch this time, rather than a kit).
>
> Like the v2 patch kit, this patch reuses the existing dump API,
> rather than inventing its own.
>
> Specifically, it uses the dump_* functions in dumpfile.h that don't
> take a FILE *, the ones that implicitly write to dump_file and/or
> alt_dump_file.  I needed a name for them, so I've taken to calling
> them the "structured dump API" (better name ideas welcome).
>
> v3 eliminates v2's optinfo_guard class, instead using "dump_*_loc"
> calls as delimiters when consolidating "dump_*" calls.  There's a
> new dump_context class which has responsibility for consolidating
> them into optimization records.
>
> The dump_*_loc calls now capture more than just a location_t: they
> capture the profile_count and the location in GCC's own sources where
> the dump is being emitted from.
>
> This works by introducing a new "dump_location_t" class as the
> argument of those dump_*_loc calls.  The dump_location_t can
> be constructed from a gimple * or from an rtx_insn *, so that
> rather than writing:
>
>   dump_printf_loc (MSG_NOTE, gimple_location (stmt),
>                    "some message: %i", 42);
>
> you can write:
>
>   dump_printf_loc (MSG_NOTE, stmt,
>                    "some message: %i", 42);
>
> and the dump_location_t constructor will grab the location_t and
> profile_count of stmt, and the location of the "dump_printf_loc"
> callsite (and gracefully handle "stmt" being NULL).
>
> Earlier versions of the patch captured the location of the
> dump_*_loc call via preprocessor hacks, or didn't work properly;
> this version of the patch works more cleanly: internally,
> dump_location_t is split into two new classes:
>   * dump_user_location_t: the location_t and profile_count within
>     the *user's code*, and
>   * dump_impl_location_t: the __builtin_FILE/LINE/FUNCTION within
>     the *implementation* code (i.e. GCC or a plugin), captured
>     "automagically" via default params
>
> These classes are sometimes used elsewhere in the code.  For
> example, "vect_location" becomes a dump_user_location_t
> (location_t and profile_count), so that in e.g:
>
>   vect_location = find_loop_location (loop);
>
> it's capturing the location_t and profile_count, and then when
> it's used here:
>
>   dump_printf_loc (MSG_NOTE, vect_location, "foo");
>
> the dump_location_t is constructed from the vect_location
> plus the dump_impl_location_t at that callsite.
>
> In contrast, loop-unroll.c's report_unroll's "locus" param
> becomes a dump_location_t: we're interested in where it was
> called from, not in the locations of the various dump_*_loc calls
> within it.
>
> Previous versions of the patch captured a gimple *, and needed
> GTY markers; in this patch, the dump_user_location_t is now just a
> location_t and a profile_count.
>
> The v2 patch added an overload for dump_printf_loc so that you
> could pass in either a location_t, or the new type; this version
> of the patch eliminates that: they all now take dump_location_t.
>
> Doing so required adding support for rtx_insn *, so that one can
> write this kind of thing in RTL passes:
>
>   dump_printf_loc (MSG_NOTE, insn, "foo");
>
> One knock-on effect is that get_loop_location now returns a
> dump_user_location_t rather than a location_t, so that it has
> hotness information.
>
> Richi: would you like me to split out this location-handling
> code into a separate patch?  (It's kind of redundant without
> adding the remarks and optimization records work, but if that's
> easier I can do it)

I think that would be easier because it doesn't require the JSON
stuff and so I'll happily approve it.

Thus - trying to review that bits (and sorry for the delay).

+  location_t srcloc = loc.get_location_t ();
+
   if (dump_file && (dump_kind & pflags))
     {
-      dump_loc (dump_kind, dump_file, loc);
+      dump_loc (dump_kind, dump_file, srcloc);
       print_gimple_stmt (dump_file, gs, spc, dump_flags | extra_dump_flags);
     }

   if (alt_dump_file && (dump_kind & alt_flags))
     {
-      dump_loc (dump_kind, alt_dump_file, 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);
+    }

seeing this in multiple places.  I seem to remember that
dump_file / alt_dump_file was suposed to handle dumping
into two locations - a dump file and optinfo (or stdout).  This looks
like the optinfo "stream" is even more separate.  Could that
obsolete the alt_dump_file stream?  I'd need to review existing stuff
in more detail to answer but maybe you already know from recently
digging into this.

Oh, and all the if (optinfo_enable_p ()) stuff is for the followup then, right?

I like the boiler-plate changes to dump_* using stuff a lot, so the
infrastructure to do that (the location wrapping) and these boiler-plate
changes are pre-approved if split out.

I think the *_REMARK stuff should get attention of the respective
maintainers - not sure what the difference between NOTE and REMARK
is ;)

Thanks and sorry again for the repeated delays...
Richard.

>
> The v3 patch adds more detail to remarks: they now show the gcc
> source location that emitted them e.g.:
>
> test.c:8:3: remark:   Symbolic number of iterations is '(unsigned int)
> n_9(D)' [pass=vect] [count(precise)=76800000] [../../src/gcc/tree-vect-loop.c:1387:vect_analyze_loop_form]
>
> and I added new command-line options for controlling the above:
> * -fno-diagnostics-show-remark-hotness
> * -fno-diagnostics-show-remark-origin
> * -fno-diagnostics-show-remark-pass
>
> An example of remark output (showing colors) can be seen here:
>
>   https://dmalcolm.fedorapeople.org/gcc/2018-06-18/test.cc.remarks.html
>
> I haven't yet implemented options for filtering remarks (I'm thinking
> of using the optgroups from -fopt-info, a hotness threshold, and pragmas
> for narrowing them to a specific region of the user's code); though
> the HTML visualization from the JSON output is likely to provide more
> flexibility.
>
> I got rid of GCC_UNLIKELY in favor of a __builtin_expect in
> dump_enabled_p, but I haven't measured the impact yet.
>
> Other changes relative to v2:
> * added class dump_context; eliminate class pending_optinfo; moved optinfo
>   emission from optinfo dtor and into dump_context
> * added selftests for dump_* consolidation, for JSON emission, and for
>   remarks
> * minimized global state in JSON emission
> * renamed OPTINFO_SCOPE to AUTO_DUMP_SCOPE and moved from optinfo.h to
>   dumpfile.h (and similar changes to the support class)
> * added "m_pass" field to optinfo, reading current_pass at time of
>   creation, rather than as needed later on
>
> Successfully bootstrapped & regrtested on x86_64-pc-linux-gnu
> (relative to r261555).
>
> How is this looking?
>
> As before, this patch requires the JSON support patch from v1 of the kit:
>   "[PATCH 02/10] Add JSON implementation"
>     https://gcc.gnu.org/ml/gcc-patches/2018-05/msg01676.html
>
> This approach means we can use all of the existing dump_* calls without
> having to rewrite anything, gaining the ability to prioritize dump messages
> by code hotness and to track where in GCC any dump message came from
> without needing to resort to "grep".
>
> But in terms of actually helping users figure out "how do I get gcc to
> vectorize this loop?", it's only a start.  Maybe followup activity would be
> to go through the existing dump messages and to make them more user-friendly.
> Or to add new dump API entrypoints?
> I find the MSG_* a bit verbose, so maybe instead of e.g.:
>
>   dump_printf_loc (MSG_MISSED_OPTIMIZATION, call_stmt,
>                    "can't inline function call: ");
>   dump_symtab_node (callee);
>   dump_printf (" into ");
>   dump_symtab_node (caller);
>   dump_printf (" as body is not available\n");
>
> there could be, say:
>
>  missed_opt_at (call_stmt,
>                 ("can't inline function call: %N into %N"
>                  " as body is not available\n"),
>                 callee, caller);
>
> (plus, say "optimized_at", "opt_note_at"), introducing a new family
> of format codes (so that the optimization records "know" how to
> embed them).
>
> This would also allow for i18n; such API calls would be more explicitly
> aimed at tech-savvy end-users.
>
> Anyway, that last bit is more me just thinking aloud about possible future
> work here, so here's the v3 patch as it is:
>
> gcc/ChangeLog:
>         * Makefile.in (OBJS): Add optinfo.o, optinfo-emit-diagnostics.o,
>         optinfo-emit-json.o.
>         (CFLAGS-optinfo-emit-json.o): Add -DTARGET_NAME as per toplev.o.
>         * cfgloop.c (get_loop_location): Convert return type from
>         location_t to dump_user_location_t, replacing INSN_LOCATION lookups
>         by implicit construction from rtx_insn *, and using
>         dump_user_location_t::from_function_decl for the fallback case.
>         * cfgloop.h (get_loop_location): Convert return type from
>         location_t to dump_user_location_t.
>         * cgraph.c (cgraph_node::get_body): Replace assignment to
>         "dump_file" with call to set_dump_file.
>         * cgraphunit.c (walk_polymorphic_call_targets): Update call to
>         dump_printf_loc to pass in a dump_location_t rather than a
>         location_t, via the gimple stmt.
>         * common.opt (fremarks): New option.
>         (fdiagnostics-show-remark-hotness): New option.
>         (fdiagnostics-show-remark-origin): New option.
>         (fdiagnostics-show-remark-pass): New option.
>         (fsave-optimization-record): New option.
>         * coretypes.h  (class symtab_node): New forward declaration.
>         (struct cgraph_node): Likewise.
>         (class varpool_node): Likewise.
>         (struct kv_pair): Move here from dumpfile.c.
>         * coverage.c (get_coverage_counts): Update calls to
>         dump_printf_loc to pass in dump_location_t rather than a
>         location_t.
>         * 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.
>         (-fsave-optimization-record): New option.
>         (-fremarks): New option.
>         (-fno-diagnostics-show-remark-hotness): New option.
>         (-fno-diagnostics-show-remark-origin): New option.
>         (-fno-diagnostics-show-remark-pass): New option.
>         * dump-context.h: New file.
>         * dumpfile.c: Include "optinfo.h", "cgraph.h",
>         "optinfo-emit-json.h", "optinfo-internal.h", "backend.h",
>         "gimple.h", "rtl.h", "dump-context.h", "tree-pass.h", "selftest.h"
>         (alt_dump_file): Make static, and group with...
>         (alt_flags): ...this definition.
>         (dumps_are_enabled): New variable.
>         (refresh_dumps_are_enabled): New function.
>         (set_dump_file): New function.
>         (set_alt_dump_file): New function.
>         (struct kv_pair): Move from here to coretypes.h.
>         (optgroup_options): Make non-static.
>         (dump_user_location_t::dump_user_location_t): New ctors
>         (dump_user_location_t::from_function_decl): New function.
>         (dump_loc): Make static.  Add indentation based on scope depth.
>         (dump_context::~dump_context): New dtor.
>         (dump_gimple_stmt): Move implementation to...
>         (dump_context::dump_gimple_stmt): ...this new method.  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 method.  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 method.  Add the
>         tree to any pending optinfo, creating one if need be.
>         (dump_generic_expr_loc): Delete.
>         (dump_printf): Move implementation to...
>         (dump_context::dump_printf_va): ...this new method.  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 method.  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 method.  Add the value to
>         any pending optinfo, creating one if need be.
>         (dump_context::dump_symtab_node): New method.
>         (dump_context::get_scope_depth): New method.
>         (dump_context::begin_scope): New method.
>         (dump_context::end_scope): New method.
>         (dump_context::ensure_pending_optinfo): New method.
>         (dump_context::begin_next_optinfo): New method.
>         (dump_context::end_any_optinfo): New method.
>         (dump_context::s_current): New global.
>         (dump_context::s_default): New global.
>         (dump_symtab_node): New function.
>         (get_dump_scope_depth): New function.
>         (dump_begin_scope): New function.
>         (dump_end_scope): New function.
>         (gcc::dump_manager::dump_start): Replace assignments to
>         "dump_file" and "alt_dump_file" with call to set_dump_file and
>         set_alt_dump_file.
>         (gcc::dump_manager::dump_finish): Likewise.
>         (selftest::temp_dump_context::temp_dump_context): New ctor.
>         (selftest::temp_dump_context::~temp_dump_context): New dtor.
>         (selftest::test_impl_location): New test.
>         (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): New function.
>         * dumpfile.h: Include "profile-count.h".
>         (dump_file, dump_flags, dump_file_name): Move decls to top of
>         file, to split them out from the "Structured dumping" API.
>         (set_dump_file): New function decl.
>         (dumps_are_enabled): New variable decl.
>         (dump_enabled_p): Rewrite in terms of new "dumps_are_enabled"
>         global.
>         (class dump_user_location_t): New class.
>         (struct dump_impl_location_t): New struct.
>         (class dump_location_t): New class.
>         (dump_printf_loc): Convert 2nd param from source_location to
>         const dump_location_t &.
>         (dump_generic_expr_loc): Delete.
>         (dump_gimple_stmt_loc): Convert 2nd param from source_location to
>         const dump_location_t &.
>         (dump_symtab_node): New decl.
>         (get_dump_scope_depth): New decl.
>         (dump_begin_scope): New decl.
>         (dump_end_scope): New decl.
>         (class auto_dump_scope): New class.
>         (AUTO_DUMP_SCOPE): New macro.
>         (dump_function, print_combine_total_stats, enable_rtl_dump_file):
>         Move these decls, to split them out from the "Structured dumping"
>         API.
>         (alt_dump_file): Delete decl.
>         (optgroup_options): New decl.
>         (class dump_manager): Add leading comment.
>         * gimple-fold.c (fold_gimple_assign): Update call to
>         dump_printf_loc to pass in a dump_location_t rather than a
>         location_t, via the gimple stmt.
>         (gimple_fold_call): Likewise.
>         * gimple-loop-interchange.cc
>         (loop_cand::analyze_iloop_reduction_var): Update for change to
>         check_reduction_path.
>         (tree_loop_interchange::interchange): Update for change to
>         find_loop_location.  Add a usage of AUTO_DUMP_SCOPE.
>         * gimple-pretty-print.c (gimple_dump_bb_buff): Make non-static.
>         * gimple-pretty-print.h (gimple_dump_bb_buff): New decl.
>         * graphite-isl-ast-to-gimple.c (scop_to_isl_ast): Update for
>         change in return-type of find_loop_location.
>         (graphite_regenerate_ast_isl): Likewise.
>         * graphite-optimize-isl.c (optimize_isl): Likewise.
>         * graphite.c (graphite_transform_loops): Update for change in
>         return-type of find_loop_location.
>         * ipa-devirt.c (ipa_devirt): Update call to dump_printf_loc to
>         pass in a dump_location_t rather than a location_t, via the
>         gimple stmt.
>         * ipa-prop.c (ipa_make_edge_direct_to_target): Likewise.
>         (ipa_make_edge_direct_to_target): Likewise.
>         * ipa.c (walk_polymorphic_call_targets): Likewise.
>         * loop-unroll.c (report_unroll): Convert "locus" param from
>         location_t to dump_location_t.
>         (decide_unrolling): Update for change to get_loop_location's
>         return type.
>         * omp-grid.c (struct grid_prop): Convert field "target_loc" from
>         location_t to dump_user_location_t.
>         (grid_find_single_omp_among_assignments_1): Updates calls to
>         dump_printf_loc to pass in a dump_location_t rather than a
>         location_t, via the gimple stmt.
>         (grid_parallel_clauses_gridifiable): Convert "tloc" from
>         location_t to dump_location_t.  Updates calls to dump_printf_loc
>         to pass in a dump_location_t rather than a location_t, via the
>         gimple stmt.
>         (grid_inner_loop_gridifiable_p): Likewise.
>         (grid_dist_follows_simple_pattern): Likewise.
>         (grid_gfor_follows_tiling_pattern): Likewise.
>         (grid_target_follows_gridifiable_pattern): Likewise.
>         (grid_attempt_target_gridification): Convert initialization
>         of local "grid" from memset to zero-initialization; FIXME: does
>         this require C++11?  Update call to dump_printf_loc to pass in a
>         optinfo_location rather than a location_t, via the gimple stmt.
>         * opt-functions.awk (function): Handle "Remark" by adding
>         CL_REMARK.
>         * optinfo-emit-diagnostics.cc: New file.
>         * optinfo-emit-diagnostics.h: New file.
>         * optinfo-emit-json.cc: New file.
>         * optinfo-emit-json.h: New file.
>         * optinfo-internal.h: New file.
>         * optinfo.cc: New file.
>         * optinfo.h: New file.
>         * 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.
>         * passes.c: Include "optinfo.h" and "optinfo-emit-json.h".
>         (execute_optinfo_function_dump): New function.
>         (execute_one_ipa_transform_pass): Add per-function call to
>         execute_optinfo_function_dump.
>         (execute_one_pass): Likewise.
>         * pretty-print.c (test_pp_format): Move save and restore of quotes
>         to class auto_fix_quotes, and add an instance.
>         * profile-count.c (profile_quality_as_string): New function.
>         * profile-count.h (profile_quality_as_string): New decl.
>         (profile_count::quality): New accessor.
>         * profile.c (read_profile_edge_counts): Updates call to
>         dump_printf_loc to pass in a dump_location_t rather than a
>         location_t
>         (compute_branch_probabilities): Likewise.
>         * selftest-run-tests.c (selftest::run_tests): Call
>         dumpfile_c_tests, optinfo_cc_tests,
>         optinfo_emit_diagnostics_cc_tests, and optinfo_emit_json_cc_tests.
>         * selftest.c: Include "intl.h".
>         (selftest::auto_fix_quotes::auto_fix_quotes): New ctor.
>         (selftest::auto_fix_quotes::~auto_fix_quotes): New dtor.
>         * selftest.h (selftest::auto_fix_quotes): New class.
>         (dumpfile_c_tests): New decl.
>         (optinfo_cc_tests): New decl.
>         (optinfo_emit_diagnostics_cc_tests): New decl.
>         (optinfo_emit_json_cc_tests): New decl.
>         * toplev.c: Include "optinfo-emit-json.h".
>         (compile_file): Call optimization_records_start and
>         optimization_records_finish.
>         * tree-loop-distribution.c (pass_loop_distribution::execute):
>         Update for change in return type of find_loop_location.
>         * tree-nested.c (lower_nested_functions): Replace assignments to
>         "dump_file" with calls to set_dump_file.
>         * tree-parloops.c (parallelize_loops): Update for change in return
>         type of find_loop_location.
>         * tree-ssa-live.c: Include "optinfo.h".
>         (remove_unused_scope_block_p): Retain inlining information if
>         optinfo_wants_inlining_info_p returns true.
>         * tree-ssa-loop-ivcanon.c (try_unroll_loop_completely): Convert
>         "locus" from location_t to dump_user_location_t.
>         (canonicalize_loop_induction_variables): Likewise.
>         * tree-ssa-loop-ivopts.c (tree_ssa_iv_optimize_loop): Update
>         for change in return type of find_loop_location.
>         * tree-ssa-loop-niter.c (number_of_iterations_exit): Update call
>         to dump_printf_loc to pass in a dump_location_t rather than a
>         location_t, via the stmt.
>         * tree-vect-loop-manip.c (find_loop_location): Convert return
>         type from source_location to dump_user_location_t.
>         (vect_do_peeling): Update for above change.
>         (vect_loop_versioning): Update for change in type of
>         vect_location.
>         * tree-vect-loop.c (check_reduction_path): Convert "loc" param
>         from location_t to dump_user_location_t.
>         (vect_estimate_min_profitable_iters): Update for change in type
>         of vect_location.
>         * tree-vect-slp.c (vect_print_slp_tree): Convert param "loc" from
>         location_t to dump_location_t.
>         (vect_slp_bb): Update for change in type of vect_location.
>         * tree-vectorizer.c (vect_location): Convert from source_location
>         to dump_user_location_t.
>         (vectorize_loops): Update for change in vect_location's type.  Add
>         top-level DUMP_VECT_SCOPE.
>         (increase_alignment): Update for change in vect_location's type.
>         * tree-vectorizer.h: Include "optinfo.h".
>         (vect_location): Convert from source_location to
>         dump_user_location_t.
>         (DUMP_VECT_SCOPE): Convert to usage of AUTO_DUMP_SCOPE.
>         (find_loop_location): Convert return type from source_location to
>         dump_user_location_t.
>         (check_reduction_path): Convert 1st param from location_t to
>         dump_user_location_t.
>         * value-prof.c (check_counter): Update call to dump_printf_loc to
>         pass in a dump_user_location_t rather than a location_t; update
>         call to error_at for change in type of "locus".
>         (check_ic_target): Update call to dump_printf_loc to
>         pass in a dump_user_location_t rather than a location_t, via the
>         call_stmt.
>
> 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                              |   4 +
>  gcc/cfgloop.c                                |  12 +-
>  gcc/cfgloop.h                                |   2 +-
>  gcc/cgraph.c                                 |   4 +-
>  gcc/cgraphunit.c                             |   3 +-
>  gcc/common.opt                               |  21 +
>  gcc/coretypes.h                              |  15 +
>  gcc/coverage.c                               |  22 +-
>  gcc/diagnostic-color.c                       |   2 +
>  gcc/diagnostic-core.h                        |   2 +
>  gcc/diagnostic.c                             |  17 +
>  gcc/diagnostic.def                           |   1 +
>  gcc/doc/invoke.texi                          |  83 ++-
>  gcc/dump-context.h                           | 112 ++++
>  gcc/dumpfile.c                               | 648 +++++++++++++++++++---
>  gcc/dumpfile.h                               | 258 ++++++++-
>  gcc/fortran/gfc-diagnostic.def               |   1 +
>  gcc/gimple-fold.c                            |   6 +-
>  gcc/gimple-loop-interchange.cc               |   7 +-
>  gcc/gimple-pretty-print.c                    |   2 +-
>  gcc/gimple-pretty-print.h                    |   2 +
>  gcc/graphite-isl-ast-to-gimple.c             |   4 +-
>  gcc/graphite-optimize-isl.c                  |   4 +-
>  gcc/graphite.c                               |   2 +-
>  gcc/ipa-devirt.c                             |   3 +-
>  gcc/ipa-prop.c                               |  10 +-
>  gcc/ipa.c                                    |   9 +-
>  gcc/loop-unroll.c                            |   4 +-
>  gcc/omp-grid.c                               |  47 +-
>  gcc/opt-functions.awk                        |   1 +
>  gcc/optinfo-emit-diagnostics.cc              | 317 +++++++++++
>  gcc/optinfo-emit-diagnostics.h               |  26 +
>  gcc/optinfo-emit-json.cc                     | 773 +++++++++++++++++++++++++++
>  gcc/optinfo-emit-json.h                      |  39 ++
>  gcc/optinfo-internal.h                       | 145 +++++
>  gcc/optinfo.cc                               | 254 +++++++++
>  gcc/optinfo.h                                | 147 +++++
>  gcc/opts.c                                   |   4 +
>  gcc/opts.h                                   |  13 +-
>  gcc/passes.c                                 |  17 +
>  gcc/pretty-print.c                           |   9 +-
>  gcc/profile-count.c                          |  28 +
>  gcc/profile-count.h                          |   5 +
>  gcc/profile.c                                |  14 +-
>  gcc/selftest-run-tests.c                     |   4 +
>  gcc/selftest.c                               |  20 +
>  gcc/selftest.h                               |  24 +
>  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 +
>  gcc/toplev.c                                 |   5 +
>  gcc/tree-loop-distribution.c                 |   2 +-
>  gcc/tree-nested.c                            |   4 +-
>  gcc/tree-parloops.c                          |   3 +-
>  gcc/tree-ssa-live.c                          |   4 +-
>  gcc/tree-ssa-loop-ivcanon.c                  |   8 +-
>  gcc/tree-ssa-loop-ivopts.c                   |   2 +-
>  gcc/tree-ssa-loop-niter.c                    |   2 +-
>  gcc/tree-ssa-sccvn.c                         |   3 +-
>  gcc/tree-vect-loop-manip.c                   |  16 +-
>  gcc/tree-vect-loop.c                         |   8 +-
>  gcc/tree-vect-slp.c                          |   5 +-
>  gcc/tree-vectorizer.c                        |  17 +-
>  gcc/tree-vectorizer.h                        |  25 +-
>  gcc/value-prof.c                             |  15 +-
>  66 files changed, 3229 insertions(+), 230 deletions(-)
>  create mode 100644 gcc/dump-context.h
>  create mode 100644 gcc/optinfo-emit-diagnostics.cc
>  create mode 100644 gcc/optinfo-emit-diagnostics.h
>  create mode 100644 gcc/optinfo-emit-json.cc
>  create mode 100644 gcc/optinfo-emit-json.h
>  create mode 100644 gcc/optinfo-internal.h
>  create mode 100644 gcc/optinfo.cc
>  create mode 100644 gcc/optinfo.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 9b85787..23060a3 100644
> --- a/gcc/Makefile.in
> +++ b/gcc/Makefile.in
> @@ -1421,6 +1421,9 @@ OBJS = \
>         omp-grid.o \
>         omp-low.o \
>         omp-simd-clone.o \
> +       optinfo.o \
> +       optinfo-emit-diagnostics.o \
> +       optinfo-emit-json.o \
>         optabs.o \
>         optabs-libfuncs.o \
>         optabs-query.o \
> @@ -2248,6 +2251,7 @@ s-bversion: BASE-VER
>         $(STAMP) s-bversion
>
>  CFLAGS-toplev.o += -DTARGET_NAME=\"$(target_noncanonical)\"
> +CFLAGS-optinfo-emit-json.o += -DTARGET_NAME=\"$(target_noncanonical)\"
>
>  pass-instances.def: $(srcdir)/passes.def $(PASSES_EXTRA) \
>                     $(srcdir)/gen-pass-instances.awk
> diff --git a/gcc/cfgloop.c b/gcc/cfgloop.c
> index 8af793c..e27cd39 100644
> --- a/gcc/cfgloop.c
> +++ b/gcc/cfgloop.c
> @@ -1800,7 +1800,7 @@ loop_exits_from_bb_p (struct loop *loop, basic_block bb)
>
>  /* Return location corresponding to the loop control condition if possible.  */
>
> -location_t
> +dump_user_location_t
>  get_loop_location (struct loop *loop)
>  {
>    rtx_insn *insn = NULL;
> @@ -1819,7 +1819,7 @@ get_loop_location (struct loop *loop)
>        FOR_BB_INSNS_REVERSE (desc->in_edge->src, insn)
>          {
>            if (INSN_P (insn) && INSN_HAS_LOCATION (insn))
> -            return INSN_LOCATION (insn);
> +            return insn;
>          }
>      }
>    /* If loop has a single exit, then the loop control branch
> @@ -1829,24 +1829,24 @@ get_loop_location (struct loop *loop)
>        FOR_BB_INSNS_REVERSE (exit->src, insn)
>          {
>            if (INSN_P (insn) && INSN_HAS_LOCATION (insn))
> -            return INSN_LOCATION (insn);
> +            return insn;
>          }
>      }
>    /* Next check the latch, to see if it is non-empty.  */
>    FOR_BB_INSNS_REVERSE (loop->latch, insn)
>      {
>        if (INSN_P (insn) && INSN_HAS_LOCATION (insn))
> -        return INSN_LOCATION (insn);
> +        return insn;
>      }
>    /* Finally, if none of the above identifies the loop control branch,
>       return the first location in the loop header.  */
>    FOR_BB_INSNS (loop->header, insn)
>      {
>        if (INSN_P (insn) && INSN_HAS_LOCATION (insn))
> -        return INSN_LOCATION (insn);
> +        return insn;
>      }
>    /* If all else fails, simply return the current function location.  */
> -  return DECL_SOURCE_LOCATION (current_function_decl);
> +  return dump_user_location_t::from_function_decl (current_function_decl);
>  }
>
>  /* Records that every statement in LOOP is executed I_BOUND times.
> diff --git a/gcc/cfgloop.h b/gcc/cfgloop.h
> index af9bfab..80a31c4 100644
> --- a/gcc/cfgloop.h
> +++ b/gcc/cfgloop.h
> @@ -357,7 +357,7 @@ extern bool loop_exit_edge_p (const struct loop *, const_edge);
>  extern bool loop_exits_to_bb_p (struct loop *, basic_block);
>  extern bool loop_exits_from_bb_p (struct loop *, basic_block);
>  extern void mark_loop_exit_edges (void);
> -extern location_t get_loop_location (struct loop *loop);
> +extern dump_user_location_t get_loop_location (struct loop *loop);
>
>  /* Loops & cfg manipulation.  */
>  extern basic_block *get_loop_body (const struct loop *);
> diff --git a/gcc/cgraph.c b/gcc/cgraph.c
> index 3899467..d19f1aa 100644
> --- a/gcc/cgraph.c
> +++ b/gcc/cgraph.c
> @@ -3582,7 +3582,7 @@ cgraph_node::get_body (void)
>        const char *saved_dump_file_name = dump_file_name;
>        dump_flags_t saved_dump_flags = dump_flags;
>        dump_file_name = NULL;
> -      dump_file = NULL;
> +      set_dump_file (NULL);
>
>        push_cfun (DECL_STRUCT_FUNCTION (decl));
>        execute_all_ipa_transforms ();
> @@ -3593,7 +3593,7 @@ cgraph_node::get_body (void)
>        updated = true;
>
>        current_pass = saved_current_pass;
> -      dump_file = saved_dump_file;
> +      set_dump_file (saved_dump_file);
>        dump_file_name = saved_dump_file_name;
>        dump_flags = saved_dump_flags;
>      }
> diff --git a/gcc/cgraphunit.c b/gcc/cgraphunit.c
> index 04b6919..7cfb8a0 100644
> --- a/gcc/cgraphunit.c
> +++ b/gcc/cgraphunit.c
> @@ -928,8 +928,7 @@ walk_polymorphic_call_targets (hash_set<void *> *reachable_call_targets,
>             }
>            if (dump_enabled_p ())
>              {
> -             location_t locus = gimple_location_safe (edge->call_stmt);
> -             dump_printf_loc (MSG_OPTIMIZED_LOCATIONS, locus,
> +             dump_printf_loc (MSG_OPTIMIZED_LOCATIONS, edge->call_stmt,
>                                "devirtualizing call in %s to %s\n",
>                                edge->caller->name (), target->name ());
>             }
> diff --git a/gcc/common.opt b/gcc/common.opt
> index 4aebcaf..141f5dd 100644
> --- a/gcc/common.opt
> +++ b/gcc/common.opt
> @@ -506,6 +506,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
>
> @@ -1273,6 +1278,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.
> @@ -1942,6 +1959,10 @@ fopt-info-
>  Common Joined RejectNegative Var(common_deferred_options) Defer
>  -fopt-info[-<type>=filename]   Dump compiler optimization details.
>
> +fsave-optimization-record
> +Common Report Var(flag_save_optimization_record) Optimization
> +Write a SRCFILE.opt-record.json file detailing what optimizations were performed.
> +
>  foptimize-register-move
>  Common Ignore
>  Does nothing. Preserved for backward compatibility.
> diff --git a/gcc/coretypes.h b/gcc/coretypes.h
> index 283b4eb..33f3d21 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_def, 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;
> @@ -325,6 +332,14 @@ namespace gcc {
>
>  typedef std::pair <tree, tree> tree_pair;
>
> +/* Define a name->value mapping.  */
> +template <typename ValueType>
> +struct kv_pair
> +{
> +  const char *const name;      /* the name of the value */
> +  const ValueType value;       /* the value of the name */
> +};
> +
>  #else
>
>  struct _dont_use_rtx_here_;
> diff --git a/gcc/coverage.c b/gcc/coverage.c
> index 84fff13..350cc45 100644
> --- a/gcc/coverage.c
> +++ b/gcc/coverage.c
> @@ -342,12 +342,16 @@ get_coverage_counts (unsigned counter, unsigned expected,
>        static int warned = 0;
>
>        if (!warned++ && dump_enabled_p ())
> -       dump_printf_loc (MSG_OPTIMIZED_LOCATIONS, input_location,
> -                         (flag_guess_branch_prob
> -                          ? "file %s not found, execution counts estimated\n"
> -                          : "file %s not found, execution counts assumed to "
> -                            "be zero\n"),
> -                         da_file_name);
> +       {
> +         dump_user_location_t loc
> +           = dump_user_location_t::from_location_t (input_location);
> +         dump_printf_loc (MSG_OPTIMIZED_LOCATIONS, loc,
> +                          (flag_guess_branch_prob
> +                           ? "file %s not found, execution counts estimated\n"
> +                           : "file %s not found, execution counts assumed to "
> +                           "be zero\n"),
> +                          da_file_name);
> +       }
>        return NULL;
>      }
>    if (PARAM_VALUE (PARAM_PROFILE_FUNC_INTERNAL_ID))
> @@ -378,7 +382,9 @@ get_coverage_counts (unsigned counter, unsigned expected,
>                     "its profile data (counter %qs)", id, ctr_names[counter]);
>        if (warning_printed && dump_enabled_p ())
>         {
> -          dump_printf_loc (MSG_OPTIMIZED_LOCATIONS, input_location,
> +         dump_user_location_t loc
> +           = dump_user_location_t::from_location_t (input_location);
> +          dump_printf_loc (MSG_OPTIMIZED_LOCATIONS, loc,
>                             "use -Wno-error=coverage-mismatch to tolerate "
>                             "the mismatch but performance may drop if the "
>                             "function is hot\n");
> @@ -386,7 +392,7 @@ get_coverage_counts (unsigned counter, unsigned expected,
>           if (!seen_error ()
>               && !warned++)
>             {
> -             dump_printf_loc (MSG_OPTIMIZED_LOCATIONS, input_location,
> +             dump_printf_loc (MSG_OPTIMIZED_LOCATIONS, loc,
>                                 "coverage mismatch ignored\n");
>               dump_printf (MSG_OPTIMIZED_LOCATIONS,
>                             flag_guess_branch_prob
> 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 b06ea6e..7454ae5 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.
> @@ -416,7 +417,8 @@ Objective-C and Objective-C++ Dialects}.
>  -freorder-blocks-algorithm=@var{algorithm} @gol
>  -freorder-blocks-and-partition  -freorder-functions @gol
>  -frerun-cse-after-loop  -freschedule-modulo-scheduled-loops @gol
> --frounding-math  -fsched2-use-superblocks  -fsched-pressure @gol
> +-frounding-math  -fsave-optimization-record @gol
> +-fsched2-use-superblocks  -fsched-pressure @gol
>  -fsched-spec-load  -fsched-spec-load-dangerous @gol
>  -fsched-stalled-insns-dep[=@var{n}]  -fsched-stalled-insns[=@var{n}] @gol
>  -fsched-group-heuristic  -fsched-critical-path-heuristic @gol
> @@ -470,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
> @@ -9904,6 +9911,15 @@ Future versions of GCC may provide finer control of this setting
>  using C99's @code{FENV_ACCESS} pragma.  This command-line option
>  will be used to specify the default state for @code{FENV_ACCESS}.
>
> +@item -fsave-optimization-record
> +@opindex fsave-optimization-record
> +Write a SRCFILE.opt-record.json file detailing what optimizations
> +were performed.
> +FIXME: The precise format is not yet set in stone, but it ought
> +to be stabilized and then documented somewhere.
> +FIXME: should this be described here within the optimization options,
> +or within the developer options?
> +
>  @item -fsignaling-nans
>  @opindex fsignaling-nans
>  Compile code assuming that IEEE signaling NaNs may generate user-visible
> @@ -12037,6 +12053,71 @@ 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.
> +
> +Rather than attempting to parse the textual remark format, consider
> +using @option{-fsave-optimization-record}, which works from the same
> +data internally.
> +
> +@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/dump-context.h b/gcc/dump-context.h
> new file mode 100644
> index 0000000..2986317
> --- /dev/null
> +++ b/gcc/dump-context.h
> @@ -0,0 +1,112 @@
> +/* Support code for handling the various dump_* calls in dumpfile.h
> +   Copyright (C) 2018 Free Software Foundation, Inc.
> +
> +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_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 ();
> +
> + private:
> +  optinfo &ensure_pending_optinfo ();
> +  optinfo &begin_next_optinfo (const dump_location_t &loc);
> +  void end_any_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 class for use in selftests for temporarily using a different
> +   dump_context.  */
> +
> +class temp_dump_context
> +{
> + public:
> +  temp_dump_context (bool new_flag_remarks);
> +  ~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 2f11284..3be4af5 100644
> --- a/gcc/dumpfile.c
> +++ b/gcc/dumpfile.c
> @@ -29,6 +29,16 @@ along with GCC; see the file COPYING3.  If not see
>  #include "profile-count.h"
>  #include "tree-cfg.h"
>  #include "langhooks.h"
> +#include "optinfo.h"
> +#include "cgraph.h" /* for selftests.  */
> +#include "optinfo-emit-json.h"
> +#include "optinfo-internal.h" /* for selftests.  */
> +#include "backend.h"
> +#include "gimple.h" /* for dump_user_location_t ctor.  */
> +#include "rtl.h" /* for dump_user_location_t ctor.  */
> +#include "dump-context.h"
> +#include "tree-pass.h" /* for "current_pass".  */
> +#include "selftest.h"
>
>  /* If non-NULL, return one past-the-end of the matching SUBPART of
>     the WHOLE string.  */
> @@ -36,18 +46,52 @@ along with GCC; see the file COPYING3.  If not see
>     (strncmp (whole, part, strlen (part)) ? NULL : whole + strlen (part))
>
>  static dump_flags_t pflags;                  /* current dump_flags */
> -static dump_flags_t alt_flags;               /* current opt_info flags */
>
>  static void dump_loc (dump_flags_t, FILE *, source_location);
> +
> +/* Current -fopt-info output stream, if any, and flags.  */
> +static FILE *alt_dump_file = NULL;
> +static dump_flags_t alt_flags;
> +
>  static FILE *dump_open_alternate_stream (struct dump_file_info *);
>
>  /* These are currently used for communicating between passes.
>     However, instead of accessing them directly, the passes can use
>     dump_printf () for dumps.  */
>  FILE *dump_file = NULL;
> -FILE *alt_dump_file = NULL;
>  const char *dump_file_name;
>  dump_flags_t dump_flags;
> +bool dumps_are_enabled = false;
> +
> +
> +/* Update the "dumps_are_enabled" global; to be called whenever dump_file
> +   or alt_dump_file change.  */
> +
> +static void
> +refresh_dumps_are_enabled ()
> +{
> +  dumps_are_enabled = (dump_file || alt_dump_file || optinfo_enabled_p ());
> +}
> +
> +/* Set global "dump_file" to NEW_DUMP_FILE, refreshing the "dumps_are_enabled"
> +   global.  */
> +
> +void
> +set_dump_file (FILE *new_dump_file)
> +{
> +  dump_file = new_dump_file;
> +  refresh_dumps_are_enabled ();
> +}
> +
> +/* Set "alt_dump_file" to NEW_ALT_DUMP_FILE, refreshing the "dumps_are_enabled"
> +   global.  */
> +
> +static void
> +set_alt_dump_file (FILE *new_alt_dump_file)
> +{
> +  alt_dump_file = new_alt_dump_file;
> +  refresh_dumps_are_enabled ();
> +}
>
>  #define DUMP_FILE_INFO(suffix, swtch, dkind, num) \
>    {suffix, swtch, NULL, NULL, NULL, NULL, NULL, dkind, TDF_NONE, TDF_NONE, \
> @@ -74,14 +118,6 @@ static struct dump_file_info dump_files[TDI_end] =
>    DUMP_FILE_INFO (NULL, "ipa-all", DK_ipa, 0),
>  };
>
> -/* Define a name->number mapping for a dump flag value.  */
> -template <typename ValueType>
> -struct kv_pair
> -{
> -  const char *const name;      /* the name of the value */
> -  const ValueType value;       /* the value of the name */
> -};
> -
>  /* Table of dump options. This must be consistent with the TDF_* flags
>     in dumpfile.h and opt_info_options below. */
>  static const kv_pair<dump_flags_t> dump_options[] =
> @@ -132,7 +168,7 @@ static const kv_pair<dump_flags_t> optinfo_verbosity_options[] =
>  };
>
>  /* Flags used for -fopt-info groups.  */
> -static const kv_pair<optgroup_flags_t> optgroup_options[] =
> +const kv_pair<optgroup_flags_t> optgroup_options[] =
>  {
>    {"ipa", OPTGROUP_IPA},
>    {"loop", OPTGROUP_LOOP},
> @@ -358,9 +394,53 @@ dump_open_alternate_stream (struct dump_file_info *dfi)
>    return stream;
>  }
>
> +/* Implementation of "structured dumping API".  */
> +
> +/* Construct a dump_user_location_t from STMT (using its location and
> +   hotness).  */
> +
> +dump_user_location_t::dump_user_location_t (gimple *stmt)
> +: m_count (), m_loc (UNKNOWN_LOCATION)
> +{
> +  if (stmt)
> +    {
> +      if (stmt->bb)
> +       m_count = stmt->bb->count;
> +      m_loc = gimple_location (stmt);
> +    }
> +}
> +
> +/* Construct a dump_user_location_t from an RTL instruction (using its
> +   location and hotness).  */
> +dump_user_location_t::dump_user_location_t (rtx_insn *insn)
> +: m_count (), m_loc (UNKNOWN_LOCATION)
> +{
> +  if (insn)
> +    {
> +      basic_block bb = BLOCK_FOR_INSN (insn);
> +      if (bb)
> +       m_count = bb->count;
> +      m_loc = INSN_LOCATION (insn);
> +    }
> +}
> +
> +/* Construct from a function declaration.  This one requires spelling out
> +   to avoid accidentally constructing from other kinds of tree.  */
> +
> +dump_user_location_t
> +dump_user_location_t::from_function_decl (tree fndecl)
> +{
> +  gcc_assert (fndecl);
> +
> +  // FIXME: profile count for function?
> +  return dump_user_location_t (profile_count (),
> +                              DECL_SOURCE_LOCATION (fndecl));
> +}
> +
> +
>  /* Print source location on DFILE if enabled.  */
>
> -void
> +static void
>  dump_loc (dump_flags_t dump_kind, FILE *dfile, source_location loc)
>  {
>    if (dump_kind)
> @@ -373,137 +453,363 @@ dump_loc (dump_flags_t dump_kind, FILE *dfile, source_location loc)
>                   DECL_SOURCE_FILE (current_function_decl),
>                   DECL_SOURCE_LINE (current_function_decl),
>                   DECL_SOURCE_COLUMN (current_function_decl));
> +      /* Indentation based on scope depth.  */
> +      fprintf (dfile, "%*s", get_dump_scope_depth (), "");
>      }
>  }
>
> +/* Implementation of dump_context methods.  */
> +
> +/* 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, source_location 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))
>      {
> -      dump_loc (dump_kind, dump_file, loc);
> +      dump_loc (dump_kind, dump_file, srcloc);
>        print_gimple_stmt (dump_file, gs, spc, dump_flags | extra_dump_flags);
>      }
>
>    if (alt_dump_file && (dump_kind & alt_flags))
>      {
> -      dump_loc (dump_kind, alt_dump_file, 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);
> +    }
> +}
>
> -/* Similar to dump_generic_expr, except additionally print the source
> -   location.  */
> +/* Output a formatted message using FORMAT on appropriate dump streams.  */
>
>  void
> -dump_generic_expr_loc (dump_flags_t dump_kind, source_location loc,
> -                      dump_flags_t extra_dump_flags, tree t)
> +dump_context::dump_printf_va (dump_flags_t dump_kind, const char *format,
> +                             va_list ap)
>  {
>    if (dump_file && (dump_kind & pflags))
>      {
> -      dump_loc (dump_kind, dump_file, loc);
> -      print_generic_expr (dump_file, t, dump_flags | extra_dump_flags);
> +      va_list aq;
> +      va_copy (aq, ap);
> +      vfprintf (dump_file, format, aq);
> +      va_end (aq);
>      }
>
>    if (alt_dump_file && (dump_kind & alt_flags))
>      {
> -      dump_loc (dump_kind, alt_dump_file, loc);
> -      print_generic_expr (alt_dump_file, t, dump_flags | extra_dump_flags);
> +      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);
>      }
>  }
>
> -/* Output a formatted message using FORMAT on appropriate dump streams.  */
> +/* Similar to dump_printf, except source location is also printed, and
> +   dump location captured.  */
>
>  void
> -dump_printf (dump_flags_t dump_kind, 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;
> -      va_start (ap, format);
> -      vfprintf (dump_file, format, ap);
> -      va_end (ap);
> +      dump_loc (dump_kind, dump_file, srcloc);
> +      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);
> +      dump_loc (dump_kind, alt_dump_file, srcloc);
> +      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);
>      }
>  }
>
> -/* Similar to dump_printf, except source location is also printed.  */
> +/* Output VALUE in decimal to appropriate dump streams.  */
>
> +template<unsigned int N, typename C>
>  void
> -dump_printf_loc (dump_flags_t dump_kind, source_location loc,
> -                const char *format, ...)
> +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;
>    if (dump_file && (dump_kind & pflags))
> +    print_dec (value, dump_file, sgn);
> +
> +  if (alt_dump_file && (dump_kind & alt_flags))
> +    print_dec (value, alt_dump_file, sgn);
> +
> +  if (optinfo_enabled_p ())
>      {
> -      va_list ap;
> -      dump_loc (dump_kind, dump_file, loc);
> -      va_start (ap, format);
> -      vfprintf (dump_file, format, ap);
> -      va_end (ap);
> +      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 ())
>      {
> -      va_list ap;
> -      dump_loc (dump_kind, alt_dump_file, loc);
> -      va_start (ap, format);
> -      vfprintf (alt_dump_file, format, ap);
> -      va_end (ap);
> +      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 remarks and -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.
> +   Push a "scope" opinfo 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--;
> +  optimization_records_maybe_pop_dump_scope ();
> +}
> +
> +/* 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 as a diagnostic remark or to optimization records as appropriate.  */
> +
> +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
> +   methods.  */
> +
> +/* 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);
> +}
> +
> +/* 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)
>  {
> -  STATIC_ASSERT (poly_coeff_traits<C>::signedness >= 0);
> -  signop sgn = poly_coeff_traits<C>::signedness ? SIGNED : UNSIGNED;
> -  if (dump_file && (dump_kind & pflags))
> -    print_dec (value, dump_file, sgn);
> -
> -  if (alt_dump_file && (dump_kind & alt_flags))
> -    print_dec (value, alt_dump_file, sgn);
> +  dump_context::get ().dump_dec (dump_kind, value);
>  }
>
>  template void dump_dec (dump_flags_t, const poly_uint16 &);
> @@ -512,6 +818,45 @@ 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 &);
>
> +/* Output the name of NODE on appropriate dump streams.  */
> +
> +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 remarks and -fopt-info (for showing nesting via indentation).  */
> +
> +unsigned int
> +get_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.
> +   Push a "scope" opinfo if optinfos are enabled.
> +   Increment the scope depth.  */
> +
> +void
> +dump_begin_scope (const char *name, const dump_location_t &loc)
> +{
> +  dump_context::get ().begin_scope (name, loc);
> +}
> +
> +/* Pop a nested dump scope.  */
> +
> +void
> +dump_end_scope ()
> +{
> +  dump_context::get ().end_scope ();
> +}
> +
> +/* End of implementation of "structured dumping API".  */
> +
>  /* Start a dump for PHASE. Store user-supplied dump flags in
>     *FLAG_PTR.  Return the number of streams opened.  Set globals
>     DUMP_FILE, and ALT_DUMP_FILE to point to the opened streams, and
> @@ -541,7 +886,7 @@ dump_start (int phase, dump_flags_t *flag_ptr)
>          }
>        free (name);
>        dfi->pstream = stream;
> -      dump_file = dfi->pstream;
> +      set_dump_file (dfi->pstream);
>        /* Initialize current dump flags. */
>        pflags = dfi->pflags;
>      }
> @@ -551,7 +896,7 @@ dump_start (int phase, dump_flags_t *flag_ptr)
>      {
>        dfi->alt_stream = stream;
>        count++;
> -      alt_dump_file = dfi->alt_stream;
> +      set_alt_dump_file (dfi->alt_stream);
>        /* Initialize current -fopt-info flags. */
>        alt_flags = dfi->alt_flags;
>      }
> @@ -582,8 +927,8 @@ dump_finish (int phase)
>
>    dfi->alt_stream = NULL;
>    dfi->pstream = NULL;
> -  dump_file = NULL;
> -  alt_dump_file = NULL;
> +  set_dump_file (NULL);
> +  set_alt_dump_file (NULL);
>    dump_flags = TDF_NONE;
>    alt_flags = TDF_NONE;
>    pflags = TDF_NONE;
> @@ -1021,6 +1366,7 @@ dump_basic_block (dump_flags_t dump_kind, basic_block bb, int indent)
>      dump_bb (dump_file, bb, indent, TDF_DETAILS);
>    if (alt_dump_file && (dump_kind & alt_flags))
>      dump_bb (alt_dump_file, bb, indent, TDF_DETAILS);
> +  // TODO: should this also write to optinfo?
>  }
>
>  /* Dump FUNCTION_DECL FN as tree dump PHASE.  */
> @@ -1059,3 +1405,179 @@ enable_rtl_dump_file (void)
>                             NULL);
>    return num_enabled > 0;
>  }
> +
> +#if CHECKING_P
> +
> +/* temp_dump_context's ctor.  Temporarily override the dump_context,
> +   and the value of "flag_remarks" (to forcibly enable optinfo-generation).  */
> +
> +temp_dump_context::temp_dump_context (bool new_flag_remarks)
> +: m_context (),
> +  m_saved (&dump_context ().get ()),
> +  m_saved_flag_remarks (flag_remarks)
> +{
> +  dump_context::s_current = &m_context;
> +  flag_remarks = new_flag_remarks;
> +}
> +
> +/* temp_dump_context's dtor.  Restore the saved values of dump_context and
> +   "flag_remarks".  */
> +
> +temp_dump_context::~temp_dump_context ()
> +{
> +  dump_context::s_current = m_saved;
> +  flag_remarks = m_saved_flag_remarks;
> +}
> +
> +namespace selftest {
> +
> +/* Verify that the dump_location_t constructor ca


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