Use -fopt-info in unswitch pass.
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.
This commit is contained in:
parent
e7fac1e1a5
commit
df704591a2
|
@ -84,16 +84,26 @@ const char *profile_quality_display_names[] =
|
|||
"precise"
|
||||
};
|
||||
|
||||
/* Dump THIS to BUFFER. */
|
||||
|
||||
void
|
||||
profile_count::dump (char *buffer) const
|
||||
{
|
||||
if (!initialized_p ())
|
||||
sprintf (buffer, "uninitialized");
|
||||
else
|
||||
sprintf (buffer, "%" PRId64 " (%s)", m_val,
|
||||
profile_quality_display_names[m_quality]);
|
||||
}
|
||||
|
||||
/* Dump THIS to F. */
|
||||
|
||||
void
|
||||
profile_count::dump (FILE *f) const
|
||||
{
|
||||
if (!initialized_p ())
|
||||
fprintf (f, "uninitialized");
|
||||
else
|
||||
fprintf (f, "%" PRId64 " (%s)", m_val,
|
||||
profile_quality_display_names[m_quality]);
|
||||
char buffer[64];
|
||||
dump (buffer);
|
||||
fputs (buffer, f);
|
||||
}
|
||||
|
||||
/* Dump THIS to stderr. */
|
||||
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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" } } */
|
||||
|
|
|
@ -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" } } */
|
||||
|
||||
|
|
|
@ -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" } } */
|
||||
|
|
|
@ -49,4 +49,3 @@ int main()
|
|||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -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. */
|
||||
|
|
|
@ -37,6 +37,7 @@ along with GCC; see the file COPYING3. If not see
|
|||
#include "gimple-iterator.h"
|
||||
#include "cfghooks.h"
|
||||
#include "tree-ssa-loop-manip.h"
|
||||
#include "tree-vectorizer.h"
|
||||
|
||||
/* This file implements the loop unswitching, i.e. transformation of loops like
|
||||
|
||||
|
@ -273,14 +274,17 @@ tree_unswitch_single_loop (class loop *loop, int num)
|
|||
bool changed = false;
|
||||
HOST_WIDE_INT iterations;
|
||||
|
||||
dump_user_location_t loc = find_loop_location (loop);
|
||||
|
||||
/* 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_NOTE, loc,
|
||||
"Not unswitching cold loops\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -288,8 +292,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_NOTE, loc,
|
||||
"Not unswitching, loop too big\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -300,9 +305,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_NOTE, loc,
|
||||
"Not unswitching, loop is not expected"
|
||||
" to iterate\n");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -320,10 +326,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 +451,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 +528,10 @@ 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_printf_loc (MSG_MISSED_OPTIMIZATION, find_loop_location (loop),
|
||||
"Not unswitching, loop is not expected"
|
||||
" to iterate\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -623,26 +632,31 @@ find_loop_guard (class loop *loop)
|
|||
else
|
||||
return NULL;
|
||||
|
||||
dump_user_location_t loc = find_loop_location (loop);
|
||||
|
||||
/* 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 +666,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 +681,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 +839,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 = find_loop_location (loop);
|
||||
|
||||
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 +883,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 +909,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 +948,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);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue