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 RESULT_DECL (PR middle-end/27337)


Hi!

As the testcases show, RESULT_DECL wasn't handled at all in several places
in OpenMP gimplification/lowering/expand, yet it is created by the C++
frontend early even at -O0.
In addition to that, this patch fixes one issue with
firstprivate(x) lastprivate(x)
for x passed by reference or VLA (the code would allocate the memory or var
twice, the copy constructor was done on the first, while the rest of the
function would use the second) and a minor formatting issue in
*.ompexp dumps.

Ok for trunk?

2006-04-27  Jakub Jelinek  <jakub@redhat.com>

	PR middle-end/27337
	* gimplify.c (gimplify_scan_omp_clauses): Handle INDIRECT_REF
	around RESULT_DECL for result passed by reference.
	(gimplify_expr): Call omp_notice_variable when RESULT_DECL is seen.
	* omp-low.c (use_pointer_for_field): Don't look at
	DECL_HAS_VALUE_EXPR_P for RESULT_DECLs.
	(scan_omp_1): Call remap_decl on RESULT_DECLs.
	(lower_rec_input_clauses): Don't allocate VLA memory for the second
	time or var for passing by reference for
	OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE clauses.  Allow creation of
	TREE_ADDRESSABLE variables when passing by reference.

	* omp-low.c (dump_omp_region): Fix output formatting.
cp/
	* cp-gimplify.c (cxx_omp_privatize_by_reference): New function.
	* cp-tree.h (cxx_omp_privatize_by_reference): New prototype.
	* cp-objcp-common.h (LANG_HOOKS_OMP_PRIVATIZE_BY_REFERENCE): Define.
testsuite/
	* g++.dg/gomp/pr27337-1.C: New test.
	* g++.dg/gomp/pr27337-2.C: New test.
libgomp/
	* testsuite/libgomp.c++/pr27337.C: New test.

--- gcc/gimplify.c.jj	2006-04-15 00:14:39.000000000 +0200
+++ gcc/gimplify.c	2006-04-27 15:17:02.000000000 +0200
@@ -4504,6 +4504,11 @@ gimplify_scan_omp_clauses (tree *list_p,
 	      remove = true;
 	      break;
 	    }
