Hi!

This patch makes sure that when we remove all depend clauses from a
construct (e.g. because all of them refer to invalid iterations), we don't
leave ordered construct without clauses in (because that means omp ordered
threads).  Furthermore, it attempts to optimize adjacent #pragma omp ordered
depend(sink:...) directives.  And makes sure we don't lower them to any
code, the goal is to do something about them only during expansion.
The patch also treats them as stand-alone directives for the construction
of omp regions and edges in the cfg (so we don't emit GIMPLE_OMP_RETURN
for those).

2015-09-14  Jakub Jelinek  <ja...@redhat.com>

        * omp-low.c (lower_omp_ordered_clauses): Add GSI_P argument.
        Use XALLOCAVEC, don't check for gimple_omp_for_collapse 0.
        Merge adjacent ordered depend(sink:) statements.  If removing
        all depend clauses, replace also the ordered stmt with GIMPLE_NOP.
        (lower_omp_ordered): Call lower_omp_ordered_clauses only if depend
        clause is present.  Don't do anything else after that call.
        (build_omp_regions_1): Treat GIMPLE_OMP_ORDERED with depend clause
        as stand-alone directive.
        (make_gimple_omp_edges): Likewise.

--- gcc/omp-low.c.jj    2015-09-10 14:46:48.000000000 +0200
+++ gcc/omp-low.c       2015-09-14 15:00:15.713086562 +0200
@@ -11185,6 +11185,13 @@ build_omp_regions_1 (basic_block bb, str
                  gcc_unreachable ();
                }
            }
+         else if (code == GIMPLE_OMP_ORDERED
+                  && find_omp_clause (gimple_omp_ordered_clauses
+                                        (as_a <gomp_ordered *> (stmt)),
+                                      OMP_CLAUSE_DEPEND))
+           /* #pragma omp ordered depend is also just a stand-alone
+              directive.  */
+           region = NULL;
          /* ..., this directive becomes the parent for a new region.  */
          if (region)
            parent = region;
@@ -12110,22 +12117,54 @@ lower_omp_taskgroup (gimple_stmt_iterato
 /* Fold the OMP_ORDERED_CLAUSES for the OMP_ORDERED in STMT if possible.  */
 
 static void
-lower_omp_ordered_clauses (gomp_ordered *ord_stmt, omp_context *ctx)
+lower_omp_ordered_clauses (gimple_stmt_iterator *gsi_p, gomp_ordered *ord_stmt,
+                          omp_context *ctx)
 {
   struct omp_for_data fd;
   if (!ctx->outer || gimple_code (ctx->outer->stmt) != GIMPLE_OMP_FOR)
     return;
 
   unsigned int len = gimple_omp_for_collapse (ctx->outer->stmt);
-  if (!len)
-    return;
-  struct omp_for_data_loop *loops
-    = (struct omp_for_data_loop *)
-    alloca (len * sizeof (struct omp_for_data_loop));
+  struct omp_for_data_loop *loops = XALLOCAVEC (struct omp_for_data_loop, len);
   extract_omp_for_data (as_a <gomp_for *> (ctx->outer->stmt), &fd, loops);
   if (!fd.ordered)
     return;
 
+  tree *list_p = gimple_omp_ordered_clauses_ptr (ord_stmt);
+  tree c = gimple_omp_ordered_clauses (ord_stmt);
+  if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND
+      && OMP_CLAUSE_DEPEND_KIND (c) == OMP_CLAUSE_DEPEND_SINK)
+    {
+      /* Merge depend clauses from multiple adjacent
+        #pragma omp ordered depend(sink:...) constructs
+        into one #pragma omp ordered depend(sink:...), so that
+        we can optimize them together.  */
+      gimple_stmt_iterator gsi = *gsi_p;
+      gsi_next (&gsi);
+      while (!gsi_end_p (gsi))
+       {
+         gimple stmt = gsi_stmt (gsi);
+         if (is_gimple_debug (stmt)
+             || gimple_code (stmt) == GIMPLE_NOP)
+           {
+             gsi_next (&gsi);
+             continue;
+           }
+         if (gimple_code (stmt) != GIMPLE_OMP_ORDERED)
+           break;
+         gomp_ordered *ord_stmt2 = as_a <gomp_ordered *> (stmt);
+         c = gimple_omp_ordered_clauses (ord_stmt2);
+         if (c == NULL_TREE
+             || OMP_CLAUSE_CODE (c) != OMP_CLAUSE_DEPEND
+             || OMP_CLAUSE_DEPEND_KIND (c) != OMP_CLAUSE_DEPEND_SINK)
+           break;
+         while (*list_p)
+           list_p = &OMP_CLAUSE_CHAIN (*list_p);
+         *list_p = c;
+         gsi_remove (&gsi, true);
+       }
+    }
+
   /* Canonicalize sink dependence clauses into one folded clause if
      possible.
 
@@ -12183,8 +12222,7 @@ lower_omp_ordered_clauses (gomp_ordered
   tree *iter_vars = (tree *) alloca (sizeof (tree) * len);
   memset (iter_vars, 0, sizeof (tree) * len);
 
-  tree *list_p = gimple_omp_ordered_clauses_ptr (ord_stmt);
-  tree c;
+  list_p = gimple_omp_ordered_clauses_ptr (ord_stmt);
   unsigned int i;
   while ((c = *list_p) != NULL)
     {
@@ -12317,6 +12355,11 @@ lower_omp_ordered_clauses (gomp_ordered
  lower_omp_ordered_ret:
   sbitmap_free (folded_deps_used);
   folded_deps.release ();
+
+  /* Ordered without clauses is #pragma omp threads, while we want
+     a nop instead if we remove all clauses.  */
+  if (gimple_omp_ordered_clauses (ord_stmt) == NULL_TREE)
+    gsi_replace (gsi_p, gimple_build_nop (), true);
 }
 
 
@@ -12333,7 +12376,12 @@ lower_omp_ordered (gimple_stmt_iterator
   bool simd
     = find_omp_clause (gimple_omp_ordered_clauses (ord_stmt), OMP_CLAUSE_SIMD);
 
-  lower_omp_ordered_clauses (ord_stmt, ctx);
+  if (find_omp_clause (gimple_omp_ordered_clauses (ord_stmt),
+                      OMP_CLAUSE_DEPEND))
+    {
+      lower_omp_ordered_clauses (gsi_p, ord_stmt, ctx);
+      return;
+    }
 
   push_gimplify_context ();
 
@@ -14979,13 +15027,21 @@ make_gimple_omp_edges (basic_block bb, s
     case GIMPLE_OMP_TEAMS:
     case GIMPLE_OMP_MASTER:
     case GIMPLE_OMP_TASKGROUP:
-    case GIMPLE_OMP_ORDERED:
     case GIMPLE_OMP_CRITICAL:
     case GIMPLE_OMP_SECTION:
       cur_region = new_omp_region (bb, code, cur_region);
       fallthru = true;
       break;
 
+    case GIMPLE_OMP_ORDERED:
+      cur_region = new_omp_region (bb, code, cur_region);
+      fallthru = true;
+      if (find_omp_clause (gimple_omp_ordered_clauses
+                            (as_a <gomp_ordered *> (last)),
+                          OMP_CLAUSE_DEPEND))
+       cur_region = cur_region->outer;
+      break;
+
     case GIMPLE_OMP_TARGET:
       cur_region = new_omp_region (bb, code, cur_region);
       fallthru = true;

        Jakub

Reply via email to