summaryrefslogtreecommitdiff
path: root/gcc/omp-low.c
diff options
context:
space:
mode:
authorjakub <jakub@138bc75d-0d04-0410-961f-82ee72b054a4>2009-04-01 06:54:52 +0000
committerjakub <jakub@138bc75d-0d04-0410-961f-82ee72b054a4>2009-04-01 06:54:52 +0000
commit4a04f4b4ef151f7daac789989104d7a55f434f0b (patch)
tree21d252b6e42e3b03c7ed6cbdf149f1b4814d94fc /gcc/omp-low.c
parentb4a3be2d34acf2e06a466689e77639874d3e50b5 (diff)
downloadgcc-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.c51
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);
+ }
}
}