Hi!

allocatable privatized vars need access to the outer var for sizing,
but unlike e.g. firstprivate the standard allows them on orphaned
worksharing constructs or when the var is already private outside of
the worksharing construct.  Therefore, we should treat it similarly
to outer refs on simd construct.

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

2016-11-23  Jakub Jelinek  <ja...@redhat.com>

        PR middle-end/69183
        * omp-low.c (build_outer_var_ref): Change lastprivate argument
        to code, pass it recursively, adjust uses.  For OMP_CLAUSE_PRIVATE
        on worksharing constructs, treat it like clauses on simd construct.
        Formatting fix.
        (lower_rec_input_clauses): For OMP_CLAUSE_PRIVATE_OUTER_REF pass
        OMP_CLAUSE_PRIVATE as last argument to build_outer_var_ref.
        (lower_lastprivate_clauses): Pass OMP_CLAUSE_LASTPRIVATE instead
        of true as last argument to build_outer_var_ref.

        * gfortran.dg/gomp/pr69183.f90: New test.

--- gcc/omp-low.c.jj    2016-11-22 21:31:49.000000000 +0100
+++ gcc/omp-low.c       2016-11-23 16:20:31.830429649 +0100
@@ -1283,7 +1283,8 @@ build_receiver_ref (tree var, bool by_re
    this is some variable.  */
 
 static tree
-build_outer_var_ref (tree var, omp_context *ctx, bool lastprivate = false)
+build_outer_var_ref (tree var, omp_context *ctx,
+                    enum omp_clause_code code = OMP_CLAUSE_ERROR)
 {
   tree x;
 
@@ -1292,7 +1293,7 @@ build_outer_var_ref (tree var, omp_conte
   else if (is_variable_sized (var))
     {
       x = TREE_OPERAND (DECL_VALUE_EXPR (var), 0);
-      x = build_outer_var_ref (x, ctx, lastprivate);
+      x = build_outer_var_ref (x, ctx, code);
       x = build_simple_mem_ref (x);
     }
   else if (is_taskreg_ctx (ctx))
@@ -1300,11 +1301,17 @@ build_outer_var_ref (tree var, omp_conte
       bool by_ref = use_pointer_for_field (var, NULL);
       x = build_receiver_ref (var, by_ref, ctx);
     }
-  else if (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
-          && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD)
-    {
-      /* #pragma omp simd isn't a worksharing construct, and can reference even
-        private vars in its linear etc. clauses.  */
+  else if ((gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
+           && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD)
+          || (code == OMP_CLAUSE_PRIVATE
+              && (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
+                  || gimple_code (ctx->stmt) == GIMPLE_OMP_SECTIONS
+                  || gimple_code (ctx->stmt) == GIMPLE_OMP_SINGLE)))
+    {
+      /* #pragma omp simd isn't a worksharing construct, and can reference
+        even private vars in its linear etc. clauses.
+        Similarly for OMP_CLAUSE_PRIVATE with outer ref, that can refer
+        to private vars in all worksharing constructs.  */
       x = NULL_TREE;
       if (ctx->outer && is_taskreg_ctx (ctx))
        x = lookup_decl (var, ctx->outer);
@@ -1313,7 +1320,7 @@ build_outer_var_ref (tree var, omp_conte
       if (x == NULL_TREE)
        x = var;
     }
-  else if (lastprivate && is_taskloop_ctx (ctx))
+  else if (code == OMP_CLAUSE_LASTPRIVATE && is_taskloop_ctx (ctx))
     {
       gcc_assert (ctx->outer);
       splay_tree_node n
@@ -1350,7 +1357,7 @@ build_outer_var_ref (tree var, omp_conte
          gcc_assert (outer
                      && gimple_code (outer->stmt) != GIMPLE_OMP_GRID_BODY);
        }
-       x = lookup_decl (var, outer);
+      x = lookup_decl (var, outer);
     }
   else if (is_reference (var))
     /* This can happen with orphaned constructs.  If var is reference, it is
@@ -5031,7 +5038,7 @@ lower_rec_input_clauses (tree clauses, g
                  if (is_task_ctx (ctx))
                    x = build_receiver_ref (var, false, ctx);
                  else
-                   x = build_outer_var_ref (var, ctx);
+                   x = build_outer_var_ref (var, ctx, OMP_CLAUSE_PRIVATE);
                }
              else
                x = NULL;
@@ -5687,7 +5694,7 @@ lower_lastprivate_clauses (tree clauses,
                x = ovar;
            }
          if (!x)
-           x = build_outer_var_ref (var, ctx, true);
+           x = build_outer_var_ref (var, ctx, OMP_CLAUSE_LASTPRIVATE);
          if (is_reference (var))
            new_var = build_simple_mem_ref_loc (clause_loc, new_var);
          x = lang_hooks.decls.omp_clause_assign_op (c, x, new_var);
--- gcc/testsuite/gfortran.dg/gomp/pr69183.f90.jj       2016-11-23 
16:18:55.801635373 +0100
+++ gcc/testsuite/gfortran.dg/gomp/pr69183.f90  2016-11-23 16:18:41.000000000 
+0100
@@ -0,0 +1,11 @@
+! PR middle-end/69183
+! { dg-do compile }
+
+program pr69183
+  integer, allocatable :: z
+  integer :: i
+  !$omp do private(z)
+  do i = 1, 2
+    z = i
+  end do
+end

        Jakub

Reply via email to