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.

Reply via email to