From c256730cefa52bbb322ca3759a0411f9e245d366 Mon Sep 17 00:00:00 2001 From: Jakub Jelinek Date: Fri, 25 Jan 2008 13:54:42 +0100 Subject: [PATCH] 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 --- gcc/ChangeLog | 9 ++ gcc/tree-nested.c | 71 +++++++++- libgomp/ChangeLog | 6 + libgomp/testsuite/libgomp.c/pr33880.c | 123 ++++++++++++++++++ libgomp/testsuite/libgomp.fortran/pr33880.f90 | 18 +++ 5 files changed, 226 insertions(+), 1 deletion(-) create mode 100644 libgomp/testsuite/libgomp.c/pr33880.c create mode 100644 libgomp/testsuite/libgomp.fortran/pr33880.f90 diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 80a4ee6a420..f16c87ac3fa 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,12 @@ +2008-01-25 Jakub Jelinek + + 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 PR tree-optimization/34966 diff --git a/gcc/tree-nested.c b/gcc/tree-nested.c index 118f5fe4569..08f3eb1b491 100644 --- a/gcc/tree-nested.c +++ b/gcc/tree-nested.c @@ -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: diff --git a/libgomp/ChangeLog b/libgomp/ChangeLog index a4da06082e2..7a40894b68b 100644 --- a/libgomp/ChangeLog +++ b/libgomp/ChangeLog @@ -1,3 +1,9 @@ +2008-01-25 Jakub Jelinek + + PR middle-end/33880 + * testsuite/libgomp.c/pr33880.c: New test. + * testsuite/libgomp.fortran/pr33880.f90: New test. + 2008-01-24 David Edelsohn * configure: Regenerate. diff --git a/libgomp/testsuite/libgomp.c/pr33880.c b/libgomp/testsuite/libgomp.c/pr33880.c new file mode 100644 index 00000000000..5d719cd635d --- /dev/null +++ b/libgomp/testsuite/libgomp.c/pr33880.c @@ -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; +} diff --git a/libgomp/testsuite/libgomp.fortran/pr33880.f90 b/libgomp/testsuite/libgomp.fortran/pr33880.f90 new file mode 100644 index 00000000000..679cab6822d --- /dev/null +++ b/libgomp/testsuite/libgomp.fortran/pr33880.f90 @@ -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