Commit 01a8cacc by Richard Biener Committed by Richard Biener

re PR tree-optimization/66623 (Unsafe FP math reduction used in strict math mode)

2017-06-09  Richard Biener  <rguenther@suse.de>

	PR tree-optimization/66623
	* tree-vect-loop.c (vect_is_simple_reduction): Cleanup,
	refactor check_reduction into two parts, properly computing
	whether we have to check reduction validity for outer loop
	vectorization.

	* gcc.dg/vect/pr66623.c: New testcase.

From-SVN: r249053
parent 6d1115c5
2017-06-09 Richard Biener <rguenther@suse.de>
PR tree-optimization/66623
* tree-vect-loop.c (vect_is_simple_reduction): Cleanup,
refactor check_reduction into two parts, properly computing
whether we have to check reduction validity for outer loop
vectorization.
2017-06-09 Richard Biener <rguenther@suse.de>
PR tree-optimization/79483
* graphite-scop-detection.c (order): New global.
(get_order): Compute bb to order mapping that satisfies code
......
2017-06-09 Richard Biener <rguenther@suse.de>
PR tree-optimization/66623
* gcc.dg/vect/pr66623.c: New testcase.
2017-06-09 Richard Biener <rguenther@suse.de>
PR tree-optimization/79483
* gcc.dg/graphite/pr79483.c: New testcase.
......
/* { dg-require-effective-target vect_float } */
#include "tree-vect.h"
extern void abort (void);
#define OP *
#define INIT 1.0
float __attribute__((noinline,noclone))
foo (float *__restrict__ i)
{
float l = INIT;
int a;
int b;
for (a = 0; a < 4; a++)
for (b = 0; b < 4; b++)
l = l OP i[b];
return l;
}
float __attribute__((noinline,noclone))
foo_ref (float *__restrict__ i)
{
float l = INIT;
l = l OP i[0];
l = l OP i[1];
l = l OP i[2];
l = l OP i[3];
l = l OP i[0];
l = l OP i[1];
l = l OP i[2];
l = l OP i[3];
l = l OP i[0];
l = l OP i[1];
l = l OP i[2];
l = l OP i[3];
l = l OP i[0];
l = l OP i[1];
l = l OP i[2];
l = l OP i[3];
return l;
}
union u
{
float f;
unsigned int u;
};
int
main (void)
{
union u res, res2;
float a[4];
if (sizeof (float) != sizeof (unsigned int))
return 0;
check_vect ();
a[0] = 0.01;
a[1] = 0.01;
a[2] = 0.01;
a[3] = 1.0;
res.f = foo_ref (a);
res2.f = foo (a);
if (res.u != res2.u)
abort ();
return 0;
}
/* need -ffast-math to vectorize this loop. */
/* ARM NEON passes -ffast-math to these tests, so expect this to fail. */
/* { dg-final { scan-tree-dump-times "vectorized 0 loops" 1 "vect" { xfail arm_neon_ok } } } */
......@@ -2727,8 +2727,6 @@ vect_is_simple_reduction (loop_vec_info loop_info, gimple *phi,
{
struct loop *loop = (gimple_bb (phi))->loop_father;
struct loop *vect_loop = LOOP_VINFO_LOOP (loop_info);
edge latch_e = loop_latch_edge (loop);
tree loop_arg = PHI_ARG_DEF_FROM_EDGE (phi, latch_e);
gimple *def_stmt, *def1 = NULL, *def2 = NULL, *phi_use_stmt = NULL;
enum tree_code orig_code, code;
tree op1, op2, op3 = NULL_TREE, op4 = NULL_TREE;
......@@ -2742,11 +2740,6 @@ vect_is_simple_reduction (loop_vec_info loop_info, gimple *phi,
*double_reduc = false;
*v_reduc_type = TREE_CODE_REDUCTION;
/* Check validity of the reduction only for the innermost loop. */
bool check_reduction = ! flow_loop_nested_p (vect_loop, loop);
gcc_assert ((check_reduction && loop == vect_loop)
|| (!check_reduction && flow_loop_nested_p (vect_loop, loop)));
name = PHI_RESULT (phi);
/* ??? If there are no uses of the PHI result the inner loop reduction
won't be detected as possibly double-reduction by vectorizable_reduction
......@@ -2775,13 +2768,15 @@ vect_is_simple_reduction (loop_vec_info loop_info, gimple *phi,
{
if (dump_enabled_p ())
dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
"reduction used in loop.\n");
"reduction value used in loop.\n");
return NULL;
}
phi_use_stmt = use_stmt;
}
edge latch_e = loop_latch_edge (loop);
tree loop_arg = PHI_ARG_DEF_FROM_EDGE (phi, latch_e);
if (TREE_CODE (loop_arg) != SSA_NAME)
{
if (dump_enabled_p ())
......@@ -2795,18 +2790,22 @@ vect_is_simple_reduction (loop_vec_info loop_info, gimple *phi,
}
def_stmt = SSA_NAME_DEF_STMT (loop_arg);
if (!def_stmt)
if (gimple_nop_p (def_stmt))
{
if (dump_enabled_p ())
dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
"reduction: no def_stmt.\n");
"reduction: no def_stmt\n");
return NULL;
}
if (!is_gimple_assign (def_stmt) && gimple_code (def_stmt) != GIMPLE_PHI)
{
if (dump_enabled_p ())
dump_gimple_stmt (MSG_NOTE, TDF_SLIM, def_stmt, 0);
{
dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
"reduction: unhandled reduction operation: ");
dump_gimple_stmt (MSG_MISSED_OPTIMIZATION, TDF_SLIM, def_stmt, 0);
}
return NULL;
}
......@@ -2822,6 +2821,7 @@ vect_is_simple_reduction (loop_vec_info loop_info, gimple *phi,
}
nloop_uses = 0;
auto_vec<gphi *, 3> lcphis;
FOR_EACH_IMM_USE_FAST (use_p, imm_iter, name)
{
gimple *use_stmt = USE_STMT (use_p);
......@@ -2829,6 +2829,9 @@ vect_is_simple_reduction (loop_vec_info loop_info, gimple *phi,
continue;
if (flow_bb_inside_loop_p (loop, gimple_bb (use_stmt)))
nloop_uses++;
else
/* We can have more than one loop-closed PHI. */
lcphis.safe_push (as_a <gphi *> (use_stmt));
if (nloop_uses > 1)
{
if (dump_enabled_p ())
......@@ -2873,6 +2876,27 @@ vect_is_simple_reduction (loop_vec_info loop_info, gimple *phi,
return NULL;
}
/* If we are vectorizing an inner reduction we are executing that
in the original order only in case we are not dealing with a
double reduction. */
bool check_reduction = true;
if (flow_loop_nested_p (vect_loop, loop))
{
gphi *lcphi;
unsigned i;
check_reduction = false;
FOR_EACH_VEC_ELT (lcphis, i, lcphi)
FOR_EACH_IMM_USE_FAST (use_p, imm_iter, gimple_phi_result (lcphi))
{
gimple *use_stmt = USE_STMT (use_p);
if (is_gimple_debug (use_stmt))
continue;
if (! flow_bb_inside_loop_p (vect_loop, gimple_bb (use_stmt)))
check_reduction = true;
}
}
bool nested_in_vect_loop = flow_loop_nested_p (vect_loop, loop);
code = orig_code = gimple_assign_rhs_code (def_stmt);
/* We can handle "res -= x[i]", which is non-associative by
......@@ -2887,27 +2911,8 @@ vect_is_simple_reduction (loop_vec_info loop_info, gimple *phi,
if (code == COND_EXPR)
{
if (check_reduction)
if (! nested_in_vect_loop)
*v_reduc_type = COND_REDUCTION;
}
else if (!commutative_tree_code (code) || !associative_tree_code (code))
{
if (dump_enabled_p ())
report_vect_op (MSG_MISSED_OPTIMIZATION, def_stmt,
"reduction: not commutative/associative: ");
return NULL;
}
if (get_gimple_rhs_class (code) != GIMPLE_BINARY_RHS)
{
if (code != COND_EXPR)
{
if (dump_enabled_p ())
report_vect_op (MSG_MISSED_OPTIMIZATION, def_stmt,
"reduction: not binary operation: ");
return NULL;
}
op3 = gimple_assign_rhs1 (def_stmt);
if (COMPARISON_CLASS_P (op3))
......@@ -2918,30 +2923,35 @@ vect_is_simple_reduction (loop_vec_info loop_info, gimple *phi,
op1 = gimple_assign_rhs2 (def_stmt);
op2 = gimple_assign_rhs3 (def_stmt);
if (TREE_CODE (op1) != SSA_NAME && TREE_CODE (op2) != SSA_NAME)
{
if (dump_enabled_p ())
report_vect_op (MSG_MISSED_OPTIMIZATION, def_stmt,
"reduction: uses not ssa_names: ");
return NULL;
}
}
else
else if (!commutative_tree_code (code) || !associative_tree_code (code))
{
if (dump_enabled_p ())
report_vect_op (MSG_MISSED_OPTIMIZATION, def_stmt,
"reduction: not commutative/associative: ");
return NULL;
}
else if (get_gimple_rhs_class (code) == GIMPLE_BINARY_RHS)
{
op1 = gimple_assign_rhs1 (def_stmt);
op2 = gimple_assign_rhs2 (def_stmt);
}
else
{
if (dump_enabled_p ())
report_vect_op (MSG_MISSED_OPTIMIZATION, def_stmt,
"reduction: not handled operation: ");
return NULL;
}
if (TREE_CODE (op1) != SSA_NAME && TREE_CODE (op2) != SSA_NAME)
{
if (dump_enabled_p ())
report_vect_op (MSG_MISSED_OPTIMIZATION, def_stmt,
"reduction: uses not ssa_names: ");
if (TREE_CODE (op1) != SSA_NAME && TREE_CODE (op2) != SSA_NAME)
{
if (dump_enabled_p ())
report_vect_op (MSG_MISSED_OPTIMIZATION, def_stmt,
"reduction: both uses not ssa_names: ");
return NULL;
}
}
return NULL;
}
type = TREE_TYPE (gimple_assign_lhs (def_stmt));
if ((TREE_CODE (op1) == SSA_NAME
......@@ -3091,7 +3101,7 @@ vect_is_simple_reduction (loop_vec_info loop_info, gimple *phi,
== vect_internal_def
&& !is_loop_header_bb_p (gimple_bb (def2)))))))
{
if (check_reduction && orig_code != MINUS_EXPR)
if (! nested_in_vect_loop && orig_code != MINUS_EXPR)
{
/* Check if we can swap operands (just for simplicity - so that
the rest of the code can assume that the reduction variable
......@@ -3145,7 +3155,8 @@ vect_is_simple_reduction (loop_vec_info loop_info, gimple *phi,
}
/* Try to find SLP reduction chain. */
if (check_reduction && code != COND_EXPR
if (! nested_in_vect_loop
&& code != COND_EXPR
&& vect_is_slp_reduction (loop_info, phi, def_stmt))
{
if (dump_enabled_p ())
......
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