This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[gomp] Fix handling of nested functions


Hi!

My question whether nested functions are supposed to see the original
or OpenMP remapped variables was answered:
http://www.openmp.org/pipermail/omp/2006/000532.html
that they are supposed to see the original ones (and thus if they
are privatized, the code is undefined), which is certainly much easier
to implement, especially for nested function pointers.

So, here is a patch that fixes the testcases from the 2 PRs and also
fixes #pragma omp section handling.

Ok to commit?

2006-09-22  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.

	* testsuite/libgomp.c/nestedfn-4.c: New test.
	* testsuite/libgomp.c/nestedfn-5.c: New test.
	* testsuite/libgomp.fortran/nestedfn3.f90: New test.
	
--- gcc/tree-nested.c.jj	2006-07-20 08:26:15.000000000 +0200
+++ gcc/tree-nested.c	2006-09-22 18:02:17.000000000 +0200
@@ -1,5 +1,5 @@
 /* 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.
 
@@ -104,6 +104,7 @@ struct nesting_info GTY ((chain_next ("%
 
   bool any_parm_remapped;
   bool any_tramp_created;
+  char static_chain_added;
 };
 
 
@@ -1626,6 +1627,7 @@ convert_call_expr (tree *tp, int *walk_s
   struct walk_stmt_info *wi = (struct walk_stmt_info *) data;
   struct nesting_info *info = wi->info;
   tree t = *tp, decl, target_context;
+  char save_static_chain_added;
 
   *walk_subtrees = 0;
   switch (TREE_CODE (t))
@@ -1636,8 +1638,12 @@ convert_call_expr (tree *tp, int *walk_s
 	break;
       target_context = decl_function_context (decl);
       if (target_context && !DECL_NO_STATIC_CHAIN (decl))
-	TREE_OPERAND (t, 2)
-	  = get_static_chain (info, target_context, &wi->tsi);
+	{
+	  TREE_OPERAND (t, 2)
+	    = get_static_chain (info, target_context, &wi->tsi);
+	  info->static_chain_added
+	    |= (1 << (info->context != target_context));
+	}
       break;
 
     case RETURN_EXPR:
@@ -1647,8 +1653,43 @@ convert_call_expr (tree *tp, int *walk_s
       *walk_subtrees = 1;
       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));
+      if ((info->static_chain_added & 1) != 0)
+	{
+	  tree c, decl;
+	  decl = info->frame_decl;
+	  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;
+	}
+      if ((info->static_chain_added & 2) != 0)
+	{
+	  tree c, decl;
+	  decl = get_chain_decl (info);
+	  /* Don't add CHAIN.* twice, convert_nonlocal_reference could
+	     have already added it.  */
+	  for (c = OMP_PARALLEL_CLAUSES (t); c; c = OMP_CLAUSE_CHAIN (c))
+	    if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE
+		&& 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_SECTIONS:
+    case OMP_SECTION:
     case OMP_SINGLE:
     case OMP_MASTER:
     case OMP_ORDERED:
--- libgomp/testsuite/libgomp.c/nestedfn-4.c.jj	2006-09-22 17:38:43.000000000 +0200
+++ libgomp/testsuite/libgomp.c/nestedfn-4.c	2006-09-22 17:38:54.000000000 +0200
@@ -0,0 +1,65 @@
+/* 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;
+}
--- libgomp/testsuite/libgomp.c/nestedfn-5.c.jj	2006-09-22 18:06:21.000000000 +0200
+++ libgomp/testsuite/libgomp.c/nestedfn-5.c	2006-09-22 18:04:50.000000000 +0200
@@ -0,0 +1,38 @@
+/* { 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;
+}
+
--- libgomp/testsuite/libgomp.fortran/nestedfn3.f90.jj	2006-09-22 17:39:27.000000000 +0200
+++ libgomp/testsuite/libgomp.fortran/nestedfn3.f90	2006-09-22 17:42:59.000000000 +0200
@@ -0,0 +1,24 @@
+! 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

	Jakub


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]