diff --git a/gcc/cfgloopmanip.h b/gcc/cfgloopmanip.h index c40cfeae0e3e8e8126a085a8a4bebabac035d205..75b2a5e9b7565bfde49bbdc23fecd0e5f0c85e14 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 73b24c9a6f22bc6a28a261be05d651cf86368f42..83c2c1c6792777834bf170fc65250045f9eaf46b 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 e965cf94eb77a2797b08fcbfa978c849bfa99485..e41ec73a52a7104d78bbc123646ac6e08d5a1dbb 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