From e67d7a1ea15cb266edf4a9ae2315eae6b1e8003a Mon Sep 17 00:00:00 2001 From: Tom de Vries Date: Fri, 31 Jul 2015 06:26:44 +0000 Subject: [PATCH] Don't cancel loop tree in parloops 2015-07-31 Tom de Vries 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 simple latch bb. Handle case that omp_for already has its own loop struct. * tree-parloops.c (create_phi_for_local_result) (create_call_for_reduction): Handle simple latch bb. (create_parallel_loop): Add simple latch bb to preserve LOOPS_HAVE_SIMPLE_LATCHES. Record new exit. Handle simple latch bb. (gen_parallel_loop): Remove call to cancel_loop_tree. (parallelize_loops): Skip loops that are inner loops of parallelized loops. (pass_parallelize_loops::execute) [ENABLE_CHECKING]: Call verify_loop_structure. From-SVN: r226427 --- gcc/ChangeLog | 20 ++++++++++++++++++ gcc/omp-low.c | 32 +++++++++++++++++++++++++++-- gcc/tree-parloops.c | 49 +++++++++++++++++++++++++++++++++------------ 3 files changed, 86 insertions(+), 15 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 4985050a743..831aba8f865 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,23 @@ +2015-07-31 Tom de Vries + + 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 simple latch bb. Handle case + that omp_for already has its own loop struct. + * tree-parloops.c (create_phi_for_local_result) + (create_call_for_reduction): Handle simple latch bb. + (create_parallel_loop): Add simple latch bb to preserve + LOOPS_HAVE_SIMPLE_LATCHES. Record new exit. Handle simple latch bb. + (gen_parallel_loop): Remove call to cancel_loop_tree. + (parallelize_loops): Skip loops that are inner loops of parallelized + loops. + (pass_parallelize_loops::execute) [ENABLE_CHECKING]: Call + verify_loop_structure. + 2015-07-30 Anatoly Sokolov * config/v850/v850.h (LIBCALL_VALUE): Remove macros. diff --git a/gcc/omp-low.c b/gcc/omp-low.c index 313560633f6..0f5c0f15215 100644 --- a/gcc/omp-low.c +++ b/gcc/omp-low.c @@ -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 (); } @@ -6535,7 +6539,8 @@ expand_omp_for_static_nochunk (struct omp_region *region, body_bb = single_succ (seq_start_bb); if (!broken_loop) { - gcc_assert (BRANCH_EDGE (cont_bb)->dest == body_bb); + gcc_assert (BRANCH_EDGE (cont_bb)->dest == body_bb + || single_succ (BRANCH_EDGE (cont_bb)->dest) == body_bb); gcc_assert (EDGE_COUNT (cont_bb->succs) == 2); } exit_bb = region->exit; @@ -6818,6 +6823,11 @@ expand_omp_for_static_nochunk (struct omp_region *region, if (!broken_loop) { ep = find_edge (cont_bb, body_bb); + if (ep == NULL) + { + ep = BRANCH_EDGE (cont_bb); + gcc_assert (single_succ (ep->dest) == body_bb); + } if (gimple_omp_for_combined_p (fd->for_stmt)) { remove_edge (ep); @@ -6843,9 +6853,19 @@ 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 + || single_pred (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 +9004,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 +9516,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 (); diff --git a/gcc/tree-parloops.c b/gcc/tree-parloops.c index b06265c4bb8..d017479ec2e 100644 --- a/gcc/tree-parloops.c +++ b/gcc/tree-parloops.c @@ -1032,21 +1032,22 @@ create_phi_for_local_result (reduction_info **slot, struct loop *loop) struct reduction_info *const reduc = *slot; edge e; gphi *new_phi; - basic_block store_bb; + basic_block store_bb, continue_bb; tree local_res; source_location locus; /* STORE_BB is the block where the phi should be stored. It is the destination of the loop exit. (Find the fallthru edge from GIMPLE_OMP_CONTINUE). */ - store_bb = FALLTHRU_EDGE (loop->latch)->dest; + continue_bb = single_pred (loop->latch); + store_bb = FALLTHRU_EDGE (continue_bb)->dest; /* STORE_BB has two predecessors. One coming from the loop (the reduction's result is computed at the loop), and another coming from a block preceding the loop, when no iterations are executed (the initial value should be taken). */ - if (EDGE_PRED (store_bb, 0) == FALLTHRU_EDGE (loop->latch)) + if (EDGE_PRED (store_bb, 0) == FALLTHRU_EDGE (continue_bb)) e = EDGE_PRED (store_bb, 1); else e = EDGE_PRED (store_bb, 0); @@ -1055,7 +1056,7 @@ create_phi_for_local_result (reduction_info **slot, struct loop *loop) locus = gimple_location (reduc->reduc_stmt); new_phi = create_phi_node (local_res, store_bb); add_phi_arg (new_phi, reduc->init, e, locus); - add_phi_arg (new_phi, lhs, FALLTHRU_EDGE (loop->latch), locus); + add_phi_arg (new_phi, lhs, FALLTHRU_EDGE (continue_bb), locus); reduc->new_phi = new_phi; return 1; @@ -1134,7 +1135,8 @@ create_call_for_reduction (struct loop *loop, { reduction_list->traverse (loop); /* Find the fallthru edge from GIMPLE_OMP_CONTINUE. */ - ld_st_data->load_bb = FALLTHRU_EDGE (loop->latch)->dest; + basic_block continue_bb = single_pred (loop->latch); + ld_st_data->load_bb = FALLTHRU_EDGE (continue_bb)->dest; reduction_list ->traverse (ld_st_data); } @@ -1981,7 +1983,7 @@ create_parallel_loop (struct loop *loop, tree loop_fn, tree data, tree new_data, unsigned n_threads, location_t loc) { gimple_stmt_iterator gsi; - basic_block bb, paral_bb, for_bb, ex_bb; + basic_block bb, paral_bb, for_bb, ex_bb, continue_bb; tree t, param; gomp_parallel *omp_par_stmt; gimple omp_return_stmt1, omp_return_stmt2; @@ -2052,8 +2054,12 @@ create_parallel_loop (struct loop *loop, tree loop_fn, tree data, gcc_assert (exit == single_dom_exit (loop)); guard = make_edge (for_bb, ex_bb, 0); - single_succ_edge (loop->latch)->flags = 0; - end = make_edge (loop->latch, ex_bb, EDGE_FALLTHRU); + /* Split the latch edge, so LOOPS_HAVE_SIMPLE_LATCHES is still valid. */ + loop->latch = split_edge (single_succ_edge (loop->latch)); + single_pred_edge (loop->latch)->flags = 0; + end = make_edge (single_pred (loop->latch), ex_bb, EDGE_FALLTHRU); + rescan_loop_exit (end, true, false); + for (gphi_iterator gpi = gsi_start_phis (ex_bb); !gsi_end_p (gpi); gsi_next (&gpi)) { @@ -2102,7 +2108,8 @@ create_parallel_loop (struct loop *loop, tree loop_fn, tree data, SSA_NAME_DEF_STMT (initvar) = for_stmt; /* Emit GIMPLE_OMP_CONTINUE. */ - gsi = gsi_last_bb (loop->latch); + continue_bb = single_pred (loop->latch); + gsi = gsi_last_bb (continue_bb); omp_cont_stmt = gimple_build_omp_continue (cvar_next, cvar); gimple_set_location (omp_cont_stmt, loc); gsi_insert_after (&gsi, omp_cont_stmt, GSI_NEW_STMT); @@ -2298,10 +2305,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) @@ -2587,6 +2590,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; @@ -2604,6 +2608,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)) { @@ -2663,6 +2680,7 @@ parallelize_loops (void) continue; changed = true; + skip_loop = loop->inner; if (dump_file && (dump_flags & TDF_DETAILS)) { if (loop->inner) @@ -2729,6 +2747,11 @@ pass_parallelize_loops::execute (function *fun) if (parallelize_loops ()) { fun->curr_properties &= ~(PROP_gimple_eomp); + +#ifdef ENABLE_CHECKING + verify_loop_structure (); +#endif + return TODO_update_ssa; } -- 2.30.2