diff options
author | jakub <jakub@138bc75d-0d04-0410-961f-82ee72b054a4> | 2009-04-01 06:54:52 +0000 |
---|---|---|
committer | jakub <jakub@138bc75d-0d04-0410-961f-82ee72b054a4> | 2009-04-01 06:54:52 +0000 |
commit | 4a04f4b4ef151f7daac789989104d7a55f434f0b (patch) | |
tree | 21d252b6e42e3b03c7ed6cbdf149f1b4814d94fc /gcc/omp-low.c | |
parent | b4a3be2d34acf2e06a466689e77639874d3e50b5 (diff) | |
download | gcc-4a04f4b4ef151f7daac789989104d7a55f434f0b.tar.gz |
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.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@145390 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/omp-low.c')
-rw-r--r-- | gcc/omp-low.c | 51 |
1 files changed, 48 insertions, 3 deletions
diff --git a/gcc/omp-low.c b/gcc/omp-low.c index 40658760d38..b96da5fe1e2 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); + } } } |