Commit 9fb9293a by Richard Sandiford Committed by Richard Sandiford

poly_int: vectorizable_induction

This patch makes vectorizable_induction cope with variable-length
vectors.  For now we punt on SLP inductions, but patchees after
the main SVE submission add support for those too.

2018-01-03  Richard Sandiford  <richard.sandiford@linaro.org>
	    Alan Hayward  <alan.hayward@arm.com>
	    David Sherwood  <david.sherwood@arm.com>

gcc/
	* tree-vect-loop.c (vectorizable_induction): Treat the number
	of units as polynomial.  Punt on SLP inductions.  Use an integer
	VEC_SERIES_EXPR for variable-length integer reductions.  Use a
	cast of such a series for variable-length floating-point
	reductions.

Co-Authored-By: Alan Hayward <alan.hayward@arm.com>
Co-Authored-By: David Sherwood <david.sherwood@arm.com>

From-SVN: r256134
parent e54dd6d3
...@@ -2,6 +2,16 @@ ...@@ -2,6 +2,16 @@
Alan Hayward <alan.hayward@arm.com> Alan Hayward <alan.hayward@arm.com>
David Sherwood <david.sherwood@arm.com> David Sherwood <david.sherwood@arm.com>
* tree-vect-loop.c (vectorizable_induction): Treat the number
of units as polynomial. Punt on SLP inductions. Use an integer
VEC_SERIES_EXPR for variable-length integer reductions. Use a
cast of such a series for variable-length floating-point
reductions.
2018-01-03 Richard Sandiford <richard.sandiford@linaro.org>
Alan Hayward <alan.hayward@arm.com>
David Sherwood <david.sherwood@arm.com>
* tree.h (build_index_vector): Declare. * tree.h (build_index_vector): Declare.
* tree.c (build_index_vector): New function. * tree.c (build_index_vector): New function.
* tree-vect-loop.c (get_initial_defs_for_reduction): Treat the number * tree-vect-loop.c (get_initial_defs_for_reduction): Treat the number
...@@ -6693,7 +6693,7 @@ vectorizable_induction (gimple *phi, ...@@ -6693,7 +6693,7 @@ vectorizable_induction (gimple *phi,
return false; return false;
tree vectype = STMT_VINFO_VECTYPE (stmt_info); tree vectype = STMT_VINFO_VECTYPE (stmt_info);
unsigned nunits = TYPE_VECTOR_SUBPARTS (vectype); poly_uint64 nunits = TYPE_VECTOR_SUBPARTS (vectype);
if (slp_node) if (slp_node)
ncopies = 1; ncopies = 1;
...@@ -6758,6 +6758,16 @@ vectorizable_induction (gimple *phi, ...@@ -6758,6 +6758,16 @@ vectorizable_induction (gimple *phi,
iv_loop = loop; iv_loop = loop;
gcc_assert (iv_loop == (gimple_bb (phi))->loop_father); gcc_assert (iv_loop == (gimple_bb (phi))->loop_father);
if (slp_node && !nunits.is_constant ())
{
/* The current SLP code creates the initial value element-by-element. */
if (dump_enabled_p ())
dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
"SLP induction not supported for variable-length"
" vectors.\n");
return false;
}
if (!vec_stmt) /* transformation not required. */ if (!vec_stmt) /* transformation not required. */
{ {
STMT_VINFO_TYPE (stmt_info) = induc_vec_info_type; STMT_VINFO_TYPE (stmt_info) = induc_vec_info_type;
...@@ -6806,6 +6816,9 @@ vectorizable_induction (gimple *phi, ...@@ -6806,6 +6816,9 @@ vectorizable_induction (gimple *phi,
[VF*S, VF*S, VF*S, VF*S] for all. */ [VF*S, VF*S, VF*S, VF*S] for all. */
if (slp_node) if (slp_node)
{ {
/* Enforced above. */
unsigned int const_nunits = nunits.to_constant ();
/* Convert the init to the desired type. */ /* Convert the init to the desired type. */
stmts = NULL; stmts = NULL;
init_expr = gimple_convert (&stmts, TREE_TYPE (vectype), init_expr); init_expr = gimple_convert (&stmts, TREE_TYPE (vectype), init_expr);
...@@ -6834,19 +6847,20 @@ vectorizable_induction (gimple *phi, ...@@ -6834,19 +6847,20 @@ vectorizable_induction (gimple *phi,
/* Now generate the IVs. */ /* Now generate the IVs. */
unsigned group_size = SLP_TREE_SCALAR_STMTS (slp_node).length (); unsigned group_size = SLP_TREE_SCALAR_STMTS (slp_node).length ();
unsigned nvects = SLP_TREE_NUMBER_OF_VEC_STMTS (slp_node); unsigned nvects = SLP_TREE_NUMBER_OF_VEC_STMTS (slp_node);
unsigned elts = nunits * nvects; unsigned elts = const_nunits * nvects;
unsigned nivs = least_common_multiple (group_size, nunits) / nunits; unsigned nivs = least_common_multiple (group_size,
const_nunits) / const_nunits;
gcc_assert (elts % group_size == 0); gcc_assert (elts % group_size == 0);
tree elt = init_expr; tree elt = init_expr;
unsigned ivn; unsigned ivn;
for (ivn = 0; ivn < nivs; ++ivn) for (ivn = 0; ivn < nivs; ++ivn)
{ {
tree_vector_builder elts (vectype, nunits, 1); tree_vector_builder elts (vectype, const_nunits, 1);
stmts = NULL; stmts = NULL;
for (unsigned eltn = 0; eltn < nunits; ++eltn) for (unsigned eltn = 0; eltn < const_nunits; ++eltn)
{ {
if (ivn*nunits + eltn >= group_size if (ivn*const_nunits + eltn >= group_size
&& (ivn*nunits + eltn) % group_size == 0) && (ivn * const_nunits + eltn) % group_size == 0)
elt = gimple_build (&stmts, PLUS_EXPR, TREE_TYPE (elt), elt = gimple_build (&stmts, PLUS_EXPR, TREE_TYPE (elt),
elt, step_expr); elt, step_expr);
elts.quick_push (elt); elts.quick_push (elt);
...@@ -6883,7 +6897,7 @@ vectorizable_induction (gimple *phi, ...@@ -6883,7 +6897,7 @@ vectorizable_induction (gimple *phi,
if (ivn < nvects) if (ivn < nvects)
{ {
unsigned vfp unsigned vfp
= least_common_multiple (group_size, nunits) / group_size; = least_common_multiple (group_size, const_nunits) / group_size;
/* Generate [VF'*S, VF'*S, ... ]. */ /* Generate [VF'*S, VF'*S, ... ]. */
if (SCALAR_FLOAT_TYPE_P (TREE_TYPE (step_expr))) if (SCALAR_FLOAT_TYPE_P (TREE_TYPE (step_expr)))
{ {
...@@ -6958,18 +6972,45 @@ vectorizable_induction (gimple *phi, ...@@ -6958,18 +6972,45 @@ vectorizable_induction (gimple *phi,
stmts = NULL; stmts = NULL;
new_name = gimple_convert (&stmts, TREE_TYPE (vectype), init_expr); new_name = gimple_convert (&stmts, TREE_TYPE (vectype), init_expr);
tree_vector_builder elts (vectype, nunits, 1); unsigned HOST_WIDE_INT const_nunits;
elts.quick_push (new_name); if (nunits.is_constant (&const_nunits))
for (i = 1; i < nunits; i++)
{ {
/* Create: new_name_i = new_name + step_expr */ tree_vector_builder elts (vectype, const_nunits, 1);
new_name = gimple_build (&stmts, PLUS_EXPR, TREE_TYPE (new_name),
new_name, step_expr);
elts.quick_push (new_name); elts.quick_push (new_name);
for (i = 1; i < const_nunits; i++)
{
/* Create: new_name_i = new_name + step_expr */
new_name = gimple_build (&stmts, PLUS_EXPR, TREE_TYPE (new_name),
new_name, step_expr);
elts.quick_push (new_name);
}
/* Create a vector from [new_name_0, new_name_1, ...,
new_name_nunits-1] */
vec_init = gimple_build_vector (&stmts, &elts);
} }
/* Create a vector from [new_name_0, new_name_1, ..., else if (INTEGRAL_TYPE_P (TREE_TYPE (step_expr)))
new_name_nunits-1] */ /* Build the initial value directly from a VEC_SERIES_EXPR. */
vec_init = gimple_build_vector (&stmts, &elts); vec_init = gimple_build (&stmts, VEC_SERIES_EXPR, vectype,
new_name, step_expr);
else
{
/* Build:
[base, base, base, ...]
+ (vectype) [0, 1, 2, ...] * [step, step, step, ...]. */
gcc_assert (SCALAR_FLOAT_TYPE_P (TREE_TYPE (step_expr)));
gcc_assert (flag_associative_math);
tree index = build_index_vector (vectype, 0, 1);
tree base_vec = gimple_build_vector_from_val (&stmts, vectype,
new_name);
tree step_vec = gimple_build_vector_from_val (&stmts, vectype,
step_expr);
vec_init = gimple_build (&stmts, FLOAT_EXPR, vectype, index);
vec_init = gimple_build (&stmts, MULT_EXPR, vectype,
vec_init, step_vec);
vec_init = gimple_build (&stmts, PLUS_EXPR, vectype,
vec_init, base_vec);
}
if (stmts) if (stmts)
{ {
new_bb = gsi_insert_seq_on_edge_immediate (pe, stmts); new_bb = gsi_insert_seq_on_edge_immediate (pe, stmts);
......
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