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

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

	PR tree-optimization/65930
	* tree-vect-loop.c (vect_is_simple_reduction): For reduction
	chains also allow a leading and trailing conversion.
	* tree-vect-slp.c (vect_get_and_check_slp_defs): Handle
	intermediate reduction chains.
	(vect_analyze_slp_instance): Likewise.  Build a SLP
	node for a trailing conversion manually.

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

From-SVN: r277603
This commit is contained in:
Richard Biener 2019-10-30 09:21:09 +00:00 committed by Richard Biener
parent 91c4891af8
commit b4673569c2
5 changed files with 91 additions and 5 deletions

View File

@ -1,3 +1,13 @@
2019-10-30 Richard Biener <rguenther@suse.de>
PR tree-optimization/65930
* tree-vect-loop.c (vect_is_simple_reduction): For reduction
chains also allow a leading and trailing conversion.
* tree-vect-slp.c (vect_get_and_check_slp_defs): Handle
intermediate reduction chains.
(vect_analyze_slp_instance): Likewise. Build a SLP
node for a trailing conversion manually.
2019-10-30 Martin Liska <mliska@suse.cz>
* cgraph.c (cgraph_node::local_info): Transform to ...

View File

@ -1,3 +1,8 @@
2019-10-30 Richard Biener <rguenther@suse.de>
PR tree-optimization/65930
* gcc.dg/vect/pr65930-2.c: New testcase.
2019-10-30 Mark Eggleston <mark.eggleston@codethink.com>
* gfortran.dg/no_overwrite_recursive_1.f90: New test.

View File

@ -0,0 +1,28 @@
/* { dg-require-effective-target vect_int } */
#include "tree-vect.h"
int __attribute__((noipa))
bar (unsigned int *x, int n)
{
int sum = 4;
x = __builtin_assume_aligned (x, __BIGGEST_ALIGNMENT__);
for (int i = 0; i < n; ++i)
sum += x[i*4+0]+ x[i*4 + 1] + x[i*4 + 2] + x[i*4 + 3];
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, 4) != 260)
abort ();
return 0;
}
/* { dg-final { scan-tree-dump "vectorized 1 loops" "vect" } } */
/* { dg-final { scan-tree-dump "Loop contains only SLP stmts" "vect" } } */
/* { dg-final { scan-tree-dump "vectorizing stmts using SLP" "vect" } } */

View File

@ -3005,14 +3005,21 @@ vect_is_simple_reduction (loop_vec_info loop_info, stmt_vec_info phi_info,
for (i = path.length () - 1; i >= 1; --i)
{
gimple *stmt = USE_STMT (path[i].second);
if (gimple_assign_rhs_code (stmt) != code
stmt_vec_info stmt_info = loop_info->lookup_stmt (stmt);
STMT_VINFO_REDUC_IDX (stmt_info)
= path[i].second->use - gimple_assign_rhs1_ptr (stmt);
enum tree_code stmt_code = gimple_assign_rhs_code (stmt);
bool leading_conversion = (CONVERT_EXPR_CODE_P (stmt_code)
&& (i == 1 || i == path.length () - 1));
if ((stmt_code != code && !leading_conversion)
/* 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;
stmt_vec_info stmt_info = loop_info->lookup_stmt (stmt);
STMT_VINFO_REDUC_IDX (stmt_info)
= path[i].second->use - gimple_assign_rhs1_ptr (stmt);
/* For reduction chains we support a trailing/leading
conversions. We do not store those in the actual chain. */
if (leading_conversion)
continue;
reduc_chain.safe_push (stmt_info);
}
if (is_slp_reduc && reduc_chain.length () > 1)

View File

@ -419,6 +419,13 @@ again:
if (first)
{
/* For the swapping logic below force vect_reduction_def
for the reduction op in a SLP reduction group. */
if (!STMT_VINFO_DATA_REF (stmt_info)
&& REDUC_GROUP_FIRST_ELEMENT (stmt_info)
&& (int)i == STMT_VINFO_REDUC_IDX (stmt_info)
&& def_stmt_info)
dt = vect_reduction_def;
oprnd_info->first_dt = dt;
oprnd_info->first_op_type = TREE_TYPE (oprnd);
}
@ -2041,7 +2048,8 @@ vect_analyze_slp_instance (vec_info *vinfo,
/* Mark the first element of the reduction chain as reduction to properly
transform the node. In the reduction analysis phase only the last
element of the chain is marked as reduction. */
STMT_VINFO_DEF_TYPE (stmt_info) = vect_reduction_def;
STMT_VINFO_DEF_TYPE (stmt_info)
= STMT_VINFO_DEF_TYPE (scalar_stmts.last ());
STMT_VINFO_REDUC_DEF (vect_orig_stmt (stmt_info))
= STMT_VINFO_REDUC_DEF (vect_orig_stmt (scalar_stmts.last ()));
}
@ -2071,6 +2079,34 @@ vect_analyze_slp_instance (vec_info *vinfo,
delete bst_map;
if (node != NULL)
{
/* If this is a reduction chain with a conversion in front
amend the SLP tree with a node for that. */
if (!dr
&& REDUC_GROUP_FIRST_ELEMENT (stmt_info)
&& STMT_VINFO_DEF_TYPE (stmt_info) != vect_reduction_def)
{
/* Get at the conversion stmt - we know it's the single use
of the last stmt of the reduction chain. */
gimple *tem = vect_orig_stmt (scalar_stmts[group_size - 1])->stmt;
use_operand_p use_p;
gimple *use_stmt;
bool r = single_imm_use (gimple_assign_lhs (tem), &use_p, &use_stmt);
gcc_assert (r);
next_info = vinfo->lookup_stmt (use_stmt);
next_info = vect_stmt_to_vectorize (next_info);
scalar_stmts = vNULL;
scalar_stmts.create (group_size);
for (unsigned i = 0; i < group_size; ++i)
scalar_stmts.quick_push (next_info);
slp_tree conv = vect_create_new_slp_node (scalar_stmts);
SLP_TREE_CHILDREN (conv).quick_push (node);
node = conv;
/* We also have to fake this conversion stmt as SLP reduction group
so we don't have to mess with too much code elsewhere. */
REDUC_GROUP_FIRST_ELEMENT (next_info) = next_info;
REDUC_GROUP_NEXT_ELEMENT (next_info) = NULL;
}
/* Calculate the unrolling factor based on the smallest type. */
poly_uint64 unrolling_factor
= calculate_unrolling_factor (max_nunits, group_size);