summaryrefslogtreecommitdiff
path: root/gcc/tree-vect-slp.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/tree-vect-slp.c')
-rw-r--r--gcc/tree-vect-slp.c255
1 files changed, 116 insertions, 139 deletions
diff --git a/gcc/tree-vect-slp.c b/gcc/tree-vect-slp.c
index 0800a3f6b23..15d589d3452 100644
--- a/gcc/tree-vect-slp.c
+++ b/gcc/tree-vect-slp.c
@@ -403,9 +403,9 @@ again:
{
case vect_constant_def:
case vect_external_def:
- case vect_reduction_def:
break;
+ case vect_reduction_def:
case vect_induction_def:
case vect_internal_def:
oprnd_info->def_stmts.quick_push (def_stmt);
@@ -943,13 +943,31 @@ vect_build_slp_tree (vec_info *vinfo,
else
return NULL;
- /* If the SLP node is a PHI (induction), terminate the recursion. */
+ /* If the SLP node is a PHI (induction or reduction), terminate
+ the recursion. */
if (gimple_code (stmt) == GIMPLE_PHI)
{
- FOR_EACH_VEC_ELT (stmts, i, stmt)
- if (stmt != stmts[0])
- /* Induction from different IVs is not supported. */
- return NULL;
+ vect_def_type def_type = STMT_VINFO_DEF_TYPE (vinfo_for_stmt (stmt));
+ /* Induction from different IVs is not supported. */
+ if (def_type == vect_induction_def)
+ {
+ FOR_EACH_VEC_ELT (stmts, i, stmt)
+ if (stmt != stmts[0])
+ return NULL;
+ }
+ else
+ {
+ /* Else def types have to match. */
+ FOR_EACH_VEC_ELT (stmts, i, stmt)
+ {
+ /* But for reduction chains only check on the first stmt. */
+ if (GROUP_FIRST_ELEMENT (vinfo_for_stmt (stmt))
+ && GROUP_FIRST_ELEMENT (vinfo_for_stmt (stmt)) != stmt)
+ continue;
+ if (STMT_VINFO_DEF_TYPE (vinfo_for_stmt (stmt)) != def_type)
+ return NULL;
+ }
+ }
node = vect_create_new_slp_node (stmts);
return node;
}
@@ -1005,6 +1023,7 @@ vect_build_slp_tree (vec_info *vinfo,
unsigned int j;
if (oprnd_info->first_dt != vect_internal_def
+ && oprnd_info->first_dt != vect_reduction_def
&& oprnd_info->first_dt != vect_induction_def)
continue;
@@ -2102,15 +2121,13 @@ vect_analyze_slp (vec_info *vinfo, unsigned max_tree_size)
{
unsigned int i;
gimple *first_element;
- bool ok = false;
if (dump_enabled_p ())
dump_printf_loc (MSG_NOTE, vect_location, "=== vect_analyze_slp ===\n");
/* Find SLP sequences starting from groups of grouped stores. */
FOR_EACH_VEC_ELT (vinfo->grouped_stores, i, first_element)
- if (vect_analyze_slp_instance (vinfo, first_element, max_tree_size))
- ok = true;
+ vect_analyze_slp_instance (vinfo, first_element, max_tree_size);
if (loop_vec_info loop_vinfo = dyn_cast <loop_vec_info> (vinfo))
{
@@ -2118,22 +2135,28 @@ vect_analyze_slp (vec_info *vinfo, unsigned max_tree_size)
{
/* Find SLP sequences starting from reduction chains. */
FOR_EACH_VEC_ELT (loop_vinfo->reduction_chains, i, first_element)
- if (vect_analyze_slp_instance (vinfo, first_element,
+ if (! vect_analyze_slp_instance (vinfo, first_element,
max_tree_size))
- ok = true;
- else
- return false;
-
- /* Don't try to vectorize SLP reductions if reduction chain was
- detected. */
- return ok;
+ {
+ /* Dissolve reduction chain group. */
+ gimple *next, *stmt = first_element;
+ while (stmt)
+ {
+ stmt_vec_info vinfo = vinfo_for_stmt (stmt);
+ next = GROUP_NEXT_ELEMENT (vinfo);
+ GROUP_FIRST_ELEMENT (vinfo) = NULL;
+ GROUP_NEXT_ELEMENT (vinfo) = NULL;
+ stmt = next;
+ }
+ STMT_VINFO_DEF_TYPE (vinfo_for_stmt (first_element))
+ = vect_internal_def;
+ }
}
/* Find SLP sequences starting from groups of reductions. */
- if (loop_vinfo->reductions.length () > 1
- && vect_analyze_slp_instance (vinfo, loop_vinfo->reductions[0],
- max_tree_size))
- ok = true;
+ if (loop_vinfo->reductions.length () > 1)
+ vect_analyze_slp_instance (vinfo, loop_vinfo->reductions[0],
+ max_tree_size);
}
return true;
@@ -2432,7 +2455,7 @@ destroy_bb_vec_info (bb_vec_info bb_vinfo)
the subtree. Return TRUE if the operations are supported. */
static bool
-vect_slp_analyze_node_operations (slp_tree node)
+vect_slp_analyze_node_operations (slp_tree node, slp_instance node_instance)
{
bool dummy;
int i, j;
@@ -2443,32 +2466,73 @@ vect_slp_analyze_node_operations (slp_tree node)
return true;
FOR_EACH_VEC_ELT (SLP_TREE_CHILDREN (node), i, child)
- if (!vect_slp_analyze_node_operations (child))
+ if (!vect_slp_analyze_node_operations (child, node_instance))
return false;
- bool res = true;
- FOR_EACH_VEC_ELT (SLP_TREE_SCALAR_STMTS (node), i, stmt)
+ stmt = SLP_TREE_SCALAR_STMTS (node)[0];
+ stmt_vec_info stmt_info = vinfo_for_stmt (stmt);
+ gcc_assert (stmt_info);
+ gcc_assert (STMT_SLP_TYPE (stmt_info) != loop_vect);
+
+ /* For BB vectorization vector types are assigned here.
+ Memory accesses already got their vector type assigned
+ in vect_analyze_data_refs. */
+ bb_vec_info bb_vinfo = STMT_VINFO_BB_VINFO (stmt_info);
+ if (bb_vinfo
+ && ! STMT_VINFO_DATA_REF (stmt_info))
{
- stmt_vec_info stmt_info = vinfo_for_stmt (stmt);
- gcc_assert (stmt_info);
- gcc_assert (STMT_SLP_TYPE (stmt_info) != loop_vect);
-
- /* Push SLP node def-type to stmt operands. */
- FOR_EACH_VEC_ELT (SLP_TREE_CHILDREN (node), j, child)
- if (SLP_TREE_DEF_TYPE (child) != vect_internal_def)
- STMT_VINFO_DEF_TYPE (vinfo_for_stmt (SLP_TREE_SCALAR_STMTS (child)[i]))
- = SLP_TREE_DEF_TYPE (child);
- res = vect_analyze_stmt (stmt, &dummy, node);
- /* Restore def-types. */
- FOR_EACH_VEC_ELT (SLP_TREE_CHILDREN (node), j, child)
- if (SLP_TREE_DEF_TYPE (child) != vect_internal_def)
- STMT_VINFO_DEF_TYPE (vinfo_for_stmt (SLP_TREE_SCALAR_STMTS (child)[i]))
- = vect_internal_def;
- if (! res)
- break;
+ gcc_assert (PURE_SLP_STMT (stmt_info));
+
+ tree scalar_type = TREE_TYPE (gimple_get_lhs (stmt));
+ if (dump_enabled_p ())
+ {
+ dump_printf_loc (MSG_NOTE, vect_location,
+ "get vectype for scalar type: ");
+ dump_generic_expr (MSG_NOTE, TDF_SLIM, scalar_type);
+ dump_printf (MSG_NOTE, "\n");
+ }
+
+ tree vectype = get_vectype_for_scalar_type (scalar_type);
+ if (!vectype)
+ {
+ if (dump_enabled_p ())
+ {
+ dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
+ "not SLPed: unsupported data-type ");
+ dump_generic_expr (MSG_MISSED_OPTIMIZATION, TDF_SLIM,
+ scalar_type);
+ dump_printf (MSG_MISSED_OPTIMIZATION, "\n");
+ }
+ return false;
+ }
+
+ if (dump_enabled_p ())
+ {
+ dump_printf_loc (MSG_NOTE, vect_location, "vectype: ");
+ dump_generic_expr (MSG_NOTE, TDF_SLIM, vectype);
+ dump_printf (MSG_NOTE, "\n");
+ }
+
+ gimple *sstmt;
+ FOR_EACH_VEC_ELT (SLP_TREE_SCALAR_STMTS (node), i, sstmt)
+ STMT_VINFO_VECTYPE (vinfo_for_stmt (sstmt)) = vectype;
}
- return res;
+ /* Push SLP node def-type to stmt operands. */
+ FOR_EACH_VEC_ELT (SLP_TREE_CHILDREN (node), j, child)
+ if (SLP_TREE_DEF_TYPE (child) != vect_internal_def)
+ STMT_VINFO_DEF_TYPE (vinfo_for_stmt (SLP_TREE_SCALAR_STMTS (child)[0]))
+ = SLP_TREE_DEF_TYPE (child);
+ bool res = vect_analyze_stmt (stmt, &dummy, node, node_instance);
+ /* Restore def-types. */
+ FOR_EACH_VEC_ELT (SLP_TREE_CHILDREN (node), j, child)
+ if (SLP_TREE_DEF_TYPE (child) != vect_internal_def)
+ STMT_VINFO_DEF_TYPE (vinfo_for_stmt (SLP_TREE_SCALAR_STMTS (child)[0]))
+ = vect_internal_def;
+ if (! res)
+ return false;
+
+ return true;
}
@@ -2487,7 +2551,8 @@ vect_slp_analyze_operations (vec<slp_instance> slp_instances, void *data)
for (i = 0; slp_instances.iterate (i, &instance); )
{
- if (!vect_slp_analyze_node_operations (SLP_INSTANCE_TREE (instance)))
+ if (!vect_slp_analyze_node_operations (SLP_INSTANCE_TREE (instance),
+ instance))
{
dump_printf_loc (MSG_NOTE, vect_location,
"removing SLP instance operations starting from: ");
@@ -2976,8 +3041,7 @@ vect_mask_constant_operand_p (gimple *stmt, int opnum)
static void
vect_get_constant_vectors (tree op, slp_tree slp_node,
vec<tree> *vec_oprnds,
- unsigned int op_num, unsigned int number_of_vectors,
- int reduc_index)
+ unsigned int op_num, unsigned int number_of_vectors)
{
vec<gimple *> stmts = SLP_TREE_SCALAR_STMTS (slp_node);
gimple *stmt = stmts[0];
@@ -2996,8 +3060,6 @@ vect_get_constant_vectors (tree op, slp_tree slp_node,
bool constant_p, is_store;
tree neutral_op = NULL;
enum tree_code code = gimple_expr_code (stmt);
- gimple *def_stmt;
- struct loop *loop;
gimple_seq ctor_seq = NULL;
/* Check if vector type is a boolean vector. */
@@ -3009,64 +3071,6 @@ vect_get_constant_vectors (tree op, slp_tree slp_node,
vector_type = get_vectype_for_scalar_type (TREE_TYPE (op));
nunits = TYPE_VECTOR_SUBPARTS (vector_type);
- if (STMT_VINFO_DEF_TYPE (stmt_vinfo) == vect_reduction_def
- && reduc_index != -1)
- {
- op_num = reduc_index;
- op = gimple_op (stmt, op_num + 1);
- /* For additional copies (see the explanation of NUMBER_OF_COPIES below)
- we need either neutral operands or the original operands. See
- get_initial_def_for_reduction() for details. */
- switch (code)
- {
- case WIDEN_SUM_EXPR:
- case DOT_PROD_EXPR:
- case SAD_EXPR:
- case PLUS_EXPR:
- case MINUS_EXPR:
- case BIT_IOR_EXPR:
- case BIT_XOR_EXPR:
- if (SCALAR_FLOAT_TYPE_P (TREE_TYPE (op)))
- neutral_op = build_real (TREE_TYPE (op), dconst0);
- else
- neutral_op = build_int_cst (TREE_TYPE (op), 0);
-
- break;
-
- case MULT_EXPR:
- if (SCALAR_FLOAT_TYPE_P (TREE_TYPE (op)))
- neutral_op = build_real (TREE_TYPE (op), dconst1);
- else
- neutral_op = build_int_cst (TREE_TYPE (op), 1);
-
- break;
-
- case BIT_AND_EXPR:
- neutral_op = build_int_cst (TREE_TYPE (op), -1);
- break;
-
- /* For MIN/MAX we don't have an easy neutral operand but
- the initial values can be used fine here. Only for
- a reduction chain we have to force a neutral element. */
- case MAX_EXPR:
- case MIN_EXPR:
- if (!GROUP_FIRST_ELEMENT (stmt_vinfo))
- neutral_op = NULL;
- else
- {
- def_stmt = SSA_NAME_DEF_STMT (op);
- loop = (gimple_bb (stmt))->loop_father;
- neutral_op = PHI_ARG_DEF_FROM_EDGE (def_stmt,
- loop_preheader_edge (loop));
- }
- break;
-
- default:
- gcc_assert (!GROUP_FIRST_ELEMENT (stmt_vinfo));
- neutral_op = NULL;
- }
- }
-
if (STMT_VINFO_DATA_REF (stmt_vinfo))
{
is_store = true;
@@ -3077,11 +3081,6 @@ vect_get_constant_vectors (tree op, slp_tree slp_node,
gcc_assert (op);
- if (CONSTANT_CLASS_P (op))
- constant_p = true;
- else
- constant_p = false;
-
/* NUMBER_OF_COPIES is the number of times we need to use the same values in
created vectors. It is greater than 1 if unrolling is performed.
@@ -3101,6 +3100,7 @@ vect_get_constant_vectors (tree op, slp_tree slp_node,
number_of_copies = nunits * number_of_vectors / group_size;
number_of_places_left_in_vector = nunits;
+ constant_p = true;
elts = XALLOCAVEC (tree, nunits);
bool place_after_defs = false;
for (j = 0; j < number_of_copies; j++)
@@ -3154,25 +3154,6 @@ vect_get_constant_vectors (tree op, slp_tree slp_node,
}
}
- if (reduc_index != -1)
- {
- loop = (gimple_bb (stmt))->loop_father;
- def_stmt = SSA_NAME_DEF_STMT (op);
-
- gcc_assert (loop);
-
- /* Get the def before the loop. In reduction chain we have only
- one initial value. */
- if ((j != (number_of_copies - 1)
- || (GROUP_FIRST_ELEMENT (vinfo_for_stmt (stmt))
- && i != 0))
- && neutral_op)
- op = neutral_op;
- else
- op = PHI_ARG_DEF_FROM_EDGE (def_stmt,
- loop_preheader_edge (loop));
- }
-
/* Create 'vect_ = {op0,op1,...,opn}'. */
number_of_places_left_in_vector--;
tree orig_op = op;
@@ -3236,8 +3217,6 @@ vect_get_constant_vectors (tree op, slp_tree slp_node,
if (number_of_places_left_in_vector == 0)
{
- number_of_places_left_in_vector = nunits;
-
if (constant_p)
vec_cst = build_vector (vector_type, elts);
else
@@ -3268,6 +3247,8 @@ vect_get_constant_vectors (tree op, slp_tree slp_node,
}
voprnds.quick_push (init);
place_after_defs = false;
+ number_of_places_left_in_vector = nunits;
+ constant_p = true;
}
}
}
@@ -3340,7 +3321,7 @@ vect_get_slp_vect_defs (slp_tree slp_node, vec<tree> *vec_oprnds)
void
vect_get_slp_defs (vec<tree> ops, slp_tree slp_node,
- vec<vec<tree> > *vec_oprnds, int reduc_index)
+ vec<vec<tree> > *vec_oprnds)
{
gimple *first_stmt;
int number_of_vects = 0, i;
@@ -3421,20 +3402,16 @@ vect_get_slp_defs (vec<tree> ops, slp_tree slp_node,
/* For reduction defs we call vect_get_constant_vectors (), since we are
looking for initial loop invariant values. */
- if (vectorized_defs && reduc_index == -1)
+ if (vectorized_defs)
/* The defs are already vectorized. */
vect_get_slp_vect_defs (child, &vec_defs);
else
/* Build vectors from scalar defs. */
vect_get_constant_vectors (oprnd, slp_node, &vec_defs, i,
- number_of_vects, reduc_index);
+ number_of_vects);
vec_oprnds->quick_push (vec_defs);
- /* For reductions, we only need initial values. */
- if (reduc_index != -1)
- return;
-
first_iteration = false;
}
}