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>
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;
}
/* 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,
from the receiver (aka child) side and initializers for REFERENCE_TYPE
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))
{
/* For reduction with placeholder in SIMD loop,
defer adding the initialization of the reference,
because if we decide to use SIMD array for it,
the initilization could cause expansion ICE. */
if (c_kind == OMP_CLAUSE_REDUCTION
&& OMP_CLAUSE_REDUCTION_PLACEHOLDER (c)
&& is_simd)
/* For reduction in SIMD loop, defer adding the
initialization of the reference, because if we decide
to use SIMD array for it, the initilization could cause
expansion ICE. */
if (c_kind == OMP_CLAUSE_REDUCTION && is_simd)
x = NULL_TREE;
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
initialization now. */
else if (is_reference (var) && is_simd)
{
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);
}
}
handle_simd_reference (clause_loc, new_vard, ilist);
x = lang_hooks.decls.omp_clause_default_ctor
(c, new_var, unshare_expr (x));
if (x)
@ -3573,6 +3576,13 @@ lower_rec_input_clauses (tree clauses, gimple_seq *ilist, gimple_seq *dlist,
if (code == MINUS_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
&& lower_rec_simd_input_clauses (new_var, ctx, max_vf,
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);
ref = build_outer_var_ref (var, ctx);
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
{
if (is_reference (var) && is_simd)
handle_simd_reference (clause_loc, new_vard, ilist);
gimplify_assign (new_var, x, ilist);
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>
* 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 ();
}