re PR middle-end/33880 (ICE: in extract_omp_for_data, at omp-low.c:162)

PR middle-end/33880
	* tree-nested.c (walk_omp_for): New function.
	(convert_nonlocal_reference, convert_local_reference): Call
	walk_omp_for on OMP_FOR.
	(convert_call_expr): Call walk_body on OMP_FOR's
	OMP_FOR_PRE_INIT_BODY.

	* testsuite/libgomp.c/pr33880.c: New test.
	* testsuite/libgomp.fortran/pr33880.f90: New test.

From-SVN: r131825
This commit is contained in:
Jakub Jelinek 2008-01-25 13:54:42 +01:00 committed by Jakub Jelinek
parent 59805c3b29
commit c256730cef
5 changed files with 226 additions and 1 deletions

View File

@ -1,3 +1,12 @@
2008-01-25 Jakub Jelinek <jakub@redhat.com>
PR middle-end/33880
* tree-nested.c (walk_omp_for): New function.
(convert_nonlocal_reference, convert_local_reference): Call
walk_omp_for on OMP_FOR.
(convert_call_expr): Call walk_body on OMP_FOR's
OMP_FOR_PRE_INIT_BODY.
2008-01-25 Richard Guenther <rguenther@suse.de>
PR tree-optimization/34966

View File

@ -1,5 +1,5 @@
/* Nested function decomposition for trees.
Copyright (C) 2004, 2005, 2006, 2007 Free Software Foundation, Inc.
Copyright (C) 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
This file is part of GCC.
@ -665,6 +665,59 @@ walk_function (walk_tree_fn callback, struct nesting_info *info)
walk_body (callback, info, &DECL_SAVED_TREE (info->context));
}
/* Invoke CALLBACK on OMP_FOR init, cond, incr and pre-body. */
static void
walk_omp_for (walk_tree_fn callback, struct nesting_info *info, tree for_stmt)
{
struct walk_stmt_info wi;
tree t, list = NULL, empty;
walk_body (callback, info, &OMP_FOR_PRE_BODY (for_stmt));
empty = build_empty_stmt ();
append_to_statement_list_force (empty, &list);
memset (&wi, 0, sizeof (wi));
wi.callback = callback;
wi.info = info;
wi.tsi = tsi_last (list);
t = OMP_FOR_INIT (for_stmt);
gcc_assert (TREE_CODE (t) == GIMPLE_MODIFY_STMT);
SET_EXPR_LOCUS (empty, EXPR_LOCUS (t));
wi.val_only = false;
walk_tree (&GIMPLE_STMT_OPERAND (t, 0), callback, &wi, NULL);
wi.val_only = true;
wi.is_lhs = false;
walk_tree (&GIMPLE_STMT_OPERAND (t, 1), callback, &wi, NULL);
t = OMP_FOR_COND (for_stmt);
gcc_assert (COMPARISON_CLASS_P (t));
SET_EXPR_LOCUS (empty, EXPR_LOCUS (t));
wi.val_only = false;
walk_tree (&TREE_OPERAND (t, 0), callback, &wi, NULL);
wi.val_only = true;
wi.is_lhs = false;
walk_tree (&TREE_OPERAND (t, 1), callback, &wi, NULL);
t = OMP_FOR_INCR (for_stmt);
gcc_assert (TREE_CODE (t) == GIMPLE_MODIFY_STMT);
SET_EXPR_LOCUS (empty, EXPR_LOCUS (t));
wi.val_only = false;
walk_tree (&GIMPLE_STMT_OPERAND (t, 0), callback, &wi, NULL);
t = GIMPLE_STMT_OPERAND (t, 1);
gcc_assert (BINARY_CLASS_P (t));
wi.val_only = false;
walk_tree (&TREE_OPERAND (t, 0), callback, &wi, NULL);
wi.val_only = true;
wi.is_lhs = false;
walk_tree (&TREE_OPERAND (t, 1), callback, &wi, NULL);
/* Remove empty statement added above from the end of statement list. */
tsi_delink (&wi.tsi);
append_to_statement_list (list, &OMP_FOR_PRE_BODY (for_stmt));
}
/* Similarly for ROOT and all functions nested underneath, depth first. */
static void
@ -1065,6 +1118,13 @@ convert_nonlocal_reference (tree *tp, int *walk_subtrees, void *data)
break;
case OMP_FOR:
save_suppress = info->suppress_expansion;
convert_nonlocal_omp_clauses (&OMP_FOR_CLAUSES (t), wi);
walk_omp_for (convert_nonlocal_reference, info, t);
walk_body (convert_nonlocal_reference, info, &OMP_FOR_BODY (t));
info->suppress_expansion = save_suppress;
break;
case OMP_SECTIONS:
case OMP_SINGLE:
save_suppress = info->suppress_expansion;
@ -1350,6 +1410,13 @@ convert_local_reference (tree *tp, int *walk_subtrees, void *data)
break;
case OMP_FOR:
save_suppress = info->suppress_expansion;
convert_local_omp_clauses (&OMP_FOR_CLAUSES (t), wi);
walk_omp_for (convert_local_reference, info, t);
walk_body (convert_local_reference, info, &OMP_FOR_BODY (t));
info->suppress_expansion = save_suppress;
break;
case OMP_SECTIONS:
case OMP_SINGLE:
save_suppress = info->suppress_expansion;
@ -1682,6 +1749,8 @@ convert_call_expr (tree *tp, int *walk_subtrees, void *data)
break;
case OMP_FOR:
walk_body (convert_call_expr, info, &OMP_FOR_PRE_BODY (t));
/* FALLTHRU */
case OMP_SECTIONS:
case OMP_SECTION:
case OMP_SINGLE:

