summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJakub Jelinek <jakub@redhat.com>2006-05-02 12:44:55 +0200
committerJakub Jelinek <jakub@gcc.gnu.org>2006-05-02 12:44:55 +0200
commit077b0dfbfe62790f11c2d173da10b80ed752f9d1 (patch)
treee7fe929b16a97446edb70447a1000494b145b0dd
parent2aee3e57aed77de4f5ef28a8711b315aeb1bf77c (diff)
downloadgcc-077b0dfbfe62790f11c2d173da10b80ed752f9d1.tar.gz
re PR middle-end/27337 (OpenMP ICE in expand_expr_real_1 at expr.c:6814)
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. From-SVN: r113456
-rw-r--r--gcc/ChangeLog14
-rw-r--r--gcc/cp/ChangeLog7
-rw-r--r--gcc/cp/cp-gimplify.c11
-rw-r--r--gcc/cp/cp-objcp-common.h2
-rw-r--r--gcc/cp/cp-tree.h1
-rw-r--r--gcc/gimplify.c17
-rw-r--r--gcc/omp-low.c18
-rw-r--r--gcc/testsuite/ChangeLog4
-rw-r--r--gcc/testsuite/g++.dg/gomp/pr27337-1.C22
-rw-r--r--gcc/testsuite/g++.dg/gomp/pr27337-2.C22
-rw-r--r--libgomp/ChangeLog5
-rw-r--r--libgomp/testsuite/libgomp.c++/pr27337.C91
12 files changed, 208 insertions, 6 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 9a0849a8794..f9213111d18 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,5 +1,19 @@
2006-05-02 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.
+
PR middle-end/27328
* omp-low.c (remove_exit_barrier): Handle NULL exit_bb.
(expand_omp_parallel): Likewise.
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index bdc1f41268c..937d5e80f15 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,10 @@
+2006-05-02 Jakub Jelinek <jakub@redhat.com>
+
+ PR middle-end/27337
+ * 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.
+
2006-04-30 Mark Mitchell <mark@codesourcery.com>
PR c++/27094
diff --git a/gcc/cp/cp-gimplify.c b/gcc/cp/cp-gimplify.c
index be85ebb56f1..4746103e618 100644
--- a/gcc/cp/cp-gimplify.c
+++ b/gcc/cp/cp-gimplify.c
@@ -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 decl)
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);
+}
diff --git a/gcc/cp/cp-objcp-common.h b/gcc/cp/cp-objcp-common.h
index 96e6eb699dc..65eb6aedfa3 100644
--- a/gcc/cp/cp-objcp-common.h
+++ b/gcc/cp/cp-objcp-common.h
@@ -161,5 +161,7 @@ extern tree objcp_tsubst_copy_and_build (tree, tree, tsubst_flags_t,
#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 */
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 1e3c1b7807d..2e5739a7eb6 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -4267,6 +4267,7 @@ extern tree cxx_omp_clause_default_ctor (tree, tree);
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,
diff --git a/gcc/gimplify.c b/gcc/gimplify.c
index 3ee21d865af..af3d9243128 100644
--- a/gcc/gimplify.c
+++ b/gcc/gimplify.c
@@ -4504,6 +4504,11 @@ gimplify_scan_omp_clauses (tree *list_p, tree *pre_p, bool in_parallel)
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, tree *pre_p, bool in_parallel)
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, tree *post_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;
diff --git a/gcc/omp-low.c b/gcc/omp-low.c
index 62b715e37ad..f344e6933fb 100644
--- a/gcc/omp-low.c
+++ b/gcc/omp-low.c
@@ -491,7 +491,7 @@ use_pointer_for_field (tree decl, bool shared_p)
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
@@ -724,7 +724,7 @@ dump_omp_region (FILE *file, struct omp_region *region, int indent)
}
if (region->exit)
- fprintf (file, "%*sbb: %d: OMP_RETURN\n", 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, void *data)
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, tree *ilist, tree *dlist,
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, tree *ilist, tree *dlist,
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, tree *ilist, tree *dlist,
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
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index b890b64302b..d5b92bb4258 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,5 +1,9 @@
2006-05-02 Jakub Jelinek <jakub@redhat.com>
+ PR middle-end/27337
+ * g++.dg/gomp/pr27337-1.C: New test.
+ * g++.dg/gomp/pr27337-2.C: New test.
+
PR middle-end/27328
* gcc.dg/gomp/pr27328.c: New test.
diff --git a/gcc/testsuite/g++.dg/gomp/pr27337-1.C b/gcc/testsuite/g++.dg/gomp/pr27337-1.C
new file mode 100644
index 00000000000..6c26070ab34
--- /dev/null
+++ b/gcc/testsuite/g++.dg/gomp/pr27337-1.C
@@ -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;
+}
diff --git a/gcc/testsuite/g++.dg/gomp/pr27337-2.C b/gcc/testsuite/g++.dg/gomp/pr27337-2.C
new file mode 100644
index 00000000000..d1ae4a139f2
--- /dev/null
+++ b/gcc/testsuite/g++.dg/gomp/pr27337-2.C
@@ -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;
+}
diff --git a/libgomp/ChangeLog b/libgomp/ChangeLog
index 657b7ea0425..754d0f91df6 100644
--- a/libgomp/ChangeLog
+++ b/libgomp/ChangeLog
@@ -1,3 +1,8 @@
+2006-05-02 Jakub Jelinek <jakub@redhat.com>
+
+ PR middle-end/27337
+ * testsuite/libgomp.c++/pr27337.C: New test.
+
2006-04-26 Jakub Jelinek <jakub@redhat.com>
PR c/26171
diff --git a/libgomp/testsuite/libgomp.c++/pr27337.C b/libgomp/testsuite/libgomp.c++/pr27337.C
new file mode 100644
index 00000000000..c12154e02b6
--- /dev/null
+++ b/libgomp/testsuite/libgomp.c++/pr27337.C
@@ -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;
+}