Hi!

The following patch adds lastprivate(conditional:) support for simd
construct (at least when not combined with worksharing construct, that will
be done incrementally).

Bootstrapped/regtested on x86_64-linux and i686-linux, committed to trunk.

2019-05-31  Jakub Jelinek  <ja...@redhat.com>

        * tree.h (OMP_CLAUSE__CONDTEMP__ITER): Define.
        * gimplify.c (gimplify_scan_omp_clauses): Allow lastprivate conditional
        on OMP_SIMD if not nested inside of worksharing loop that also has
        lastprivate conditional clause for the same decl.
        (gimplify_omp_for): Add _condtemp_ clauses to OMP_SIMD if needed.
        * omp-low.c (scan_sharing_clauses): Handle OMP_CLAUSE__CONDTEMP_ also
        on simd.
        (lower_rec_input_clauses): Likewise.  Handle lastprivate conditional
        on simd construct.
        (lower_lastprivate_conditional_clauses): Handle lastprivate conditional
        on simd construct.
        (lower_lastprivate_clauses): Likewise.
        (lower_omp_sections): Call lower_lastprivate_conditional_clauses before
        calling lower_rec_input_clauses.
        (lower_omp_for): Likewise.
        (lower_omp_1): Use first rather than second OMP_CLAUSE__CONDTEMP_
        clause on simd construct.
        * omp-expand.c (expand_omp_simd): Initialize cond_var if
        OMP_CLAUSE__CONDTEMP_ clause is present.

        * c-c++-common/gomp/lastprivate-conditional-2.c (foo): Don't expect
        a sorry on lastprivate conditional on simd construct.
        * gcc.dg/vect/vect-simd-6.c: New test.
        * gcc.dg/vect/vect-simd-7.c: New test.

--- gcc/tree.h.jj       2019-05-29 09:42:27.337398449 +0200
+++ gcc/tree.h  2019-05-31 15:22:18.098541471 +0200
@@ -1752,6 +1752,10 @@ class auto_suppress_location_wrappers
 #define OMP_CLAUSE__GRIDDIM__GROUP(NODE) \
   OMP_CLAUSE_OPERAND (OMP_CLAUSE_SUBCODE_CHECK (NODE, OMP_CLAUSE__GRIDDIM_), 1)
 
