This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[gomp] Fix handling of RESULT_DECL (PR middle-end/27337)
- From: Jakub Jelinek <jakub at redhat dot com>
- To: Richard Henderson <rth at redhat dot com>, Diego Novillo <dnovillo at redhat dot com>
- Cc: gcc-patches at gcc dot gnu dot org
- Date: Thu, 27 Apr 2006 12:42:43 -0400
- Subject: [gomp] Fix handling of RESULT_DECL (PR middle-end/27337)
- Reply-to: Jakub Jelinek <jakub at redhat dot com>
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