aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJakub Jelinek <jakub@redhat.com>2009-04-01 09:06:12 +0200
committerJakub Jelinek <jakub@gcc.gnu.org>2009-04-01 09:06:12 +0200
commitec60c12749ad95b9e7658eab6df1140eac207492 (patch)
tree2fb1e2a23e8eb9c1052eddbd5f963dcc81c2180d
parente356bc7ac9f598fd691f04329bc7083a7270861f (diff)
re PR other/39591 (GOMP_loop_end illegally optmized into GOMP_loop_end_nowait)
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. * testsuite/libgomp.c/pr39591-1.c: New test. * testsuite/libgomp.c/pr39591-2.c: New test. * testsuite/libgomp.c/pr39591-3.c: New test. From-SVN: r145391
-rw-r--r--gcc/ChangeLog7
-rw-r--r--gcc/omp-low.c51
-rw-r--r--libgomp/ChangeLog7
-rw-r--r--libgomp/testsuite/libgomp.c/pr39591-1.c33
-rw-r--r--libgomp/testsuite/libgomp.c/pr39591-2.c39
-rw-r--r--libgomp/testsuite/libgomp.c/pr39591-3.c40
6 files changed, 174 insertions, 3 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index e6590e4dbcf..e7f60cb587b 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -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-03-30 Sebastian Pop <sebastian.pop@amd.com>
* doc/invoke.texi (-floop-interchange, -floop-strip-mine,
diff --git a/gcc/omp-low.c b/gcc/omp-low.c
index dce89fa2464..0a9e59b69a1 100644
--- a/gcc/omp-low.c
+++ b/gcc/omp-low.c
@@ -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.
@@ -3121,6 +3121,7 @@ remove_exit_barrier (struct omp_region *region)
edge_iterator ei;
edge e;
gimple stmt;
+ int any_addressable_vars = -1;
exit_bb = region->exit;
@@ -3146,8 +3147,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);
+ }
}
}
diff --git a/libgomp/ChangeLog b/libgomp/ChangeLog
index a77fdde70e9..15eb2c6c769 100644
--- a/libgomp/ChangeLog
+++ b/libgomp/ChangeLog
@@ -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
index 00000000000..dfd8d9e8aca
--- /dev/null
+++ b/libgomp/testsuite/libgomp.c/pr39591-1.c
@@ -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
index 00000000000..b5f8f9cc7b2
--- /dev/null
+++ b/libgomp/testsuite/libgomp.c/pr39591-2.c
@@ -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
index 00000000000..a9aeea7c83a
--- /dev/null
+++ b/libgomp/testsuite/libgomp.c/pr39591-3.c
@@ -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;
+}