+/* _CONDTEMP_ holding temporary with iteration count.  */
+#define OMP_CLAUSE__CONDTEMP__ITER(NODE) \
+  (OMP_CLAUSE_SUBCODE_CHECK (NODE, OMP_CLAUSE__CONDTEMP_)->base.public_flag)
+
 /* SSA_NAME accessors.  */
 
 /* Whether SSA_NAME NODE is a virtual operand.  This simply caches the
--- gcc/gimplify.c.jj   2019-05-30 23:19:14.464931841 +0200
+++ gcc/gimplify.c      2019-05-31 18:52:21.487672269 +0200
@@ -8146,17 +8146,29 @@ gimplify_scan_omp_clauses (tree *list_p,
            }
          if (OMP_CLAUSE_LASTPRIVATE_CONDITIONAL (c))
            {
-             if (code == OMP_FOR
-                 || code == OMP_SECTIONS
-                 || region_type == ORT_COMBINED_PARALLEL)
-               flags |= GOVD_LASTPRIVATE_CONDITIONAL;
-             else
+             splay_tree_node n = NULL;
+             if (code == OMP_SIMD
+                 && outer_ctx
+                 && outer_ctx->region_type == ORT_WORKSHARE)
+               {
+                 n = splay_tree_lookup (outer_ctx->variables,
+                                        (splay_tree_key) decl);
+                 if (n == NULL
+                     && outer_ctx->outer_context
+                     && (outer_ctx->outer_context->region_type
+                         == ORT_COMBINED_PARALLEL))
+                   n = splay_tree_lookup (outer_ctx->outer_context->variables,
+                                          (splay_tree_key) decl);
+               }
+             if (n && (n->value & GOVD_LASTPRIVATE_CONDITIONAL) != 0)
                {
                  sorry_at (OMP_CLAUSE_LOCATION (c),
                            "%<conditional%> modifier on %<lastprivate%> "
                            "clause not supported yet");
                  OMP_CLAUSE_LASTPRIVATE_CONDITIONAL (c) = 0;
                }
+             else
+               flags |= GOVD_LASTPRIVATE_CONDITIONAL;
            }
          if (outer_ctx
              && (outer_ctx->region_type == ORT_COMBINED_PARALLEL
@@ -11559,6 +11571,28 @@ gimplify_omp_for (tree *expr_p, gimple_s
          omp_add_variable (ctx, var, GOVD_CONDTEMP | GOVD_SEEN);
        }
     }
+  else if (TREE_CODE (orig_for_stmt) == OMP_SIMD)
+    {
+      unsigned lastprivate_conditional = 0;
+      for (tree c = gimple_omp_for_clauses (gfor); c; c = OMP_CLAUSE_CHAIN (c))
+       if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
+           && OMP_CLAUSE_LASTPRIVATE_CONDITIONAL (c))
+         ++lastprivate_conditional;
+      if (lastprivate_conditional)
+       {
+         struct omp_for_data fd;
+         omp_extract_for_data (gfor, &fd, NULL);
+         tree type = unsigned_type_for (fd.iter_type);
+         while (lastprivate_conditional--)
+           {
+             tree c = build_omp_clause (UNKNOWN_LOCATION,
+                                        OMP_CLAUSE__CONDTEMP_);
+             OMP_CLAUSE_DECL (c) = create_tmp_var (type);
+             OMP_CLAUSE_CHAIN (c) = gimple_omp_for_clauses (gfor);
+             gimple_omp_for_set_clauses (gfor, c);
+           }
+       }
+    }
 
   if (ret != GS_ALL_DONE)
     return GS_ERROR;
--- gcc/omp-low.c.jj    2019-05-31 11:52:20.491195088 +0200
+++ gcc/omp-low.c       2019-05-31 19:35:04.980181644 +0200
@@ -1414,12 +1414,16 @@ scan_sharing_clauses (tree clauses, omp_
          break;
 
        case OMP_CLAUSE__CONDTEMP_:
+         decl = OMP_CLAUSE_DECL (c);
          if (is_parallel_ctx (ctx))
            {
-             decl = OMP_CLAUSE_DECL (c);
              install_var_field (decl, false, 3, ctx);
              install_var_local (decl, ctx);
            }
+         else if (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
+                  && (gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD)
+                  && !OMP_CLAUSE__CONDTEMP__ITER (c))
+           install_var_local (decl, ctx);
          break;
 
        case OMP_CLAUSE__CACHE_:
@@ -3840,6 +3844,11 @@ lower_rec_input_clauses (tree clauses, g
          if (integer_onep (OMP_CLAUSE_SIMDLEN_EXPR (c)))
            sctx.max_vf = 1;
          break;
+       case OMP_CLAUSE__CONDTEMP_:
+         /* FIXME: lastprivate(conditional:) not handled for SIMT yet.  */
+         if (sctx.is_simt)
+           sctx.max_vf = 1;
+         break;
        default:
          continue;
        }
@@ -4054,7 +4063,8 @@ lower_rec_input_clauses (tree clauses, g
                }
              continue;
            case OMP_CLAUSE__CONDTEMP_:
-             if (is_parallel_ctx (ctx))
+             if (is_parallel_ctx (ctx)
+                 || (is_simd && !OMP_CLAUSE__CONDTEMP__ITER (c)))
                break;
              continue;
            default:
@@ -4730,6 +4740,11 @@ lower_rec_input_clauses (tree clauses, g
                  SET_DECL_VALUE_EXPR (new_var, x);
                  DECL_HAS_VALUE_EXPR_P (new_var) = 1;
                }
+             else if (is_simd && !OMP_CLAUSE__CONDTEMP__ITER (c))
+               {
+                 x = build_zero_cst (TREE_TYPE (var));
+                 goto do_private;
+               }
              break;
 
            case OMP_CLAUSE_LASTPRIVATE:
