https://gcc.gnu.org/g:58b657a872ae7bc9815a9c60398cd3bec0626b81

commit r17-4782-g58b657a872ae7bc9815a9c60398cd3bec0626b81
Author: Richard Biener <[email protected]>
Date:   Wed Sep 30 11:03:28 2026 +0200

    tree-optimization/127670 - vectorizable_shift and live stmts
    
    vectorizable_shift inspects scalar stmts to decide whether to
    use a shift by scalar.  This is fragile and not optimal.  For
    the testcase the shift argument is live and since only part
    of the SLP node is part of the computed scalar coverage not
    all scalar shift arguments are replaced during code generation.
    As we re-analyze we get into conflicting results and ICE.
    The following does a first step towards fixing up vectorizable_shift
    by computing uniformity of the shift argument from the SLP node
    for the shift argument, using its scalar defs (which are never
    replaced).
    
            PR tree-optimization/127670
            * tree-vect-stmts.cc (vectorizable_shift): Analyze defs
            of the shift operand SLP node instead of the scalar stmt
            operands for uniformity.
    
            * gcc.dg/vect/bb-slp-pr127670.c: New testcase.

Diff:
---
 gcc/testsuite/gcc.dg/vect/bb-slp-pr127670.c | 13 ++++++++++++
 gcc/tree-vect-stmts.cc                      | 32 ++++++++++++++---------------
 2 files changed, 28 insertions(+), 17 deletions(-)

diff --git a/gcc/testsuite/gcc.dg/vect/bb-slp-pr127670.c 
b/gcc/testsuite/gcc.dg/vect/bb-slp-pr127670.c
new file mode 100644
index 000000000000..983464296ec1
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/vect/bb-slp-pr127670.c
@@ -0,0 +1,13 @@
+/* { dg-do compile } */
+
+int x[4];
+int j[4];
+
+void
+foo (void)
+{
+  x[0] = (x[0] << j[0]) + j[0];
+  x[1] = (x[0] << j[0]) + j[1];
+  x[2] = (x[2] << j[0]) + j[2];
+  x[3] = (x[3] << j[0]) + j[3];
+}
diff --git a/gcc/tree-vect-stmts.cc b/gcc/tree-vect-stmts.cc
index 244f319d0e41..18d0dd8ff3a3 100644
--- a/gcc/tree-vect-stmts.cc
+++ b/gcc/tree-vect-stmts.cc
@@ -6268,20 +6268,6 @@ vectorizable_shift (vec_info *vinfo,
           || dt[1] == vect_external_def
           || dt[1] == vect_internal_def)
     {
-      /* In SLP, need to check whether the shift count is the same,
-        in loops if it is a constant or invariant, it is always
-        a scalar shift.  */
-      vec<stmt_vec_info> stmts = SLP_TREE_SCALAR_STMTS (slp_node);
-      stmt_vec_info slpstmt_info;
-
-      FOR_EACH_VEC_ELT (stmts, k, slpstmt_info)
-       if (slpstmt_info)
-         {
-           gassign *slpstmt = as_a <gassign *> (slpstmt_info->stmt);
-           if (!operand_equal_p (gimple_assign_rhs2 (slpstmt), op1, 0))
-             scalar_shift_arg = false;
-         }
-
       /* For internal SLP defs we have to make sure we see scalar stmts
         for all vector elements.
         ???  For different vectors we could resort to a different
@@ -6289,14 +6275,26 @@ vectorizable_shift (vec_info *vinfo,
         takes the first.  */
       if (dt[1] == vect_internal_def
          && maybe_ne (nunits_out * vect_get_num_copies (vinfo, slp_node),
-                      stmts.length ()))
+                      SLP_TREE_LANES (slp_node)))
        scalar_shift_arg = false;
-
       /* If the shift amount is computed by a pattern stmt we cannot
          use the scalar amount directly thus give up and use a vector
         shift.  */
-      if (op1_def_stmt_info && is_pattern_stmt_p (op1_def_stmt_info))
+      else if (op1_def_stmt_info && is_pattern_stmt_p (op1_def_stmt_info))
        scalar_shift_arg = false;
+      else
+       {
+         tree l0 = vect_get_slp_scalar_def (slp_op1, 0);
+         if (!l0)
+           scalar_shift_arg = false;
+         else
+           for (k = 1; k < SLP_TREE_LANES (slp_node); ++k)
+             if (!operand_equal_p (vect_get_slp_scalar_def (slp_op1, k), l0))
+               {
+                 scalar_shift_arg = false;
+                 break;
+               }
+       }
     }
   else
     {

Reply via email to