https://gcc.gnu.org/bugzilla/show_bug.cgi?id=126551
--- Comment #4 from GCC Commits <cvs-commit at gcc dot gnu.org> --- The master branch has been updated by Tamar Christina <[email protected]>: https://gcc.gnu.org/g:8c46d2fae76b2ddaafec2f14121469f7dd67f745 commit r17-5332-g8c46d2fae76b2ddaafec2f14121469f7dd67f745 Author: Tamar Christina <[email protected]> Date: Mon Oct 19 12:52:32 2026 +0100 vect: don't create unsupported reduction recurrence in ifcvt [PR126551] The example float f (const float *x, int n) { float acc = 0; for (int i = 0; i < n; ++i) { float d = x[i]; if (d < 0) acc += d; acc += d * 3.0f; } return acc; } compiled at -Ofast fails to vectorize with note: vect_is_simple_use: operand acc_17 = PHI <acc_13(8), 0.0(18)>, type of def: unknown missed: Unsupported pattern. missed: not vectorized: unsupported use in stmt. due to note: Analyze phi: acc_17 = PHI <acc_13(8), 0.0(18)> missed: reduction used in loop. missed: Unknown def-use cycle pattern. This is happening because before if-convert we have the following reduction: acc_1 = PHI <acc_0, acc_2> if (cond) acc_2 = acc_1 + value; and so the reduction value is updated only on some paths. if-cvt changes this into acc_3 = cond ? acc_2 : acc_1; but since acc_2 itself is acc_1 + value this is actually acc_3 = cond ? acc_1 + value : acc_1; This is semantically sound but hides the recurrence from the vectorizer. In principle if-cvt creates acc_1 = PHI <0, acc_3> acc_2 = acc_1 + value acc_3 = cond ? acc_2 : acc_1 so the loop carried value acc_3 is inside the COND_EXPR and acc_1 is used twice inside the same reduction. The update chain is PHI -> PLUS -> COND_EXPR -> PHI \--------------^ which is a problem since reduction analysis needs a single statement that updates the loop carried accumulator. Note that if the user supplied this form manually, if-cvt rewrites it to one of two forms that the vectorizer can handle. It either rewrites it to COND_ADD and this removing the PLUS + COND_EXPR or it floats out the cond_expr. This patch does the latter, as picking COND_ADD here is premature, it forces selection of a masked target even though the vectorizer these days can convert the cond expr to a masked operation on its own based on costing. Essentially we change cond ? base + addend : base or cond ? base : base + addend into base + (cond ? addend : 0) or base + (cond ? 0 : addend) -0.0 is used for FP when signed zeros are being honored. this turns the recurrence into a form the vectorizer can handle. gcc/ChangeLog: PR tree-optimization/126551 * tree-if-conv.cc (is_cond_scalar_reduction): Recognize intermediate conditional additions in reduction update chains. (convert_scalar_cond_reduction): Keep the addition unconditional for intermediate reduction. (predicate_scalar_phi): Pass the intermediate flag. gcc/testsuite/ChangeLog: PR tree-optimization/126551 * gcc.dg/vect/cond-reduc-ifcvt-1.c: New test. * gcc.dg/vect/cond-reduc-ifcvt-2.c: Likewise. * gcc.dg/vect/cond-reduc-ifcvt-3.c: Likewise. * gcc.dg/vect/cond-reduc-ifcvt-4.c: Likewise. * gcc.dg/vect/cond-reduc-ifcvt-5.c: Likewise. * gcc.dg/vect/cond-reduc-ifcvt-6.c: Likewise. * gcc.dg/vect/vect-switch-ifcvt-2.c: Expect one loop to be vectorized. * gcc.target/aarch64/sve/cond-reduc-ifcvt-trap.c: New test.