+	  /* Handle NRV results passed by reference.  */
+	  if (TREE_CODE (decl) == INDIRECT_REF
+	      && TREE_CODE (TREE_OPERAND (decl, 0)) == RESULT_DECL
+	      && DECL_BY_REFERENCE (TREE_OPERAND (decl, 0)))
+	    OMP_CLAUSE_DECL (c) = decl = TREE_OPERAND (decl, 0);
 	  omp_add_variable (ctx, decl, flags);
 	  if (TREE_CODE (c) == OMP_CLAUSE_REDUCTION
 	      && OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
@@ -4531,6 +4536,11 @@ gimplify_scan_omp_clauses (tree *list_p,
 	      remove = true;
 	      break;
 	    }
+	  /* Handle NRV results passed by reference.  */
+	  if (TREE_CODE (decl) == INDIRECT_REF
+	      && TREE_CODE (TREE_OPERAND (decl, 0)) == RESULT_DECL
+	      && DECL_BY_REFERENCE (TREE_OPERAND (decl, 0)))
+	    OMP_CLAUSE_DECL (c) = decl = TREE_OPERAND (decl, 0);
 	do_notice:
 	  if (outer_ctx)
 	    omp_notice_variable (outer_ctx, decl, true);
@@ -5558,6 +5568,13 @@ gimplify_expr (tree *expr_p, tree *pre_p
 	  ret = gimplify_var_or_parm_decl (expr_p);
 	  break;
 
+	case RESULT_DECL:
+	  /* When within an OpenMP context, notice uses of variables.  */
+	  if (gimplify_omp_ctxp)
+	    omp_notice_variable (gimplify_omp_ctxp, *expr_p, true);
+	  ret = GS_ALL_DONE;
+	  break;
+
 	case SSA_NAME:
 	  /* Allow callbacks into the gimplifier during optimization.  */
 	  ret = GS_ALL_DONE;
--- gcc/omp-low.c.jj	2006-04-26 11:26:11.000000000 +0200
+++ gcc/omp-low.c	2006-04-27 18:25:51.000000000 +0200
@@ -491,7 +491,7 @@ use_pointer_for_field (tree decl, bool s
 	 without analyzing the expression whether or not its location
 	 is accessible to anyone else.  In the case of nested parallel
 	 regions it certainly may be.  */
-      if (DECL_HAS_VALUE_EXPR_P (decl))
+      if (TREE_CODE (decl) != RESULT_DECL && DECL_HAS_VALUE_EXPR_P (decl))
 	return true;
 
       /* Do not use copy-in/copy-out for variables that have their
@@ -719,12 +719,12 @@ dump_omp_region (FILE *file, struct omp_
 
   if (region->cont)
     {
-      fprintf (file, "%*sbb %d: OMP_CONTINUE", indent, "",
+      fprintf (file, "%*sbb %d: OMP_CONTINUE\n", indent, "",
 	       region->cont->index);
     }
     
   if (region->exit)
-    fprintf (file, "%*sbb: %d: OMP_RETURN", indent, "",
+    fprintf (file, "%*sbb %d: OMP_RETURN\n", indent, "",
 	     region->exit->index);
   else
     fprintf (file, "%*s[no exit marker]\n", indent, "");
@@ -1286,6 +1286,7 @@ scan_omp_1 (tree *tp, int *walk_subtrees
     case VAR_DECL:
     case PARM_DECL:
     case LABEL_DECL:
+    case RESULT_DECL:
       if (ctx)
 	*tp = remap_decl (t, &ctx->cb);
       break;
@@ -1518,10 +1519,14 @@ lower_rec_input_clauses (tree clauses, t
 	      break;
 	    case OMP_CLAUSE_SHARED:
 	    case OMP_CLAUSE_FIRSTPRIVATE:
-	    case OMP_CLAUSE_LASTPRIVATE:
 	    case OMP_CLAUSE_COPYIN:
 	    case OMP_CLAUSE_REDUCTION:
 	      break;
+	    case OMP_CLAUSE_LASTPRIVATE:
+	      if (pass != 0
+		  && OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
+		continue;
+	      break;
 	    default:
 	      continue;
 	    }
@@ -1564,7 +1569,8 @@ lower_rec_input_clauses (tree clauses, t
 		 code that expects a pointer to something that expects
 		 a direct variable.  Note that this doesn't apply to
 		 C++, since reference types are disallowed in data
-		 sharing clauses there.  */
+		 sharing clauses there, except for NRV optimized
+		 return values.  */
 	      if (pass == 0)
 		continue;
 
@@ -1575,7 +1581,9 @@ lower_rec_input_clauses (tree clauses, t
 		  if (DECL_NAME (var))
 		    name = IDENTIFIER_POINTER (DECL_NAME (new_var));
 
-		  x = create_tmp_var (TREE_TYPE (TREE_TYPE (new_var)), name);
+		  x = create_tmp_var_raw (TREE_TYPE (TREE_TYPE (new_var)),
+					  name);
+		  gimple_add_tmp_var (x);
 		  x = build_fold_addr_expr_with_type (x, TREE_TYPE (new_var));
 		}
 	      else
--- gcc/cp/cp-gimplify.c.jj	2006-03-21 17:10:36.000000000 +0100
+++ gcc/cp/cp-gimplify.c	2006-04-27 15:33:36.000000000 +0200
@@ -1,6 +1,6 @@
 /* C++-specific tree lowering bits; see also c-gimplify.c and tree-gimple.c.
 
-   Copyright (C) 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
+   Copyright (C) 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
    Contributed by Jason Merrill <jason@redhat.com>
 
 This file is part of GCC.
@@ -870,3 +870,12 @@ cxx_omp_clause_dtor (tree clause, tree d
 
   return ret;
 }
+
+/* True if OpenMP should privatize what this DECL points to rather
+   than the DECL itself.  */
+
+bool
+cxx_omp_privatize_by_reference (tree decl)
+{
+  return TREE_CODE (decl) == RESULT_DECL && DECL_BY_REFERENCE (decl);
+}
--- gcc/cp/cp-tree.h.jj	2006-04-26 10:40:02.000000000 +0200
+++ gcc/cp/cp-tree.h	2006-04-27 15:32:02.000000000 +0200
@@ -4267,6 +4267,7 @@ extern tree cxx_omp_clause_default_ctor	
 extern tree cxx_omp_clause_copy_ctor		(tree, tree, tree);
 extern tree cxx_omp_clause_assign_op		(tree, tree, tree);
 extern tree cxx_omp_clause_dtor			(tree, tree);
+extern bool cxx_omp_privatize_by_reference	(tree);
 
 /* in tree.c */
 extern void lang_check_failed			(const char *, int,
--- gcc/cp/cp-objcp-common.h.jj	2006-03-12 09:51:26.000000000 +0100
+++ gcc/cp/cp-objcp-common.h	2006-04-27 15:31:04.000000000 +0200
@@ -161,5 +161,7 @@ extern tree objcp_tsubst_copy_and_build 
 #define LANG_HOOKS_OMP_CLAUSE_ASSIGN_OP cxx_omp_clause_assign_op
 #undef LANG_HOOKS_OMP_CLAUSE_DTOR
 #define LANG_HOOKS_OMP_CLAUSE_DTOR cxx_omp_clause_dtor
+#undef LANG_HOOKS_OMP_PRIVATIZE_BY_REFERENCE
+#define LANG_HOOKS_OMP_PRIVATIZE_BY_REFERENCE cxx_omp_privatize_by_reference
 
 #endif /* GCC_CP_OBJCP_COMMON */
--- gcc/testsuite/g++.dg/gomp/pr27337-1.C.jj	2006-04-27 17:00:39.000000000 +0200
+++ gcc/testsuite/g++.dg/gomp/pr27337-1.C	2006-04-27 17:00:18.000000000 +0200
@@ -0,0 +1,22 @@
+// PR middle-end/27337
+// { dg-do compile }
+
+struct S
+{
+  S ();
+  ~S ();
+  double &operator* () const;
+};
+
+S
+foo ()
+{
+  int i;
+  S ret;
+
+#pragma omp parallel for
+  for (i = 0; i < 2; i++)
+    *ret += i;
+
+  return ret;
+}
--- gcc/testsuite/g++.dg/gomp/pr27337-2.C.jj	2006-04-27 17:00:42.000000000 +0200
+++ gcc/testsuite/g++.dg/gomp/pr27337-2.C	2006-04-27 17:00:54.000000000 +0200
@@ -0,0 +1,22 @@
+// PR middle-end/27337
+// { dg-do compile }
+
+struct S
+{
+  S ();
+  ~S ();
+  int i;
+};
+
+S
+foo ()
+{
+  int i;
+  S ret;
+
+#pragma omp parallel for firstprivate (ret) lastprivate (ret)
+  for (i = 0; i < 2; i++)
+    ret.i += i;
+
+  return ret;
+}
--- libgomp/testsuite/libgomp.c++/pr27337.C.jj	2006-04-27 16:58:53.000000000 +0200
+++ libgomp/testsuite/libgomp.c++/pr27337.C	2006-04-27 18:30:16.000000000 +0200
@@ -0,0 +1,91 @@
+// PR middle-end/27337
+// { dg-do run }
+
+#include <omp.h>
+
+extern "C" void abort (void);
+
+struct S
+{
+  S ();
+  ~S ();
+  S (const S &);
+  int i;
+};
+
+int n[3];
+
+S::S () : i(18)
+{
+  if (omp_get_thread_num () != 0)
+#pragma omp atomic
+    n[0]++;
+}
+
+S::~S ()
+{
+  if (omp_get_thread_num () != 0)
+#pragma omp atomic
+    n[1]++;
+}
+
+S::S (const S &x)
+{
+  if (x.i != 18)
+    abort ();
+  i = 118;
+  if (omp_get_thread_num () != 0)
+#pragma omp atomic
+    n[2]++;
+}
+
+S
+foo ()
+{
+  int i;
+  S ret;
+
+#pragma omp parallel for firstprivate (ret) lastprivate (ret) \
+			 schedule (static, 1) num_threads (4)
+  for (i = 0; i < 4; i++)
+    {
+      ret.i += omp_get_thread_num ();
+      // FIXME: The following barrier should be unnecessary.
+#pragma omp barrier
+    }
+
+  return ret;
+}
+
+S
+bar ()
+{
+  int i;
+  S ret;
+
+#pragma omp parallel for num_threads (4)
+  for (i = 0; i < 4; i++)
+#pragma omp atomic
+    ret.i += omp_get_thread_num () + 1;
+
+  return ret;
+}
+
+S x;
+
+int
+main (void)
+{
+  omp_set_dynamic (false);
+  x = foo ();
+  if (n[0] != 0 || n[1] != 3 || n[2] != 3)
+    abort ();
+  if (x.i != 118 + 3)
+    abort ();
+  x = bar ();
+  if (n[0] != 0 || n[1] != 3 || n[2] != 3)
+    abort ();
+  if (x.i != 18 + 0 + 1 + 2 + 3 + 4)
+    abort ();
+  return 0;
+}

	Jakub


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