https://gcc.gnu.org/g:a057d429ba49a2ad991a3e5931e5508c3035e9af
commit r17-5642-ga057d429ba49a2ad991a3e5931e5508c3035e9af Author: Richard Biener <[email protected]> Date: Tue Oct 27 16:04:22 2026 +0100 tree-optimization/128187 - vector reductions with single cycle The following fixes the conditional/masked call code generation when vectorizing a reduction forced to a single cycle. The code was not really prepared for operations with not exactly two operands, for the testcase that is FMA. PR tree-optimization/128187 * tree-vect-loop.cc (vect_transform_reduction): Handle both two and three argument masked internal functions. * gcc.dg/vect/vect-pr128187.c: New testcase. Diff: --- gcc/testsuite/gcc.dg/vect/vect-pr128187.c | 13 +++++++++++++ gcc/tree-vect-loop.cc | 28 ++++++++++++++-------------- 2 files changed, 27 insertions(+), 14 deletions(-) diff --git a/gcc/testsuite/gcc.dg/vect/vect-pr128187.c b/gcc/testsuite/gcc.dg/vect/vect-pr128187.c new file mode 100644 index 000000000000..4f258f4eff28 --- /dev/null +++ b/gcc/testsuite/gcc.dg/vect/vect-pr128187.c @@ -0,0 +1,13 @@ +/* { dg-do compile } */ +/* { dg-additional-options "-ffast-math --param vect-partial-vector-usage=2" } */ +/* { dg-additional-options "-march=x86-64-v4" { target { x86_64-*-* i?86-*-* } } } */ + +double f(double *a, int *d, int n, double s) +{ + for (int i = 0; i < n; i++) + { + s = __builtin_fma(a[i], a[i], s); + d[i] = 1; + } + return s; +} diff --git a/gcc/tree-vect-loop.cc b/gcc/tree-vect-loop.cc index 1f22aeeb03d2..8110eb943b95 100644 --- a/gcc/tree-vect-loop.cc +++ b/gcc/tree-vect-loop.cc @@ -8304,7 +8304,8 @@ vect_transform_reduction (loop_vec_info loop_vinfo, for (unsigned i = 0; i < num; ++i) { gimple *new_stmt; - tree vop[3] = { vec_oprnds[0][i], vec_oprnds[1][i], NULL_TREE }; + tree vop[3] = { vec_oprnds[0][i], vec_oprnds[1][i], + op.num_ops >= 3 ? vec_oprnds[2][i] : NULL_TREE }; if (!vop[0] || !vop[1]) { tree reduc_vop = vec_oprnds[reduc_index][i]; @@ -8331,23 +8332,25 @@ vect_transform_reduction (loop_vec_info loop_vinfo, yet. */ gcc_assert (!lane_reducing); + auto_vec<tree> args (op.num_ops + (cond_fn_p ? 0 : 2)); tree mask = vect_get_loop_mask (loop_vinfo, gsi, masks, vec_in_num, vectype_in, mask_index++); - gcall *call; - if (code.is_internal_fn () && cond_fn_p) + if (cond_fn_p) { - gcc_assert (op.num_ops >= 3 - && internal_fn_mask_index (internal_fn (code)) == 0); - vop[2] = vec_oprnds[2][i]; + gcc_assert (internal_fn_mask_index (internal_fn (code)) == 0); mask = prepare_vec_mask (loop_vinfo, TREE_TYPE (mask), mask, vop[0], gsi); - call = gimple_build_call_internal (cond_fn, 4, mask, vop[1], - vop[2], vop[reduc_index]); } - else - call = gimple_build_call_internal (cond_fn, 4, mask, vop[0], - vop[1], vop[reduc_index]); + gcc_assert (internal_fn_mask_index (internal_fn (cond_fn)) == 0); + args.quick_push (mask); + for (unsigned j = cond_fn_p ? 1 : 0; + j < op.num_ops - (cond_fn_p ? 1 : 0); ++j) + args.quick_push (vop[j]); + gcc_assert (internal_fn_else_index (internal_fn (cond_fn)) + == (int) args.length ()); + args.quick_push (vop[reduc_index]); + gcall *call = gimple_build_call_internal_vec (cond_fn, args); new_temp = make_ssa_name (vec_dest, call); gimple_call_set_lhs (call, new_temp); gimple_call_set_nothrow (call, true); @@ -8356,9 +8359,6 @@ vect_transform_reduction (loop_vec_info loop_vinfo, } else { - if (op.num_ops >= 3) - vop[2] = vec_oprnds[2][i]; - if (masked_loop_p && mask_by_cond_expr) { tree mask = vect_get_loop_mask (loop_vinfo, gsi, masks,
