]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
re PR middle-end/33880 (ICE: in extract_omp_for_data, at omp-low.c:162)
authorJakub Jelinek <jakub@redhat.com>
Fri, 25 Jan 2008 12:54:42 +0000 (13:54 +0100)
committerJakub Jelinek <jakub@gcc.gnu.org>
Fri, 25 Jan 2008 12:54:42 +0000 (13:54 +0100)
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
gcc/tree-nested.c
libgomp/ChangeLog
libgomp/testsuite/libgomp.c/pr33880.c [new file with mode: 0644]
libgomp/testsuite/libgomp.fortran/pr33880.f90 [new file with mode: 0644]

index 80a4ee6a4206a5c2088d73f5971d60131ebb6f4f..f16c87ac3fa821a1f02b6a473930a92cee6f6f7c 100644 (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
index 118f5fe456916c69f3d7c765a0b9f10bb3fd8a11..08f3eb1b49191884420e22f8e5524afcebc166d7 100644 (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:
index a4da06082e2ac0a3fe685236a55c83eac0a52d9e..7a40894b68bd3ea1d9a79a0145eeebc6b5f01664 100644 (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.
diff --git a/libgomp/testsuite/libgomp.c/pr33880.c b/libgomp/testsuite/libgomp.c/pr33880.c
new file mode 100644 (file)
index 0000000..5d719cd
--- /dev/null
@@ -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 (file)
index 0000000..679cab6
--- /dev/null
@@ -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