re PR middle-end/61252 (Invalid code produced for omp simd reduction(min:var) where var is reference)

PR middle-end/61252
	* omp-low.c (handle_simd_reference): New function.
	(lower_rec_input_clauses): Use it.  Defer adding reference
	initialization even for reduction without placeholder if in simd,
	handle it properly later on.

	* testsuite/libgomp.c++/simd-9.C: New test.

From-SVN: r210679
This commit is contained in:
Jakub Jelinek 2014-05-21 10:04:03 +02:00 committed by Jakub Jelinek
parent c3d96270fc
commit decaaec811
4 changed files with 108 additions and 24 deletions

View File

@ -1,3 +1,11 @@
2014-05-21 Jakub Jelinek <jakub@redhat.com>
PR middle-end/61252
* omp-low.c (handle_simd_reference): New function.
(lower_rec_input_clauses): Use it. Defer adding reference
initialization even for reduction without placeholder if in simd,
handle it properly later on.
2014-05-20 Jan Hubicka <hubicka@ucw.cz> 2014-05-20 Jan Hubicka <hubicka@ucw.cz>
PR tree-optimization/60899 PR tree-optimization/60899

View File

@ -2998,6 +2998,27 @@ lower_rec_simd_input_clauses (tree new_var, omp_context *ctx, int &max_vf,
return true; return true;
} }
/* Helper function of lower_rec_input_clauses. For a reference
in simd reduction, add an underlying variable it will reference. */
static void
handle_simd_reference (location_t loc, tree new_vard, gimple_seq *ilist)
{
tree z = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (new_vard)));
if (TREE_CONSTANT (z))
{
const char *name = NULL;
if (DECL_NAME (new_vard))
name = IDENTIFIER_POINTER (DECL_NAME (new_vard));
z = create_tmp_var_raw (TREE_TYPE (TREE_TYPE (new_vard)), name);
gimple_add_tmp_var (z);
TREE_ADDRESSABLE (z) = 1;
z = build_fold_addr_expr_loc (loc, z);
gimplify_assign (new_vard, z, ilist);
}
}
/* Generate code to implement the input clauses, FIRSTPRIVATE and COPYIN, /* Generate code to implement the input clauses, FIRSTPRIVATE and COPYIN,
from the receiver (aka child) side and initializers for REFERENCE_TYPE from the receiver (aka child) side and initializers for REFERENCE_TYPE
private variables. Initialization statements go in ILIST, while calls private variables. Initialization statements go in ILIST, while calls
@ -3189,13 +3210,11 @@ lower_rec_input_clauses (tree clauses, gimple_seq *ilist, gimple_seq *dlist,
} }
else if (TREE_CONSTANT (x)) else if (TREE_CONSTANT (x))
{ {
/* For reduction with placeholder in SIMD loop, /* For reduction in SIMD loop, defer adding the
defer adding the initialization of the reference, initialization of the reference, because if we decide
because if we decide to use SIMD array for it, to use SIMD array for it, the initilization could cause
the initilization could cause expansion ICE. */ expansion ICE. */
if (c_kind == OMP_CLAUSE_REDUCTION if (c_kind == OMP_CLAUSE_REDUCTION && is_simd)
&& OMP_CLAUSE_REDUCTION_PLACEHOLDER (c)
&& is_simd)
x = NULL_TREE; x = NULL_TREE;
else else
{ {
@ -3524,23 +3543,7 @@ lower_rec_input_clauses (tree clauses, gimple_seq *ilist, gimple_seq *dlist,
But if they aren't used, we need to emit the deferred But if they aren't used, we need to emit the deferred
initialization now. */ initialization now. */
else if (is_reference (var) && is_simd) else if (is_reference (var) && is_simd)
{ handle_simd_reference (clause_loc, new_vard, ilist);
tree z
= TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (new_vard)));
if (TREE_CONSTANT (z))
{
const char *name = NULL;
if (DECL_NAME (var))
name = IDENTIFIER_POINTER (DECL_NAME (new_vard));
z = create_tmp_var_raw
(TREE_TYPE (TREE_TYPE (new_vard)), name);
gimple_add_tmp_var (z);
TREE_ADDRESSABLE (z) = 1;
z = build_fold_addr_expr_loc (clause_loc, z);
gimplify_assign (new_vard, z, ilist);
}
}
x = lang_hooks.decls.omp_clause_default_ctor x = lang_hooks.decls.omp_clause_default_ctor
(c, new_var, unshare_expr (x)); (c, new_var, unshare_expr (x));
if (x) if (x)
@ -3573,6 +3576,13 @@ lower_rec_input_clauses (tree clauses, gimple_seq *ilist, gimple_seq *dlist,
if (code == MINUS_EXPR) if (code == MINUS_EXPR)
code = PLUS_EXPR; code = PLUS_EXPR;
tree new_vard = new_var;
if (is_simd && is_reference (var))
{
gcc_assert (TREE_CODE (new_var) == MEM_REF);
new_vard = TREE_OPERAND (new_var, 0);
gcc_assert (DECL_P (new_vard));
}
if (is_simd if (is_simd
&& lower_rec_simd_input_clauses (new_var, ctx, max_vf, && lower_rec_simd_input_clauses (new_var, ctx, max_vf,
idx, lane, ivar, lvar)) idx, lane, ivar, lvar))
@ -3584,9 +3594,18 @@ lower_rec_input_clauses (tree clauses, gimple_seq *ilist, gimple_seq *dlist,
x = build2 (code, TREE_TYPE (ref), ref, ivar); x = build2 (code, TREE_TYPE (ref), ref, ivar);
ref = build_outer_var_ref (var, ctx); ref = build_outer_var_ref (var, ctx);
gimplify_assign (ref, x, &llist[1]); gimplify_assign (ref, x, &llist[1]);
if (new_vard != new_var)
{
SET_DECL_VALUE_EXPR (new_vard,
build_fold_addr_expr (lvar));
DECL_HAS_VALUE_EXPR_P (new_vard) = 1;
}
} }
else else
{ {
if (is_reference (var) && is_simd)
handle_simd_reference (clause_loc, new_vard, ilist);
gimplify_assign (new_var, x, ilist); gimplify_assign (new_var, x, ilist);
if (is_simd) if (is_simd)
{ {

View File

@ -1,3 +1,8 @@
2014-05-21 Jakub Jelinek <jakub@redhat.com>
PR middle-end/61252
* testsuite/libgomp.c++/simd-9.C: New test.
2014-05-18 Uros Bizjak <ubizjak@gmail.com> 2014-05-18 Uros Bizjak <ubizjak@gmail.com>
* libgomp.texi (Runitme Library Routines): Remove multiple @menu. * libgomp.texi (Runitme Library Routines): Remove multiple @menu.

View File

@ -0,0 +1,52 @@
// { dg-do run }
// { dg-options "-O2" }
// { dg-additional-options "-msse2" { target sse2_runtime } }
// { dg-additional-options "-mavx" { target avx_runtime } }
extern "C" void abort ();
int a[1024] __attribute__((aligned (32))) = { 1 };
#pragma omp declare reduction (foo:int:omp_out += omp_in) \
initializer (omp_priv = 0)
__attribute__((noinline, noclone)) void
foo (int &u, int &v)
{
int i;
#pragma omp simd aligned(a : 32) reduction(foo:u) reduction(+:v)
for (i = 0; i < 1024; i++)
{
int x = a[i];
u += x;
v += x;
}
}
__attribute__((noinline, noclone)) void
bar (int &u, int &v)
{
int i;
#pragma omp simd aligned(a : 32) reduction(foo:u) reduction(+:v) \
safelen(1)
for (i = 0; i < 1024; i++)
{
int x = a[i];
u += x;
v += x;
}
}
int
main ()
{
int i;
for (i = 0; i < 1024; i++)
a[i] = (i & 31) + (i / 128);
int u = 0, v = 0;
foo (u, v);
if (u != 19456 || v != 19456)
abort ();
u = 0; v = 0;
bar (u, v);
if (u != 19456 || v != 19456)
abort ();
}