With the matches[] improvement we can now readily pick the largest
isomorphic group to vectorize directly.
Bootstrapped and tested on x86_64-unknown-linux-gnu and aarch64-linux-gnu.
* tree-vect-slp.cc (vect_build_slp_instance): Pick the
largest isomorphic subset when vectorizing a BB reduction.
---
gcc/tree-vect-slp.cc | 45 +++++++++++++++++---------------------------
1 file changed, 17 insertions(+), 28 deletions(-)
diff --git a/gcc/tree-vect-slp.cc b/gcc/tree-vect-slp.cc
index f88646879b7..06c241a7562 100644
--- a/gcc/tree-vect-slp.cc
+++ b/gcc/tree-vect-slp.cc
@@ -4355,46 +4355,35 @@ vect_build_slp_instance (vec_info *vinfo,
Iff there is any mismatches in the toplevel stmts those will prevail,
otherwise we get the non-power-of-two tail of the lanes failed.
For BB reductions we mainly want to catch the first case so we pick
- a more useful subset of lanes to reduce. */
- if (kind == slp_inst_kind_bb_reduc && matches[0] == 0)
+ a more useful subset of lanes to reduce. Pick the largest matching
+ subset of that covers half of the group or more. */
+ if (kind == slp_inst_kind_bb_reduc && matches[0] != -1)
{
- unsigned n_matching = 0;
+ unsigned *n_matching = XALLOCAVEC (unsigned, group_size);
+ memset (n_matching, 0, sizeof (unsigned) * group_size);
for (unsigned i = 0; i < group_size; ++i)
- if (matches[i] == 0)
- n_matching++;
- vec<stmt_vec_info> scalar_stmts2 = vNULL;
- /* Try matched parts and put the rest to remain. */
- if (n_matching >= 2 && n_matching >= group_size / 2)
+ if (matches[i] != -2 && matches[i] != -1)
+ n_matching[matches[i].v]++;
+ unsigned largest_i = 0;
+ for (unsigned i = 1; i < group_size; ++i)
+ if (n_matching[i] > n_matching[largest_i])
+ largest_i = i;
+ /* Pick the largest matching part and put the rest to remain. */
+ if (n_matching[largest_i] >= 2
+ && n_matching[largest_i] >= group_size / 2)
{
/* As we know the matches[] stmts match up, recursing for
non-power-of-two sizes will just force-fail the tail
for us at hopefully optimal vector size and succesfully
finish discovery. */
- scalar_stmts2.create (n_matching);
- for (unsigned i = 0; i < group_size; ++i)
- if (matches[i] == 0)
- scalar_stmts2.quick_push (scalar_stmts[i]);
- else
- remain.safe_push
- (gimple_get_lhs (vect_orig_stmt (scalar_stmts[i])->stmt));
- }
- /* Try the non-matching part. */
- else if (group_size - n_matching >= 2)
- {
- /* We do not know whether the !matches[] part matches, so avoid
- cutting to a multiple of the vector size too early. We should
- make progress by means of remain only growing and most of the
- time prefering the matching[] part. */
- scalar_stmts2.create (scalar_stmts.length () - n_matching);
+ vec<stmt_vec_info> scalar_stmts2;
+ scalar_stmts2.create (n_matching[largest_i]);
for (unsigned i = 0; i < group_size; ++i)
- if (matches[i] != 0)
+ if (matches[i] == (int)largest_i)
scalar_stmts2.quick_push (scalar_stmts[i]);
else
remain.safe_push
(gimple_get_lhs (vect_orig_stmt (scalar_stmts[i])->stmt));
- }
- if (scalar_stmts2.exists ())
- {
if (dump_enabled_p ())
dump_printf_loc (MSG_NOTE, vect_location, "Splitting %d "
"non-matching lanes to scalar remains\n",
--
2.51.0