View File

@ -1,3 +1,9 @@
2008-01-25 Jakub Jelinek <jakub@redhat.com>
PR middle-end/33880
* testsuite/libgomp.c/pr33880.c: New test.
* testsuite/libgomp.fortran/pr33880.f90: New test.
2008-01-24 David Edelsohn <edelsohn@gnu.org>
* configure: Regenerate.

View File

@ -0,0 +1,123 @@
/* PR middle-end/33880 */
/* { dg-do run } */
extern void abort (void);
void
test1 (void)
{
int i = 0, j = 0;
void bar (void)
{
i++;
j++;
}
bar ();
#pragma omp parallel for num_threads(4)
for (i = 0; i < 100; i++)
#pragma omp atomic
j += 1;
if (j != 101)
abort ();
#pragma omp parallel for lastprivate(i) num_threads(2)
for (i = 0; i < 100; i++)
#pragma omp atomic
j += 1;
if (i != 100)
abort ();
i = 3;
bar ();
if (j != 202)
abort ();
if (i != 4)
abort ();
}
void
test2 (void)
{
int i = -1, j = 99, k, l = 9, m = 0;
void bar (void)
{
i++;
j++;
l++;
m++;
}
bar ();
#pragma omp parallel for num_threads(4)
for (k = i; k < j; k += l)
#pragma omp atomic
m += 1;
bar ();
if (i != 1 || j != 101 || l != 11 || m != 12)
abort ();
}
void
test3 (void)
{
int i, j, k, l, m;
void bar (void)
{
#pragma omp parallel for num_threads(4)
for (i = j; i < k; i += l)
#pragma omp atomic
m += 1;
}
void baz (void)
{
#pragma omp parallel for num_threads(2) lastprivate(i)
for (i = j; i < k * 2; i += l / 2)
#pragma omp atomic
m += 1;
}
i = 7;
j = 0;
k = 100;
l = 2;
m = 0;
bar ();
if (j != 0 || k != 100 || l != 2 || m != 50)
abort ();
baz ();
if (i != 200 || j != 0 || k != 100 || l != 2 || m != 250)
abort ();
}
void
test4 (void)
{
int i, j, k, l, m = 0;
int foo (void)
{
return j;
}
int bar (void)
{
return k;
}
int baz (void)
{
return l;
}
j = 0;
k = 1000;
l = 2;
#pragma omp parallel for num_threads(8) lastprivate(i)
for (i = foo (); i < bar (); i += baz ())
#pragma omp atomic
m += 1;
if (i != 1000 || m != 500 || j != 0 || k != 1000 || l != 2)
abort ();
}
int
main (void)
{
test1 ();
test2 ();
test3 ();
test4 ();
return 0;
}

View File

@ -0,0 +1,18 @@
! PR middle-end/33880
! { dg-do run }
program pr33880
integer :: i, j
call something ()
!$omp parallel do
do i = 1, 1000
!$omp atomic
j = j + 1
end do
if (j .ne. 1000) call abort
contains
subroutine something()
i = 0
j = 0
end subroutine something
end program pr33880