Commit a70ad3bb by Jakub Jelinek Committed by Jakub Jelinek

re PR middle-end/25261 ([gomp] Nested function calls in #pragma omp parallel blocks)

	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.

	* gcc.dg/gomp/nestedfn-1.c: New test.

	* testsuite/libgomp.c/nestedfn-4.c: New test.
	* testsuite/libgomp.c/nestedfn-5.c: New test.
	* testsuite/libgomp.fortran/nestedfn3.f90: New test.

From-SVN: r117235
parent 9b9e4cd6
2006-09-26 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.
2006-09-25 Matthias Klose <doko@debian.org> 2006-09-25 Matthias Klose <doko@debian.org>
* doc/invoke.texi: Add missing full stop. * doc/invoke.texi: Add missing full stop.
......
2006-09-26 Jakub Jelinek <jakub@redhat.com>
PR middle-end/25261
PR middle-end/28790
* gcc.dg/gomp/nestedfn-1.c: New test.
2006-09-26 Andrew Pinski <pinskia@physics.uc.edu> 2006-09-26 Andrew Pinski <pinskia@physics.uc.edu>
PR objc/29195 PR objc/29195
/* This testcase violates the OpenMP requirements, as nested functions
access the original variables.
We test it just to make sure we don't ICE on it. */
/* { dg-do compile } */
/* { dg-options "-O2 -fopenmp" } */
extern void abort (void);
extern int omp_get_thread_num ();
extern void omp_set_dynamic (int);
int
main (void)
{
int j = 0, k = 6, l = 7, m = 8;
void foo (void)
{
int i = 5;
int bar (void)
{
return i + 1 + (j > 100 ? 10000 : 0);
}
#pragma omp sections private (i)
{
#pragma omp section
{
i = 6;
if (bar () != 6)
#pragma omp atomic
++j;
}
#pragma omp section
{
if (bar () != 6)
#pragma omp atomic
++j;
}
}
if (k != 6 || l != 7 || m != 8)
#pragma omp atomic
++j;
}
omp_set_dynamic (0);
#pragma omp parallel num_threads (2) firstprivate (k) shared (l) private (m)
{
if (omp_get_thread_num () != 0)
k += omp_get_thread_num ();
m = 9;
foo ();
}
if (j)
abort ();
return 0;
}
/* Nested function decomposition for trees. /* 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. This file is part of GCC.
...@@ -104,6 +104,7 @@ struct nesting_info GTY ((chain_next ("%h.next"))) ...@@ -104,6 +104,7 @@ struct nesting_info GTY ((chain_next ("%h.next")))
bool any_parm_remapped; bool any_parm_remapped;
bool any_tramp_created; bool any_tramp_created;
char static_chain_added;
}; };
...@@ -1626,6 +1627,8 @@ convert_call_expr (tree *tp, int *walk_subtrees, void *data) ...@@ -1626,6 +1627,8 @@ convert_call_expr (tree *tp, int *walk_subtrees, void *data)
struct walk_stmt_info *wi = (struct walk_stmt_info *) data; struct walk_stmt_info *wi = (struct walk_stmt_info *) data;
struct nesting_info *info = wi->info; struct nesting_info *info = wi->info;
tree t = *tp, decl, target_context; tree t = *tp, decl, target_context;
char save_static_chain_added;
int i;
*walk_subtrees = 0; *walk_subtrees = 0;
switch (TREE_CODE (t)) switch (TREE_CODE (t))
...@@ -1636,8 +1639,12 @@ convert_call_expr (tree *tp, int *walk_subtrees, void *data) ...@@ -1636,8 +1639,12 @@ convert_call_expr (tree *tp, int *walk_subtrees, void *data)
break; break;
target_context = decl_function_context (decl); target_context = decl_function_context (decl);
if (target_context && !DECL_NO_STATIC_CHAIN (decl)) if (target_context && !DECL_NO_STATIC_CHAIN (decl))
{
TREE_OPERAND (t, 2) TREE_OPERAND (t, 2)
= get_static_chain (info, target_context, &wi->tsi); = get_static_chain (info, target_context, &wi->tsi);
info->static_chain_added
|= (1 << (info->context != target_context));
}
break; break;
case RETURN_EXPR: case RETURN_EXPR:
...@@ -1647,8 +1654,36 @@ convert_call_expr (tree *tp, int *walk_subtrees, void *data) ...@@ -1647,8 +1654,36 @@ convert_call_expr (tree *tp, int *walk_subtrees, void *data)
*walk_subtrees = 1; *walk_subtrees = 1;
break; 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));
for (i = 0; i < 2; i++)
{
tree c, decl;
if ((info->static_chain_added & (1 << i)) == 0)
continue;
decl = i ? get_chain_decl (info) : info->frame_decl;
/* Don't add CHAIN.* or FRAME.* twice. */
for (c = OMP_PARALLEL_CLAUSES (t); c; c = OMP_CLAUSE_CHAIN (c))
if ((OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE
|| OMP_CLAUSE_CODE (c) == OMP_CLAUSE_SHARED)
&& 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_FOR:
case OMP_SECTIONS: case OMP_SECTIONS:
case OMP_SECTION:
case OMP_SINGLE: case OMP_SINGLE:
case OMP_MASTER: case OMP_MASTER:
case OMP_ORDERED: case OMP_ORDERED:
......
2006-09-26 Jakub Jelinek <jakub@redhat.com> 2006-09-26 Jakub Jelinek <jakub@redhat.com>
PR middle-end/25261
PR middle-end/28790
* testsuite/libgomp.c/nestedfn-4.c: New test.
* testsuite/libgomp.c/nestedfn-5.c: New test.
* testsuite/libgomp.fortran/nestedfn3.f90: New test.
PR fortran/29097 PR fortran/29097
* testsuite/libgomp.fortran/condinc1.f: New test. * testsuite/libgomp.fortran/condinc1.f: New test.
* testsuite/libgomp.fortran/condinc2.f: New test. * testsuite/libgomp.fortran/condinc2.f: New test.
......
/* 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;
}
/* { 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;
}
! 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
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment