aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRichard Sandiford <richard.sandiford@arm.com>2019-11-14 15:33:49 +0000
committerRichard Sandiford <rsandifo@gcc.gnu.org>2019-11-14 15:33:49 +0000
commit60838d634634a70d65a126166c944b159ac7649c (patch)
treeb64a9b2ac2d31399b5c1c0dee684a6cc4ad1818b
parent9c437a108a14b9bdc44659c131b0da944e5ffeab (diff)
downloadgcc-60838d634634a70d65a126166c944b159ac7649c.zip
gcc-60838d634634a70d65a126166c944b159ac7649c.tar.gz
gcc-60838d634634a70d65a126166c944b159ac7649c.tar.bz2
Consider building nodes from scalars in vect_slp_analyze_node_operations
If the statements in an SLP node aren't similar enough to be vectorised, or aren't something the vectoriser has code to handle, the BB vectoriser tries building the vector from scalars instead. This patch does the same thing if we're able to build a viable-looking tree but fail later during the analysis phase, e.g. because the target doesn't support a particular vector operation. This is needed to avoid regressions with a later patch. 2019-11-14 Richard Sandiford <richard.sandiford@arm.com> gcc/ * tree-vect-slp.c (vect_contains_pattern_stmt_p): New function. (vect_slp_convert_to_external): Likewise. (vect_slp_analyze_node_operations): If analysis fails, try building the node from scalars instead. gcc/testsuite/ * gcc.dg/vect/bb-slp-div-2.c: New test. From-SVN: r278246
-rw-r--r--gcc/ChangeLog7
-rw-r--r--gcc/testsuite/ChangeLog4
-rw-r--r--gcc/testsuite/gcc.dg/vect/bb-slp-div-2.c14
-rw-r--r--gcc/tree-vect-slp.c58
4 files changed, 83 insertions, 0 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 2798f15..4bccc16 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,5 +1,12 @@
2019-11-14 Richard Sandiford <richard.sandiford@arm.com>
+ * tree-vect-slp.c (vect_contains_pattern_stmt_p): New function.
+ (vect_slp_convert_to_external): Likewise.
+ (vect_slp_analyze_node_operations): If analysis fails, try building
+ the node from scalars instead.
+
+2019-11-14 Richard Sandiford <richard.sandiford@arm.com>
+
* tree-cfg.c (verify_gimple_assign_unary): Handle conversions
between vector types.
* tree-vect-stmts.c (vectorizable_conversion): Extend the
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 29da1f3..5af7ea0 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,5 +1,9 @@
2019-11-14 Richard Sandiford <richard.sandiford@arm.com>
+ * gcc.dg/vect/bb-slp-div-2.c: New test.
+
+2019-11-14 Richard Sandiford <richard.sandiford@arm.com>
+
* gcc.dg/vect/bb-slp-pr69907.c: Do not expect BB vectorization
to fail for aarch64 targets.
* gcc.dg/vect/no-scevccp-outer-12.c: Expect the test to pass
diff --git a/gcc/testsuite/gcc.dg/vect/bb-slp-div-2.c b/gcc/testsuite/gcc.dg/vect/bb-slp-div-2.c
new file mode 100644
index 0000000..715c22a
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/vect/bb-slp-div-2.c
@@ -0,0 +1,14 @@
+/* { dg-do compile } */
+
+int x[4], y[4], z[4];
+
+void
+f (void)
+{
+ x[0] += y[0] / z[0] * 2;
+ x[1] += y[1] / z[1] * 2;
+ x[2] += y[2] / z[2] * 2;
+ x[3] += y[3] / z[3] * 2;
+}
+
+/* { dg-final { scan-tree-dump "basic block vectorized" "slp2" { target vect_int } } } */
diff --git a/gcc/tree-vect-slp.c b/gcc/tree-vect-slp.c
index a46bba5..1c1e502 100644
--- a/gcc/tree-vect-slp.c
+++ b/gcc/tree-vect-slp.c
@@ -224,6 +224,19 @@ vect_free_oprnd_info (vec<slp_oprnd_info> &oprnds_info)
}
+/* Return true if STMTS contains a pattern statement. */
+
+static bool
+vect_contains_pattern_stmt_p (vec<stmt_vec_info> stmts)
+{
+ stmt_vec_info stmt_info;
+ unsigned int i;
+ FOR_EACH_VEC_ELT (stmts, i, stmt_info)
+ if (is_pattern_stmt_p (stmt_info))
+ return true;
+ return false;
+}
+
/* Find the place of the data-ref in STMT_INFO in the interleaving chain
that starts from FIRST_STMT_INFO. Return -1 if the data-ref is not a part
of the chain. */
@@ -2694,6 +2707,39 @@ vect_slp_analyze_node_operations_1 (vec_info *vinfo, slp_tree node,
return vect_analyze_stmt (stmt_info, &dummy, node, node_instance, cost_vec);
}
+/* Try to build NODE from scalars, returning true on success.
+ NODE_INSTANCE is the SLP instance that contains NODE. */
+
+static bool
+vect_slp_convert_to_external (vec_info *vinfo, slp_tree node,
+ slp_instance node_instance)
+{
+ stmt_vec_info stmt_info;
+ unsigned int i;
+
+ if (!is_a <bb_vec_info> (vinfo)
+ || node == SLP_INSTANCE_TREE (node_instance)
+ || vect_contains_pattern_stmt_p (SLP_TREE_SCALAR_STMTS (node)))
+ return false;
+
+ if (dump_enabled_p ())
+ dump_printf_loc (MSG_NOTE, vect_location,
+ "Building vector operands from scalars instead\n");
+
+ /* Don't remove and free the child nodes here, since they could be
+ referenced by other structures. The analysis and scheduling phases
+ (need to) ignore child nodes of anything that isn't vect_internal_def. */
+ unsigned int group_size = SLP_TREE_SCALAR_STMTS (node).length ();
+ SLP_TREE_DEF_TYPE (node) = vect_external_def;
+ SLP_TREE_SCALAR_OPS (node).safe_grow (group_size);
+ FOR_EACH_VEC_ELT (SLP_TREE_SCALAR_STMTS (node), i, stmt_info)
+ {
+ tree lhs = gimple_get_lhs (vect_orig_stmt (stmt_info)->stmt);
+ SLP_TREE_SCALAR_OPS (node)[i] = lhs;
+ }
+ return true;
+}
+
/* Analyze statements contained in SLP tree NODE after recursively analyzing
the subtree. NODE_INSTANCE contains NODE and VINFO contains INSTANCE.
@@ -2720,6 +2766,13 @@ vect_slp_analyze_node_operations (vec_info *vinfo, slp_tree node,
{
SLP_TREE_NUMBER_OF_VEC_STMTS (node)
= SLP_TREE_NUMBER_OF_VEC_STMTS (*leader);
+ /* Cope with cases in which we made a late decision to build the
+ node from scalars. */
+ if (SLP_TREE_DEF_TYPE (*leader) == vect_external_def
+ && vect_slp_convert_to_external (vinfo, node, node_instance))
+ ;
+ else
+ gcc_assert (SLP_TREE_DEF_TYPE (node) == SLP_TREE_DEF_TYPE (*leader));
return true;
}
@@ -2779,6 +2832,11 @@ vect_slp_analyze_node_operations (vec_info *vinfo, slp_tree node,
if (SLP_TREE_SCALAR_STMTS (child).length () != 0)
STMT_VINFO_DEF_TYPE (SLP_TREE_SCALAR_STMTS (child)[0]) = dt[j];
+ /* If this node can't be vectorized, try pruning the tree here rather
+ than felling the whole thing. */
+ if (!res && vect_slp_convert_to_external (vinfo, node, node_instance))
+ res = true;
+
return res;
}