Don't cancel loop tree in parloops
authorTom de Vries <tom@codesourcery.com>
Fri, 31 Jul 2015 06:26:44 +0000 (06:26 +0000)
committerTom de Vries <vries@gcc.gnu.org>
Fri, 31 Jul 2015 06:26:44 +0000 (06:26 +0000)
2015-07-31  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 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
gcc/omp-low.c
gcc/tree-parloops.c

index 4985050a743e7a4e2cc5842b49046d75e0a901b8..831aba8f865afeb340bdffe4c2d7fb71b77cd68f 100644 (file)
@@ -1,3 +1,23 @@
+2015-07-31  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 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  <aesok@post.ru>
 
        * config/v850/v850.h (LIBCALL_VALUE): Remove macros.
index 313560633f66e8b3516e907a6495e5586f1cdebe..0f5c0f1521523fa53253dc58bdedaf39c5ed705c 100644 (file)
@@ -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 ();
index b06265c4bb85686a1632df15a05c30a96f95a2b2..d017479ec2e2d83a8827cb00bdb86eb938ff4648 100644 (file)
@@ -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 <struct loop *, create_phi_for_local_result> (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 <struct clsn_data *, create_call_for_reduction_1> (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;
     }