aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJan Hubicka <jh@suse.cz>2023-04-27 15:49:37 +0200
committerJan Hubicka <jh@suse.cz>2023-04-27 15:49:37 +0200
commitf2d6beb7a4ddf18dd95fdcc336181a8702a9f55f (patch)
treebbc9f1449c74cdf0b8f661d8929105415ae9b42d
parent65369ab62cee68eb7f6ef65e3d12d1969a9e20ee (diff)
downloadgcc-f2d6beb7a4ddf18dd95fdcc336181a8702a9f55f.zip
gcc-f2d6beb7a4ddf18dd95fdcc336181a8702a9f55f.tar.gz
gcc-f2d6beb7a4ddf18dd95fdcc336181a8702a9f55f.tar.bz2
Unloop loops that no longer loops in tree-ssa-loop-ch
I noticed this after adding sanity check that the upper bound on number of iterations never drop to -1. It seems to be relatively common case (happening few hundred times in testsuite and also during bootstrap) that loop-ch duplicates enough so the loop itself no longer loops. This is later detected in loop unrolling but since we test the number of iterations anyway it seems better to do that earlier. * cfgloopmanip.h (unloop_loops): Export. * tree-ssa-loop-ch.cc (ch_base::copy_headers): Unloop loops that no longer loop. * tree-ssa-loop-ivcanon.cc (unloop_loops): Export; do not free vectors of loops to unloop. (canonicalize_induction_variables): Free vectors here. (tree_unroll_loops_completely): Free vectors here.
-rw-r--r--gcc/cfgloopmanip.h4
-rw-r--r--gcc/tree-ssa-loop-ch.cc33
-rw-r--r--gcc/tree-ssa-loop-ivcanon.cc20
3 files changed, 43 insertions, 14 deletions
diff --git a/gcc/cfgloopmanip.h b/gcc/cfgloopmanip.h
index c40cfea..75b2a5e 100644
--- a/gcc/cfgloopmanip.h
+++ b/gcc/cfgloopmanip.h
@@ -43,6 +43,10 @@ extern edge create_empty_if_region_on_edge (edge, tree);
extern class loop *create_empty_loop_on_edge (edge, tree, tree, tree, tree,
tree *, tree *, class loop *);
extern void unloop (class loop *, bool *, bitmap);
+extern void unloop_loops (vec<class loop *> &loops_to_unloop,
+ vec<int> &loops_to_unloop_nunroll,
+ bitmap loop_closed_ssa_invalidated,
+ bool *irred_invalidated);
extern void copy_loop_info (class loop *loop, class loop *target);
extern class loop * duplicate_loop (class loop *, class loop *,
class loop * = NULL);
diff --git a/gcc/tree-ssa-loop-ch.cc b/gcc/tree-ssa-loop-ch.cc
index 73b24c9..83c2c1c 100644
--- a/gcc/tree-ssa-loop-ch.cc
+++ b/gcc/tree-ssa-loop-ch.cc
@@ -396,6 +396,8 @@ ch_base::copy_headers (function *fun)
auto_vec<loop_p> candidates;
auto_vec<std::pair<edge, loop_p> > copied;
+ auto_vec<class loop *> loops_to_unloop;
+ auto_vec<int> loops_to_unloop_nunroll;
mark_dfs_back_edges ();
gimple_ranger *ranger = new gimple_ranger;
@@ -408,6 +410,14 @@ ch_base::copy_headers (function *fun)
"Analyzing loop %i\n", loop->num);
header = loop->header;
+ if (!get_max_loop_iterations_int (loop))
+ {
+ if (dump_file && (dump_flags & TDF_DETAILS))
+ fprintf (dump_file, "Loop %d never loops.\n", loop->num);
+ loops_to_unloop.safe_push (loop);
+ loops_to_unloop_nunroll.safe_push (0);
+ continue;
+ }
/* If the loop is already a do-while style one (either because it was
written as such, or because jump threading transformed it into one),
@@ -593,13 +603,6 @@ ch_base::copy_headers (function *fun)
/* We possibly decreased number of itrations by 1. */
auto_vec<edge> exits = get_loop_exit_edges (loop);
bool precise = (nexits == (int) exits.length ());
- if (!get_max_loop_iterations_int (loop))
- {
- if (dump_file && (dump_flags & TDF_DETAILS))
- fprintf (dump_file, "Loop %d no longer loops.\n", loop->num);
- /* TODO: We can unloop like in tree-ssa-loop-ivcanon. */
- precise = false;
- }
/* Check that loop may not terminate in other way than via
basic blocks we duplicated. */
if (precise)
@@ -640,7 +643,15 @@ ch_base::copy_headers (function *fun)
precise = false;
}
}
- if (precise)
+ if (precise
+ && get_max_loop_iterations_int (loop) == 1)
+ {
+ if (dump_file && (dump_flags & TDF_DETAILS))
+ fprintf (dump_file, "Loop %d no longer loops.\n", loop->num);
+ loops_to_unloop.safe_push (loop);
+ loops_to_unloop_nunroll.safe_push (0);
+ }
+ else if (precise)
{
if (dump_file && (dump_flags & TDF_DETAILS))
fprintf (dump_file,
@@ -688,6 +699,12 @@ ch_base::copy_headers (function *fun)
BITMAP_FREE (exit_bbs);
}
}
+ if (!loops_to_unloop.is_empty ())
+ {
+ bool irred_invalidated;
+ unloop_loops (loops_to_unloop, loops_to_unloop_nunroll, NULL, &irred_invalidated);
+ changed = true;
+ }
free (bbs);
free (copied_bbs);
diff --git a/gcc/tree-ssa-loop-ivcanon.cc b/gcc/tree-ssa-loop-ivcanon.cc
index e965cf9..e41ec73 100644
--- a/gcc/tree-ssa-loop-ivcanon.cc
+++ b/gcc/tree-ssa-loop-ivcanon.cc
@@ -618,8 +618,10 @@ static bitmap peeled_loops;
LOOP_CLOSED_SSA_INVALIDATED is used to bookkepp the case
when we need to go into loop closed SSA form. */
-static void
-unloop_loops (bitmap loop_closed_ssa_invalidated,
+void
+unloop_loops (vec<class loop *> &loops_to_unloop,
+ vec<int> &loops_to_unloop_nunroll,
+ bitmap loop_closed_ssa_invalidated,
bool *irred_invalidated)
{
while (loops_to_unloop.length ())
@@ -653,8 +655,6 @@ unloop_loops (bitmap loop_closed_ssa_invalidated,
gsi = gsi_start_bb (latch_edge->dest);
gsi_insert_after (&gsi, stmt, GSI_NEW_STMT);
}
- loops_to_unloop.release ();
- loops_to_unloop_nunroll.release ();
/* Remove edges in peeled copies. Given remove_path removes dominated
regions we need to cope with removal of already removed paths. */
@@ -1326,7 +1326,10 @@ canonicalize_induction_variables (void)
}
gcc_assert (!need_ssa_update_p (cfun));
- unloop_loops (loop_closed_ssa_invalidated, &irred_invalidated);
+ unloop_loops (loops_to_unloop, loops_to_unloop_nunroll,
+ loop_closed_ssa_invalidated, &irred_invalidated);
+ loops_to_unloop.release ();
+ loops_to_unloop_nunroll.release ();
if (irred_invalidated
&& loops_state_satisfies_p (LOOPS_HAVE_MARKED_IRREDUCIBLE_REGIONS))
mark_irreducible_loops ();
@@ -1473,7 +1476,12 @@ tree_unroll_loops_completely (bool may_increase_size, bool unroll_outer)
{
unsigned i;
- unloop_loops (loop_closed_ssa_invalidated, &irred_invalidated);
+ unloop_loops (loops_to_unloop,
+ loops_to_unloop_nunroll,
+ loop_closed_ssa_invalidated,
+ &irred_invalidated);
+ loops_to_unloop.release ();
+ loops_to_unloop_nunroll.release ();
/* We cannot use TODO_update_ssa_no_phi because VOPS gets confused. */
if (loop_closed_ssa_invalidated