Don't cancel loop tree in parloops
2015-07-20 Tom de Vries <tom@codesourcery.com>
PR tree-optimization/66846
* omp-low.c (expand_omp_taskreg) [ENABLE_CHECKING]: Call
verify_loop_structure for child_cfun if !LOOPS_NEED_FIXUP.
(expand_omp_target) [ENABLE_CHECKING]: Same.
(execute_expand_omp) [ENABLE_CHECKING]: Call verify_loop_structure for
cfun if !LOOPS_NEED_FIXUP.
(expand_omp_for_static_nochunk): Handle case that omp_for already has
its own loop struct.
* passes.def: Add pass_tree_loop_init after pass_expand_omp_ssa in
pass_parallelize_loops.
* tree-parloops.c (create_parallel_loop): Add comment.
(gen_parallel_loop): Remove call to cancel_loop_tree.
(parallelize_loops): Skip loops that are inner loops of parallelized
loops.
(pass_parallelize_loops::execute): Clear LOOPS_HAVE_RECORDED_EXITS and
LOOPS_HAVE_SIMPLE_LATCHES on loop state.
[ENABLE_CHECKING]: Call verify_loop_structure.
* tree-ssa-loop.c (pass_tree_loop_init::clone): New function.
---
gcc/omp-low.c | 22 +++++++++++++++++++++-
gcc/passes.def | 1 +
gcc/tree-parloops.c | 33 +++++++++++++++++++++++++++++----
gcc/tree-ssa-loop.c | 1 +
4 files changed, 52 insertions(+), 5 deletions(-)
@@ -5604,6 +5604,10 @@ expand_omp_taskreg (struct omp_region *region)
}
if (gimple_in_ssa_p (cfun))
update_ssa (TODO_update_ssa);
+#ifdef ENABLE_CHECKING
+ if (!loops_state_satisfies_p (LOOPS_NEED_FIXUP))
+ verify_loop_structure ();
+#endif
pop_cfun ();
}
@@ -6843,9 +6847,17 @@ expand_omp_for_static_nochunk (struct omp_region *region,
set_immediate_dominator (CDI_DOMINATORS, fin_bb,
recompute_dominator (CDI_DOMINATORS, fin_bb));
+ struct loop *loop = body_bb->loop_father;
+ if (loop != entry_bb->loop_father)
+ {
+ gcc_assert (loop->header == body_bb);
+ gcc_assert (broken_loop || loop->latch == region->cont);
+ return;
+ }
+
if (!broken_loop && !gimple_omp_for_combined_p (fd->for_stmt))
{
- struct loop *loop = alloc_loop ();
+ loop = alloc_loop ();
loop->header = body_bb;
if (collapse_bb == NULL)
loop->latch = cont_bb;
@@ -8984,6 +8996,10 @@ expand_omp_target (struct omp_region *region)
if (changed)
cleanup_tree_cfg ();
}
+#ifdef ENABLE_CHECKING
+ if (!loops_state_satisfies_p (LOOPS_NEED_FIXUP))
+ verify_loop_structure ();
+#endif
pop_cfun ();
}
@@ -9492,6 +9508,10 @@ execute_expand_omp (void)
expand_omp (root_omp_region);
+#ifdef ENABLE_CHECKING
+ if (!loops_state_satisfies_p (LOOPS_NEED_FIXUP))
+ verify_loop_structure ();
+#endif
cleanup_tree_cfg ();
free_omp_regions ();
@@ -246,6 +246,7 @@ along with GCC; see the file COPYING3. If not see
NEXT_PASS (pass_parallelize_loops);
PUSH_INSERT_PASSES_WITHIN (pass_parallelize_loops)
NEXT_PASS (pass_expand_omp_ssa);
+ NEXT_PASS (pass_tree_loop_init);
POP_INSERT_PASSES ()
NEXT_PASS (pass_ch_vect);
NEXT_PASS (pass_if_conversion);
@@ -2045,7 +2045,14 @@ create_parallel_loop (struct loop *loop, tree loop_fn, tree data,
guard = make_edge (for_bb, ex_bb, 0);
single_succ_edge (loop->latch)->flags = 0;
+
+ /* After creating this edge, the latch has two successors, so
+ LOOPS_HAVE_SIMPLE_LATCHES is no longer valid. Furthermore, this exit is
+ not recorded. We'll update the loop state as such at the end of the
+ pass, since it's not needed earlier, and doing it earlier will invalidate
+ info for loops we still need to process. */
end = make_edge (loop->latch, ex_bb, EDGE_FALLTHRU);
+
for (gphi_iterator gpi = gsi_start_phis (ex_bb);
!gsi_end_p (gpi); gsi_next (&gpi))
{
@@ -2282,10 +2289,6 @@ gen_parallel_loop (struct loop *loop,
scev_reset ();
- /* Cancel the loop (it is simpler to do it here rather than to teach the
- expander to do it). */
- cancel_loop_tree (loop);
-
/* Free loop bound estimations that could contain references to
removed statements. */
FOR_EACH_LOOP (loop, 0)
@@ -2521,6 +2524,7 @@ parallelize_loops (void)
unsigned n_threads = flag_tree_parallelize_loops;
bool changed = false;
struct loop *loop;
+ struct loop *skip_loop = NULL;
struct tree_niter_desc niter_desc;
struct obstack parloop_obstack;
HOST_WIDE_INT estimated;
@@ -2538,6 +2542,19 @@ parallelize_loops (void)
FOR_EACH_LOOP (loop, 0)
{
+ if (loop == skip_loop)
+ {
+ if (dump_file && (dump_flags & TDF_DETAILS))
+ fprintf (dump_file,
+ "Skipping loop %d as inner loop of parallelized loop\n",
+ loop->num);
+
+ skip_loop = loop->inner;
+ continue;
+ }
+ else
+ skip_loop = NULL;
+
reduction_list.empty ();
if (dump_file && (dump_flags & TDF_DETAILS))
{
@@ -2597,6 +2614,7 @@ parallelize_loops (void)
continue;
changed = true;
+ skip_loop = loop->inner;
if (dump_file && (dump_flags & TDF_DETAILS))
{
if (loop->inner)
@@ -2663,6 +2681,13 @@ pass_parallelize_loops::execute (function *fun)
if (parallelize_loops ())
{
fun->curr_properties &= ~(PROP_gimple_eomp);
+
+ release_recorded_exits ();
+ loops_state_clear (LOOPS_HAVE_SIMPLE_LATCHES);
+#ifdef ENABLE_CHECKING
+ verify_loop_structure ();
+#endif
+
return TODO_update_ssa;
}
@@ -210,6 +210,7 @@ public:
/* opt_pass methods: */
virtual unsigned int execute (function *);
+ opt_pass * clone () { return new pass_tree_loop_init (m_ctxt); }
}; // class pass_tree_loop_init
--
1.9.1