Commit b7ff7cef by Richard Biener Committed by Richard Biener

re PR tree-optimization/65930 (Reduction with sign-change not handled)

2019-10-29  Richard Biener  <rguenther@suse.de>

	PR tree-optimization/65930
	* tree-vect-loop.c (check_reduction_path): Relax single-use
	check allowing out-of-loop uses.
	(vect_is_simple_reduction): SLP reduction chains cannot have
	intermediate stmts used outside of the loop.
	(vect_create_epilog_for_reduction): The adjustment might need
	to be converted.
	(vectorizable_reduction): Annotate live stmts of the reduction
	chain with STMT_VINFO_REDUC_DEF.
	* tree-vect-stms.c (process_use): Remove no longer true asserts.

	* gcc.dg/vect/pr65930-1.c: New testcase.

From-SVN: r277566
parent bc73c4c2
2019-10-29 Richard Biener <rguenther@suse.de>
PR tree-optimization/65930
* tree-vect-loop.c (check_reduction_path): Relax single-use
check allowing out-of-loop uses.
(vect_is_simple_reduction): SLP reduction chains cannot have
intermediate stmts used outside of the loop.
(vect_create_epilog_for_reduction): The adjustment might need
to be converted.
(vectorizable_reduction): Annotate live stmts of the reduction
chain with STMT_VINFO_REDUC_DEF.
* tree-vect-stms.c (process_use): Remove no longer true asserts.
2019-10-29 Richard Sandiford <richard.sandiford@arm.com> 2019-10-29 Richard Sandiford <richard.sandiford@arm.com>
* calls.c (pass_by_reference): Leave the target to decide whether * calls.c (pass_by_reference): Leave the target to decide whether
2019-10-29 Richard Biener <rguenther@suse.de>
PR tree-optimization/65930
* gcc.dg/vect/pr65930-1.c: New testcase.
2019-10-29 Richard Sandiford <richard.sandiford@arm.com> 2019-10-29 Richard Sandiford <richard.sandiford@arm.com>
Kugan Vivekanandarajah <kugan.vivekanandarajah@linaro.org> Kugan Vivekanandarajah <kugan.vivekanandarajah@linaro.org>
Prathamesh Kulkarni <prathamesh.kulkarni@linaro.org> Prathamesh Kulkarni <prathamesh.kulkarni@linaro.org>
......
/* { dg-require-effective-target vect_int } */
#include "tree-vect.h"
unsigned __attribute__((noipa))
bar (unsigned int *x)
{
int sum = 4;
x = __builtin_assume_aligned (x, __BIGGEST_ALIGNMENT__);
for (int i = 0; i < 16; ++i)
sum += x[i];
return sum;
}
int
main()
{
static int a[16] __attribute__((aligned(__BIGGEST_ALIGNMENT__)))
= { 1, 3, 5, 8, 9, 10, 17, 18, 23, 29, 30, 55, 42, 2, 3, 1 };
check_vect ();
if (bar (a) != 260)
abort ();
return 0;
}
/* { dg-final { scan-tree-dump "vectorized 1 loops" "vect" } } */
...@@ -2678,8 +2678,7 @@ pop: ...@@ -2678,8 +2678,7 @@ pop:
{ {
gimple *use_stmt = USE_STMT (path[i].second); gimple *use_stmt = USE_STMT (path[i].second);
tree op = USE_FROM_PTR (path[i].second); tree op = USE_FROM_PTR (path[i].second);
if (! has_single_use (op) if (! is_gimple_assign (use_stmt)
|| ! is_gimple_assign (use_stmt)
/* The following make sure we can compute the operand index /* The following make sure we can compute the operand index
easily plus it mostly disallows chaining via COND_EXPR condition easily plus it mostly disallows chaining via COND_EXPR condition
operands. */ operands. */
...@@ -2690,7 +2689,21 @@ pop: ...@@ -2690,7 +2689,21 @@ pop:
fail = true; fail = true;
break; break;
} }
enum tree_code use_code = gimple_assign_rhs_code (use_stmt); /* Check there's only a single stmt the op is used on inside
of the loop. */
imm_use_iterator imm_iter;
gimple *op_use_stmt;
unsigned cnt = 0;
FOR_EACH_IMM_USE_STMT (op_use_stmt, imm_iter, op)
if (!is_gimple_debug (op_use_stmt)
&& flow_bb_inside_loop_p (loop, gimple_bb (op_use_stmt)))
cnt++;
if (cnt != 1)
{
fail = true;
break;
}
tree_code use_code = gimple_assign_rhs_code (use_stmt);
if (use_code == MINUS_EXPR) if (use_code == MINUS_EXPR)
{ {
use_code = PLUS_EXPR; use_code = PLUS_EXPR;
...@@ -2922,7 +2935,10 @@ vect_is_simple_reduction (loop_vec_info loop_info, stmt_vec_info phi_info, ...@@ -2922,7 +2935,10 @@ vect_is_simple_reduction (loop_vec_info loop_info, stmt_vec_info phi_info,
for (i = path.length () - 1; i >= 1; --i) for (i = path.length () - 1; i >= 1; --i)
{ {
gimple *stmt = USE_STMT (path[i].second); gimple *stmt = USE_STMT (path[i].second);
if (gimple_assign_rhs_code (stmt) != code) if (gimple_assign_rhs_code (stmt) != code
/* We can only handle the final value in epilogue
generation for reduction chains. */
|| (i != 1 && !has_single_use (gimple_assign_lhs (stmt))))
is_slp_reduc = false; is_slp_reduc = false;
stmt_vec_info stmt_info = loop_info->lookup_stmt (stmt); stmt_vec_info stmt_info = loop_info->lookup_stmt (stmt);
STMT_VINFO_REDUC_IDX (stmt_info) STMT_VINFO_REDUC_IDX (stmt_info)
...@@ -4119,11 +4135,11 @@ vect_create_epilog_for_reduction (stmt_vec_info stmt_info, ...@@ -4119,11 +4135,11 @@ vect_create_epilog_for_reduction (stmt_vec_info stmt_info,
stmt_vec_info phi_info; stmt_vec_info phi_info;
gimple_stmt_iterator exit_gsi; gimple_stmt_iterator exit_gsi;
tree vec_dest; tree vec_dest;
tree new_temp = NULL_TREE, new_dest, new_name, new_scalar_dest; tree new_temp = NULL_TREE, new_name, new_scalar_dest;
gimple *epilog_stmt = NULL; gimple *epilog_stmt = NULL;
gimple *exit_phi; gimple *exit_phi;
tree bitsize; tree bitsize;
tree expr, def; tree def;
tree orig_name, scalar_result; tree orig_name, scalar_result;
imm_use_iterator imm_iter, phi_imm_iter; imm_use_iterator imm_iter, phi_imm_iter;
use_operand_p use_p, phi_use_p; use_operand_p use_p, phi_use_p;
...@@ -5048,25 +5064,26 @@ vect_create_epilog_for_reduction (stmt_vec_info stmt_info, ...@@ -5048,25 +5064,26 @@ vect_create_epilog_for_reduction (stmt_vec_info stmt_info,
if (adjustment_def) if (adjustment_def)
{ {
gcc_assert (!slp_reduc); gcc_assert (!slp_reduc);
gimple_seq stmts = NULL;
if (nested_in_vect_loop) if (nested_in_vect_loop)
{ {
new_phi = new_phis[0]; new_phi = new_phis[0];
gcc_assert (TREE_CODE (TREE_TYPE (adjustment_def)) == VECTOR_TYPE); gcc_assert (VECTOR_TYPE_P (TREE_TYPE (adjustment_def)));
expr = build2 (code, vectype, PHI_RESULT (new_phi), adjustment_def); adjustment_def = gimple_convert (&stmts, vectype, adjustment_def);
new_dest = vect_create_destination_var (scalar_dest, vectype); new_temp = gimple_build (&stmts, code, vectype,
PHI_RESULT (new_phi), adjustment_def);
} }
else else
{ {
new_temp = scalar_results[0]; new_temp = scalar_results[0];
gcc_assert (TREE_CODE (TREE_TYPE (adjustment_def)) != VECTOR_TYPE); gcc_assert (TREE_CODE (TREE_TYPE (adjustment_def)) != VECTOR_TYPE);
expr = build2 (code, scalar_type, new_temp, adjustment_def); adjustment_def = gimple_convert (&stmts, scalar_type, adjustment_def);
new_dest = vect_create_destination_var (scalar_dest, scalar_type); new_temp = gimple_build (&stmts, code, scalar_type,
new_temp, adjustment_def);
} }
epilog_stmt = gimple_build_assign (new_dest, expr); epilog_stmt = gimple_seq_last_stmt (stmts);
new_temp = make_ssa_name (new_dest, epilog_stmt); gsi_insert_seq_before (&exit_gsi, stmts, GSI_SAME_STMT);
gimple_assign_set_lhs (epilog_stmt, new_temp);
gsi_insert_before (&exit_gsi, epilog_stmt, GSI_SAME_STMT);
if (nested_in_vect_loop) if (nested_in_vect_loop)
{ {
stmt_vec_info epilog_stmt_info = loop_vinfo->add_stmt (epilog_stmt); stmt_vec_info epilog_stmt_info = loop_vinfo->add_stmt (epilog_stmt);
...@@ -5742,6 +5759,10 @@ vectorizable_reduction (stmt_vec_info stmt_info, slp_tree slp_node, ...@@ -5742,6 +5759,10 @@ vectorizable_reduction (stmt_vec_info stmt_info, slp_tree slp_node,
} }
if (!REDUC_GROUP_FIRST_ELEMENT (def)) if (!REDUC_GROUP_FIRST_ELEMENT (def))
only_slp_reduc_chain = false; only_slp_reduc_chain = false;
/* ??? For epilogue generation live members of the chain need
to point back to the PHI for info_for_reduction to work. */
if (STMT_VINFO_LIVE_P (def))
STMT_VINFO_REDUC_DEF (def) = phi_info;
reduc_def = gimple_op (def->stmt, 1 + STMT_VINFO_REDUC_IDX (def)); reduc_def = gimple_op (def->stmt, 1 + STMT_VINFO_REDUC_IDX (def));
reduc_chain_length++; reduc_chain_length++;
} }
...@@ -7443,10 +7464,10 @@ vectorizable_live_operation (stmt_vec_info stmt_info, ...@@ -7443,10 +7464,10 @@ vectorizable_live_operation (stmt_vec_info stmt_info,
gcc_assert (STMT_VINFO_LIVE_P (stmt_info)); gcc_assert (STMT_VINFO_LIVE_P (stmt_info));
/* The last stmt of a reduction is live and vectorized via /* If a stmt of a reduction is live, vectorize it via
vect_create_epilog_for_reduction. vectorizable_reduction assessed vect_create_epilog_for_reduction. vectorizable_reduction assessed
validity so just trigger the transform here. */ validity so just trigger the transform here. */
if (STMT_VINFO_REDUC_DEF (vect_orig_stmt (stmt_info))) if (STMT_VINFO_REDUC_DEF (stmt_info))
{ {
if (!vec_stmt_p) if (!vec_stmt_p)
return true; return true;
......
...@@ -457,7 +457,6 @@ process_use (stmt_vec_info stmt_vinfo, tree use, loop_vec_info loop_vinfo, ...@@ -457,7 +457,6 @@ process_use (stmt_vec_info stmt_vinfo, tree use, loop_vec_info loop_vinfo,
bool force) bool force)
{ {
stmt_vec_info dstmt_vinfo; stmt_vec_info dstmt_vinfo;
basic_block bb, def_bb;
enum vect_def_type dt; enum vect_def_type dt;
/* case 1: we are only interested in uses that need to be vectorized. Uses /* case 1: we are only interested in uses that need to be vectorized. Uses
...@@ -473,28 +472,8 @@ process_use (stmt_vec_info stmt_vinfo, tree use, loop_vec_info loop_vinfo, ...@@ -473,28 +472,8 @@ process_use (stmt_vec_info stmt_vinfo, tree use, loop_vec_info loop_vinfo,
if (!dstmt_vinfo) if (!dstmt_vinfo)
return opt_result::success (); return opt_result::success ();
def_bb = gimple_bb (dstmt_vinfo->stmt); basic_block def_bb = gimple_bb (dstmt_vinfo->stmt);
basic_block bb = gimple_bb (stmt_vinfo->stmt);
/* case 2: A reduction phi (STMT) defined by a reduction stmt (DSTMT_VINFO).
DSTMT_VINFO must have already been processed, because this should be the
only way that STMT, which is a reduction-phi, was put in the worklist,
as there should be no other uses for DSTMT_VINFO in the loop. So we just
check that everything is as expected, and we are done. */
bb = gimple_bb (stmt_vinfo->stmt);
if (gimple_code (stmt_vinfo->stmt) == GIMPLE_PHI
&& STMT_VINFO_DEF_TYPE (stmt_vinfo) == vect_reduction_def
&& gimple_code (dstmt_vinfo->stmt) != GIMPLE_PHI
&& STMT_VINFO_DEF_TYPE (dstmt_vinfo) == vect_reduction_def
&& bb->loop_father == def_bb->loop_father)
{
if (dump_enabled_p ())
dump_printf_loc (MSG_NOTE, vect_location,
"reduc-stmt defining reduc-phi in the same nest.\n");
gcc_assert (STMT_VINFO_RELEVANT (dstmt_vinfo) < vect_used_by_reduction);
gcc_assert (STMT_VINFO_LIVE_P (dstmt_vinfo)
|| STMT_VINFO_RELEVANT (dstmt_vinfo) > vect_unused_in_scope);
return opt_result::success ();
}
/* case 3a: outer-loop stmt defining an inner-loop stmt: /* case 3a: outer-loop stmt defining an inner-loop stmt:
outer-loop-header-bb: outer-loop-header-bb:
......
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