summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorjakub <jakub@138bc75d-0d04-0410-961f-82ee72b054a4>2008-01-25 12:54:42 +0000
committerjakub <jakub@138bc75d-0d04-0410-961f-82ee72b054a4>2008-01-25 12:54:42 +0000
commitb43fc0dc6333c862d43f9db0e51334ac53007d81 (patch)
tree9a5c3be70549d48c772a09123c8b458d609517b3
parent8090c12d167f85ca166f65c3f49f8818ebd42e5f (diff)
downloadgcc-b43fc0dc6333c862d43f9db0e51334ac53007d81.tar.gz
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. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@131825 138bc75d-0d04-0410-961f-82ee72b054a4
-rw-r--r--gcc/ChangeLog9
-rw-r--r--gcc/tree-nested.c71
-rw-r--r--libgomp/ChangeLog6
-rw-r--r--libgomp/testsuite/libgomp.c/pr33880.c123
-rw-r--r--libgomp/testsuite/libgomp.fortran/pr33880.f9018
5 files changed, 226 insertions, 1 deletions
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 <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
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 <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.
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