diff options
-rw-r--r-- | gcc/ChangeLog | 7 | ||||
-rw-r--r-- | gcc/omp-low.c | 51 | ||||
-rw-r--r-- | libgomp/ChangeLog | 7 | ||||
-rw-r--r-- | libgomp/testsuite/libgomp.c/pr39591-1.c | 33 | ||||
-rw-r--r-- | libgomp/testsuite/libgomp.c/pr39591-2.c | 39 | ||||
-rw-r--r-- | libgomp/testsuite/libgomp.c/pr39591-3.c | 40 |
6 files changed, 174 insertions, 3 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index b767290..bbb7af8 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-04-01 Anatoly Sokolov <aesok@post.ru> * config/avr/avr.h (avr_case_values_threshold): Remove declaration. diff --git a/gcc/omp-low.c b/gcc/omp-low.c index 4065876..b96da5f 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. @@ -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); + } } } diff --git a/libgomp/ChangeLog b/libgomp/ChangeLog index a77fdde..15eb2c6c 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 0000000..dfd8d9e --- /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 0000000..b5f8f9c --- /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 0000000..a9aeea7 --- /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; +} |