OSDN Git Service

PR other/39591
authorjakub <jakub@138bc75d-0d04-0410-961f-82ee72b054a4>
Wed, 1 Apr 2009 06:54:52 +0000 (06:54 +0000)
committerjakub <jakub@138bc75d-0d04-0410-961f-82ee72b054a4>
Wed, 1 Apr 2009 06:54:52 +0000 (06:54 +0000)
* omp-low.c (remove_exit_barrier): Don't optimize if there are any
addressable variables in the parallel that could go out of scope while
running queued tasks.

* testsuite/libgomp.c/pr39591-1.c: New test.
* testsuite/libgomp.c/pr39591-2.c: New test.
* testsuite/libgomp.c/pr39591-3.c: New test.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@145390 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/ChangeLog
gcc/omp-low.c
libgomp/ChangeLog
libgomp/testsuite/libgomp.c/pr39591-1.c [new file with mode: 0644]
libgomp/testsuite/libgomp.c/pr39591-2.c [new file with mode: 0644]
libgomp/testsuite/libgomp.c/pr39591-3.c [new file with mode: 0644]

index b767290..bbb7af8 100644 (file)
@@ -1,3 +1,10 @@
+2009-04-01  Jakub Jelinek  <jakub@redhat.com>
+
+       PR other/39591
+       * omp-low.c (remove_exit_barrier): Don't optimize if there are any
+       addressable variables in the parallel that could go out of scope while
+       running queued tasks.
+
 2009-04-01  Anatoly Sokolov  <aesok@post.ru>
 
        * config/avr/avr.h (avr_case_values_threshold): Remove declaration.
index 4065876..b96da5f 100644 (file)
@@ -3,7 +3,7 @@
    marshalling to implement data sharing and copying clauses.
    Contributed by Diego Novillo <dnovillo@redhat.com>
 
-   Copyright (C) 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
+   Copyright (C) 2005, 2006, 2007, 2008, 2009 Free Software Foundation, Inc.
 
 This file is part of GCC.
 
@@ -3123,6 +3123,7 @@ remove_exit_barrier (struct omp_region *region)
   edge_iterator ei;
   edge e;
   gimple stmt;
+  int any_addressable_vars = -1;
 
   exit_bb = region->exit;
 
@@ -3148,8 +3149,52 @@ remove_exit_barrier (struct omp_region *region)
       if (gsi_end_p (gsi))
        continue;
       stmt = gsi_stmt (gsi);
-      if (gimple_code (stmt) == GIMPLE_OMP_RETURN)
-       gimple_omp_return_set_nowait (stmt);
+      if (gimple_code (stmt) == GIMPLE_OMP_RETURN
+         && !gimple_omp_return_nowait_p (stmt))
+       {
+         /* OpenMP 3.0 tasks unfortunately prevent this optimization
+            in many cases.  If there could be tasks queued, the barrier
+            might be needed to let the tasks run before some local
+            variable of the parallel that the task uses as shared
+            runs out of scope.  The task can be spawned either
+            from within current function (this would be easy to check)
+            or from some function it calls and gets passed an address
+            of such a variable.  */
+         if (any_addressable_vars < 0)
+           {
+             gimple parallel_stmt = last_stmt (region->entry);
+             tree child_fun = gimple_omp_parallel_child_fn (parallel_stmt);
+             tree local_decls = DECL_STRUCT_FUNCTION (child_fun)->local_decls;
+             tree block;
+
+             any_addressable_vars = 0;
+             for (; local_decls; local_decls = TREE_CHAIN (local_decls))
+               if (TREE_ADDRESSABLE (TREE_VALUE (local_decls)))
+                 {
+                   any_addressable_vars = 1;
+                   break;
+                 }
+             for (block = gimple_block (stmt);
+                  !any_addressable_vars
+                  && block
+                  && TREE_CODE (block) == BLOCK;
+                  block = BLOCK_SUPERCONTEXT (block))
+               {
+                 for (local_decls = BLOCK_VARS (block);
+                      local_decls;
+                      local_decls = TREE_CHAIN (local_decls))
+                   if (TREE_ADDRESSABLE (local_decls))
+                     {
+                       any_addressable_vars = 1;
+                       break;
+                     }
+                 if (block == gimple_block (parallel_stmt))
+                   break;
+               }
+           }
+         if (!any_addressable_vars)
+           gimple_omp_return_set_nowait (stmt);
+       }
     }
 }
 
