On December 8, 2021 10:32:20 AM GMT+01:00, "Martin Liška" <mli...@suse.cz> wrote: >The patch is about porting of dump information to -fopt-info so >that we can compare the current pass with a modified one. > >Right now, there are 1945 'optimized: Unswitching loop on condition' lines >for SPEC 2006 benchmark. > >Moreover, I adjusted dump functions in profile-count.{ch} so that it dumps >to a string buffer. > >Patch can bootstrap on x86_64-linux-gnu and survives regression tests. > >Ready to be installed? >Thanks, >Martin > >gcc/ChangeLog: > > * profile-count.c (profile_count::dump): Add function > that can dump to a provided buffer. > (profile_probability::dump): Likewise. > * profile-count.h: Likewise. > * tree-ssa-loop-unswitch.c (tree_unswitch_single_loop): > Use dump_printf_loc infrastructure. > (tree_unswitch_outer_loop): Likewise. > (find_loop_guard): Likewise. > (hoist_guard): Likewise. > >gcc/testsuite/ChangeLog: > > * gcc.dg/loop-unswitch-1.c: Adjust test-case based on > dump_printf_loc. > * gcc.dg/loop-unswitch-2.c: Likewise. > * gcc.dg/loop-unswitch-3.c: Likewise. > * gcc.dg/loop-unswitch-4.c: Likewise. > * gcc.dg/loop-unswitch-5.c: Likewise. >--- > gcc/profile-count.c | 48 ++++++--- > gcc/profile-count.h | 6 ++ > gcc/testsuite/gcc.dg/loop-unswitch-1.c | 4 +- > gcc/testsuite/gcc.dg/loop-unswitch-2.c | 5 +- > gcc/testsuite/gcc.dg/loop-unswitch-3.c | 7 +- > gcc/testsuite/gcc.dg/loop-unswitch-4.c | 1 - > gcc/testsuite/gcc.dg/loop-unswitch-5.c | 2 +- > gcc/tree-ssa-loop-unswitch.c | 131 +++++++++++++++---------- > 8 files changed, 128 insertions(+), 76 deletions(-) > >diff --git a/gcc/profile-count.c b/gcc/profile-count.c >index f7f4dffdc90..c04b4fe823d 100644 >--- a/gcc/profile-count.c >+++ b/gcc/profile-count.c >@@ -84,18 +84,28 @@ const char *profile_quality_display_names[] = > "precise" > }; > >-/* Dump THIS to F. */ >+/* Dump THIS to BUFFER. */ > > void >-profile_count::dump (FILE *f) const >+profile_count::dump (char *buffer) const > { > if (!initialized_p ()) >- fprintf (f, "uninitialized"); >+ sprintf (buffer, "uninitialized"); > else >- fprintf (f, "%" PRId64 " (%s)", m_val, >+ sprintf (buffer, "%" PRId64 " (%s)", m_val, > profile_quality_display_names[m_quality]); > } > >+/* Dump THIS to F. */ >+ >+void >+profile_count::dump (FILE *f) const >+{ >+ char buffer[64]; >+ dump (buffer); >+ fputs (buffer, f); >+} >+ > /* Dump THIS to stderr. */ > > void >@@ -151,32 +161,44 @@ profile_count::stream_out (struct lto_output_stream *ob) > streamer_write_uhwi_stream (ob, m_quality); > } > >-/* Dump THIS to F. */ >+ >+/* Output THIS to BUFFER. */ > > void >-profile_probability::dump (FILE *f) const >+profile_probability::dump (char *buffer) const > { > if (!initialized_p ()) >- fprintf (f, "uninitialized"); >+ sprintf (buffer, "uninitialized"); > else > { > /* Make difference between 0.00 as a roundoff error and actual 0. > Similarly for 1. */ > if (m_val == 0) >- fprintf (f, "never"); >+ buffer += sprintf (buffer, "never"); > else if (m_val == max_probability) >- fprintf (f, "always"); >+ buffer += sprintf (buffer, "always"); > else >- fprintf (f, "%3.1f%%", (double)m_val * 100 / max_probability); >+ buffer += sprintf (buffer, "%3.1f%%", (double)m_val * 100 / >max_probability); >+ > if (m_quality == ADJUSTED) >- fprintf (f, " (adjusted)"); >+ sprintf (buffer, " (adjusted)"); > else if (m_quality == AFDO) >- fprintf (f, " (auto FDO)"); >+ sprintf (buffer, " (auto FDO)"); > else if (m_quality == GUESSED) >- fprintf (f, " (guessed)"); >+ sprintf (buffer, " (guessed)"); > } > } > >+/* Dump THIS to F. */ >+ >+void >+profile_probability::dump (FILE *f) const >+{ >+ char buffer[64]; >+ dump (buffer); >+ fputs (buffer, f); >+} >+ > /* Dump THIS to stderr. */ > > void >diff --git a/gcc/profile-count.h b/gcc/profile-count.h >index c7a45ac5ee3..f86091f23a8 100644 >--- a/gcc/profile-count.h >+++ b/gcc/profile-count.h >@@ -609,6 +609,9 @@ public: > /* Output THIS to F. */ > void dump (FILE *f) const; > >+ /* Output THIS to BUFFER. */ >+ void dump (char *buffer) const; >+ > /* Print THIS to stderr. */ > void debug () const; > >@@ -1208,6 +1211,9 @@ public: > /* Output THIS to F. */ > void dump (FILE *f) const; > >+ /* Output THIS to BUFFER. */ >+ void dump (char *buffer) const; >+ > /* Print THIS to stderr. */ > void debug () const; > >diff --git a/gcc/testsuite/gcc.dg/loop-unswitch-1.c >b/gcc/testsuite/gcc.dg/loop-unswitch-1.c >index de2fb2c0e4b..f9d628df510 100644 >--- a/gcc/testsuite/gcc.dg/loop-unswitch-1.c >+++ b/gcc/testsuite/gcc.dg/loop-unswitch-1.c >@@ -1,6 +1,6 @@ > /* For PR rtl-optimization/27735 */ > /* { dg-do compile } */ >-/* { dg-options "-O2 -funswitch-loops -fdump-tree-unswitch-details >-fno-finite-loops" } */ >+/* { dg-options "-O2 -funswitch-loops -fdump-tree-unswitch-all >-fno-finite-loops" } */ > > void set_color(void); > void xml_colorize_line(unsigned int *p, int state) >@@ -33,4 +33,4 @@ parse_tag: ; > } > > /* Test that we actually unswitched something. */ >-/* { dg-final { scan-tree-dump ";; Unswitching loop" "unswitch" } } */ >+/* { dg-final { scan-tree-dump "Unswitching loop" "unswitch" } } */ >diff --git a/gcc/testsuite/gcc.dg/loop-unswitch-2.c >b/gcc/testsuite/gcc.dg/loop-unswitch-2.c >index f8e99bd1669..e92ae553516 100644 >--- a/gcc/testsuite/gcc.dg/loop-unswitch-2.c >+++ b/gcc/testsuite/gcc.dg/loop-unswitch-2.c >@@ -1,5 +1,5 @@ > /* { dg-do compile } */ >-/* { dg-options "-O2 -funswitch-loops -fdump-tree-unswitch-details >-fno-thread-jumps" } */ >+/* { dg-options "-O2 -funswitch-loops -fdump-tree-unswitch-all >-fno-thread-jumps" } */ > > void foo (float **a, float **b, float *c, int n, int m, int l) > { >@@ -11,6 +11,5 @@ void foo (float **a, float **b, float *c, int n, int m, int >l) > c[i] += a[i][k] * b[k][j]; > } > >-/* { dg-final { scan-tree-dump-times "guard hoisted" 3 "unswitch" } } */ >+/* { dg-final { scan-tree-dump-times "Guard hoisted" 3 "unswitch" } } */ > /* { dg-final { scan-tree-dump-not "Invalid sum" "unswitch" } } */ >- >diff --git a/gcc/testsuite/gcc.dg/loop-unswitch-3.c >b/gcc/testsuite/gcc.dg/loop-unswitch-3.c >index 089b6106711..31a90ef23eb 100644 >--- a/gcc/testsuite/gcc.dg/loop-unswitch-3.c >+++ b/gcc/testsuite/gcc.dg/loop-unswitch-3.c >@@ -1,5 +1,5 @@ > /* { dg-do compile } */ >-/* { dg-options "-O2 -funswitch-loops -fdump-tree-unswitch-details" } */ >+/* { dg-options "-O2 -funswitch-loops -fdump-tree-unswitch-all" } */ > > #include <stdlib.h> > #define N 32 >@@ -21,7 +21,4 @@ float *foo(int ustride, int size, float *src) > return buffer; > } > >-/* { dg-final { scan-tree-dump-times "guard hoisted" 1 "unswitch" } } */ >-/* { dg-final { scan-tree-dump-not "Invalid sum" "unswitch" } } */ >- >- >+/* { dg-final { scan-tree-dump-times "Guard hoisted" 1 "unswitch" } } */ >diff --git a/gcc/testsuite/gcc.dg/loop-unswitch-4.c >b/gcc/testsuite/gcc.dg/loop-unswitch-4.c >index 320a1cdb507..05d0fe80321 100644 >--- a/gcc/testsuite/gcc.dg/loop-unswitch-4.c >+++ b/gcc/testsuite/gcc.dg/loop-unswitch-4.c >@@ -49,4 +49,3 @@ int main() > > return 0; > } >- >diff --git a/gcc/testsuite/gcc.dg/loop-unswitch-5.c >b/gcc/testsuite/gcc.dg/loop-unswitch-5.c >index b41e85379ae..77880005301 100644 >--- a/gcc/testsuite/gcc.dg/loop-unswitch-5.c >+++ b/gcc/testsuite/gcc.dg/loop-unswitch-5.c >@@ -1,6 +1,6 @@ > /* PR middle-end/71691 */ > /* { dg-do run } */ >-/* { dg-options "-fno-tree-vrp -O2 -funswitch-loops >-fdump-tree-unswitch-details" } */ >+/* { dg-options "-fno-tree-vrp -O2 -funswitch-loops" } */ > > /* Note: The -fno-tree-vrp above is only there to avoid VRP papering > over the problem. */ >diff --git a/gcc/tree-ssa-loop-unswitch.c b/gcc/tree-ssa-loop-unswitch.c >index fe4dacc0833..e7b405b9357 100644 >--- a/gcc/tree-ssa-loop-unswitch.c >+++ b/gcc/tree-ssa-loop-unswitch.c >@@ -273,14 +273,17 @@ tree_unswitch_single_loop (class loop *loop, int num) > bool changed = false; > HOST_WIDE_INT iterations; > >+ dump_user_location_t loc (last_stmt (loop->header));
Can you please use loop_location as I told you elsewhere? > /* Perform initial tests if unswitch is eligible. */ > if (num == 0) > { > /* 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, loc, >+ "Not unswitching cold loops\n"); That's going to be very noisy even for loops that have no unsiwtchung candidate. Please use MGS_NOTE because of that. > return false; > } > >@@ -288,8 +291,9 @@ tree_unswitch_single_loop (class loop *loop, int num) > if (tree_num_loop_insns (loop, &eni_size_weights) > > (unsigned) 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, loc, >+ "Not unswitching, loop too big\n"); Likewise. > return false; > } > >@@ -300,9 +304,10 @@ tree_unswitch_single_loop (class 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, loc, >+ "Not unswitching, loop is not expected" >+ " to iterate\n"); Likewise. Otherwise looks OK. Richard. > return false; > } > } >@@ -320,10 +325,10 @@ tree_unswitch_single_loop (class loop *loop, int num) > > if (i == loop->num_nodes) > { >- if (dump_file >- && num > param_max_unswitch_level >- && (dump_flags & TDF_DETAILS)) >- fprintf (dump_file, ";; Not unswitching anymore, hit max level\n"); >+ if (dump_enabled_p () >+ && num > param_max_unswitch_level) >+ dump_printf_loc (MSG_MISSED_OPTIMIZATION, loc, >+ "Not unswitching anymore, hit max level\n"); > > if (found == loop->num_nodes) > { >@@ -445,8 +450,10 @@ tree_unswitch_single_loop (class 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, loc, >+ "Unswitching loop on condition: %G\n", >+ last_stmt (bbs[found])); > > initialize_original_copy_tables (); > /* Unswitch the loop on this condition. */ >@@ -520,9 +527,13 @@ tree_unswitch_outer_loop (class 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_user_location_t loc (last_stmt (loop->header)); >+ dump_printf_loc (MSG_MISSED_OPTIMIZATION, loc, >+ "Not unswitching, loop is not expected" >+ " to iterate\n"); >+ } > return false; > } > >@@ -623,26 +634,31 @@ find_loop_guard (class loop *loop) > else > return NULL; > >+ dump_user_location_t loc (last_stmt (loop->header)); >+ > /* Guard edge must skip inner 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, loc, >+ "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, loc, >+ "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, loc, >+ "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) >@@ -652,9 +668,9 @@ find_loop_guard (class 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_NOTE, loc, "guard operands have definitions" >+ " inside loop\n"); > return NULL; > } > } >@@ -667,23 +683,26 @@ find_loop_guard (class 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, loc, >+ "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, loc, >+ "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_OPTIMIZED_LOCATIONS, loc, >+ "suitable to hoist\n"); > end: > if (body) > free (body); >@@ -822,13 +841,19 @@ hoist_guard (class 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)) >+ >+ dump_user_location_t loc (last_stmt (loop->header)); >+ >+ 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); >+ char buffer[64]; >+ guard->probability.dump (buffer); >+ >+ dump_printf_loc (MSG_OPTIMIZED_LOCATIONS, loc, >+ "Moving guard %i->%i (prob %s) to bb %i, " >+ "new preheader is %i\n", >+ guard->src->index, guard->dest->index, >+ buffer, e->src->index, e->dest->index); > } > > gcc_assert (loop_preheader_edge (loop)->src == e->dest); >@@ -860,11 +885,14 @@ hoist_guard (class loop *loop, edge guard) > fprintf (dump_file, " 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"); >+ char buffer[64]; >+ new_edge->probability.dump (buffer); >+ >+ dump_printf_loc (MSG_NOTE, loc, >+ "Estimated probability of skipping loop is %s\n", >+ buffer); > } > > /* Update profile after the transform: >@@ -883,15 +911,15 @@ hoist_guard (class 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:"); > 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_loc (MSG_NOTE, loc, >+ "Scaling nonguarded BBs in loop: %i\n", >+ bb->index); > if (e->probability.initialized_p ()) > scale_bbs_frequencies (&bb, 1, e->probability); > } >@@ -922,8 +950,9 @@ hoist_guard (class 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_MISSED_OPTIMIZATION, loc, >+ "Guard hoisted\n"); > > free (body); > }