@@ -4757,15 +4772,52 @@ lower_rec_input_clauses (tree clauses, g
                {
                  tree y = lang_hooks.decls.omp_clause_dtor (c, new_var);
                  if ((TREE_ADDRESSABLE (new_var) || nx || y
-                      || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE)
+                      || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
+                      || OMP_CLAUSE_CODE (c) == OMP_CLAUSE__CONDTEMP_)
                      && lower_rec_simd_input_clauses (new_var, ctx, &sctx,
                                                       ivar, lvar))
                    {
                      if (nx)
                        x = lang_hooks.decls.omp_clause_default_ctor
                                                (c, unshare_expr (ivar), x);
+                     else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE__CONDTEMP_)
+                       {
+                         x = build2 (MODIFY_EXPR, TREE_TYPE (ivar),
+                                     unshare_expr (ivar), x);
+                         nx = x;
+                       }
                      if (nx && x)
                        gimplify_and_add (x, &llist[0]);
+                     if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
+                         && OMP_CLAUSE_LASTPRIVATE_CONDITIONAL (c))
+                       {
+                         tree v
+                           = *ctx->lastprivate_conditional_map->get (new_var);
+                         tree t = create_tmp_var (TREE_TYPE (v));
+                         tree z = build_zero_cst (TREE_TYPE (v));
+                         tree orig_v
+                           = build_outer_var_ref (var, ctx,
+                                                  OMP_CLAUSE_LASTPRIVATE);
+                         gimple_seq_add_stmt (dlist,
+                                              gimple_build_assign (t, z));
+                         gcc_assert (DECL_HAS_VALUE_EXPR_P (v));
+                         tree civar = DECL_VALUE_EXPR (v);
+                         gcc_assert (TREE_CODE (civar) == ARRAY_REF);
+                         civar = unshare_expr (civar);
+                         TREE_OPERAND (civar, 1) = sctx.idx;
+                         x = build2 (MODIFY_EXPR, TREE_TYPE (t), t,
+                                     unshare_expr (civar));
+                         x = build2 (COMPOUND_EXPR, TREE_TYPE (orig_v), x,
+                                     build2 (MODIFY_EXPR, TREE_TYPE (orig_v),
+                                             orig_v, unshare_expr (ivar)));
+                         tree cond = build2 (LT_EXPR, boolean_type_node, t,
+                                             civar);
+                         x = build3 (COND_EXPR, void_type_node, cond, x,
+                                     void_node);
+                         gimple_seq tseq = NULL;
+                         gimplify_and_add (x, &tseq);
+                         gimple_seq_add_seq (&llist[1], tseq);
+                       }
                      if (y)
                        {
                          y = lang_hooks.decls.omp_clause_dtor (c, ivar);
@@ -5222,7 +5274,17 @@ lower_rec_input_clauses (tree clauses, g
     }
 
   if (known_eq (sctx.max_vf, 1U))
-    sctx.is_simt = false;
+    {
+      sctx.is_simt = false;
+      if (ctx->lastprivate_conditional_map)
+       {
+         /* When not vectorized, treat lastprivate(conditional:) like
+            normal lastprivate, as there will be just one simd lane
+            writing the privatized variable.  */
+         delete ctx->lastprivate_conditional_map;
+         ctx->lastprivate_conditional_map = NULL;
+       }
+    }
 
   if (nonconst_simd_if)
     {
@@ -5398,10 +5460,39 @@ lower_lastprivate_conditional_clauses (t
   tree iter_type = NULL_TREE;
   tree cond_ptr = NULL_TREE;
   tree iter_var = NULL_TREE;
+  bool is_simd = (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
+                 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD);
+  tree next = *clauses;
   for (tree c = *clauses; c; c = OMP_CLAUSE_CHAIN (c))
     if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
        && OMP_CLAUSE_LASTPRIVATE_CONDITIONAL (c))
       {
+       if (is_simd)
+         {
+           tree cc = omp_find_clause (next, OMP_CLAUSE__CONDTEMP_);
+           gcc_assert (cc);
+           if (iter_type == NULL_TREE)
+             {
+               iter_type = TREE_TYPE (OMP_CLAUSE_DECL (cc));
+               iter_var = create_tmp_var_raw (iter_type);
+               DECL_CONTEXT (iter_var) = current_function_decl;
+               DECL_SEEN_IN_BIND_EXPR_P (iter_var) = 1;
+               DECL_CHAIN (iter_var) = ctx->block_vars;
+               ctx->block_vars = iter_var;
+               tree c3
+                 = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE__CONDTEMP_);
+               OMP_CLAUSE__CONDTEMP__ITER (c3) = 1;
+               OMP_CLAUSE_DECL (c3) = iter_var;
+               OMP_CLAUSE_CHAIN (c3) = *clauses;
+               *clauses = c3;
+               ctx->lastprivate_conditional_map = new hash_map<tree, tree>;
+             }
+           next = OMP_CLAUSE_CHAIN (cc);
+           tree o = lookup_decl (OMP_CLAUSE_DECL (c), ctx);
+           tree v = lookup_decl (OMP_CLAUSE_DECL (cc), ctx);
+           ctx->lastprivate_conditional_map->put (o, v);
+           continue;
+         }
        if (iter_type == NULL)
          {
            if (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR)
@@ -5440,6 +5531,7 @@ lower_lastprivate_conditional_clauses (t
            ctx->block_vars = iter_var;
            tree c3
              = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE__CONDTEMP_);
+           OMP_CLAUSE__CONDTEMP__ITER (c3) = 1;
            OMP_CLAUSE_DECL (c3) = iter_var;
            OMP_CLAUSE_CHAIN (c3) = OMP_CLAUSE_CHAIN (c2);
            OMP_CLAUSE_CHAIN (c2) = c3;
@@ -5559,9 +5651,12 @@ lower_lastprivate_clauses (tree clauses,
       tree lab2 = NULL_TREE;
 
       if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
-         && OMP_CLAUSE_LASTPRIVATE_CONDITIONAL (c))
+         && OMP_CLAUSE_LASTPRIVATE_CONDITIONAL (c)
+         && ctx->lastprivate_conditional_map)
        {
-         gcc_assert (body_p && ctx->lastprivate_conditional_map);
+         gcc_assert (body_p);
+         if (simduid)
+           goto next;
          if (cond_ptr == NULL_TREE)
            {
              cond_ptr = omp_find_clause (orig_clauses, OMP_CLAUSE__CONDTEMP_);
@@ -5701,6 +5796,7 @@ lower_lastprivate_clauses (tree clauses,
            gimple_seq_add_stmt (this_stmt_list, gimple_build_label (lab2));
        }
 
+     next:
       c = OMP_CLAUSE_CHAIN (c);
       if (c == NULL && !par_clauses)
        {
@@ -6826,15 +6922,15 @@ lower_omp_sections (gimple_stmt_iterator
       gimple_seq_add_stmt (&ilist, gimple_build_assign (rtmp, temp));
     }
 
+  tree *clauses_ptr = gimple_omp_sections_clauses_ptr (stmt);
+  lower_lastprivate_conditional_clauses (clauses_ptr, ctx);
+
   lower_rec_input_clauses (gimple_omp_sections_clauses (stmt),
                           &ilist, &dlist, ctx, NULL);
 
   control = create_tmp_var (unsigned_type_node, ".section");
   gimple_omp_sections_set_control (stmt, control);
 
-  tree *clauses_ptr = gimple_omp_sections_clauses_ptr (stmt);
-  lower_lastprivate_conditional_clauses (clauses_ptr, ctx);
-
   new_body = gimple_omp_body (stmt);
   gimple_omp_set_body (stmt, NULL);
   tgsi = gsi_start (new_body);
@@ -8486,14 +8582,14 @@ lower_omp_for (gimple_stmt_iterator *gsi
       gimple_seq_add_stmt (&body, gimple_build_assign (rtmp, temp));
     }
 
+  lower_lastprivate_conditional_clauses (gimple_omp_for_clauses_ptr (stmt),
+                                        ctx);
+
   lower_rec_input_clauses (gimple_omp_for_clauses (stmt), &body, &dlist, ctx,
                           fdp);
   gimple_seq_add_seq (rclauses ? &tred_ilist : &body,
                      gimple_omp_for_pre_body (stmt));
 
-  lower_lastprivate_conditional_clauses (gimple_omp_for_clauses_ptr (stmt),
-                                        ctx);
-
   lower_omp (gimple_omp_body_ptr (stmt), ctx);
 
   /* Lower the header expressions.  At this point, we can assume that
@@ -10721,8 +10817,10 @@ lower_omp_1 (gimple_stmt_iterator *gsi_p
                else
                  clauses = gimple_omp_sections_clauses (up->stmt);
                tree c = omp_find_clause (clauses, OMP_CLAUSE__CONDTEMP_);
-               c = omp_find_clause (OMP_CLAUSE_CHAIN (c),
-                                    OMP_CLAUSE__CONDTEMP_);
+               if (!OMP_CLAUSE__CONDTEMP__ITER (c))
+                 c = omp_find_clause (OMP_CLAUSE_CHAIN (c),
+                                      OMP_CLAUSE__CONDTEMP_);
+               gcc_assert (OMP_CLAUSE__CONDTEMP__ITER (c));
                gimple *g = gimple_build_assign (*v, OMP_CLAUSE_DECL (c));
                gsi_insert_after (gsi_p, g, GSI_SAME_STMT);
              }
--- gcc/omp-expand.c.jj 2019-05-30 23:19:14.470931743 +0200
+++ gcc/omp-expand.c    2019-05-31 17:53:31.488672774 +0200
@@ -4908,7 +4908,10 @@ expand_omp_simd (struct omp_region *regi
                              OMP_CLAUSE_IF);
   tree simdlen = omp_find_clause (gimple_omp_for_clauses (fd->for_stmt),
                                  OMP_CLAUSE_SIMDLEN);
+  tree condtemp = omp_find_clause (gimple_omp_for_clauses (fd->for_stmt),
+                                  OMP_CLAUSE__CONDTEMP_);
   tree n1, n2;
+  tree cond_var = condtemp ? OMP_CLAUSE_DECL (condtemp) : NULL_TREE;
 
   if (safelen)
     {
@@ -5038,6 +5041,18 @@ expand_omp_simd (struct omp_region *regi
            expand_omp_build_assign (&gsi, fd->loops[i].v, t);
          }
     }
+  if (cond_var)
+    {
+      if (POINTER_TYPE_P (type)
+         || TREE_CODE (n1) != INTEGER_CST
+         || fd->loop.cond_code != LT_EXPR
+         || tree_int_cst_sgn (n1) != 1)
+       expand_omp_build_assign (&gsi, cond_var,
+                                build_one_cst (TREE_TYPE (cond_var)));
+      else
+       expand_omp_build_assign (&gsi, cond_var,
+                                fold_convert (TREE_TYPE (cond_var), n1));
+    }
 
   /* Remove the GIMPLE_OMP_FOR statement.  */
   gsi_remove (&gsi, true);
@@ -5103,6 +5118,19 @@ expand_omp_simd (struct omp_region *regi
              expand_omp_build_assign (&gsi, fd->loops[i].v, t);
            }
        }
+      if (cond_var)
+       {
+         if (POINTER_TYPE_P (type)
+             || TREE_CODE (n1) != INTEGER_CST
+             || fd->loop.cond_code != LT_EXPR
+             || tree_int_cst_sgn (n1) != 1)
+           t = fold_build2 (PLUS_EXPR, TREE_TYPE (cond_var), cond_var,
+                            build_one_cst (TREE_TYPE (cond_var)));
+         else
+           t = fold_build2 (PLUS_EXPR, TREE_TYPE (cond_var), cond_var,
+                            fold_convert (TREE_TYPE (cond_var), step));
+         expand_omp_build_assign (&gsi, cond_var, t);
+       }
 
       /* Remove GIMPLE_OMP_CONTINUE.  */
       gsi_remove (&gsi, true);
--- gcc/testsuite/c-c++-common/gomp/lastprivate-conditional-2.c.jj      
2019-05-29 09:49:20.450598508 +0200
+++ gcc/testsuite/c-c++-common/gomp/lastprivate-conditional-2.c 2019-05-31 
19:49:36.577018973 +0200
@@ -8,7 +8,7 @@ foo (int *p)
   for (i = 0; i < 32; i++)
     if (p[i])
       a = i;
-  #pragma omp simd lastprivate (conditional: b) /* { dg-message "not supported 
yet" } */
+  #pragma omp simd lastprivate (conditional: b)
   for (i = 0; i < 32; i++)
     if (p[i])
       b = i;
--- gcc/testsuite/gcc.dg/vect/vect-simd-6.c.jj  2019-05-31 18:33:20.810088504 
+0200
+++ gcc/testsuite/gcc.dg/vect/vect-simd-6.c     2019-05-31 18:39:27.113174246 
+0200
@@ -0,0 +1,52 @@
+/* { dg-additional-options "-fopenmp-simd" } */
+/* { dg-final { scan-tree-dump-times "vectorized \[12] loops" 2 "vect" { 
target vect_condition } } } */
+
+#include "tree-vect.h"
+
+int v;
+
+__attribute__((noipa)) int
+foo (int *a)
+{
+  int x = 5;
+  #pragma omp simd lastprivate (conditional: x)
+  for (int i = 0; i < 128; i++)
+    if (a[i])
+      x = a[i];
+  return x;
+}
+
+__attribute__((noipa)) int
+bar (int *a, int *b)
+{
+  int x = 0;
+  #pragma omp simd lastprivate (conditional: x, v)
+  for (int i = 16; i < 128; ++i)
+    {
+      if (a[i])
+       x = a[i];
+      if (b[i])
+       v = b[i] + 10;
+    }
+  return x;
+}
+
+int
+main ()
+{
+  int a[128], b[128], i;
+  check_vect ();
+  for (i = 0; i < 128; i++)
+    {
+      a[i] = ((i % 11) == 2) ? i + 10 : 0;
+      asm volatile ("" : "+g" (i));
+      b[i] = ((i % 13) == 5) ? i * 2 : 0;
+    }
+  if (foo (a) != 133)
+    abort ();
+  if (bar (b, a) != 244)
+    abort ();
+  if (v != 143)
+    abort ();
+  return 0;
+}
--- gcc/testsuite/gcc.dg/vect/vect-simd-7.c.jj  2019-05-31 19:36:59.609320792 
+0200
+++ gcc/testsuite/gcc.dg/vect/vect-simd-7.c     2019-05-31 19:37:18.718010587 
+0200
@@ -0,0 +1,51 @@
+/* { dg-additional-options "-fopenmp-simd" } */
+
+#include "tree-vect.h"
+
+int v;
+
+__attribute__((noipa)) int
+foo (int *a)
+{
+  int x = 5;
+  #pragma omp simd lastprivate (conditional: x) safelen (1)
+  for (int i = 0; i < 128; i++)
+    if (a[i])
+      x = a[i];
+  return x;
+}
+
+__attribute__((noipa)) int
+bar (int *a, int *b)
+{
+  int x = 0;
+  #pragma omp simd lastprivate (conditional: x, v) if (0)
+  for (int i = 16; i < 128; ++i)
+    {
+      if (a[i])
+       x = a[i];
+      if (b[i])
+       v = b[i] + 10;
+    }
+  return x;
+}
+
+int
+main ()
+{
+  int a[128], b[128], i;
+  check_vect ();
+  for (i = 0; i < 128; i++)
+    {
+      a[i] = ((i % 11) == 2) ? i + 10 : 0;
+      asm volatile ("" : "+g" (i));
+      b[i] = ((i % 13) == 5) ? i * 2 : 0;
+    }
+  if (foo (a) != 133)
+    abort ();
+  if (bar (b, a) != 244)
+    abort ();
+  if (v != 143)
+    abort ();
+  return 0;
+}

        Jakub

Reply via email to