diff options
author | Richard Biener <rguenther@suse.de> | 2020-10-30 09:57:02 +0100 |
---|---|---|
committer | Richard Biener <rguenther@suse.de> | 2020-10-30 10:46:08 +0100 |
commit | c0bfd9672e19caf08e45afeb4277f848488ced2b (patch) | |
tree | 642a29ab93daa78a76c13bc16834256c655c653c /gcc/tree-vect-slp.c | |
parent | 7de23b8c536397117bbea04a722fa1b86564dd7c (diff) | |
download | gcc-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.c | 162 |
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. */ |