Refactor SLP instance analysis
This refactors the toplevel entry to analyze an SLP instance to expose a worker analyzing from a vector of stmts and an SLP entry kind. 2020-10-26 Richard Biener <rguenther@suse.de> * tree-vect-slp.c (enum slp_instance_kind): New. (vect_build_slp_instance): Split out from... (vect_analyze_slp_instance): ... this.
This commit is contained in:
parent
425bb53b54
commit
63b2149fb4
@ -1997,124 +1997,50 @@ calculate_unrolling_factor (poly_uint64 nunits, unsigned int group_size)
|
||||
return exact_div (common_multiple (nunits, group_size), group_size);
|
||||
}
|
||||
|
||||
/* Analyze an SLP instance starting from a group of grouped stores. Call
|
||||
vect_build_slp_tree to build a tree of packed stmts if possible.
|
||||
Return FALSE if it's impossible to SLP any stmt in the loop. */
|
||||
enum slp_instance_kind {
|
||||
slp_inst_kind_store,
|
||||
slp_inst_kind_reduc_group,
|
||||
slp_inst_kind_reduc_chain,
|
||||
slp_inst_kind_ctor
|
||||
};
|
||||
|
||||
static bool
|
||||
vect_analyze_slp_instance (vec_info *vinfo,
|
||||
scalar_stmts_to_slp_tree_map_t *bst_map,
|
||||
stmt_vec_info stmt_info, unsigned max_tree_size)
|
||||
stmt_vec_info stmt_info, unsigned max_tree_size);
|
||||
|
||||
/* Analyze an SLP instance starting from SCALAR_STMTS which are a group
|
||||
of KIND. Return true if successful. */
|
||||
|
||||
static bool
|
||||
vect_build_slp_instance (vec_info *vinfo,
|
||||
slp_instance_kind kind,
|
||||
vec<stmt_vec_info> scalar_stmts,
|
||||
stmt_vec_info root_stmt_info,
|
||||
unsigned max_tree_size,
|
||||
scalar_stmts_to_slp_tree_map_t *bst_map,
|
||||
/* ??? We need stmt_info for group splitting. */
|
||||
stmt_vec_info stmt_info_)
|
||||
{
|
||||
slp_instance new_instance;
|
||||
slp_tree node;
|
||||
unsigned int group_size;
|
||||
unsigned int i;
|
||||
struct data_reference *dr = STMT_VINFO_DATA_REF (stmt_info);
|
||||
vec<stmt_vec_info> scalar_stmts;
|
||||
bool constructor = false;
|
||||
|
||||
if (is_a <bb_vec_info> (vinfo))
|
||||
vect_location = stmt_info->stmt;
|
||||
if (STMT_VINFO_GROUPED_ACCESS (stmt_info))
|
||||
{
|
||||
group_size = DR_GROUP_SIZE (stmt_info);
|
||||
}
|
||||
else if (!dr && REDUC_GROUP_FIRST_ELEMENT (stmt_info))
|
||||
{
|
||||
gcc_assert (is_a <loop_vec_info> (vinfo));
|
||||
group_size = REDUC_GROUP_SIZE (stmt_info);
|
||||
}
|
||||
else if (is_gimple_assign (stmt_info->stmt)
|
||||
&& gimple_assign_rhs_code (stmt_info->stmt) == CONSTRUCTOR)
|
||||
{
|
||||
group_size = CONSTRUCTOR_NELTS (gimple_assign_rhs1 (stmt_info->stmt));
|
||||
constructor = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
gcc_assert (is_a <loop_vec_info> (vinfo));
|
||||
group_size = as_a <loop_vec_info> (vinfo)->reductions.length ();
|
||||
}
|
||||
|
||||
/* Create a node (a root of the SLP tree) for the packed grouped stores. */
|
||||
scalar_stmts.create (group_size);
|
||||
stmt_vec_info next_info = stmt_info;
|
||||
if (STMT_VINFO_GROUPED_ACCESS (stmt_info))
|
||||
{
|
||||
/* Collect the stores and store them in SLP_TREE_SCALAR_STMTS. */
|
||||
while (next_info)
|
||||
{
|
||||
scalar_stmts.safe_push (vect_stmt_to_vectorize (next_info));
|
||||
next_info = DR_GROUP_NEXT_ELEMENT (next_info);
|
||||
}
|
||||
}
|
||||
else if (!dr && REDUC_GROUP_FIRST_ELEMENT (stmt_info))
|
||||
{
|
||||
/* Collect the reduction stmts and store them in
|
||||
SLP_TREE_SCALAR_STMTS. */
|
||||
while (next_info)
|
||||
{
|
||||
scalar_stmts.safe_push (vect_stmt_to_vectorize (next_info));
|
||||
next_info = REDUC_GROUP_NEXT_ELEMENT (next_info);
|
||||
}
|
||||
/* 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)
|
||||
= 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 ()));
|
||||
}
|
||||
else if (constructor)
|
||||
{
|
||||
tree rhs = gimple_assign_rhs1 (stmt_info->stmt);
|
||||
tree val;
|
||||
FOR_EACH_CONSTRUCTOR_VALUE (CONSTRUCTOR_ELTS (rhs), i, val)
|
||||
{
|
||||
if (TREE_CODE (val) == SSA_NAME)
|
||||
{
|
||||
gimple* def = SSA_NAME_DEF_STMT (val);
|
||||
stmt_vec_info def_info = vinfo->lookup_stmt (def);
|
||||
/* Value is defined in another basic block. */
|
||||
if (!def_info)
|
||||
return false;
|
||||
def_info = vect_stmt_to_vectorize (def_info);
|
||||
scalar_stmts.safe_push (def_info);
|
||||
}
|
||||
else
|
||||
return false;
|
||||
}
|
||||
if (dump_enabled_p ())
|
||||
dump_printf_loc (MSG_NOTE, vect_location,
|
||||
"Analyzing vectorizable constructor: %G\n",
|
||||
stmt_info->stmt);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Collect reduction statements. */
|
||||
vec<stmt_vec_info> reductions = as_a <loop_vec_info> (vinfo)->reductions;
|
||||
for (i = 0; reductions.iterate (i, &next_info); i++)
|
||||
scalar_stmts.safe_push (next_info);
|
||||
}
|
||||
|
||||
if (dump_enabled_p ())
|
||||
{
|
||||
dump_printf_loc (MSG_NOTE, vect_location,
|
||||
"Starting SLP discovery for\n");
|
||||
for (i = 0; i < scalar_stmts.length (); ++i)
|
||||
for (unsigned i = 0; i < scalar_stmts.length (); ++i)
|
||||
dump_printf_loc (MSG_NOTE, vect_location,
|
||||
" %G", scalar_stmts[i]->stmt);
|
||||
}
|
||||
|
||||
/* Build the tree for the SLP instance. */
|
||||
unsigned int group_size = scalar_stmts.length ();
|
||||
bool *matches = XALLOCAVEC (bool, group_size);
|
||||
unsigned npermutes = 0;
|
||||
poly_uint64 max_nunits = 1;
|
||||
unsigned tree_size = 0;
|
||||
node = vect_build_slp_tree (vinfo, scalar_stmts, group_size,
|
||||
&max_nunits, matches, &npermutes,
|
||||
&tree_size, bst_map);
|
||||
unsigned i;
|
||||
slp_tree node = vect_build_slp_tree (vinfo, scalar_stmts, group_size,
|
||||
&max_nunits, matches, &npermutes,
|
||||
&tree_size, bst_map);
|
||||
if (node != NULL)
|
||||
{
|
||||
/* Calculate the unrolling factor based on the smallest type. */
|
||||
@ -2148,11 +2074,11 @@ vect_analyze_slp_instance (vec_info *vinfo,
|
||||
else
|
||||
{
|
||||
/* Create a new SLP instance. */
|
||||
new_instance = XNEW (class _slp_instance);
|
||||
slp_instance new_instance = XNEW (class _slp_instance);
|
||||
SLP_INSTANCE_TREE (new_instance) = node;
|
||||
SLP_INSTANCE_UNROLLING_FACTOR (new_instance) = unrolling_factor;
|
||||
SLP_INSTANCE_LOADS (new_instance) = vNULL;
|
||||
SLP_INSTANCE_ROOT_STMT (new_instance) = constructor ? stmt_info : NULL;
|
||||
SLP_INSTANCE_ROOT_STMT (new_instance) = root_stmt_info;
|
||||
new_instance->reduc_phis = NULL;
|
||||
new_instance->cost_vec = vNULL;
|
||||
new_instance->subgraph_entries = vNULL;
|
||||
@ -2184,7 +2110,7 @@ vect_analyze_slp_instance (vec_info *vinfo,
|
||||
instructions do not generate this SLP instance. */
|
||||
if (is_a <loop_vec_info> (vinfo)
|
||||
&& loads_permuted
|
||||
&& dr
|
||||
&& kind == slp_inst_kind_store
|
||||
&& vect_store_lanes_supported
|
||||
(STMT_VINFO_VECTYPE (scalar_stmts[0]), group_size, false))
|
||||
{
|
||||
@ -2213,9 +2139,8 @@ vect_analyze_slp_instance (vec_info *vinfo,
|
||||
|
||||
/* 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)
|
||||
if (kind == slp_inst_kind_reduc_chain
|
||||
&& STMT_VINFO_DEF_TYPE (scalar_stmts[0]) != vect_reduction_def)
|
||||
{
|
||||
/* Get at the conversion stmt - we know it's the single use
|
||||
of the last stmt of the reduction chain. */
|
||||
@ -2225,7 +2150,7 @@ vect_analyze_slp_instance (vec_info *vinfo,
|
||||
bool r = single_imm_use (gimple_assign_lhs (tem),
|
||||
&use_p, &use_stmt);
|
||||
gcc_assert (r);
|
||||
next_info = vinfo->lookup_stmt (use_stmt);
|
||||
stmt_vec_info next_info = vinfo->lookup_stmt (use_stmt);
|
||||
next_info = vect_stmt_to_vectorize (next_info);
|
||||
scalar_stmts = vNULL;
|
||||
scalar_stmts.create (group_size);
|
||||
@ -2268,10 +2193,13 @@ vect_analyze_slp_instance (vec_info *vinfo,
|
||||
scalar_stmts.release ();
|
||||
}
|
||||
|
||||
stmt_vec_info stmt_info = stmt_info_;
|
||||
/* Try to break the group up into pieces. */
|
||||
if (STMT_VINFO_GROUPED_ACCESS (stmt_info)
|
||||
&& DR_IS_WRITE (STMT_VINFO_DATA_REF (stmt_info)))
|
||||
if (kind == slp_inst_kind_store)
|
||||
{
|
||||
/* ??? We could delay all the actual splitting of store-groups
|
||||
until after SLP discovery of the original group completed.
|
||||
Then we can recurse to vect_build_slp_instance directly. */
|
||||
for (i = 0; i < group_size; i++)
|
||||
if (!matches[i])
|
||||
break;
|
||||
@ -2354,6 +2282,122 @@ vect_analyze_slp_instance (vec_info *vinfo,
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/* Analyze an SLP instance starting from a group of grouped stores. Call
|
||||
vect_build_slp_tree to build a tree of packed stmts if possible.
|
||||
Return FALSE if it's impossible to SLP any stmt in the loop. */
|
||||
|
||||
static bool
|
||||
vect_analyze_slp_instance (vec_info *vinfo,
|
||||
scalar_stmts_to_slp_tree_map_t *bst_map,
|
||||
stmt_vec_info stmt_info, unsigned max_tree_size)
|
||||
{
|
||||
unsigned int group_size;
|
||||
unsigned int i;
|
||||
struct data_reference *dr = STMT_VINFO_DATA_REF (stmt_info);
|
||||
vec<stmt_vec_info> scalar_stmts;
|
||||
slp_instance_kind kind;
|
||||
|
||||
if (is_a <bb_vec_info> (vinfo))
|
||||
vect_location = stmt_info->stmt;
|
||||
if (STMT_VINFO_GROUPED_ACCESS (stmt_info))
|
||||
{
|
||||
kind = slp_inst_kind_store;
|
||||
group_size = DR_GROUP_SIZE (stmt_info);
|
||||
}
|
||||
else if (!dr && REDUC_GROUP_FIRST_ELEMENT (stmt_info))
|
||||
{
|
||||
kind = slp_inst_kind_reduc_chain;
|
||||
gcc_assert (is_a <loop_vec_info> (vinfo));
|
||||
group_size = REDUC_GROUP_SIZE (stmt_info);
|
||||
}
|
||||
else if (is_gimple_assign (stmt_info->stmt)
|
||||
&& gimple_assign_rhs_code (stmt_info->stmt) == CONSTRUCTOR)
|
||||
{
|
||||
kind = slp_inst_kind_ctor;
|
||||
group_size = CONSTRUCTOR_NELTS (gimple_assign_rhs1 (stmt_info->stmt));
|
||||
}
|
||||
else
|
||||
{
|
||||
kind = slp_inst_kind_reduc_group;
|
||||
gcc_assert (is_a <loop_vec_info> (vinfo));
|
||||
group_size = as_a <loop_vec_info> (vinfo)->reductions.length ();
|
||||
}
|
||||
|
||||
/* Create a node (a root of the SLP tree) for the packed grouped stores. */
|
||||
scalar_stmts.create (group_size);
|
||||
stmt_vec_info next_info = stmt_info;
|
||||
if (STMT_VINFO_GROUPED_ACCESS (stmt_info))
|
||||
{
|
||||
/* Collect the stores and store them in SLP_TREE_SCALAR_STMTS. */
|
||||
while (next_info)
|
||||
{
|
||||
scalar_stmts.safe_push (vect_stmt_to_vectorize (next_info));
|
||||
next_info = DR_GROUP_NEXT_ELEMENT (next_info);
|
||||
}
|
||||
}
|
||||
else if (!dr && REDUC_GROUP_FIRST_ELEMENT (stmt_info))
|
||||
{
|
||||
/* Collect the reduction stmts and store them in
|
||||
SLP_TREE_SCALAR_STMTS. */
|
||||
while (next_info)
|
||||
{
|
||||
scalar_stmts.safe_push (vect_stmt_to_vectorize (next_info));
|
||||
next_info = REDUC_GROUP_NEXT_ELEMENT (next_info);
|
||||
}
|
||||
/* 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)
|
||||
= 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 ()));
|
||||
}
|
||||
else if (kind == slp_inst_kind_ctor)
|
||||
{
|
||||
tree rhs = gimple_assign_rhs1 (stmt_info->stmt);
|
||||
tree val;
|
||||
FOR_EACH_CONSTRUCTOR_VALUE (CONSTRUCTOR_ELTS (rhs), i, val)
|
||||
{
|
||||
if (TREE_CODE (val) == SSA_NAME)
|
||||
{
|
||||
gimple* def = SSA_NAME_DEF_STMT (val);
|
||||
stmt_vec_info def_info = vinfo->lookup_stmt (def);
|
||||
/* Value is defined in another basic block. */
|
||||
if (!def_info)
|
||||
return false;
|
||||
def_info = vect_stmt_to_vectorize (def_info);
|
||||
scalar_stmts.safe_push (def_info);
|
||||
}
|
||||
else
|
||||
return false;
|
||||
}
|
||||
if (dump_enabled_p ())
|
||||
dump_printf_loc (MSG_NOTE, vect_location,
|
||||
"Analyzing vectorizable constructor: %G\n",
|
||||
stmt_info->stmt);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Collect reduction statements. */
|
||||
vec<stmt_vec_info> reductions = as_a <loop_vec_info> (vinfo)->reductions;
|
||||
for (i = 0; reductions.iterate (i, &next_info); i++)
|
||||
scalar_stmts.safe_push (next_info);
|
||||
}
|
||||
|
||||
/* Build the tree for the SLP instance. */
|
||||
bool res = vect_build_slp_instance (vinfo, kind, scalar_stmts,
|
||||
kind == slp_inst_kind_ctor
|
||||
? stmt_info : NULL,
|
||||
max_tree_size,
|
||||
bst_map, stmt_info);
|
||||
|
||||
/* ??? If this is slp_inst_kind_store and the above succeeded here's
|
||||
where we should do store group splitting. */
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
/* Fill in backedge SLP children in the SLP graph. */
|
||||
|
||||
static void
|
||||
|
Loading…
Reference in New Issue
Block a user