Hi!

This is something that happened to work in 4.4 and earlier, before
DECL_GIMPLE_FORMAL_TEMP_P removal.  If use_pointer_for_field needs to return
true because something is shared in a nested parallel and thus in-out
wouldn't work, as each thread would have its own location, and that var
isn't addressable, before DECL_GIMPLE_FORMAL_TEMP_P removal
.omp_data_2.o.y = &y;
would be gimplified as is and nothing complained about the missing
TREE_ADDRESSABLE on y, supposedly because ompexp cleaned it up.
But after that change, i.e. in 4.5+, the above is gimplified into
y.3 = y;
.omp_data_2.o.y = &y.3;
and thus the inner parallel modifies a wrong variable.
Fixed by treating it like the other case where we need to make
the var addressable for tasks.

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

2011-07-29  Jakub Jelinek  <ja...@redhat.com>

        PR middle-end/49897
        PR middle-end/49898
        * omp-low.c (use_pointer_for_field): If disallowing copy-in/out
        in nested parallel and outer is a gimple_reg, mark it as addressable
        and set its bit in task_shared_vars bitmap too.

        * testsuite/libgomp.c/pr49897-1.c: New test.
        * testsuite/libgomp.c/pr49897-2.c: New test.
        * testsuite/libgomp.c/pr49898-1.c: New test.
        * testsuite/libgomp.c/pr49898-2.c: New test.

--- gcc/omp-low.c.jj    2011-07-21 09:54:49.000000000 +0200
+++ gcc/omp-low.c       2011-07-29 16:31:08.000000000 +0200
@@ -781,7 +781,7 @@ use_pointer_for_field (tree decl, omp_co
                  break;
 
              if (c)
-               return true;
+               goto maybe_mark_addressable_and_ret;
            }
        }
 
@@ -791,7 +791,9 @@ use_pointer_for_field (tree decl, omp_co
         returns, the task hasn't necessarily terminated.  */
       if (!TREE_READONLY (decl) && is_task_ctx (shared_ctx))
        {
-         tree outer = maybe_lookup_decl_in_outer_ctx (decl, shared_ctx);
+         tree outer;
+       maybe_mark_addressable_and_ret:
+         outer = maybe_lookup_decl_in_outer_ctx (decl, shared_ctx);
          if (is_gimple_reg (outer))
            {
              /* Taking address of OUTER in lower_send_shared_vars
--- libgomp/testsuite/libgomp.c/pr49897-1.c.jj  2011-07-29 17:03:07.000000000 
+0200
+++ libgomp/testsuite/libgomp.c/pr49897-1.c     2011-07-29 17:00:23.000000000 
+0200
@@ -0,0 +1,31 @@
+/* PR middle-end/49897 */
+/* { dg-do run } */
+
+extern void abort (void);
+
+int
+main ()
+{
+  int i, j, x = 0, y, sum = 0;
+#pragma omp parallel reduction(+:sum)
+  {
+  #pragma omp for firstprivate(x) lastprivate(x, y)
+    for (i = 0; i < 10; i++)
+      {
+       x = i;
+       y = 0;
+      #pragma omp parallel reduction(+:sum)
+       {
+       #pragma omp for firstprivate(y) lastprivate(y)
+         for (j = 0; j < 10; j++)
+           {
+             y = j;
+             sum += y;
+           }
+       }
+      }
+  }
+  if (x != 9 || y != 9 || sum != 450)
+    abort ();
+  return 0;
+}
--- libgomp/testsuite/libgomp.c/pr49897-2.c.jj  2011-07-29 17:03:07.000000000 
+0200
+++ libgomp/testsuite/libgomp.c/pr49897-2.c     2011-07-29 17:00:07.000000000 
+0200
@@ -0,0 +1,25 @@
+/* PR middle-end/49897 */
+/* { dg-do run } */
+
+extern void abort (void);
+
+int
+main ()
+{
+  int i, j, x = 0, y, sum = 0;
+#pragma omp parallel for reduction(+:sum) firstprivate(x) lastprivate(x, y)
+  for (i = 0; i < 10; i++)
+    {
+      x = i;
+      y = 0;
+    #pragma omp parallel for reduction(+:sum) firstprivate(y) lastprivate(y)
+      for (j = 0; j < 10; j++)
+       {
+         y = j;
+         sum += y;
+       }
+    }
+  if (x != 9 || y != 9 || sum != 450)
+    abort ();
+  return 0;
+}
--- libgomp/testsuite/libgomp.c/pr49898-1.c.jj  2011-07-29 17:03:07.000000000 
+0200
+++ libgomp/testsuite/libgomp.c/pr49898-1.c     2011-07-29 17:01:44.000000000 
+0200
@@ -0,0 +1,26 @@
+/* PR middle-end/49898 */
+/* { dg-do run } */
+
+extern void abort (void);
+
+int
+main ()
+{
+  int i, j, sum = 0;
+#pragma omp parallel
+  {
+  #pragma omp for reduction(+:sum)
+    for (i = 0; i < 10; i++)
+      {
+      #pragma omp parallel
+       {
+       #pragma omp for reduction(+:sum)
+         for (j = 0; j < 10; j++)
+           sum += j;
+       }
+      }
+  }
+  if (sum != 450)
+    abort ();
+  return 0;
+}
--- libgomp/testsuite/libgomp.c/pr49898-2.c.jj  2011-07-29 17:03:07.000000000 
+0200
+++ libgomp/testsuite/libgomp.c/pr49898-2.c     2011-07-29 17:02:28.000000000 
+0200
@@ -0,0 +1,18 @@
+/* PR middle-end/49898 */
+/* { dg-do run } */
+
+extern void abort (void);
+
+int
+main ()
+{
+  int i, j, sum = 0;
+#pragma omp parallel for reduction(+:sum)
+  for (i = 0; i < 10; i++)
+    #pragma omp parallel for reduction(+:sum)
+    for (j = 0; j < 10; j++)
+      sum += j;
+  if (sum != 450)
+    abort ();
+  return 0;
+}

        Jakub

Reply via email to