Commit e403d17e by Richard Biener Committed by Richard Biener

re PR tree-optimization/66856 (ICE in compute_live_loop_exits, at tree-ssa-loop-manip.c:234)

2016-01-14  Richard Biener  <rguenther@suse.de>

	PR tree-optimization/66856
	* tree-vect-slp.c (vect_build_slp_tree): Refactor to build
	SLP node only if it built successfully.
	(vect_analyze_slp_instance): Adjust.

From-SVN: r232364
parent bab0ad3a
2016-01-14 Richard Biener <rguenther@suse.de>
PR tree-optimization/66856
* tree-vect-slp.c (vect_build_slp_tree): Refactor to build
SLP node only if it built successfully.
(vect_analyze_slp_instance): Adjust.
2016-01-14 Jeff Law <law@redhat.com> 2016-01-14 Jeff Law <law@redhat.com>
PR tree-optimization/69270 PR tree-optimization/69270
......
...@@ -834,20 +834,21 @@ vect_build_slp_tree_1 (vec_info *vinfo, ...@@ -834,20 +834,21 @@ vect_build_slp_tree_1 (vec_info *vinfo,
The value returned is the depth in the SLP tree where a mismatch The value returned is the depth in the SLP tree where a mismatch
was found. */ was found. */
static bool static slp_tree
vect_build_slp_tree (vec_info *vinfo, vect_build_slp_tree (vec_info *vinfo,
slp_tree *node, unsigned int group_size, vec<gimple *> stmts, unsigned int group_size,
unsigned int *max_nunits, unsigned int *max_nunits,
vec<slp_tree> *loads, vec<slp_tree> *loads,
bool *matches, unsigned *npermutes, unsigned *tree_size, bool *matches, unsigned *npermutes, unsigned *tree_size,
unsigned max_tree_size) unsigned max_tree_size)
{ {
unsigned nops, i, this_tree_size = 0; unsigned nops, i, this_tree_size = 0, this_max_nunits = *max_nunits;
gimple *stmt; gimple *stmt;
slp_tree node;
matches[0] = false; matches[0] = false;
stmt = SLP_TREE_SCALAR_STMTS (*node)[0]; stmt = stmts[0];
if (is_gimple_call (stmt)) if (is_gimple_call (stmt))
nops = gimple_call_num_args (stmt); nops = gimple_call_num_args (stmt);
else if (is_gimple_assign (stmt)) else if (is_gimple_assign (stmt))
...@@ -857,27 +858,28 @@ vect_build_slp_tree (vec_info *vinfo, ...@@ -857,27 +858,28 @@ vect_build_slp_tree (vec_info *vinfo,
nops++; nops++;
} }
else else
return false; return NULL;
bool two_operators = false; bool two_operators = false;
if (!vect_build_slp_tree_1 (vinfo, if (!vect_build_slp_tree_1 (vinfo,
SLP_TREE_SCALAR_STMTS (*node), group_size, nops, stmts, group_size, nops,
max_nunits, matches, &two_operators)) &this_max_nunits, matches, &two_operators))
return false; return NULL;
SLP_TREE_TWO_OPERATORS (*node) = two_operators;
/* If the SLP node is a load, terminate the recursion. */ /* If the SLP node is a load, terminate the recursion. */
if (STMT_VINFO_GROUPED_ACCESS (vinfo_for_stmt (stmt)) if (STMT_VINFO_GROUPED_ACCESS (vinfo_for_stmt (stmt))
&& DR_IS_READ (STMT_VINFO_DATA_REF (vinfo_for_stmt (stmt)))) && DR_IS_READ (STMT_VINFO_DATA_REF (vinfo_for_stmt (stmt))))
{ {
loads->safe_push (*node); *max_nunits = this_max_nunits;
return true; node = vect_create_new_slp_node (stmts);
loads->safe_push (node);
return node;
} }
/* Get at the operands, verifying they are compatible. */ /* Get at the operands, verifying they are compatible. */
vec<slp_oprnd_info> oprnds_info = vect_create_oprnd_info (nops, group_size); vec<slp_oprnd_info> oprnds_info = vect_create_oprnd_info (nops, group_size);
slp_oprnd_info oprnd_info; slp_oprnd_info oprnd_info;
FOR_EACH_VEC_ELT (SLP_TREE_SCALAR_STMTS (*node), i, stmt) FOR_EACH_VEC_ELT (stmts, i, stmt)
{ {
switch (vect_get_and_check_slp_defs (vinfo, stmt, i, &oprnds_info)) switch (vect_get_and_check_slp_defs (vinfo, stmt, i, &oprnds_info))
{ {
...@@ -886,7 +888,7 @@ vect_build_slp_tree (vec_info *vinfo, ...@@ -886,7 +888,7 @@ vect_build_slp_tree (vec_info *vinfo,
case -1: case -1:
matches[0] = false; matches[0] = false;
vect_free_oprnd_info (oprnds_info); vect_free_oprnd_info (oprnds_info);
return false; return NULL;
case 1: case 1:
matches[i] = false; matches[i] = false;
break; break;
...@@ -896,43 +898,43 @@ vect_build_slp_tree (vec_info *vinfo, ...@@ -896,43 +898,43 @@ vect_build_slp_tree (vec_info *vinfo,
if (!matches[i]) if (!matches[i])
{ {
vect_free_oprnd_info (oprnds_info); vect_free_oprnd_info (oprnds_info);
return false; return NULL;
} }
stmt = SLP_TREE_SCALAR_STMTS (*node)[0]; auto_vec<slp_tree, 4> children;
auto_vec<slp_tree> this_loads;
stmt = stmts[0];
/* Create SLP_TREE nodes for the definition node/s. */ /* Create SLP_TREE nodes for the definition node/s. */
FOR_EACH_VEC_ELT (oprnds_info, i, oprnd_info) FOR_EACH_VEC_ELT (oprnds_info, i, oprnd_info)
{ {
slp_tree child; slp_tree child;
unsigned old_nloads = loads->length (); unsigned old_nloads = this_loads.length ();
unsigned old_max_nunits = *max_nunits; unsigned old_tree_size = this_tree_size;
unsigned int j;
if (oprnd_info->first_dt != vect_internal_def) if (oprnd_info->first_dt != vect_internal_def)
continue; continue;
if (++this_tree_size > max_tree_size) if (++this_tree_size > max_tree_size)
{ {
FOR_EACH_VEC_ELT (children, j, child)
vect_free_slp_tree (child);
vect_free_oprnd_info (oprnds_info); vect_free_oprnd_info (oprnds_info);
return false; return NULL;
} }
child = vect_create_new_slp_node (oprnd_info->def_stmts); if ((child = vect_build_slp_tree (vinfo, oprnd_info->def_stmts,
if (!child) group_size, &this_max_nunits,
{ &this_loads, matches, npermutes,
vect_free_oprnd_info (oprnds_info); &this_tree_size,
return false; max_tree_size)) != NULL)
}
if (vect_build_slp_tree (vinfo, &child,
group_size, max_nunits, loads, matches,
npermutes, &this_tree_size, max_tree_size))
{ {
/* If we have all children of child built up from scalars then just /* If we have all children of child built up from scalars then just
throw that away and build it up this node from scalars. */ throw that away and build it up this node from scalars. */
if (!SLP_TREE_CHILDREN (child).is_empty ()) if (!SLP_TREE_CHILDREN (child).is_empty ())
{ {
unsigned int j;
slp_tree grandchild; slp_tree grandchild;
FOR_EACH_VEC_ELT (SLP_TREE_CHILDREN (child), j, grandchild) FOR_EACH_VEC_ELT (SLP_TREE_CHILDREN (child), j, grandchild)
...@@ -941,8 +943,8 @@ vect_build_slp_tree (vec_info *vinfo, ...@@ -941,8 +943,8 @@ vect_build_slp_tree (vec_info *vinfo,
if (!grandchild) if (!grandchild)
{ {
/* Roll back. */ /* Roll back. */
*max_nunits = old_max_nunits; this_loads.truncate (old_nloads);
loads->truncate (old_nloads); this_tree_size = old_tree_size;
FOR_EACH_VEC_ELT (SLP_TREE_CHILDREN (child), j, grandchild) FOR_EACH_VEC_ELT (SLP_TREE_CHILDREN (child), j, grandchild)
vect_free_slp_tree (grandchild); vect_free_slp_tree (grandchild);
SLP_TREE_CHILDREN (child).truncate (0); SLP_TREE_CHILDREN (child).truncate (0);
...@@ -952,13 +954,13 @@ vect_build_slp_tree (vec_info *vinfo, ...@@ -952,13 +954,13 @@ vect_build_slp_tree (vec_info *vinfo,
"scalars instead\n"); "scalars instead\n");
oprnd_info->def_stmts = vNULL; oprnd_info->def_stmts = vNULL;
SLP_TREE_DEF_TYPE (child) = vect_external_def; SLP_TREE_DEF_TYPE (child) = vect_external_def;
SLP_TREE_CHILDREN (*node).quick_push (child); children.safe_push (child);
continue; continue;
} }
} }
oprnd_info->def_stmts = vNULL; oprnd_info->def_stmts = vNULL;
SLP_TREE_CHILDREN (*node).quick_push (child); children.safe_push (child);
continue; continue;
} }
...@@ -977,21 +979,12 @@ vect_build_slp_tree (vec_info *vinfo, ...@@ -977,21 +979,12 @@ vect_build_slp_tree (vec_info *vinfo,
scalar version. */ scalar version. */
&& !is_pattern_stmt_p (vinfo_for_stmt (stmt))) && !is_pattern_stmt_p (vinfo_for_stmt (stmt)))
{ {
unsigned int j;
slp_tree grandchild;
/* Roll back. */
*max_nunits = old_max_nunits;
loads->truncate (old_nloads);
FOR_EACH_VEC_ELT (SLP_TREE_CHILDREN (child), j, grandchild)
vect_free_slp_tree (grandchild);
SLP_TREE_CHILDREN (child).truncate (0);
dump_printf_loc (MSG_NOTE, vect_location, dump_printf_loc (MSG_NOTE, vect_location,
"Building vector operands from scalars\n"); "Building vector operands from scalars\n");
oprnd_info->def_stmts = vNULL; child = vect_create_new_slp_node (oprnd_info->def_stmts);
SLP_TREE_DEF_TYPE (child) = vect_external_def; SLP_TREE_DEF_TYPE (child) = vect_external_def;
SLP_TREE_CHILDREN (*node).quick_push (child); children.safe_push (child);
oprnd_info->def_stmts = vNULL;
continue; continue;
} }
...@@ -1007,23 +1000,13 @@ vect_build_slp_tree (vec_info *vinfo, ...@@ -1007,23 +1000,13 @@ vect_build_slp_tree (vec_info *vinfo,
&& oprnds_info[1]->first_dt == vect_internal_def && oprnds_info[1]->first_dt == vect_internal_def
&& is_gimple_assign (stmt) && is_gimple_assign (stmt)
&& commutative_tree_code (gimple_assign_rhs_code (stmt)) && commutative_tree_code (gimple_assign_rhs_code (stmt))
&& !SLP_TREE_TWO_OPERATORS (*node) && ! two_operators
/* Do so only if the number of not successful permutes was nor more /* Do so only if the number of not successful permutes was nor more
than a cut-ff as re-trying the recursive match on than a cut-ff as re-trying the recursive match on
possibly each level of the tree would expose exponential possibly each level of the tree would expose exponential
behavior. */ behavior. */
&& *npermutes < 4) && *npermutes < 4)
{ {
unsigned int j;
slp_tree grandchild;
/* Roll back. */
*max_nunits = old_max_nunits;
loads->truncate (old_nloads);
FOR_EACH_VEC_ELT (SLP_TREE_CHILDREN (child), j, grandchild)
vect_free_slp_tree (grandchild);
SLP_TREE_CHILDREN (child).truncate (0);
/* Swap mismatched definition stmts. */ /* Swap mismatched definition stmts. */
dump_printf_loc (MSG_NOTE, vect_location, dump_printf_loc (MSG_NOTE, vect_location,
"Re-trying with swapped operands of stmts "); "Re-trying with swapped operands of stmts ");
...@@ -1037,10 +1020,11 @@ vect_build_slp_tree (vec_info *vinfo, ...@@ -1037,10 +1020,11 @@ vect_build_slp_tree (vec_info *vinfo,
dump_printf (MSG_NOTE, "\n"); dump_printf (MSG_NOTE, "\n");
/* And try again with scratch 'matches' ... */ /* And try again with scratch 'matches' ... */
bool *tem = XALLOCAVEC (bool, group_size); bool *tem = XALLOCAVEC (bool, group_size);
if (vect_build_slp_tree (vinfo, &child, if ((child = vect_build_slp_tree (vinfo, oprnd_info->def_stmts,
group_size, max_nunits, loads, group_size, &this_max_nunits,
tem, npermutes, &this_tree_size, &this_loads, tem, npermutes,
max_tree_size)) &this_tree_size,
max_tree_size)) != NULL)
{ {
/* ... so if successful we can apply the operand swapping /* ... so if successful we can apply the operand swapping
to the GIMPLE IL. This is necessary because for example to the GIMPLE IL. This is necessary because for example
...@@ -1050,12 +1034,12 @@ vect_build_slp_tree (vec_info *vinfo, ...@@ -1050,12 +1034,12 @@ vect_build_slp_tree (vec_info *vinfo,
we'll continue to process swapped operand two. */ we'll continue to process swapped operand two. */
for (j = 0; j < group_size; ++j) for (j = 0; j < group_size; ++j)
{ {
gimple *stmt = SLP_TREE_SCALAR_STMTS (*node)[j]; gimple *stmt = stmts[j];
gimple_set_plf (stmt, GF_PLF_1, false); gimple_set_plf (stmt, GF_PLF_1, false);
} }
for (j = 0; j < group_size; ++j) for (j = 0; j < group_size; ++j)
{ {
gimple *stmt = SLP_TREE_SCALAR_STMTS (*node)[j]; gimple *stmt = stmts[j];
if (!matches[j]) if (!matches[j])
{ {
/* Avoid swapping operands twice. */ /* Avoid swapping operands twice. */
...@@ -1070,7 +1054,7 @@ vect_build_slp_tree (vec_info *vinfo, ...@@ -1070,7 +1054,7 @@ vect_build_slp_tree (vec_info *vinfo,
if (flag_checking) if (flag_checking)
for (j = 0; j < group_size; ++j) for (j = 0; j < group_size; ++j)
{ {
gimple *stmt = SLP_TREE_SCALAR_STMTS (*node)[j]; gimple *stmt = stmts[j];
gcc_assert (gimple_plf (stmt, GF_PLF_1) == ! matches[j]); gcc_assert (gimple_plf (stmt, GF_PLF_1) == ! matches[j]);
} }
...@@ -1087,8 +1071,8 @@ vect_build_slp_tree (vec_info *vinfo, ...@@ -1087,8 +1071,8 @@ vect_build_slp_tree (vec_info *vinfo,
if (!grandchild) if (!grandchild)
{ {
/* Roll back. */ /* Roll back. */
*max_nunits = old_max_nunits; this_loads.truncate (old_nloads);
loads->truncate (old_nloads); this_tree_size = old_tree_size;
FOR_EACH_VEC_ELT (SLP_TREE_CHILDREN (child), j, grandchild) FOR_EACH_VEC_ELT (SLP_TREE_CHILDREN (child), j, grandchild)
vect_free_slp_tree (grandchild); vect_free_slp_tree (grandchild);
SLP_TREE_CHILDREN (child).truncate (0); SLP_TREE_CHILDREN (child).truncate (0);
...@@ -1098,30 +1082,37 @@ vect_build_slp_tree (vec_info *vinfo, ...@@ -1098,30 +1082,37 @@ vect_build_slp_tree (vec_info *vinfo,
"scalars instead\n"); "scalars instead\n");
oprnd_info->def_stmts = vNULL; oprnd_info->def_stmts = vNULL;
SLP_TREE_DEF_TYPE (child) = vect_external_def; SLP_TREE_DEF_TYPE (child) = vect_external_def;
SLP_TREE_CHILDREN (*node).quick_push (child); children.safe_push (child);
continue; continue;
} }
} }
oprnd_info->def_stmts = vNULL; oprnd_info->def_stmts = vNULL;
SLP_TREE_CHILDREN (*node).quick_push (child); children.safe_push (child);
continue; continue;
} }
++*npermutes; ++*npermutes;
} }
oprnd_info->def_stmts = vNULL; gcc_assert (child == NULL);
vect_free_slp_tree (child); FOR_EACH_VEC_ELT (children, j, child)
vect_free_slp_tree (child);
vect_free_oprnd_info (oprnds_info); vect_free_oprnd_info (oprnds_info);
return false; return NULL;
} }
vect_free_oprnd_info (oprnds_info);
if (tree_size) if (tree_size)
*tree_size += this_tree_size; *tree_size += this_tree_size;
*max_nunits = this_max_nunits;
loads->safe_splice (this_loads);
vect_free_oprnd_info (oprnds_info); node = vect_create_new_slp_node (stmts);
return true; SLP_TREE_TWO_OPERATORS (node) = two_operators;
SLP_TREE_CHILDREN (node).splice (children);
return node;
} }
/* Dump a slp tree NODE using flags specified in DUMP_KIND. */ /* Dump a slp tree NODE using flags specified in DUMP_KIND. */
...@@ -1733,16 +1724,14 @@ vect_analyze_slp_instance (vec_info *vinfo, ...@@ -1733,16 +1724,14 @@ vect_analyze_slp_instance (vec_info *vinfo,
scalar_stmts.safe_push (next); scalar_stmts.safe_push (next);
} }
node = vect_create_new_slp_node (scalar_stmts);
loads.create (group_size); loads.create (group_size);
/* Build the tree for the SLP instance. */ /* Build the tree for the SLP instance. */
bool *matches = XALLOCAVEC (bool, group_size); bool *matches = XALLOCAVEC (bool, group_size);
unsigned npermutes = 0; unsigned npermutes = 0;
if (vect_build_slp_tree (vinfo, &node, group_size, if ((node = vect_build_slp_tree (vinfo, scalar_stmts, group_size,
&max_nunits, &loads, &max_nunits, &loads, matches, &npermutes,
matches, &npermutes, NULL, max_tree_size)) NULL, max_tree_size)) != NULL)
{ {
/* Calculate the unrolling factor based on the smallest type. */ /* Calculate the unrolling factor based on the smallest type. */
if (max_nunits > nunits) if (max_nunits > nunits)
...@@ -1864,7 +1853,7 @@ vect_analyze_slp_instance (vec_info *vinfo, ...@@ -1864,7 +1853,7 @@ vect_analyze_slp_instance (vec_info *vinfo,
/* Failed to SLP. */ /* Failed to SLP. */
/* Free the allocated memory. */ /* Free the allocated memory. */
vect_free_slp_tree (node); scalar_stmts.release ();
loads.release (); loads.release ();
/* For basic block SLP, try to break the group up into multiples of the /* For basic block SLP, try to break the group up into multiples of the
......
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