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
This commit is contained in:
Jakub Jelinek 2006-05-02 12:44:55 +02:00 committed by Jakub Jelinek
parent 2aee3e57ae
commit 077b0dfbfe
12 changed files with 208 additions and 6 deletions

View File

@ -1,5 +1,19 @@
2006-05-02 Jakub Jelinek <jakub@redhat.com> 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 PR middle-end/27328
* omp-low.c (remove_exit_barrier): Handle NULL exit_bb. * omp-low.c (remove_exit_barrier): Handle NULL exit_bb.
(expand_omp_parallel): Likewise. (expand_omp_parallel): Likewise.

View File

@ -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> 2006-04-30 Mark Mitchell <mark@codesourcery.com>
PR c++/27094 PR c++/27094

View File

@ -1,6 +1,6 @@
/* C++-specific tree lowering bits; see also c-gimplify.c and tree-gimple.c. /* 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> Contributed by Jason Merrill <jason@redhat.com>
This file is part of GCC. This file is part of GCC.
@ -870,3 +870,12 @@ cxx_omp_clause_dtor (tree clause, tree decl)
return ret; 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);
}

View File

@ -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 #define LANG_HOOKS_OMP_CLAUSE_ASSIGN_OP cxx_omp_clause_assign_op
#undef LANG_HOOKS_OMP_CLAUSE_DTOR #undef LANG_HOOKS_OMP_CLAUSE_DTOR
#define LANG_HOOKS_OMP_CLAUSE_DTOR cxx_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 */ #endif /* GCC_CP_OBJCP_COMMON */

View File

@ -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_copy_ctor (tree, tree, tree);
extern tree cxx_omp_clause_assign_op (tree, tree, tree); extern tree cxx_omp_clause_assign_op (tree, tree, tree);
extern tree cxx_omp_clause_dtor (tree, tree); extern tree cxx_omp_clause_dtor (tree, tree);
extern bool cxx_omp_privatize_by_reference (tree);
/* in tree.c */ /* in tree.c */
extern void lang_check_failed (const char *, int, extern void lang_check_failed (const char *, int,

View File

@ -4504,6 +4504,11 @@ gimplify_scan_omp_clauses (tree *list_p, tree *pre_p, bool in_parallel)
remove = true; remove = true;
break; 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); omp_add_variable (ctx, decl, flags);
if (TREE_CODE (c) == OMP_CLAUSE_REDUCTION if (TREE_CODE (c) == OMP_CLAUSE_REDUCTION
&& OMP_CLAUSE_REDUCTION_PLACEHOLDER (c)) && OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
@ -4531,6 +4536,11 @@ gimplify_scan_omp_clauses (tree *list_p, tree *pre_p, bool in_parallel)
remove = true; remove = true;
break; 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: do_notice:
if (outer_ctx) if (outer_ctx)
omp_notice_variable (outer_ctx, decl, true); 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); ret = gimplify_var_or_parm_decl (expr_p);
break; 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: case SSA_NAME:
/* Allow callbacks into the gimplifier during optimization. */ /* Allow callbacks into the gimplifier during optimization. */
ret = GS_ALL_DONE; ret = GS_ALL_DONE;

View File

@ -491,7 +491,7 @@ use_pointer_for_field (tree decl, bool shared_p)
without analyzing the expression whether or not its location without analyzing the expression whether or not its location
is accessible to anyone else. In the case of nested parallel is accessible to anyone else. In the case of nested parallel
regions it certainly may be. */ 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; return true;
/* Do not use copy-in/copy-out for variables that have their /* 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) if (region->exit)
fprintf (file, "%*sbb: %d: OMP_RETURN\n", indent, "", fprintf (file, "%*sbb %d: OMP_RETURN\n", indent, "",
region->exit->index); region->exit->index);
else else
fprintf (file, "%*s[no exit marker]\n", indent, ""); 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 VAR_DECL:
case PARM_DECL: case PARM_DECL:
case LABEL_DECL: case LABEL_DECL:
case RESULT_DECL:
if (ctx) if (ctx)
*tp = remap_decl (t, &ctx->cb); *tp = remap_decl (t, &ctx->cb);
break; break;
@ -1518,10 +1519,14 @@ lower_rec_input_clauses (tree clauses, tree *ilist, tree *dlist,
break; break;
case OMP_CLAUSE_SHARED: case OMP_CLAUSE_SHARED:
case OMP_CLAUSE_FIRSTPRIVATE: case OMP_CLAUSE_FIRSTPRIVATE:
case OMP_CLAUSE_LASTPRIVATE:
case OMP_CLAUSE_COPYIN: case OMP_CLAUSE_COPYIN:
case OMP_CLAUSE_REDUCTION: case OMP_CLAUSE_REDUCTION:
break; break;
case OMP_CLAUSE_LASTPRIVATE:
if (pass != 0
&& OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
continue;
break;
default: default:
continue; continue;
} }
@ -1564,7 +1569,8 @@ lower_rec_input_clauses (tree clauses, tree *ilist, tree *dlist,
code that expects a pointer to something that expects code that expects a pointer to something that expects
a direct variable. Note that this doesn't apply to a direct variable. Note that this doesn't apply to
C++, since reference types are disallowed in data C++, since reference types are disallowed in data
sharing clauses there. */ sharing clauses there, except for NRV optimized
return values. */
if (pass == 0) if (pass == 0)
continue; continue;
@ -1575,7 +1581,9 @@ lower_rec_input_clauses (tree clauses, tree *ilist, tree *dlist,
if (DECL_NAME (var)) if (DECL_NAME (var))
name = IDENTIFIER_POINTER (DECL_NAME (new_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)); x = build_fold_addr_expr_with_type (x, TREE_TYPE (new_var));
} }
else else

View File

@ -1,5 +1,9 @@
2006-05-02 Jakub Jelinek <jakub@redhat.com> 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 PR middle-end/27328
* gcc.dg/gomp/pr27328.c: New test. * gcc.dg/gomp/pr27328.c: New test.

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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> 2006-04-26 Jakub Jelinek <jakub@redhat.com>
PR c/26171 PR c/26171

View File

@ -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;
}