aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog10
-rw-r--r--gcc/tree-vect-loop.c75
2 files changed, 68 insertions, 17 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index eda6625..25f476a 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -2,6 +2,16 @@
Alan Hayward <alan.hayward@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.c (build_index_vector): New function.
* tree-vect-loop.c (get_initial_defs_for_reduction): Treat the number
diff --git a/gcc/tree-vect-loop.c b/gcc/tree-vect-loop.c
index 93e430c..2b3bb07 100644
--- a/gcc/tree-vect-loop.c
+++ b/gcc/tree-vect-loop.c
@@ -6693,7 +6693,7 @@ vectorizable_induction (gimple *phi,
return false;
tree vectype = STMT_VINFO_VECTYPE (stmt_info);
- unsigned nunits = TYPE_VECTOR_SUBPARTS (vectype);
+ poly_uint64 nunits = TYPE_VECTOR_SUBPARTS (vectype);
if (slp_node)
ncopies = 1;
@@ -6758,6 +6758,16 @@ vectorizable_induction (gimple *phi,
iv_loop = loop;
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. */
{
STMT_VINFO_TYPE (stmt_info) = induc_vec_info_type;
@@ -6806,6 +6816,9 @@ vectorizable_induction (gimple *phi,
[VF*S, VF*S, VF*S, VF*S] for all. */
if (slp_node)
{
+ /* Enforced above. */
+ unsigned int const_nunits = nunits.to_constant ();
+
/* Convert the init to the desired type. */
stmts = NULL;
init_expr = gimple_convert (&stmts, TREE_TYPE (vectype), init_expr);
@@ -6834,19 +6847,20 @@ vectorizable_induction (gimple *phi,
/* Now generate the IVs. */
unsigned group_size = SLP_TREE_SCALAR_STMTS (slp_node).length ();
unsigned nvects = SLP_TREE_NUMBER_OF_VEC_STMTS (slp_node);
- unsigned elts = nunits * nvects;
- unsigned nivs = least_common_multiple (group_size, nunits) / nunits;
+ unsigned elts = const_nunits * nvects;
+ unsigned nivs = least_common_multiple (group_size,
+ const_nunits) / const_nunits;
gcc_assert (elts % group_size == 0);
tree elt = init_expr;
unsigned ivn;
for (ivn = 0; ivn < nivs; ++ivn)
{
- tree_vector_builder elts (vectype, nunits, 1);
+ tree_vector_builder elts (vectype, const_nunits, 1);
stmts = NULL;
- for (unsigned eltn = 0; eltn < nunits; ++eltn)
+ for (unsigned eltn = 0; eltn < const_nunits; ++eltn)
{
- if (ivn*nunits + eltn >= group_size
- && (ivn*nunits + eltn) % group_size == 0)
+ if (ivn*const_nunits + eltn >= group_size
+ && (ivn * const_nunits + eltn) % group_size == 0)
elt = gimple_build (&stmts, PLUS_EXPR, TREE_TYPE (elt),
elt, step_expr);
elts.quick_push (elt);
@@ -6883,7 +6897,7 @@ vectorizable_induction (gimple *phi,
if (ivn < nvects)
{
unsigned vfp
- = least_common_multiple (group_size, nunits) / group_size;
+ = least_common_multiple (group_size, const_nunits) / group_size;
/* Generate [VF'*S, VF'*S, ... ]. */
if (SCALAR_FLOAT_TYPE_P (TREE_TYPE (step_expr)))
{
@@ -6958,18 +6972,45 @@ vectorizable_induction (gimple *phi,
stmts = NULL;
new_name = gimple_convert (&stmts, TREE_TYPE (vectype), init_expr);
- tree_vector_builder elts (vectype, nunits, 1);
- elts.quick_push (new_name);
- for (i = 1; i < nunits; i++)
+ unsigned HOST_WIDE_INT const_nunits;
+ if (nunits.is_constant (&const_nunits))
{
- /* Create: new_name_i = new_name + step_expr */
- new_name = gimple_build (&stmts, PLUS_EXPR, TREE_TYPE (new_name),
- new_name, step_expr);
+ tree_vector_builder elts (vectype, const_nunits, 1);
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, ...,
- new_name_nunits-1] */
- vec_init = gimple_build_vector (&stmts, &elts);
+ else if (INTEGRAL_TYPE_P (TREE_TYPE (step_expr)))
+ /* Build the initial value directly from a VEC_SERIES_EXPR. */
+ 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)
{
new_bb = gsi_insert_seq_on_edge_immediate (pe, stmts);