diff options
author | Jakub Jelinek <jakub@redhat.com> | 2006-05-02 12:44:55 +0200 |
---|---|---|
committer | Jakub Jelinek <jakub@gcc.gnu.org> | 2006-05-02 12:44:55 +0200 |
commit | 077b0dfbfe62790f11c2d173da10b80ed752f9d1 (patch) | |
tree | e7fe929b16a97446edb70447a1000494b145b0dd | |
parent | 2aee3e57aed77de4f5ef28a8711b315aeb1bf77c (diff) | |
download | gcc-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/ChangeLog | 14 | ||||
-rw-r--r-- | gcc/cp/ChangeLog | 7 | ||||
-rw-r--r-- | gcc/cp/cp-gimplify.c | 11 | ||||
-rw-r--r-- | gcc/cp/cp-objcp-common.h | 2 | ||||
-rw-r--r-- | gcc/cp/cp-tree.h | 1 | ||||
-rw-r--r-- | gcc/gimplify.c | 17 | ||||
-rw-r--r-- | gcc/omp-low.c | 18 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 4 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/gomp/pr27337-1.C | 22 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/gomp/pr27337-2.C | 22 | ||||
-rw-r--r-- | libgomp/ChangeLog | 5 | ||||
-rw-r--r-- | libgomp/testsuite/libgomp.c++/pr27337.C | 91 |
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; +} |