aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/testsuite/gcc.dg/vect/bb-slp-layout-19.c34
-rw-r--r--gcc/tree-vect-slp.cc69
2 files changed, 77 insertions, 26 deletions
diff --git a/gcc/testsuite/gcc.dg/vect/bb-slp-layout-19.c b/gcc/testsuite/gcc.dg/vect/bb-slp-layout-19.c
new file mode 100644
index 0000000..f075a83
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/vect/bb-slp-layout-19.c
@@ -0,0 +1,34 @@
+/* { dg-do compile } */
+/* { dg-additional-options "-fno-tree-loop-vectorize" } */
+
+extern int a[][4], b[][4], c[][4], d[4], e[4];
+void f()
+{
+ int t0 = a[0][3];
+ int t1 = a[1][3];
+ int t2 = a[2][3];
+ int t3 = a[3][3];
+ int a0 = 0, a1 = 0, a2 = 0, a3 = 0, b0 = 0, b1 = 0, b2 = 0, b3 = 0;
+ for (int j = 0; j < 100; ++j)
+ for (int i = 0; i < 400; i += 4)
+ {
+ a0 += b[i][3] * t0;
+ a1 += b[i][2] * t1;
+ a2 += b[i][1] * t2;
+ a3 += b[i][0] * t3;
+ b0 += c[i][3] * t0;
+ b1 += c[i][2] * t1;
+ b2 += c[i][1] * t2;
+ b3 += c[i][0] * t3;
+ }
+ d[0] = a0;
+ d[1] = a1;
+ d[2] = a2;
+ d[3] = a3;
+ e[0] = b0;
+ e[1] = b1;
+ e[2] = b2;
+ e[3] = b3;
+}
+
+/* { dg-final { scan-tree-dump-times "add new stmt: \[^\\n\\r\]* = VEC_PERM_EXPR" 3 "slp1" { target { vect_int_mult && vect_perm } } } } */
diff --git a/gcc/tree-vect-slp.cc b/gcc/tree-vect-slp.cc
index 1cf79ee..59ec66a 100644
--- a/gcc/tree-vect-slp.cc
+++ b/gcc/tree-vect-slp.cc
@@ -6435,47 +6435,64 @@ get_ultimate_leader (slp_instance instance,
return instance;
}
+namespace {
+/* Subroutine of vect_bb_partition_graph_r. Map KEY to INSTANCE in
+ KEY_TO_INSTANCE, making INSTANCE the leader of any previous mapping
+ for KEY. Return true if KEY was already in KEY_TO_INSTANCE.
+
+ INSTANCE_LEADER is as for get_ultimate_leader. */
+
+template<typename T>
+bool
+vect_map_to_instance (slp_instance instance, T key,
+ hash_map<T, slp_instance> &key_to_instance,
+ hash_map<slp_instance, slp_instance> &instance_leader)
+{
+ bool existed_p;
+ slp_instance &key_instance = key_to_instance.get_or_insert (key, &existed_p);
+ if (!existed_p)
+ ;
+ else if (key_instance != instance)
+ {
+ /* If we're running into a previously marked key make us the
+ leader of the current ultimate leader. This keeps the
+ leader chain acyclic and works even when the current instance
+ connects two previously independent graph parts. */
+ slp_instance key_leader
+ = get_ultimate_leader (key_instance, instance_leader);
+ if (key_leader != instance)
+ instance_leader.put (key_leader, instance);
+ }
+ key_instance = instance;
+ return existed_p;
+}
+}
+
/* Worker of vect_bb_partition_graph, recurse on NODE. */
static void
vect_bb_partition_graph_r (bb_vec_info bb_vinfo,
slp_instance instance, slp_tree node,
hash_map<stmt_vec_info, slp_instance> &stmt_to_instance,
- hash_map<slp_instance, slp_instance> &instance_leader,
- hash_set<slp_tree> &visited)
+ hash_map<slp_tree, slp_instance> &node_to_instance,
+ hash_map<slp_instance, slp_instance> &instance_leader)
{
stmt_vec_info stmt_info;
unsigned i;
FOR_EACH_VEC_ELT (SLP_TREE_SCALAR_STMTS (node), i, stmt_info)
- {
- bool existed_p;
- slp_instance &stmt_instance
- = stmt_to_instance.get_or_insert (stmt_info, &existed_p);
- if (!existed_p)
- ;
- else if (stmt_instance != instance)
- {
- /* If we're running into a previously marked stmt make us the
- leader of the current ultimate leader. This keeps the
- leader chain acyclic and works even when the current instance
- connects two previously independent graph parts. */
- slp_instance stmt_leader
- = get_ultimate_leader (stmt_instance, instance_leader);
- if (stmt_leader != instance)
- instance_leader.put (stmt_leader, instance);
- }
- stmt_instance = instance;
- }
+ vect_map_to_instance (instance, stmt_info, stmt_to_instance,
+ instance_leader);
- if (!SLP_TREE_SCALAR_STMTS (node).is_empty () && visited.add (node))
+ if (vect_map_to_instance (instance, node, node_to_instance,
+ instance_leader))
return;
slp_tree child;
FOR_EACH_VEC_ELT (SLP_TREE_CHILDREN (node), i, child)
if (child && SLP_TREE_DEF_TYPE (child) == vect_internal_def)
vect_bb_partition_graph_r (bb_vinfo, instance, child, stmt_to_instance,
- instance_leader, visited);
+ node_to_instance, instance_leader);
}
/* Partition the SLP graph into pieces that can be costed independently. */
@@ -6489,16 +6506,16 @@ vect_bb_partition_graph (bb_vec_info bb_vinfo)
corresponding SLP graph entry and upon visiting a previously
marked stmt, make the stmts leader the current SLP graph entry. */
hash_map<stmt_vec_info, slp_instance> stmt_to_instance;
+ hash_map<slp_tree, slp_instance> node_to_instance;
hash_map<slp_instance, slp_instance> instance_leader;
- hash_set<slp_tree> visited;
slp_instance instance;
for (unsigned i = 0; bb_vinfo->slp_instances.iterate (i, &instance); ++i)
{
instance_leader.put (instance, instance);
vect_bb_partition_graph_r (bb_vinfo,
instance, SLP_INSTANCE_TREE (instance),
- stmt_to_instance, instance_leader,
- visited);
+ stmt_to_instance, node_to_instance,
+ instance_leader);
}
/* Then collect entries to each independent subgraph. */