index a77fdde..15eb2c6 100644 (file)
@@ -1,3 +1,10 @@
+2009-04-01  Jakub Jelinek  <jakub@redhat.com>
+
+       PR other/39591
+       * testsuite/libgomp.c/pr39591-1.c: New test.
+       * testsuite/libgomp.c/pr39591-2.c: New test.
+       * testsuite/libgomp.c/pr39591-3.c: New test.
+
 2009-03-25  Uros Bizjak  <ubizjak@gmail.com>
 
        * testsuite/libgomp.c/atomic-5.c: Cleanup cpuid usage.
diff --git a/libgomp/testsuite/libgomp.c/pr39591-1.c b/libgomp/testsuite/libgomp.c/pr39591-1.c
new file mode 100644 (file)
index 0000000..dfd8d9e
--- /dev/null
@@ -0,0 +1,33 @@
+/* PR other/39591 */
+/* { dg-do run } */
+/* { dg-options "-O2" } */
+
+extern void abort (void);
+
+int err;
+
+int
+main (void)
+{
+#pragma omp parallel
+  {
+    int array[40];
+    int i;
+    for (i = 0; i < sizeof array / sizeof array[0]; i++)
+      array[i] = 0x55555555;
+
+#pragma omp for schedule(dynamic)
+    for (i = 0; i < 50; i++)
+#pragma omp task shared(array)
+      {
+       int j;
+       for (j = 0; j < sizeof array / sizeof array[0]; j++)
+         if (array[j] != 0x55555555)
+#pragma omp atomic
+           err++;
+      }
+  }
+  if (err)
+    abort ();
+  return 0;
+}
diff --git a/libgomp/testsuite/libgomp.c/pr39591-2.c b/libgomp/testsuite/libgomp.c/pr39591-2.c
new file mode 100644 (file)
index 0000000..b5f8f9c
--- /dev/null
@@ -0,0 +1,39 @@
+/* PR other/39591 */
+/* { dg-do run } */
+/* { dg-options "-O2" } */
+
+extern void abort (void);
+
+int err;
+
+void __attribute__((noinline))
+foo (int *array)
+{
+#pragma omp task
+  {
+    int j;
+    for (j = 0; j < sizeof array / sizeof array[0]; j++)
+      if (array[j] != 0x55555555)
+#pragma omp atomic
+       err++;
+  }
+}
+
+int
+main (void)
+{
+#pragma omp parallel
+  {
+    int array[40];
+    int i;
+    for (i = 0; i < sizeof array / sizeof array[0]; i++)
+      array[i] = 0x55555555;
+
+#pragma omp for schedule (dynamic)
+    for (i = 0; i < 50; i++)
+      foo (array);
+  }
+  if (err)
+    abort ();
+  return 0;
+}
diff --git a/libgomp/testsuite/libgomp.c/pr39591-3.c b/libgomp/testsuite/libgomp.c/pr39591-3.c
new file mode 100644 (file)
index 0000000..a9aeea7
--- /dev/null
@@ -0,0 +1,40 @@
+/* PR other/39591 */
+/* { dg-do run } */
+/* { dg-options "-O2" } */
+
+extern void abort (void);
+
+int err, a[40];
+
+void __attribute__((noinline))
+foo (int *array)
+{
+#pragma omp task
+  {
+    int j;
+    for (j = 0; j < sizeof array / sizeof array[0]; j++)
+      if (array[j] != 0x55555555)
+#pragma omp atomic
+       err++;
+  }
+}
+
+int
+main (void)
+{
+  int k;
+  for (k = 0; k < sizeof a / sizeof a[0]; k++)
+    a[k] = 0x55555555;
+
+#pragma omp parallel
+  {
+    int i;
+
+#pragma omp for schedule (dynamic)
+    for (i = 0; i < 50; i++)
+      foo (a);
+  }
+  if (err)
+    abort ();
+  return 0;
+}