On Thu, Jan 10, 2019 at 2:55 AM David Malcolm <[email protected]> wrote:
>
> PR tree-optimization/88763 reports difficulties in getting useful
> information from the log of tree-ssa-loop-unswitch.c.
>
> As work towards improving this, this patch eliminates all uses of
> dump_file from that source file, in favor of the dump API (to
> support -fopt-info* and -fsave-optimization-record).
>
> Doing so required adding a way to dump profile_probability instances,
> so the patch adds a profile_probability::dump overload for this.
>
> Successfully bootstrapped & regrtested on x86_64-pc-linux-gnu.
>
> OK for next stage 1?
OK.
Thanks,
Richard.
> gcc/ChangeLog:
> PR tree-optimization/88763
> * cfgloop.h (find_loop_location): Move decl to here.
> * profile-count.c (profile_probability::dump): Reimplement in
> terms of...
> (profile_probability::print): ...this new function, moving the
> body here, and porting from FILE * to pretty_printer *.
> (profile_probability::dump): New function.
> * profile-count.h (class dump_metadata_t): New forward decl.
> (profile_probability::print): New decl.
> (profile_probability::dump): New overloaded decl.
> * tree-ssa-loop-unswitch.c (tree_unswitch_single_loop): Port from
> fprintf to the dump_* API.
> (tree_unswitch_outer_loop): Likewise.
> (find_loop_guard): Likewise.
> (hoist_guard): Likewise.
> * tree-vectorizer.h (find_loop_location): Move from here to
> cfgloop.h.
> ---
> gcc/cfgloop.h | 3 +
> gcc/profile-count.c | 34 ++++++++---
> gcc/profile-count.h | 7 +++
> gcc/tree-ssa-loop-unswitch.c | 135
> ++++++++++++++++++++++++++-----------------
> gcc/tree-vectorizer.h | 1 -
> 5 files changed, 120 insertions(+), 60 deletions(-)
>
> diff --git a/gcc/cfgloop.h b/gcc/cfgloop.h
> index 2e93af3..c175dcb 100644
> --- a/gcc/cfgloop.h
> +++ b/gcc/cfgloop.h
> @@ -870,4 +870,7 @@ gcov_type_to_wide_int (gcov_type val)
>
> return widest_int::from_array (a, 2);
> }
> +
> +extern dump_user_location_t find_loop_location (struct loop *);
> +
> #endif /* GCC_CFGLOOP_H */
> diff --git a/gcc/profile-count.c b/gcc/profile-count.c
> index 8c58f86..eaad18d 100644
> --- a/gcc/profile-count.c
> +++ b/gcc/profile-count.c
> @@ -148,27 +148,47 @@ profile_count::stream_out (struct lto_output_stream *ob)
> void
> profile_probability::dump (FILE *f) const
> {
> + pretty_printer pp;
> + print (&pp);
> + fprintf (f, "%s", pp_formatted_text (&pp));
> +}
> +
> +/* Print THIS to the PP. */
> +
> +void
> +profile_probability::print (pretty_printer *pp) const
> +{
> if (!initialized_p ())
> - fprintf (f, "uninitialized");
> + pp_string (pp, "uninitialized");
> else
> {
> /* Make difference between 0.00 as a roundoff error and actual 0.
> Similarly for 1. */
> if (m_val == 0)
> - fprintf (f, "never");
> + pp_string (pp, "never");
> else if (m_val == max_probability)
> - fprintf (f, "always");
> + pp_string (pp, "always");
> else
> - fprintf (f, "%3.1f%%", (double)m_val * 100 / max_probability);
> + pp_scalar (pp, "%3.1f%%", (double)m_val * 100 / max_probability);
> if (m_quality == profile_adjusted)
> - fprintf (f, " (adjusted)");
> + pp_string (pp, " (adjusted)");
> else if (m_quality == profile_afdo)
> - fprintf (f, " (auto FDO)");
> + pp_string (pp, " (auto FDO)");
> else if (m_quality == profile_guessed)
> - fprintf (f, " (guessed)");
> + pp_string (pp, " (guessed)");
> }
> }
>
> +/* Dump THIS to the active dump destinations. */
> +
> +void
> +profile_probability::dump (const dump_metadata_t &metadata) const
> +{
> + pretty_printer pp;
> + print (&pp);
> + dump_printf (metadata, "%s", pp_formatted_text (&pp));
> +}
> +
> /* Dump THIS to stderr. */
>
> void
> diff --git a/gcc/profile-count.h b/gcc/profile-count.h
> index 96b7400..a761836 100644
> --- a/gcc/profile-count.h
> +++ b/gcc/profile-count.h
> @@ -23,6 +23,7 @@ along with GCC; see the file COPYING3. If not see
>
> struct function;
> class profile_count;
> +class dump_metadata_t;
>
> /* Quality of the profile count. Because gengtype does not support enums
> inside of classes, this is in global namespace. */
> @@ -561,6 +562,12 @@ public:
> /* Output THIS to F. */
> void dump (FILE *f) const;
>
> + /* Output THIS to the active dump destinations. */
> + void dump (const dump_metadata_t &) const;
> +
> + /* Write THIS to PP. */
> + void print (pretty_printer *pp) const;
> +
> /* Print THIS to stderr. */
> void debug () const;
>
> diff --git a/gcc/tree-ssa-loop-unswitch.c b/gcc/tree-ssa-loop-unswitch.c
> index 30a2a9d..3fdbc57 100644
> --- a/gcc/tree-ssa-loop-unswitch.c
> +++ b/gcc/tree-ssa-loop-unswitch.c
> @@ -281,8 +281,10 @@ tree_unswitch_single_loop (struct loop *loop, int num)
> /* Do not unswitch in cold regions. */
> if (optimize_loop_for_size_p (loop))
> {
> - if (dump_file && (dump_flags & TDF_DETAILS))
> - fprintf (dump_file, ";; Not unswitching cold loops\n");
> + if (dump_enabled_p ())
> + dump_printf_loc (MSG_MISSED_OPTIMIZATION | TDF_DETAILS,
> + find_loop_location (loop),
> + ";; Not unswitching cold loops\n");
> return false;
> }
>
> @@ -290,8 +292,10 @@ tree_unswitch_single_loop (struct loop *loop, int num)
> if (tree_num_loop_insns (loop, &eni_size_weights)
> > (unsigned) PARAM_VALUE (PARAM_MAX_UNSWITCH_INSNS))
> {
> - if (dump_file && (dump_flags & TDF_DETAILS))
> - fprintf (dump_file, ";; Not unswitching, loop too big\n");
> + if (dump_enabled_p ())
> + dump_printf_loc (MSG_MISSED_OPTIMIZATION | TDF_DETAILS,
> + find_loop_location (loop),
> + ";; Not unswitching, loop too big\n");
> return false;
> }
>
> @@ -302,9 +306,11 @@ tree_unswitch_single_loop (struct loop *loop, int num)
> iterations = likely_max_loop_iterations_int (loop);
> if (iterations >= 0 && iterations <= 1)
> {
> - if (dump_file && (dump_flags & TDF_DETAILS))
> - fprintf (dump_file, ";; Not unswitching, loop is not expected"
> - " to iterate\n");
> + if (dump_enabled_p ())
> + dump_printf_loc (MSG_MISSED_OPTIMIZATION | TDF_DETAILS,
> + find_loop_location (loop),
> + ";; Not unswitching, loop is not expected"
> + " to iterate\n");
> return false;
> }
> }
> @@ -322,10 +328,11 @@ tree_unswitch_single_loop (struct loop *loop, int num)
>
> if (i == loop->num_nodes)
> {
> - if (dump_file
> - && num > PARAM_VALUE (PARAM_MAX_UNSWITCH_LEVEL)
> - && (dump_flags & TDF_DETAILS))
> - fprintf (dump_file, ";; Not unswitching anymore, hit max
> level\n");
> + if (dump_enabled_p ())
> + if (num > PARAM_VALUE (PARAM_MAX_UNSWITCH_LEVEL))
> + dump_printf_loc (MSG_MISSED_OPTIMIZATION | TDF_DETAILS,
> + find_loop_location (loop),
> + ";; Not unswitching anymore, hit max level\n");
>
> if (found == loop->num_nodes)
> {
> @@ -447,8 +454,10 @@ tree_unswitch_single_loop (struct loop *loop, int num)
> }
> }
>
> - if (dump_file && (dump_flags & TDF_DETAILS))
> - fprintf (dump_file, ";; Unswitching loop\n");
> + if (dump_enabled_p ())
> + dump_printf_loc (MSG_OPTIMIZED_LOCATIONS | TDF_DETAILS,
> + find_loop_location (loop),
> + ";; Unswitching loop\n");
>
> initialize_original_copy_tables ();
> /* Unswitch the loop on this condition. */
> @@ -522,9 +531,11 @@ tree_unswitch_outer_loop (struct loop *loop)
> iterations = likely_max_loop_iterations_int (loop);
> if (iterations >= 0 && iterations <= 1)
> {
> - if (dump_file && (dump_flags & TDF_DETAILS))
> - fprintf (dump_file, ";; Not unswitching, loop is not expected"
> - " to iterate\n");
> + if (dump_enabled_p ())
> + dump_printf_loc (MSG_MISSED_OPTIMIZATION | TDF_DETAILS,
> + find_loop_location (loop),
> + ";; Not unswitching, loop is not expected"
> + " to iterate\n");
> return false;
> }
>
> @@ -629,22 +640,27 @@ find_loop_guard (struct loop *loop)
> if (!dominated_by_p (CDI_DOMINATORS, loop->inner->header,
> guard_edge == fe ? te->dest : fe->dest))
> {
> - if (dump_file && (dump_flags & TDF_DETAILS))
> - fprintf (dump_file, "Guard edge %d --> %d is not around the loop!\n",
> - guard_edge->src->index, guard_edge->dest->index);
> + if (dump_enabled_p ())
> + dump_printf_loc (MSG_MISSED_OPTIMIZATION | TDF_DETAILS,
> + find_loop_location (loop),
> + "Guard edge %d --> %d is not around the loop!\n",
> + guard_edge->src->index, guard_edge->dest->index);
> return NULL;
> }
> if (guard_edge->dest == loop->latch)
> {
> - if (dump_file && (dump_flags & TDF_DETAILS))
> - fprintf (dump_file, "Guard edge destination is loop latch.\n");
> + if (dump_enabled_p ())
> + dump_printf_loc (MSG_MISSED_OPTIMIZATION | TDF_DETAILS,
> + find_loop_location (loop),
> + "Guard edge destination is loop latch.\n");
> return NULL;
> }
>
> - if (dump_file && (dump_flags & TDF_DETAILS))
> - fprintf (dump_file,
> - "Considering guard %d -> %d in loop %d\n",
> - guard_edge->src->index, guard_edge->dest->index, loop->num);
> + if (dump_enabled_p ())
> + dump_printf_loc (MSG_NOTE | TDF_DETAILS, find_loop_location (loop),
> + "Considering guard %d -> %d in loop %d\n",
> + guard_edge->src->index, guard_edge->dest->index,
> + loop->num);
> /* Check if condition operands do not have definitions inside loop since
> any bb copying is not performed. */
> FOR_EACH_SSA_TREE_OPERAND (use, cond, iter, SSA_OP_USE)
> @@ -654,9 +670,10 @@ find_loop_guard (struct loop *loop)
> if (def_bb
> && flow_bb_inside_loop_p (loop, def_bb))
> {
> - if (dump_file && (dump_flags & TDF_DETAILS))
> - fprintf (dump_file, " guard operands have definitions"
> - " inside loop\n");
> + if (dump_enabled_p ())
> + dump_printf_loc (MSG_MISSED_OPTIMIZATION | TDF_DETAILS, def,
> + " guard operands have definitions"
> + " inside loop\n");
> return NULL;
> }
> }
> @@ -669,23 +686,28 @@ find_loop_guard (struct loop *loop)
> continue;
> if (bb->flags & BB_IRREDUCIBLE_LOOP)
> {
> - if (dump_file && (dump_flags & TDF_DETAILS))
> - fprintf (dump_file, "Block %d is marked as irreducible in loop\n",
> - bb->index);
> + if (dump_enabled_p ())
> + dump_printf_loc (MSG_MISSED_OPTIMIZATION | TDF_DETAILS,
> + find_loop_location (loop),
> + "Block %d is marked as irreducible in loop\n",
> + bb->index);
> guard_edge = NULL;
> goto end;
> }
> if (!empty_bb_without_guard_p (loop, bb))
> {
> - if (dump_file && (dump_flags & TDF_DETAILS))
> - fprintf (dump_file, " block %d has side effects\n", bb->index);
> + if (dump_enabled_p ())
> + dump_printf_loc (MSG_MISSED_OPTIMIZATION | TDF_DETAILS,
> + find_loop_location (loop),
> + " block %d has side effects\n", bb->index);
> guard_edge = NULL;
> goto end;
> }
> }
>
> - if (dump_file && (dump_flags & TDF_DETAILS))
> - fprintf (dump_file, " suitable to hoist\n");
> + if (dump_enabled_p ())
> + dump_printf_loc (MSG_NOTE | TDF_DETAILS, find_loop_location (loop),
> + " suitable to hoist\n");
> end:
> if (body)
> free (body);
> @@ -824,13 +846,15 @@ hoist_guard (struct loop *loop, edge guard)
> update_stmt (cond_stmt);
> /* Create new loop pre-header. */
> e = split_block (pre_header, last_stmt (pre_header));
> - if (dump_file && (dump_flags & TDF_DETAILS))
> + if (dump_enabled_p ())
> {
> - fprintf (dump_file, " Moving guard %i->%i (prob ",
> - guard->src->index, guard->dest->index);
> - guard->probability.dump (dump_file);
> - fprintf (dump_file, ") to bb %i, new preheader is %i\n",
> - e->src->index, e->dest->index);
> + dump_printf_loc (MSG_NOTE | TDF_DETAILS, cond_stmt,
> + " Moving guard %i->%i (prob ",
> + guard->src->index, guard->dest->index);
> + guard->probability.dump (MSG_NOTE | TDF_DETAILS);
> + dump_printf (MSG_NOTE | TDF_DETAILS,
> + ") to bb %i, new preheader is %i\n",
> + e->src->index, e->dest->index);
> }
>
> gcc_assert (loop_preheader_edge (loop)->src == e->dest);
> @@ -859,14 +883,17 @@ hoist_guard (struct loop *loop, edge guard)
>
> if (skip_count > e->count ())
> {
> - fprintf (dump_file, " Capping count; expect profile inconsistency\n");
> + if (dump_enabled_p ())
> + dump_printf_loc (MSG_NOTE | TDF_DETAILS, cond_stmt,
> + " Capping count; expect profile inconsistency\n");
> skip_count = e->count ();
> }
> - if (dump_file && (dump_flags & TDF_DETAILS))
> + if (dump_enabled_p ())
> {
> - fprintf (dump_file, " Estimated probability of skipping loop is ");
> - new_edge->probability.dump (dump_file);
> - fprintf (dump_file, "\n");
> + dump_printf_loc (MSG_NOTE | TDF_DETAILS, cond_stmt,
> + " Estimated probability of skipping loop is ");
> + new_edge->probability.dump (MSG_NOTE | TDF_DETAILS);
> + dump_printf (MSG_NOTE | TDF_DETAILS, "\n");
> }
>
> /* Update profile after the transform:
> @@ -885,19 +912,22 @@ hoist_guard (struct loop *loop, edge guard)
> where profile does not change. */
> basic_block *body = get_loop_body (loop);
>
> - if (dump_file && (dump_flags & TDF_DETAILS))
> - fprintf (dump_file, " Scaling nonguarded BBs in loop:");
> + if (dump_enabled_p ())
> + dump_printf_loc (MSG_NOTE | TDF_DETAILS, find_loop_location (loop),
> + " Scaling nonguarded BBs in loop:");
> for (unsigned int i = 0; i < loop->num_nodes; i++)
> {
> basic_block bb = body[i];
> if (!dominated_by_p (CDI_DOMINATORS, bb, not_guard->dest))
> {
> - if (dump_file && (dump_flags & TDF_DETAILS))
> - fprintf (dump_file, " %i", bb->index);
> + if (dump_enabled_p ())
> + dump_printf (MSG_NOTE | TDF_DETAILS, " %i", bb->index);
> if (e->probability.initialized_p ())
> scale_bbs_frequencies (&bb, 1, e->probability);
> }
> }
> + if (dump_enabled_p ())
> + dump_printf (MSG_NOTE | TDF_DETAILS, "\n");
>
> if (fix_dom_of_exit)
> set_immediate_dominator (CDI_DOMINATORS, exit->dest, pre_header);
> @@ -924,8 +954,9 @@ hoist_guard (struct loop *loop, edge guard)
> }
> }
>
> - if (dump_file && (dump_flags & TDF_DETAILS))
> - fprintf (dump_file, "\n guard hoisted.\n");
> + if (dump_enabled_p ())
> + dump_printf_loc (MSG_OPTIMIZED_LOCATIONS | TDF_DETAILS,
> + cond_stmt, " guard hoisted.\n");
>
> free (body);
> }
> diff --git a/gcc/tree-vectorizer.h b/gcc/tree-vectorizer.h
> index d26b0f8..14489ba 100644
> --- a/gcc/tree-vectorizer.h
> +++ b/gcc/tree-vectorizer.h
> @@ -1436,7 +1436,6 @@ extern void vect_loop_versioning (loop_vec_info,
> unsigned int, bool,
> extern struct loop *vect_do_peeling (loop_vec_info, tree, tree,
> tree *, tree *, tree *, int, bool, bool);
> extern void vect_prepare_for_masked_peels (loop_vec_info);
> -extern dump_user_location_t find_loop_location (struct loop *);
> extern bool vect_can_advance_ivs_p (loop_vec_info);
>
> /* In tree-vect-stmts.c. */
> --
> 1.8.5.3
>