On Tue, Jun 26, 2018 at 3:54 PM David Malcolm <[email protected]> wrote:
>
> On Mon, 2018-06-25 at 15:34 +0200, Richard Biener wrote:
> > On Wed, Jun 20, 2018 at 6:34 PM David Malcolm <[email protected]>
> > 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.
>
> Possibly. I attempted this in v1 of the patch, but it was mixed in with
> a bunch of other stuff. I'll have another go at doing this.
>
> > Oh, and all the if (optinfo_enable_p ()) stuff is for the followup
> > then, right?
>
> Yes.
>
> > 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.
>
> Thanks. I split out the location wrapping, and have committed it to
> trunk (r262149). It's not clear to me exactly what other parts you liked,
> so I'm going to try to split out more of the non-JSON bits in the
> hope that some parts are good enough as-is, and I'll post them for review
> as followups.
>
> For reference, here's what I've committed (I added some obvious changes
> to doc/optinfo.texi).
>
> > I think the *_REMARK stuff should get attention of the respective
> > maintainers - not sure what the difference between NOTE and REMARK
> > is ;)
>
> Me neither :) I think it might come down to "this is purely a debugging
> message for a pass maintainer" (MSG_NOTE) vs "this is a high-level thing
> that an advanced user want to see" (MSG_REMARK???).
>
> One idea that occurred to me: are we overusing dump_flags_t? It's a
> mixture of TDF_* bitfields (used by our internal dumps) plus MSG_*
> bitfields (used with -fopt-info). IIRC the only TDF_ bitfield that's
> ever used with the MSG_* bitfields is TDF_DETAILS. Might it make sense
> to split out the MSG_* bitfields into a different type (dump_level_t???)
> to reinforce this split? (and thus the dump_* entrypoints that don't take
> a FILE * would take this new type). I'm not sure if this is a good idea
> or not.
Making it even more complicated doesn't make it easier to use it
"correctly". So I'd rather try to simplify it. How passes use
TDF_DETAILS vs. non-details is already highly inconsistent. This
is why I liked the original optinfo work because it somehow made
user-interesting vs. developer-interesting with the same API
(and to the same dump-file). Just that MSG_NOTE is exposed to
users while I think it should be developer-only...
IMHO the TDF_ stuff should control things at the stmt/tree/BB level,
thus be IL specific flags while the MSG_ stuff should control
pass-specific dumping detail.
Richard.
> > Thanks and sorry again for the repeated delays...
> > Richard.
>
> Thanks
> Dave
>
> [...snip...]
>
> gcc/ChangeLog:
> * 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.
> * 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.
> * coverage.c (get_coverage_counts): Update calls to
> dump_printf_loc to pass in dump_location_t rather than a
> location_t.
> * doc/optinfo.texi (Dump types): Convert example of
> dump_printf_loc from taking "locus" to taking "insn". Update
> description of the "_loc" calls to cover dump_location_t.
> * dumpfile.c: Include "backend.h", "gimple.h", "rtl.h", and
> "selftest.h".
> (dump_user_location_t::dump_user_location_t): New constructors,
> from gimple *stmt and rtx_insn *.
> (dump_user_location_t::from_function_decl): New function.
> (dump_loc): Make static.
> (dump_gimple_stmt_loc): Convert param "loc" from location_t to
> const dump_location_t &.
> (dump_generic_expr_loc): Delete.
> (dump_printf_loc): Convert param "loc" from location_t to
> const dump_location_t &.
> (selftest::test_impl_location): New function.
> (selftest::dumpfile_c_tests): New function.
> * dumpfile.h: Include "profile-count.h".
> (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 &.
> * 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.
> * 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): Likewise.
> * 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.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.
> * 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.
> * selftest.h (dumpfile_c_tests): New decl.
> * tree-loop-distribution.c (pass_loop_distribution::execute):
> Update for change in return type of find_loop_location.
> * tree-parloops.c (parallelize_loops): Likewise.
> * 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-ssa-sccvn.c (eliminate_dom_walker::before_dom_children):
> Likewise.
> * 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.
> (try_vectorize_loop_1): Update for change in vect_location's type.
> (vectorize_loops): Likewise.
> (increase_alignment): Likewise.
> * tree-vectorizer.h (vect_location): Convert from source_location
> to dump_user_location_t.
> (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/cfgloop.c | 12 +--
> gcc/cfgloop.h | 2 +-
> gcc/cgraphunit.c | 3 +-
> gcc/coverage.c | 22 ++++--
> gcc/doc/optinfo.texi | 16 +++-
> gcc/dumpfile.c | 133 ++++++++++++++++++++++++++-------
> gcc/dumpfile.h | 156
> +++++++++++++++++++++++++++++++++++++--
> gcc/gimple-fold.c | 6 +-
> gcc/gimple-loop-interchange.cc | 4 +-
> 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/profile.c | 14 +++-
> gcc/selftest-run-tests.c | 1 +
> gcc/selftest.h | 1 +
> gcc/tree-loop-distribution.c | 2 +-
> gcc/tree-parloops.c | 3 +-
> 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 | 14 ++--
> gcc/tree-vectorizer.h | 8 +-
> gcc/value-prof.c | 15 ++--
> 32 files changed, 386 insertions(+), 153 deletions(-)
>
> 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/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/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/doc/optinfo.texi b/gcc/doc/optinfo.texi
> index 8c28501..6202802 100644
> --- a/gcc/doc/optinfo.texi
> +++ b/gcc/doc/optinfo.texi
> @@ -168,7 +168,7 @@ when any of the following flags is enabled
>
> @example
> int report_flags = MSG_OPTIMIZED_LOCATIONS | TDF_RTL | TDF_DETAILS;
> -dump_printf_loc (report_flags, locus,
> +dump_printf_loc (report_flags, insn,
> "loop turned into non-loop; it never loops.\n");
> @end example
>
> @@ -181,7 +181,19 @@ Output gimple statement.
>
> Note that the above methods also have variants prefixed with
> @code{_loc}, such as @code{dump_printf_loc}, which are similar except
> -they also output the source location information.
> +they also output the source location information. The @code{_loc} variants
> +take a @code{const dump_location_t &}. This class can be constructed from
> +a @code{gimple *} or from a @code{rtx_insn *}, and so callers can pass
> +a @code{gimple *} or a @code{rtx_insn *} as the @code{_loc} argument.
> +The @code{dump_location_t} constructor will extract the source location
> +from the statement or instruction, along with the profile count, and
> +the location in GCC's own source code (or the plugin) from which the dump
> +call was emitted. Only the source location is currently used.
> +There is also a @code{dump_user_location_t} class, capturing the
> +source location and profile count, but not the dump emission location,
> +so that locations in the user's code can be passed around. This
> +can also be constructed from a @code{gimple *} and from a @code{rtx_insn *},
> +and it too can be passed as the @code{_loc} argument.
>
> @end ftable
>
> diff --git a/gcc/dumpfile.c b/gcc/dumpfile.c
> index 2f11284..122e420 100644
> --- a/gcc/dumpfile.c
> +++ b/gcc/dumpfile.c
> @@ -29,6 +29,10 @@ along with GCC; see the file COPYING3. If not see
> #include "profile-count.h"
> #include "tree-cfg.h"
> #include "langhooks.h"
> +#include "backend.h" /* for gimple.h. */
> +#include "gimple.h" /* for dump_user_location_t ctor. */
> +#include "rtl.h" /* for dump_user_location_t ctor. */
> +#include "selftest.h"
>
> /* If non-NULL, return one past-the-end of the matching SUBPART of
> the WHOLE string. */
> @@ -358,9 +362,51 @@ dump_open_alternate_stream (struct dump_file_info *dfi)
> return stream;
> }
>
> +/* 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)
> @@ -393,18 +439,19 @@ dump_gimple_stmt (dump_flags_t dump_kind, dump_flags_t
> 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_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);
> }
> }
> @@ -423,27 +470,6 @@ dump_generic_expr (dump_flags_t dump_kind, dump_flags_t
> extra_dump_flags,
> print_generic_expr (alt_dump_file, t, dump_flags | extra_dump_flags);
> }
>
> -
> -/* Similar to dump_generic_expr, except additionally print the source
> - location. */
> -
> -void
> -dump_generic_expr_loc (dump_flags_t dump_kind, source_location loc,
> - dump_flags_t extra_dump_flags, tree t)
> -{
> - if (dump_file && (dump_kind & pflags))
> - {
> - dump_loc (dump_kind, dump_file, loc);
> - print_generic_expr (dump_file, t, dump_flags | extra_dump_flags);
> - }
> -
> - 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);
> - }
> -}
> -
> /* Output a formatted message using FORMAT on appropriate dump streams. */
>
> void
> @@ -469,13 +495,14 @@ dump_printf (dump_flags_t dump_kind, const char
> *format, ...)
> /* Similar to dump_printf, except source location is also printed. */
>
> void
> -dump_printf_loc (dump_flags_t dump_kind, source_location loc,
> +dump_printf_loc (dump_flags_t dump_kind, const dump_location_t &loc,
> const char *format, ...)
> {
> + location_t srcloc = loc.get_location_t ();
> if (dump_file && (dump_kind & pflags))
> {
> va_list ap;
> - dump_loc (dump_kind, dump_file, loc);
> + dump_loc (dump_kind, dump_file, srcloc);
> va_start (ap, format);
> vfprintf (dump_file, format, ap);
> va_end (ap);
> @@ -484,7 +511,7 @@ dump_printf_loc (dump_flags_t dump_kind, source_location
> loc,
> if (alt_dump_file && (dump_kind & alt_flags))
> {
> va_list ap;
> - dump_loc (dump_kind, alt_dump_file, loc);
> + dump_loc (dump_kind, alt_dump_file, srcloc);
> va_start (ap, format);
> vfprintf (alt_dump_file, format, ap);
> va_end (ap);
> @@ -1059,3 +1086,53 @@ enable_rtl_dump_file (void)
> NULL);
> return num_enabled > 0;
> }
> +
> +#if CHECKING_P
> +
> +namespace selftest {
> +
> +/* Verify that the dump_location_t constructors capture the source location
> + at which they were called (provided that the build compiler is
> sufficiently
> + recent). */
> +
> +static void
> +test_impl_location ()
> +{
> +#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8)
> + /* Default ctor. */
> + {
> + dump_location_t loc;
> + const int expected_line = __LINE__ - 1;
> + ASSERT_STR_CONTAINS (loc.get_impl_location ().m_file, "dumpfile.c");
> + ASSERT_EQ (loc.get_impl_location ().m_line, expected_line);
> + }
> +
> + /* Constructing from a gimple. */
> + {
> + dump_location_t loc ((gimple *)NULL);
> + const int expected_line = __LINE__ - 1;
> + ASSERT_STR_CONTAINS (loc.get_impl_location ().m_file, "dumpfile.c");
> + ASSERT_EQ (loc.get_impl_location ().m_line, expected_line);
> + }
> +
> + /* Constructing from an rtx_insn. */
> + {
> + dump_location_t loc ((rtx_insn *)NULL);
> + const int expected_line = __LINE__ - 1;
> + ASSERT_STR_CONTAINS (loc.get_impl_location ().m_file, "dumpfile.c");
> + ASSERT_EQ (loc.get_impl_location ().m_line, expected_line);
> + }
> +#endif
> +}
> +
> +/* Run all of the selftests within this file. */
> +
> +void
> +dumpfile_c_tests ()
> +{
> + test_impl_location ();
> +}
> +
> +} // namespace selftest
> +
> +#endif /* CHECKING_P */
> diff --git a/gcc/dumpfile.h b/gcc/dumpfile.h
> index f6ad670..90d8930 100644
> --- a/gcc/dumpfile.h
> +++ b/gcc/dumpfile.h
> @@ -21,6 +21,7 @@ along with GCC; see the file COPYING3. If not see
> #ifndef GCC_DUMPFILE_H
> #define GCC_DUMPFILE_H 1
>
> +#include "profile-count.h"
>
> /* Different tree dump places. When you add new tree dump places,
> extend the DUMP_FILES array in dumpfile.c. */
> @@ -268,20 +269,165 @@ struct dump_file_info
> bool graph_dump_initialized;
> };
>
> +/* A class for describing where in the user's source that a dump message
> + relates to, with various constructors for convenience.
> + In particular, this lets us associate dump messages
> + with hotness information (e.g. from PGO), allowing them to
> + be prioritized by code hotness. */
> +
> +class dump_user_location_t
> +{
> + public:
> + /* Default constructor, analogous to UNKNOWN_LOCATION. */
> + dump_user_location_t () : m_count (), m_loc (UNKNOWN_LOCATION) {}
> +
> + /* Construct from a gimple statement (using its location and hotness). */
> + dump_user_location_t (gimple *stmt);
> +
> + /* Construct from an RTL instruction (using its location and hotness). */
> + dump_user_location_t (rtx_insn *insn);
> +
> + /* Construct from a location_t. This one is deprecated (since it doesn't
> + capture hotness information); it thus needs to be spelled out. */
> + static dump_user_location_t
> + from_location_t (location_t loc)
> + {
> + return dump_user_location_t (profile_count (), loc);
> + }
> +
> + /* Construct from a function declaration. This one requires spelling out
> + to avoid accidentally constructing from other kinds of tree. */
> + static dump_user_location_t
> + from_function_decl (tree fndecl);
> +
> + profile_count get_count () const { return m_count; }
> + location_t get_location_t () const { return m_loc; }
> +
> + private:
> + /* Private ctor from count and location, for use by from_location_t. */
> + dump_user_location_t (profile_count count, location_t loc)
> + : m_count (count), m_loc (loc)
> + {}
> +
> + profile_count m_count;
> + location_t m_loc;
> +};
> +
> +/* A class for identifying where in the compiler's own source
> + (or a plugin) that a dump message is being emitted from. */
> +
> +struct dump_impl_location_t
> +{
> + dump_impl_location_t (
> +#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8)
> + const char *file = __builtin_FILE (),
> + int line = __builtin_LINE (),
> + const char *function = __builtin_FUNCTION ()
> +#else
> + const char *file = __FILE__,
> + int line = __LINE__,
> + const char *function = NULL
> +#endif
> + )
> + : m_file (file), m_line (line), m_function (function)
> + {}
> +
> + const char *m_file;
> + int m_line;
> + const char *m_function;
> +};
> +
> +/* A bundle of information for describing the location of a dump message:
> + (a) the source location and hotness within the user's code, together with
> + (b) the source location within the compiler/plugin.
> +
> + The constructors use default parameters so that (b) gets sets up
> + automatically.
> +
> + The upshot is that you can pass in e.g. a gimple * to dump_printf_loc,
> + and the dump call will automatically record where in GCC's source
> + code the dump was emitted from. */
> +
> +class dump_location_t
> +{
> + public:
> + /* Default constructor, analogous to UNKNOWN_LOCATION. */
> + dump_location_t (const dump_impl_location_t &impl_location
> + = dump_impl_location_t ())
> + : m_user_location (dump_user_location_t ()),
> + m_impl_location (impl_location)
> + {
> + }
> +
> + /* Construct from a gimple statement (using its location and hotness). */
> + dump_location_t (gimple *stmt,
> + const dump_impl_location_t &impl_location
> + = dump_impl_location_t ())
> + : m_user_location (dump_user_location_t (stmt)),
> + m_impl_location (impl_location)
> + {
> + }
> +
> + /* Construct from an RTL instruction (using its location and hotness). */
> + dump_location_t (rtx_insn *insn,
> + const dump_impl_location_t &impl_location
> + = dump_impl_location_t ())
> + : m_user_location (dump_user_location_t (insn)),
> + m_impl_location (impl_location)
> + {
> + }
> +
> + /* Construct from a dump_user_location_t. */
> + dump_location_t (const dump_user_location_t &user_location,
> + const dump_impl_location_t &impl_location
> + = dump_impl_location_t ())
> + : m_user_location (user_location),
> + m_impl_location (impl_location)
> + {
> + }
> +
> + /* Construct from a location_t. This one is deprecated (since it doesn't
> + capture hotness information), and thus requires spelling out. */
> + static dump_location_t
> + from_location_t (location_t loc,
> + const dump_impl_location_t &impl_location
> + = dump_impl_location_t ())
> + {
> + return dump_location_t (dump_user_location_t::from_location_t (loc),
> + impl_location);
> + }
> +
> + const dump_user_location_t &
> + get_user_location () const { return m_user_location; }
> +
> + const dump_impl_location_t &
> + get_impl_location () const { return m_impl_location; }
> +
> + location_t get_location_t () const
> + {
> + return m_user_location.get_location_t ();
> + }
> +
> + profile_count get_count () const { return m_user_location.get_count (); }
> +
> + private:
> + dump_user_location_t m_user_location;
> + dump_impl_location_t m_impl_location;
> +};
> +
> /* In dumpfile.c */
> 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, source_location,
> - const char *, ...) ATTRIBUTE_PRINTF_3;
> +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, source_location,
> 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, source_location,
> dump_flags_t,
> - gimple *, int);
> +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);
> diff --git a/gcc/gimple-fold.c b/gcc/gimple-fold.c
> index a01bce7..f12e4a7 100644
> --- a/gcc/gimple-fold.c
> +++ b/gcc/gimple-fold.c
> @@ -347,8 +347,7 @@ fold_gimple_assign (gimple_stmt_iterator *si)
> {
> if (dump_enabled_p ())
> {
> - location_t loc = gimple_location_safe (stmt);
> - dump_printf_loc (MSG_OPTIMIZED_LOCATIONS, loc,
> + dump_printf_loc (MSG_OPTIMIZED_LOCATIONS, stmt,
> "resolving virtual function address "
> "reference to function %s\n",
> targets.length () == 1
> @@ -4061,8 +4060,7 @@ gimple_fold_call (gimple_stmt_iterator *gsi, bool
> inplace)
> tree lhs = gimple_call_lhs (stmt);
> if (dump_enabled_p ())
> {
> - location_t loc = gimple_location_safe (stmt);
> - dump_printf_loc (MSG_OPTIMIZED_LOCATIONS, loc,
> + dump_printf_loc (MSG_OPTIMIZED_LOCATIONS, stmt,
> "folding virtual function call to %s\n",
> targets.length () == 1
> ? targets[0]->name ()
> diff --git a/gcc/gimple-loop-interchange.cc b/gcc/gimple-loop-interchange.cc
> index eb35263..08aeb8e 100644
> --- a/gcc/gimple-loop-interchange.cc
> +++ b/gcc/gimple-loop-interchange.cc
> @@ -523,7 +523,7 @@ loop_cand::analyze_iloop_reduction_var (tree var)
>
> /* Handle and verify a series of stmts feeding the reduction op. */
> if (single_use != next_def
> - && !check_reduction_path (UNKNOWN_LOCATION, m_loop, phi, next,
> + && !check_reduction_path (dump_user_location_t (), m_loop, phi, next,
> gimple_assign_rhs_code (single_use)))
> return false;
>
> @@ -1578,7 +1578,7 @@ bool
> tree_loop_interchange::interchange (vec<data_reference_p> datarefs,
> vec<ddr_p> ddrs)
> {
> - location_t loc = find_loop_location (m_loop_nest[0]);
> + dump_user_location_t loc = find_loop_location (m_loop_nest[0]);
> bool changed_p = false;
> /* In each iteration we try to interchange I-th loop with (I+1)-th loop.
> The overall effect is to push inner loop to outermost level in whole
> diff --git a/gcc/graphite-isl-ast-to-gimple.c
> b/gcc/graphite-isl-ast-to-gimple.c
> index b607b12..9e78465 100644
> --- a/gcc/graphite-isl-ast-to-gimple.c
> +++ b/gcc/graphite-isl-ast-to-gimple.c
> @@ -1409,7 +1409,7 @@ scop_to_isl_ast (scop_p scop)
> isl_ctx_set_max_operations (scop->isl_context, old_max_operations);
> if (isl_ctx_last_error (scop->isl_context) != isl_error_none)
> {
> - location_t loc = find_loop_location
> + dump_user_location_t loc = find_loop_location
> (scop->scop_info->region.entry->dest->loop_father);
> if (isl_ctx_last_error (scop->isl_context) == isl_error_quota)
> dump_printf_loc (MSG_MISSED_OPTIMIZATION, loc,
> @@ -1518,7 +1518,7 @@ graphite_regenerate_ast_isl (scop_p scop)
>
> if (t.codegen_error_p ())
> {
> - location_t loc = find_loop_location
> + dump_user_location_t loc = find_loop_location
> (scop->scop_info->region.entry->dest->loop_father);
> dump_printf_loc (MSG_MISSED_OPTIMIZATION, loc,
> "loop nest not optimized, code generation error\n");
> diff --git a/gcc/graphite-optimize-isl.c b/gcc/graphite-optimize-isl.c
> index 456a797..35e9ac0 100644
> --- a/gcc/graphite-optimize-isl.c
> +++ b/gcc/graphite-optimize-isl.c
> @@ -160,7 +160,7 @@ optimize_isl (scop_p scop)
> if (!scop->transformed_schedule
> || isl_ctx_last_error (scop->isl_context) != isl_error_none)
> {
> - location_t loc = find_loop_location
> + dump_user_location_t loc = find_loop_location
> (scop->scop_info->region.entry->dest->loop_father);
> if (isl_ctx_last_error (scop->isl_context) == isl_error_quota)
> dump_printf_loc (MSG_MISSED_OPTIMIZATION, loc,
> @@ -182,7 +182,7 @@ optimize_isl (scop_p scop)
>
> if (same_schedule)
> {
> - location_t loc = find_loop_location
> + dump_user_location_t loc = find_loop_location
> (scop->scop_info->region.entry->dest->loop_father);
> dump_printf_loc (MSG_NOTE, loc,
> "loop nest not optimized, optimized schedule is "
> diff --git a/gcc/graphite.c b/gcc/graphite.c
> index bcf4828..ddf16a8 100644
> --- a/gcc/graphite.c
> +++ b/gcc/graphite.c
> @@ -412,7 +412,7 @@ graphite_transform_loops (void)
> changed = true;
> if (graphite_regenerate_ast_isl (scop))
> {
> - location_t loc = find_loop_location
> + dump_user_location_t loc = find_loop_location
> (scops[i]->scop_info->region.entry->dest->loop_father);
> dump_printf_loc (MSG_OPTIMIZED_LOCATIONS, loc,
> "loop nest optimized\n");
> diff --git a/gcc/ipa-devirt.c b/gcc/ipa-devirt.c
> index 308b6e6..e99d8cc 100644
> --- a/gcc/ipa-devirt.c
> +++ b/gcc/ipa-devirt.c
> @@ -3755,8 +3755,7 @@ ipa_devirt (void)
> {
> if (dump_enabled_p ())
> {
> - location_t locus = gimple_location_safe (e->call_stmt);
> - dump_printf_loc (MSG_OPTIMIZED_LOCATIONS, locus,
> + dump_printf_loc (MSG_OPTIMIZED_LOCATIONS, e->call_stmt,
> "speculatively devirtualizing call "
> "in %s to %s\n",
> n->dump_name (),
> diff --git a/gcc/ipa-prop.c b/gcc/ipa-prop.c
> index 000c05f..8b19fe3 100644
> --- a/gcc/ipa-prop.c
> +++ b/gcc/ipa-prop.c
> @@ -2842,8 +2842,7 @@ ipa_make_edge_direct_to_target (struct cgraph_edge *ie,
> tree target,
> {
> if (dump_enabled_p ())
> {
> - location_t loc = gimple_location_safe (ie->call_stmt);
> - dump_printf_loc (MSG_OPTIMIZED_LOCATIONS, loc,
> + dump_printf_loc (MSG_OPTIMIZED_LOCATIONS, ie->call_stmt,
> "discovered direct call non-invariant
> %s\n",
> ie->caller->dump_name ());
> }
> @@ -2853,8 +2852,7 @@ ipa_make_edge_direct_to_target (struct cgraph_edge *ie,
> tree target,
>
> if (dump_enabled_p ())
> {
> - location_t loc = gimple_location_safe (ie->call_stmt);
> - dump_printf_loc (MSG_OPTIMIZED_LOCATIONS, loc,
> + dump_printf_loc (MSG_OPTIMIZED_LOCATIONS, ie->call_stmt,
> "discovered direct call to non-function in %s,
> "
> "making it __builtin_unreachable\n",
> ie->caller->dump_name ());
> @@ -2942,9 +2940,7 @@ ipa_make_edge_direct_to_target (struct cgraph_edge *ie,
> tree target,
> }
> if (dump_enabled_p ())
> {
> - location_t loc = gimple_location_safe (ie->call_stmt);
> -
> - dump_printf_loc (MSG_OPTIMIZED_LOCATIONS, loc,
> + dump_printf_loc (MSG_OPTIMIZED_LOCATIONS, ie->call_stmt,
> "converting indirect call in %s to direct call to
> %s\n",
> ie->caller->name (), callee->name ());
> }
> diff --git a/gcc/ipa.c b/gcc/ipa.c
> index 82fc334..3b6b5e5 100644
> --- a/gcc/ipa.c
> +++ b/gcc/ipa.c
> @@ -225,13 +225,8 @@ walk_polymorphic_call_targets (hash_set<void *>
> *reachable_call_targets,
> (builtin_decl_implicit (BUILT_IN_UNREACHABLE));
>
> if (dump_enabled_p ())
> - {
> - location_t locus;
> - if (edge->call_stmt)
> - locus = gimple_location (edge->call_stmt);
> - else
> - locus = UNKNOWN_LOCATION;
> - 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->dump_name (),
> target->dump_name ());
> diff --git a/gcc/loop-unroll.c b/gcc/loop-unroll.c
> index 5a03932..48bbda0 100644
> --- a/gcc/loop-unroll.c
> +++ b/gcc/loop-unroll.c
> @@ -189,7 +189,7 @@ static rtx get_expansion (struct var_to_expand *);
> appropriate given the dump or -fopt-info settings. */
>
> static void
> -report_unroll (struct loop *loop, location_t locus)
> +report_unroll (struct loop *loop, dump_location_t locus)
> {
> dump_flags_t report_flags = MSG_OPTIMIZED_LOCATIONS | TDF_DETAILS;
>
> @@ -220,7 +220,7 @@ decide_unrolling (int flags)
> FOR_EACH_LOOP (loop, LI_FROM_INNERMOST)
> {
> loop->lpt_decision.decision = LPT_NONE;
> - location_t locus = get_loop_location (loop);
> + dump_user_location_t locus = get_loop_location (loop);
>
> if (dump_enabled_p ())
> dump_printf_loc (MSG_NOTE, locus,
> diff --git a/gcc/omp-grid.c b/gcc/omp-grid.c
> index ffa301e..6edc92f 100644
> --- a/gcc/omp-grid.c
> +++ b/gcc/omp-grid.c
> @@ -91,7 +91,7 @@ struct grid_prop
> bool tiling;
> /* Location of the target construct for optimization information
> messages. */
> - location_t target_loc;
> + dump_user_location_t target_loc;
> /* The collapse clause of the involved loops. Collapse value of all of
> them
> must be the same for gridification to take place. */
> size_t collapse;
> @@ -177,10 +177,10 @@ grid_find_single_omp_among_assignments_1 (gimple_seq
> seq, grid_prop *grid,
> GRID_MISSED_MSG_PREFIX "%s construct "
> "contains multiple OpenMP constructs\n",
> name);
> - dump_printf_loc (MSG_NOTE, gimple_location (*ret),
> + dump_printf_loc (MSG_NOTE, *ret,
> "The first OpenMP construct within "
> "a parallel\n");
> - dump_printf_loc (MSG_NOTE, gimple_location (stmt),
> + dump_printf_loc (MSG_NOTE, stmt,
> "The second OpenMP construct within "
> "a parallel\n");
> }
> @@ -195,7 +195,7 @@ grid_find_single_omp_among_assignments_1 (gimple_seq seq,
> grid_prop *grid,
> dump_printf_loc (MSG_MISSED_OPTIMIZATION, grid->target_loc,
> GRID_MISSED_MSG_PREFIX "%s construct contains "
> "a complex statement\n", name);
> - dump_printf_loc (MSG_NOTE, gimple_location (stmt),
> + dump_printf_loc (MSG_NOTE, stmt,
> "This statement cannot be analyzed for "
> "gridification\n");
> }
> @@ -286,7 +286,7 @@ grid_find_ungridifiable_statement (gimple_stmt_iterator
> *gsi,
> loop that is evaluated for possible gridification. */
>
> static bool
> -grid_parallel_clauses_gridifiable (gomp_parallel *par, location_t tloc)
> +grid_parallel_clauses_gridifiable (gomp_parallel *par, dump_user_location_t
> tloc)
> {
> tree clauses = gimple_omp_parallel_clauses (par);
> while (clauses)
> @@ -300,7 +300,7 @@ grid_parallel_clauses_gridifiable (gomp_parallel *par,
> location_t tloc)
> GRID_MISSED_MSG_PREFIX "because there is "
> "a num_threads clause of the parallel "
> "construct\n");
> - dump_printf_loc (MSG_NOTE, gimple_location (par),
> + dump_printf_loc (MSG_NOTE, par,
> "Parallel construct has a num_threads
> clause\n");
> }
> return false;
> @@ -311,7 +311,7 @@ grid_parallel_clauses_gridifiable (gomp_parallel *par,
> location_t tloc)
> dump_printf_loc (MSG_MISSED_OPTIMIZATION, tloc,
> GRID_MISSED_MSG_PREFIX "a reduction clause "
> "is present\n ");
> - dump_printf_loc (MSG_NOTE, gimple_location (par),
> + dump_printf_loc (MSG_NOTE, par,
> "Parallel construct has a reduction clause\n");
> }
> return false;
> @@ -341,7 +341,7 @@ grid_inner_loop_gridifiable_p (gomp_for *gfor, grid_prop
> *grid)
> GRID_MISSED_MSG_PREFIX "the inner loop "
> "loop bounds computation contains a complex "
> "statement\n");
> - dump_printf_loc (MSG_NOTE, gimple_location (gfor),
> + dump_printf_loc (MSG_NOTE, gfor,
> "Loop construct cannot be analyzed for "
> "gridification\n");
> }
> @@ -361,7 +361,7 @@ grid_inner_loop_gridifiable_p (gomp_for *gfor, grid_prop
> *grid)
> dump_printf_loc (MSG_MISSED_OPTIMIZATION, grid->target_loc,
> GRID_MISSED_MSG_PREFIX "the inner loop "
> "has a non-automatic schedule clause\n");
> - dump_printf_loc (MSG_NOTE, gimple_location (gfor),
> + dump_printf_loc (MSG_NOTE, gfor,
> "Loop construct has a non automatic "
> "schedule clause\n");
> }
> @@ -375,7 +375,7 @@ grid_inner_loop_gridifiable_p (gomp_for *gfor, grid_prop
> *grid)
> dump_printf_loc (MSG_MISSED_OPTIMIZATION, grid->target_loc,
> GRID_MISSED_MSG_PREFIX "a reduction "
> "clause is present\n ");
> - dump_printf_loc (MSG_NOTE, gimple_location (gfor),
> + dump_printf_loc (MSG_NOTE, gfor,
> "Loop construct has a reduction schedule "
> "clause\n");
> }
> @@ -404,7 +404,7 @@ grid_inner_loop_gridifiable_p (gomp_for *gfor, grid_prop
> *grid)
> GRID_MISSED_MSG_PREFIX "the inner loop contains "
> "statement %s which cannot be transformed\n",
> gimple_code_name[(int) gimple_code (bad)]);
> - dump_printf_loc (MSG_NOTE, gimple_location (bad),
> + dump_printf_loc (MSG_NOTE, bad,
> "This statement cannot be analyzed for "
> "gridification\n");
> }
> @@ -422,7 +422,7 @@ grid_inner_loop_gridifiable_p (gomp_for *gfor, grid_prop
> *grid)
> static bool
> grid_dist_follows_simple_pattern (gomp_for *dist, grid_prop *grid)
> {
> - location_t tloc = grid->target_loc;
> + dump_user_location_t tloc = grid->target_loc;
> gimple *stmt = grid_find_single_omp_among_assignments (gimple_omp_body
> (dist),
> grid, "distribute");
> gomp_parallel *par;
> @@ -468,7 +468,7 @@ grid_gfor_follows_tiling_pattern (gomp_for *gfor,
> grid_prop *grid)
> dump_printf_loc (MSG_MISSED_OPTIMIZATION, grid->target_loc,
> GRID_MISSED_MSG_PREFIX "an inner loop is not "
> "a simple for loop\n");
> - dump_printf_loc (MSG_NOTE, gimple_location (gfor),
> + dump_printf_loc (MSG_NOTE, gfor,
> "This statement is not a simple for loop\n");
> }
> return false;
> @@ -484,7 +484,7 @@ grid_gfor_follows_tiling_pattern (gomp_for *gfor,
> grid_prop *grid)
> dump_printf_loc (MSG_MISSED_OPTIMIZATION, grid->target_loc,
> GRID_MISSED_MSG_PREFIX "an inner loop does not "
> "have use the same collapse clause\n");
> - dump_printf_loc (MSG_NOTE, gimple_location (gfor),
> + dump_printf_loc (MSG_NOTE, gfor,
> "Loop construct uses a different collapse
> clause\n");
> }
> return false;
> @@ -524,7 +524,7 @@ grid_gfor_follows_tiling_pattern (gomp_for *gfor,
> grid_prop *grid)
> dump_printf_loc (MSG_MISSED_OPTIMIZATION, grid->target_loc,
> GRID_MISSED_MSG_PREFIX "the distribute and "
> "an internal loop do not agree on tile
> size\n");
> - dump_printf_loc (MSG_NOTE, gimple_location (gfor),
> + dump_printf_loc (MSG_NOTE, gfor,
> "Loop construct does not seem to loop over "
> "a tile size\n");
> }
> @@ -636,7 +636,7 @@ grid_dist_follows_tiling_pattern (gimple_seq seq,
> grid_prop *grid,
> dump_printf_loc (MSG_MISSED_OPTIMIZATION, grid->target_loc,
> GRID_MISSED_MSG_PREFIX "the distribute "
> "construct contains a try..catch
> region\n");
> - dump_printf_loc (MSG_NOTE, gimple_location (try_stmt),
> + dump_printf_loc (MSG_NOTE, try_stmt,
> "This statement cannot be analyzed for "
> "tiled gridification\n");
> }
> @@ -661,7 +661,7 @@ grid_dist_follows_tiling_pattern (gimple_seq seq,
> grid_prop *grid,
> dump_printf_loc (MSG_MISSED_OPTIMIZATION, grid->target_loc,
> GRID_MISSED_MSG_PREFIX "the distribute "
> "construct contains a call\n");
> - dump_printf_loc (MSG_NOTE, gimple_location (stmt),
> + dump_printf_loc (MSG_NOTE, stmt,
> "This statement cannot be analyzed for "
> "tiled gridification\n");
> }
> @@ -677,7 +677,7 @@ grid_dist_follows_tiling_pattern (gimple_seq seq,
> grid_prop *grid,
> GRID_MISSED_MSG_PREFIX "a parallel "
> "construct contains another parallel "
> "construct\n");
> - dump_printf_loc (MSG_NOTE, gimple_location (stmt),
> + dump_printf_loc (MSG_NOTE, stmt,
> "This parallel construct is nested in "
> "another one\n");
> }
> @@ -698,7 +698,7 @@ grid_dist_follows_tiling_pattern (gimple_seq seq,
> grid_prop *grid,
> GRID_MISSED_MSG_PREFIX "a loop "
> "construct is not nested within a parallel
> "
> "construct\n");
> - dump_printf_loc (MSG_NOTE, gimple_location (stmt),
> + dump_printf_loc (MSG_NOTE, stmt,
> "This loop construct is not nested in "
> "a parallel construct\n");
> }
> @@ -714,7 +714,7 @@ grid_dist_follows_tiling_pattern (gimple_seq seq,
> grid_prop *grid,
> dump_printf_loc (MSG_MISSED_OPTIMIZATION, grid->target_loc,
> GRID_MISSED_MSG_PREFIX "the distribute "
> "construct contains a complex statement\n");
> - dump_printf_loc (MSG_NOTE, gimple_location (stmt),
> + dump_printf_loc (MSG_NOTE, stmt,
> "This statement cannot be analyzed for "
> "tiled gridification\n");
> }
> @@ -734,7 +734,7 @@ grid_target_follows_gridifiable_pattern (gomp_target
> *target, grid_prop *grid)
> if (gimple_omp_target_kind (target) != GF_OMP_TARGET_KIND_REGION)
> return false;
>
> - location_t tloc = gimple_location (target);
> + dump_user_location_t tloc = target;
> grid->target_loc = tloc;
> gimple *stmt
> = grid_find_single_omp_among_assignments (gimple_omp_body (target),
> @@ -1257,14 +1257,13 @@ grid_attempt_target_gridification (gomp_target
> *target,
> gbind *tgt_bind)
> {
> /* removed group_size */
> - grid_prop grid;
> - memset (&grid, 0, sizeof (grid));
> + grid_prop grid = {};
> if (!target || !grid_target_follows_gridifiable_pattern (target, &grid))
> return;
>
> location_t loc = gimple_location (target);
> if (dump_enabled_p ())
> - dump_printf_loc (MSG_OPTIMIZED_LOCATIONS, loc,
> + dump_printf_loc (MSG_OPTIMIZED_LOCATIONS, target,
> "Target construct will be turned into a gridified HSA "
> "kernel\n");
>
> diff --git a/gcc/profile.c b/gcc/profile.c
> index 8ba6dc7..0cd0270 100644
> --- a/gcc/profile.c
> +++ b/gcc/profile.c
> @@ -447,9 +447,14 @@ read_profile_edge_counts (gcov_type *exec_counts)
> {
> static bool informed = 0;
> if (dump_enabled_p () && !informed)
> - dump_printf_loc (MSG_NOTE, input_location,
> - "corrupted profile info: edge
> count"
> - " exceeds maximal count\n");
> + {
> + dump_location_t loc
> + = dump_location_t::from_location_t
> + (input_location);
> + dump_printf_loc (MSG_NOTE, loc,
> + "corrupted profile info: edge
> count"
> + " exceeds maximal count\n");
> + }
> informed = 1;
> }
> else
> @@ -672,7 +677,8 @@ compute_branch_probabilities (unsigned cfg_checksum,
> unsigned lineno_checksum)
> if (dump_enabled_p () && informed == 0)
> {
> informed = 1;
> - dump_printf_loc (MSG_NOTE, input_location,
> + dump_printf_loc (MSG_NOTE,
> + dump_location_t::from_location_t
> (input_location),
> "correcting inconsistent profile data\n");
> }
> correct_negative_edge_counts ();
> diff --git a/gcc/selftest-run-tests.c b/gcc/selftest-run-tests.c
> index fe221ff..a9aacc02 100644
> --- a/gcc/selftest-run-tests.c
> +++ b/gcc/selftest-run-tests.c
> @@ -59,6 +59,7 @@ selftest::run_tests ()
> /* Low-level data structures. */
> bitmap_c_tests ();
> sbitmap_c_tests ();
> + dumpfile_c_tests ();
> et_forest_c_tests ();
> hash_map_tests_c_tests ();
> hash_set_tests_c_tests ();
> diff --git a/gcc/selftest.h b/gcc/selftest.h
> index fc47b2c..a5507cc 100644
> --- a/gcc/selftest.h
> +++ b/gcc/selftest.h
> @@ -188,6 +188,7 @@ extern void attribute_c_tests ();
> extern void bitmap_c_tests ();
> extern void diagnostic_c_tests ();
> extern void diagnostic_show_locus_c_tests ();
> +extern void dumpfile_c_tests ();
> extern void edit_context_c_tests ();
> extern void et_forest_c_tests ();
> extern void fibonacci_heap_c_tests ();
> diff --git a/gcc/tree-loop-distribution.c b/gcc/tree-loop-distribution.c
> index c6e0a60..1206614 100644
> --- a/gcc/tree-loop-distribution.c
> +++ b/gcc/tree-loop-distribution.c
> @@ -3117,7 +3117,7 @@ pass_loop_distribution::execute (function *fun)
> break;
>
> const char *str = loop->inner ? " nest" : "";
> - location_t loc = find_loop_location (loop);
> + dump_user_location_t loc = find_loop_location (loop);
> if (!cd)
> {
> calculate_dominance_info (CDI_DOMINATORS);
> diff --git a/gcc/tree-parloops.c b/gcc/tree-parloops.c
> index c49f032..e79a954 100644
> --- a/gcc/tree-parloops.c
> +++ b/gcc/tree-parloops.c
> @@ -3286,7 +3286,6 @@ parallelize_loops (bool oacc_kernels_p)
> struct tree_niter_desc niter_desc;
> struct obstack parloop_obstack;
> HOST_WIDE_INT estimated;
> - source_location loop_loc;
>
> /* Do not parallelize loops in the functions created by parallelization.
> */
> if (!oacc_kernels_p
> @@ -3411,7 +3410,7 @@ parallelize_loops (bool oacc_kernels_p)
> changed = true;
> skip_loop = loop->inner;
>
> - loop_loc = find_loop_location (loop);
> + dump_user_location_t loop_loc = find_loop_location (loop);
> if (loop->inner)
> dump_printf_loc (MSG_OPTIMIZED_LOCATIONS, loop_loc,
> "parallelizing outer loop %d\n", loop->num);
> diff --git a/gcc/tree-ssa-loop-ivcanon.c b/gcc/tree-ssa-loop-ivcanon.c
> index 24bf60e..5f741c3 100644
> --- a/gcc/tree-ssa-loop-ivcanon.c
> +++ b/gcc/tree-ssa-loop-ivcanon.c
> @@ -691,7 +691,7 @@ try_unroll_loop_completely (struct loop *loop,
> edge exit, tree niter, bool may_be_zero,
> enum unroll_level ul,
> HOST_WIDE_INT maxiter,
> - location_t locus, bool allow_peel)
> + dump_user_location_t locus, bool allow_peel)
> {
> unsigned HOST_WIDE_INT n_unroll = 0;
> bool n_unroll_found = false;
> @@ -1162,7 +1162,7 @@ canonicalize_loop_induction_variables (struct loop
> *loop,
> tree niter;
> HOST_WIDE_INT maxiter;
> bool modified = false;
> - location_t locus = UNKNOWN_LOCATION;
> + dump_user_location_t locus;
> struct tree_niter_desc niter_desc;
> bool may_be_zero = false;
>
> @@ -1177,7 +1177,7 @@ canonicalize_loop_induction_variables (struct loop
> *loop,
> = niter_desc.may_be_zero && !integer_zerop (niter_desc.may_be_zero);
> }
> if (TREE_CODE (niter) == INTEGER_CST)
> - locus = gimple_location (last_stmt (exit->src));
> + locus = last_stmt (exit->src);
> else
> {
> /* For non-constant niter fold may_be_zero into niter again. */
> @@ -1204,7 +1204,7 @@ canonicalize_loop_induction_variables (struct loop
> *loop,
> niter = find_loop_niter_by_eval (loop, &exit);
>
> if (exit)
> - locus = gimple_location (last_stmt (exit->src));
> + locus = last_stmt (exit->src);
>
> if (TREE_CODE (niter) != INTEGER_CST)
> exit = NULL;
> diff --git a/gcc/tree-ssa-loop-ivopts.c b/gcc/tree-ssa-loop-ivopts.c
> index 519649a..6b445bd 100644
> --- a/gcc/tree-ssa-loop-ivopts.c
> +++ b/gcc/tree-ssa-loop-ivopts.c
> @@ -7535,7 +7535,7 @@ tree_ssa_iv_optimize_loop (struct ivopts_data *data,
> struct loop *loop)
>
> gcc_assert (!data->niters);
> data->current_loop = loop;
> - data->loop_loc = find_loop_location (loop);
> + data->loop_loc = find_loop_location (loop).get_location_t ();
> data->speed = optimize_loop_for_speed_p (loop);
>
> if (dump_file && (dump_flags & TDF_DETAILS))
> diff --git a/gcc/tree-ssa-loop-niter.c b/gcc/tree-ssa-loop-niter.c
> index f5ffc0f..03588a0 100644
> --- a/gcc/tree-ssa-loop-niter.c
> +++ b/gcc/tree-ssa-loop-niter.c
> @@ -2627,7 +2627,7 @@ number_of_iterations_exit (struct loop *loop, edge exit,
> return true;
>
> if (warn)
> - dump_printf_loc (MSG_MISSED_OPTIMIZATION, gimple_location_safe (stmt),
> + dump_printf_loc (MSG_MISSED_OPTIMIZATION, stmt,
> "missed loop optimization: niters analysis ends up "
> "with assumptions.\n");
>
> diff --git a/gcc/tree-ssa-sccvn.c b/gcc/tree-ssa-sccvn.c
> index 3d025c2..e5eddf9 100644
> --- a/gcc/tree-ssa-sccvn.c
> +++ b/gcc/tree-ssa-sccvn.c
> @@ -5866,8 +5866,7 @@ eliminate_dom_walker::before_dom_children (basic_block
> b)
> fn = builtin_decl_implicit (BUILT_IN_UNREACHABLE);
> if (dump_enabled_p ())
> {
> - location_t loc = gimple_location (stmt);
> - dump_printf_loc (MSG_OPTIMIZED_LOCATIONS, loc,
> + dump_printf_loc (MSG_OPTIMIZED_LOCATIONS, stmt,
> "converting indirect call to "
> "function %s\n",
> lang_hooks.decl_printable_name (fn,
> 2));
> diff --git a/gcc/tree-vect-loop-manip.c b/gcc/tree-vect-loop-manip.c