This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[gomp] Fix handling of nested functions
- From: Jakub Jelinek <jakub at redhat dot com>
- To: Richard Henderson <rth at redhat dot com>, Diego Novillo <dnovillo at redhat dot com>
- Cc: gcc-patches at gcc dot gnu dot org
- Date: Fri, 22 Sep 2006 12:33:39 -0400
- Subject: [gomp] Fix handling of nested functions
- Reply-to: Jakub Jelinek <jakub at redhat dot com>
Hi!
My question whether nested functions are supposed to see the original
or OpenMP remapped variables was answered:
http://www.openmp.org/pipermail/omp/2006/000532.html
that they are supposed to see the original ones (and thus if they
are privatized, the code is undefined), which is certainly much easier
to implement, especially for nested function pointers.
So, here is a patch that fixes the testcases from the 2 PRs and also
fixes #pragma omp section handling.
Ok to commit?
2006-09-22 Jakub Jelinek <jakub@redhat.com>
PR middle-end/25261
PR middle-end/28790
* tree-nested.c (struct nesting_info): Added static_chain_added.
(convert_call_expr): Set static_chain_added when adding static
chain. Handle OMP_PARALLEL and OMP_SECTION.
* testsuite/libgomp.c/nestedfn-4.c: New test.
* testsuite/libgomp.c/nestedfn-5.c: New test.
* testsuite/libgomp.fortran/nestedfn3.f90: New test.
--- gcc/tree-nested.c.jj 2006-07-20 08:26:15.000000000 +0200
+++ gcc/tree-nested.c 2006-09-22 18:02:17.000000000 +0200
@@ -1,5 +1,5 @@
/* Nested function decomposition for trees.
- Copyright (C) 2004, 2005 Free Software Foundation, Inc.
+ Copyright (C) 2004, 2005, 2006 Free Software Foundation, Inc.
This file is part of GCC.
@@ -104,6 +104,7 @@ struct nesting_info GTY ((chain_next ("%
bool any_parm_remapped;
bool any_tramp_created;
+ char static_chain_added;
};
@@ -1626,6 +1627,7 @@ convert_call_expr (tree *tp, int *walk_s
struct walk_stmt_info *wi = (struct walk_stmt_info *) data;
struct nesting_info *info = wi->info;
tree t = *tp, decl, target_context;
+ char save_static_chain_added;
*walk_subtrees = 0;
switch (TREE_CODE (t))
@@ -1636,8 +1638,12 @@ convert_call_expr (tree *tp, int *walk_s
break;
target_context = decl_function_context (decl);
if (target_context && !DECL_NO_STATIC_CHAIN (decl))
- TREE_OPERAND (t, 2)
- = get_static_chain (info, target_context, &wi->tsi);
+ {
+ TREE_OPERAND (t, 2)
+ = get_static_chain (info, target_context, &wi->tsi);
+ info->static_chain_added
+ |= (1 << (info->context != target_context));
+ }
break;
case RETURN_EXPR:
@@ -1647,8 +1653,43 @@ convert_call_expr (tree *tp, int *walk_s
*walk_subtrees = 1;
break;
+ case OMP_PARALLEL:
+ save_static_chain_added = info->static_chain_added;
+ info->static_chain_added = 0;
+ walk_body (convert_call_expr, info, &OMP_PARALLEL_BODY (t));
+ if ((info->static_chain_added & 1) != 0)
+ {
+ tree c, decl;
+ decl = info->frame_decl;
+ c = build_omp_clause (OMP_CLAUSE_FIRSTPRIVATE);
+ OMP_CLAUSE_DECL (c) = decl;
+ OMP_CLAUSE_CHAIN (c) = OMP_PARALLEL_CLAUSES (t);
+ OMP_PARALLEL_CLAUSES (t) = c;
+ }
+ if ((info->static_chain_added & 2) != 0)
+ {
+ tree c, decl;
+ decl = get_chain_decl (info);
+ /* Don't add CHAIN.* twice, convert_nonlocal_reference could
+ have already added it. */
+ for (c = OMP_PARALLEL_CLAUSES (t); c; c = OMP_CLAUSE_CHAIN (c))
+ if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE
+ && OMP_CLAUSE_DECL (c) == decl)
+ break;
+ if (c == NULL)
+ {
+ c = build_omp_clause (OMP_CLAUSE_FIRSTPRIVATE);
+ OMP_CLAUSE_DECL (c) = decl;
+ OMP_CLAUSE_CHAIN (c) = OMP_PARALLEL_CLAUSES (t);
+ OMP_PARALLEL_CLAUSES (t) = c;
+ }
+ }
+ info->static_chain_added |= save_static_chain_added;
+ break;
+
case OMP_FOR:
case OMP_SECTIONS:
+ case OMP_SECTION:
case OMP_SINGLE:
case OMP_MASTER:
case OMP_ORDERED:
--- libgomp/testsuite/libgomp.c/nestedfn-4.c.jj 2006-09-22 17:38:43.000000000 +0200
+++ libgomp/testsuite/libgomp.c/nestedfn-4.c 2006-09-22 17:38:54.000000000 +0200
@@ -0,0 +1,65 @@
+/* PR middle-end/25261 */
+/* { dg-do run } */
+
+#include <omp.h>
+
+extern void abort (void);
+
+int
+main (void)
+{
+ int i = 5, j, l = 0;
+ int foo (void)
+ {
+ return i == 6;
+ }
+ int bar (void)
+ {
+ return i - 3;
+ }
+
+ omp_set_dynamic (0);
+
+#pragma omp parallel if (foo ()) num_threads (2)
+ if (omp_get_num_threads () != 1)
+#pragma omp atomic
+ l++;
+
+#pragma omp parallel for schedule (static, bar ()) num_threads (2) \
+ reduction (|:l)
+ for (j = 0; j < 4; j++)
+ if (omp_get_thread_num () != (j >= 2))
+#pragma omp atomic
+ l++;
+
+ i++;
+
+#pragma omp parallel if (foo ()) num_threads (2)
+ if (omp_get_num_threads () != 2)
+#pragma omp atomic
+ l++;
+
+#pragma omp parallel for schedule (static, bar ()) num_threads (2) \
+ reduction (|:l)
+ for (j = 0; j < 6; j++)
+ if (omp_get_thread_num () != (j >= 3))
+#pragma omp atomic
+ l++;
+
+#pragma omp parallel num_threads (4) reduction (|:l)
+ if (!foo () || bar () != 3)
+#pragma omp atomic
+ l++;
+
+ i++;
+
+#pragma omp parallel num_threads (4) reduction (|:l)
+ if (foo () || bar () != 4)
+#pragma omp atomic
+ l++;
+
+ if (l)
+ abort ();
+
+ return 0;
+}
--- libgomp/testsuite/libgomp.c/nestedfn-5.c.jj 2006-09-22 18:06:21.000000000 +0200
+++ libgomp/testsuite/libgomp.c/nestedfn-5.c 2006-09-22 18:04:50.000000000 +0200
@@ -0,0 +1,38 @@
+/* { dg-do run } */
+/* { dg-options "-O2" } */
+
+extern void abort (void);
+
+void
+foo (int *j)
+{
+ int i = 5;
+ int bar (void) { return i + 1; }
+#pragma omp sections
+ {
+ #pragma omp section
+ {
+ if (bar () != 6)
+ #pragma omp atomic
+ ++*j;
+ }
+ #pragma omp section
+ {
+ if (bar () != 6)
+ #pragma omp atomic
+ ++*j;
+ }
+ }
+}
+
+int
+main (void)
+{
+ int j = 0;
+#pragma omp parallel num_threads (2)
+ foo (&j);
+ if (j)
+ abort ();
+ return 0;
+}
+
--- libgomp/testsuite/libgomp.fortran/nestedfn3.f90.jj 2006-09-22 17:39:27.000000000 +0200
+++ libgomp/testsuite/libgomp.fortran/nestedfn3.f90 2006-09-22 17:42:59.000000000 +0200
@@ -0,0 +1,24 @@
+! PR middle-end/28790
+! { dg-do run }
+
+program nestomp
+ integer :: j
+ j = 8
+ call bar
+ if (j.ne.10) call abort
+contains
+ subroutine foo (i)
+ integer :: i
+ !$omp atomic
+ j = j + i - 5
+ end subroutine
+ subroutine bar
+ use omp_lib
+ integer :: i
+ i = 6
+ call omp_set_dynamic (.false.)
+ !$omp parallel num_threads (2)
+ call foo(i)
+ !$omp end parallel
+ end subroutine
+end
Jakub