We are detecting a cycle as double reduction where the inner loop cycle has extra out-of-loop uses. This clashes at least with assumptions from the SLP discovery code which says the cycle isn't reachable from another SLP instance. It also was not intended to support this case, in fact with GCC 14 we seem to generate wrong code here.
Bootstrapped on x86_64-unknown-linux-gnu, testing in progress. PR tree-optimization/119057 * tree-vect-loop.cc (check_reduction_path): Add argument specifying whether we're analyzing the inner loop of a double reduction. Do not allow extra uses outside of the double reduction cycle in this case. (vect_is_simple_reduction): Adjust. * gcc.dg/vect/pr119057.c: New testcase. --- gcc/testsuite/gcc.dg/vect/pr119057.c | 19 +++++++++++++++++++ gcc/tree-vect-loop.cc | 12 +++++++----- 2 files changed, 26 insertions(+), 5 deletions(-) create mode 100644 gcc/testsuite/gcc.dg/vect/pr119057.c diff --git a/gcc/testsuite/gcc.dg/vect/pr119057.c b/gcc/testsuite/gcc.dg/vect/pr119057.c new file mode 100644 index 00000000000..582bb8ff86c --- /dev/null +++ b/gcc/testsuite/gcc.dg/vect/pr119057.c @@ -0,0 +1,19 @@ +/* { dg-do compile } */ +/* { dg-additional-options "-fno-tree-vrp -fno-tree-forwprop" } */ + +int a, b, c, d; +unsigned e; +static void f(void) +{ + unsigned h; + for (d = 0; d < 2; d++) + b |= e; + h = b; + c |= h; +} +int main() +{ + for (; a; a++) + f(); + return 0; +} diff --git a/gcc/tree-vect-loop.cc b/gcc/tree-vect-loop.cc index b279ebe2793..dc15b955aad 100644 --- a/gcc/tree-vect-loop.cc +++ b/gcc/tree-vect-loop.cc @@ -4044,7 +4044,8 @@ needs_fold_left_reduction_p (tree type, code_helper code) static bool check_reduction_path (dump_user_location_t loc, loop_p loop, gphi *phi, tree loop_arg, code_helper *code, - vec<std::pair<ssa_op_iter, use_operand_p> > &path) + vec<std::pair<ssa_op_iter, use_operand_p> > &path, + bool inner_loop_of_double_reduc) { auto_bitmap visited; tree lookfor = PHI_RESULT (phi); @@ -4181,7 +4182,8 @@ pop: break; } /* Check there's only a single stmt the op is used on. For the - not value-changing tail and the last stmt allow out-of-loop uses. + not value-changing tail and the last stmt allow out-of-loop uses, + but not when this is the inner loop of a double reduction. ??? We could relax this and handle arbitrary live stmts by forcing a scalar epilogue for example. */ imm_use_iterator imm_iter; @@ -4216,7 +4218,7 @@ pop: } } else if (!is_gimple_debug (op_use_stmt) - && (*code != ERROR_MARK + && ((*code != ERROR_MARK || inner_loop_of_double_reduc) || flow_bb_inside_loop_p (loop, gimple_bb (op_use_stmt)))) FOR_EACH_IMM_USE_ON_STMT (use_p, imm_iter) @@ -4238,7 +4240,7 @@ check_reduction_path (dump_user_location_t loc, loop_p loop, gphi *phi, { auto_vec<std::pair<ssa_op_iter, use_operand_p> > path; code_helper code_; - return (check_reduction_path (loc, loop, phi, loop_arg, &code_, path) + return (check_reduction_path (loc, loop, phi, loop_arg, &code_, path, false) && code_ == code); } @@ -4449,7 +4451,7 @@ vect_is_simple_reduction (loop_vec_info loop_info, stmt_vec_info phi_info, auto_vec<std::pair<ssa_op_iter, use_operand_p> > path; code_helper code; if (check_reduction_path (vect_location, loop, phi, latch_def, &code, - path)) + path, inner_loop_of_double_reduc)) { STMT_VINFO_REDUC_CODE (phi_info) = code; if (code == COND_EXPR && !nested_in_vect_loop) -- 2.43.0