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 {
