The previous fix restricted external vector builds to defs from
the same basic-block.  That turns out too restrictive so we have
to mitigate the original issue in a different way which is
restricting it to the original case where all defs are in the
same basic-block.

Bootstrapped and tested on x86_64-unknown-linux-gnu, pushed.

        PR tree-optimization/116352
        * tree-vect-slp.cc (vect_build_slp_tree_2): When compressing
        operands from a two-operator node make sure the resulting
        operation does not mix defs from different basic-blocks.
---
 gcc/tree-vect-slp.cc | 11 ++++++++++-
 1 file changed, 10 insertions(+), 1 deletion(-)

diff --git a/gcc/tree-vect-slp.cc b/gcc/tree-vect-slp.cc
index 6d5824a97bf..f7c51b6cf68 100644
--- a/gcc/tree-vect-slp.cc
+++ b/gcc/tree-vect-slp.cc
@@ -2619,13 +2619,14 @@ out:
       if (oprnds_info[0]->def_stmts[0]
          && is_a<gassign *> (oprnds_info[0]->def_stmts[0]->stmt))
        code = gimple_assign_rhs_code (oprnds_info[0]->def_stmts[0]->stmt);
+      basic_block bb = nullptr;
 
       for (unsigned j = 0; j < group_size; ++j)
        {
          FOR_EACH_VEC_ELT (oprnds_info, i, oprnd_info)
            {
              stmt_vec_info stmt_info = oprnd_info->def_stmts[j];
-             if (!stmt_info || !stmt_info->stmt
+             if (!stmt_info
                  || !is_a<gassign *> (stmt_info->stmt)
                  || gimple_assign_rhs_code (stmt_info->stmt) != code
                  || skip_args[i])
@@ -2633,6 +2634,14 @@ out:
                  success = false;
                  break;
                }
+             /* Avoid mixing lanes with defs in different basic-blocks.  */
+             if (!bb)
+               bb = gimple_bb (vect_orig_stmt (stmt_info)->stmt);
+             else if (gimple_bb (vect_orig_stmt (stmt_info)->stmt) != bb)
+               {
+                 success = false;
+                 break;
+               }
 
              bool exists;
              unsigned &stmt_idx
-- 
2.43.0

Reply via email to