aboutsummaryrefslogtreecommitdiff
path: root/gcc/tree-vect-slp.c
diff options
context:
space:
mode:
authorRichard Biener <rguenther@suse.de>2020-10-30 09:57:02 +0100
committerRichard Biener <rguenther@suse.de>2020-10-30 10:46:08 +0100
commitc0bfd9672e19caf08e45afeb4277f848488ced2b (patch)
tree642a29ab93daa78a76c13bc16834256c655c653c /gcc/tree-vect-slp.c
parent7de23b8c536397117bbea04a722fa1b86564dd7c (diff)
downloadgcc-c0bfd9672e19caf08e45afeb4277f848488ced2b.zip
gcc-c0bfd9672e19caf08e45afeb4277f848488ced2b.tar.gz
gcc-c0bfd9672e19caf08e45afeb4277f848488ced2b.tar.bz2
tree-optimization/97633 - fix SLP scheduling of single-node cycles
This makes sure to update backedges in single-node cycles. 2020-10-30 Richard Biener <rguenther@suse.de> PR tree-optimization/97633 * tree-vect-slp.c (): Update backedges in single-node cycles. Optimize processing of externals. * g++.dg/vect/slp-pr97636.cc: New testcase. * gcc.dg/vect/bb-slp-pr97633.c: Likewise.
Diffstat (limited to 'gcc/tree-vect-slp.c')
-rw-r--r--gcc/tree-vect-slp.c162
1 files changed, 88 insertions, 74 deletions
diff --git a/gcc/tree-vect-slp.c b/gcc/tree-vect-slp.c
index 5d69a98..714e506 100644
--- a/gcc/tree-vect-slp.c
+++ b/gcc/tree-vect-slp.c
@@ -5554,97 +5554,114 @@ vect_schedule_scc (vec_info *vinfo, slp_tree node, slp_instance instance,
gcc_assert (!existed_p);
info->dfs = maxdfs;
info->lowlink = maxdfs;
- info->on_stack = true;
maxdfs++;
+
+ /* Leaf. */
+ if (SLP_TREE_DEF_TYPE (node) != vect_internal_def)
+ {
+ info->on_stack = false;
+ vect_schedule_slp_node (vinfo, node, instance);
+ return;
+ }
+
+ info->on_stack = true;
stack.safe_push (node);
+
unsigned i;
slp_tree child;
-
- /* ??? We're keeping SLP_TREE_CHILDREN of externalized nodes. */
- if (SLP_TREE_DEF_TYPE (node) == vect_internal_def)
- FOR_EACH_VEC_ELT (SLP_TREE_CHILDREN (node), i, child)
- {
- if (!child)
- continue;
- slp_scc_info *child_info = scc_info.get (child);
- if (!child_info)
- {
- vect_schedule_scc (vinfo, child, instance, scc_info, maxdfs, stack);
- /* Recursion might have re-allocated the node. */
- info = scc_info.get (node);
- child_info = scc_info.get (child);
- info->lowlink = MIN (info->lowlink, child_info->lowlink);
- }
- else if (child_info->on_stack)
- info->lowlink = MIN (info->lowlink, child_info->dfs);
- }
+ /* DFS recurse. */
+ FOR_EACH_VEC_ELT (SLP_TREE_CHILDREN (node), i, child)
+ {
+ if (!child)
+ continue;
+ slp_scc_info *child_info = scc_info.get (child);
+ if (!child_info)
+ {
+ vect_schedule_scc (vinfo, child, instance, scc_info, maxdfs, stack);
+ /* Recursion might have re-allocated the node. */
+ info = scc_info.get (node);
+ child_info = scc_info.get (child);
+ info->lowlink = MIN (info->lowlink, child_info->lowlink);
+ }
+ else if (child_info->on_stack)
+ info->lowlink = MIN (info->lowlink, child_info->dfs);
+ }
if (info->lowlink != info->dfs)
return;
+ auto_vec<slp_tree, 4> phis_to_fixup;
+
/* Singleton. */
if (stack.last () == node)
{
stack.pop ();
info->on_stack = false;
vect_schedule_slp_node (vinfo, node, instance);
- return;
+ if (SLP_TREE_CODE (node) != VEC_PERM_EXPR
+ && is_a <gphi *> (SLP_TREE_REPRESENTATIVE (node)->stmt))
+ phis_to_fixup.quick_push (node);
}
- /* SCC. */
- int last_idx = stack.length () - 1;
- while (stack[last_idx] != node)
- last_idx--;
- /* We can break the cycle at PHIs who have at least one child
- code generated. Then we could re-start the DFS walk until
- all nodes in the SCC are covered (we might have new entries
- for only back-reachable nodes). But it's simpler to just
- iterate and schedule those that are ready. */
- auto_vec<slp_tree, 4> phis_to_fixup;
- unsigned todo = stack.length () - last_idx;
- do
+ else
{
- for (int idx = stack.length () - 1; idx >= last_idx; --idx)
+ /* SCC. */
+ int last_idx = stack.length () - 1;
+ while (stack[last_idx] != node)
+ last_idx--;
+ /* We can break the cycle at PHIs who have at least one child
+ code generated. Then we could re-start the DFS walk until
+ all nodes in the SCC are covered (we might have new entries
+ for only back-reachable nodes). But it's simpler to just
+ iterate and schedule those that are ready. */
+ unsigned todo = stack.length () - last_idx;
+ do
{
- slp_tree entry = stack[idx];
- if (!entry)
- continue;
- bool phi = (SLP_TREE_CODE (entry) != VEC_PERM_EXPR
- && is_a <gphi *> (SLP_TREE_REPRESENTATIVE (entry)->stmt));
- bool ready = !phi;
- FOR_EACH_VEC_ELT (SLP_TREE_CHILDREN (entry), i, child)
- if (!child)
- {
- gcc_assert (phi);
- ready = true;
- break;
- }
- else if (scc_info.get (child)->on_stack)
- {
- if (!phi)
- {
- ready = false;
- break;
- }
- }
- else
- {
- if (phi)
- {
- ready = true;
- break;
- }
- }
- if (ready)
+ for (int idx = stack.length () - 1; idx >= last_idx; --idx)
{
- vect_schedule_slp_node (vinfo, entry, instance);
- scc_info.get (entry)->on_stack = false;
- stack[idx] = NULL;
- todo--;
- if (phi)
- phis_to_fixup.safe_push (entry);
+ slp_tree entry = stack[idx];
+ if (!entry)
+ continue;
+ bool phi = (SLP_TREE_CODE (entry) != VEC_PERM_EXPR
+ && is_a <gphi *> (SLP_TREE_REPRESENTATIVE (entry)->stmt));
+ bool ready = !phi;
+ FOR_EACH_VEC_ELT (SLP_TREE_CHILDREN (entry), i, child)
+ if (!child)
+ {
+ gcc_assert (phi);
+ ready = true;
+ break;
+ }
+ else if (scc_info.get (child)->on_stack)
+ {
+ if (!phi)
+ {
+ ready = false;
+ break;
+ }
+ }
+ else
+ {
+ if (phi)
+ {
+ ready = true;
+ break;
+ }
+ }
+ if (ready)
+ {
+ vect_schedule_slp_node (vinfo, entry, instance);
+ scc_info.get (entry)->on_stack = false;
+ stack[idx] = NULL;
+ todo--;
+ if (phi)
+ phis_to_fixup.safe_push (entry);
+ }
}
}
+ while (todo != 0);
+
+ /* Pop the SCC. */
+ stack.truncate (last_idx);
}
- while (todo != 0);
/* Now fixup the backedge def of the vectorized PHIs in this SCC. */
slp_tree phi_node;
@@ -5666,9 +5683,6 @@ vect_schedule_scc (vec_info *vinfo, slp_tree node, slp_instance instance,
e, gimple_phi_arg_location (phi, dest_idx));
}
}
-
- /* Pop the SCC. */
- stack.truncate (last_idx);
}
/* Generate vector code for SLP_INSTANCES in the loop/basic block. */