Commit decaaec8 by Jakub Jelinek Committed by Jakub Jelinek

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

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
parent c3d96270
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
......
...@@ -2998,6 +2998,27 @@ lower_rec_simd_input_clauses (tree new_var, omp_context *ctx, int &max_vf, ...@@ -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, ...@@ -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, ...@@ -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, ...@@ -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, ...@@ -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)
{ {
......
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.
......
// { 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 ();
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment