On Mon, Aug 24, 2026 at 7:50 PM Andrea Pinski
<[email protected]> wrote:
>
> On Mon, Aug 24, 2026 at 10:20 AM <[email protected]> wrote:
> >
> > From: Kyrylo Tkachov <[email protected]>
> >
> > The reduction-of-a-constant rule can change
> >
> > REDUC (V op C)
> >
> > into
> >
> > REDUC (V) op REDUC (C).
> >
> > The reduction-pair rule can then combine the result back into the original
> > form. For a scalable vector, REDUC (C) might not fold because the number of
> > lanes is not constant. The two rules then alternate during forwprop and
> > keep
> > adding dead statements until the compiler exhausts memory.
> >
> > Split the six reductions that have an inverse pair rule from FMAX and FMIN,
> > which do not. Mark the constant reduction in the first group with `!`. The
> > first transformation now succeeds only when REDUC (C) simplifies to a scalar
> > operand. The result cannot match the inverse reduction-pair rule. Keep the
> > FMAX and FMIN transformation unchanged.
> >
> > Bootstrapped and tested on aarch64-unknown-linux-gnu and confirmed with
> > a riscv cross that the OOM does not happen.
> > Ok for trunk?
> > Thanks,
> > Kyrill
> >
> > gcc/ChangeLog:
> >
> > PR tree-optimization/127039
> > * match.pd (REDUC (@0 op VECTOR_CST)): Require the constant
> > reduction
> > to simplify.
> >
> > gcc/testsuite/ChangeLog:
> >
> > PR tree-optimization/127039
> > * gcc.dg/pr127039.c: New test.
> >
> > Signed-off-by: Kyrylo Tkachov <[email protected]>
> > ---
> > gcc/match.pd | 16 ++++++++++++----
> > gcc/testsuite/gcc.dg/pr127039.c | 23 +++++++++++++++++++++++
> > 2 files changed, 35 insertions(+), 4 deletions(-)
> > create mode 100644 gcc/testsuite/gcc.dg/pr127039.c
> >
> > diff --git a/gcc/match.pd b/gcc/match.pd
> > index f8d9936e52a..d483d7b4901 100644
> > --- a/gcc/match.pd
> > +++ b/gcc/match.pd
> > @@ -14059,10 +14059,18 @@ and,
> > && !HONOR_SIGNED_ZEROS (type))
> > { elt; }))))
> >
> > -/* Fold REDUC (@0 op VECTOR_CST) as REDUC (@0) op REDUC (VECTOR_CST). */
> > -(for reduc (IFN_REDUC_PLUS IFN_REDUC_MAX IFN_REDUC_MIN IFN_REDUC_FMAX
> > - IFN_REDUC_FMIN IFN_REDUC_AND IFN_REDUC_IOR IFN_REDUC_XOR)
> > - op (plus max min IFN_FMAX IFN_FMIN bit_and bit_ior bit_xor)
> > +/* Fold REDUC (@0 op VECTOR_CST) as REDUC (@0) op REDUC (VECTOR_CST).
> > + For operators with an inverse pair rule, require the constant reduction
> > + to simplify to a scalar operand. */
> > +(for reduc (IFN_REDUC_PLUS IFN_REDUC_MAX IFN_REDUC_MIN IFN_REDUC_AND
> > + IFN_REDUC_IOR IFN_REDUC_XOR)
> > + op (plus max min bit_and bit_ior bit_xor)
> > + (simplify (reduc (op @0 VECTOR_CST@1))
> > + (op (reduc:type @0) (reduc!:type @1))))
>
> Ok.
Note I think all ops should require a constant folded constant
argument operation,
it's definitely more costly to do two actual runtime reductions compared to one.
So ... why exempt min/max?
> For a follow up patch, we can add a constant folding for an uniform
> constant vector (or even a duplicate_expr) for the following
> reductions:
> IFN_REDUC_MAX, IFN_REDUC_MIN, IFN_REDUC_AND and IFN_REDUC_IOR.
>
> I can't remember if we require the number of elements in a variable
> length vector to be always even or not; but if we require it being
> even, we can handle IFN_REDUC_XOR also.
>
>
> > +
> > +/* FMAX and FMIN do not have an inverse pair rule. */
> > +(for reduc (IFN_REDUC_FMAX IFN_REDUC_FMIN)
> > + op (IFN_FMAX IFN_FMIN)
> > (simplify (reduc (op @0 VECTOR_CST@1))
> > (op (reduc:type @0) (reduc:type @1))))
> >
> > diff --git a/gcc/testsuite/gcc.dg/pr127039.c
> > b/gcc/testsuite/gcc.dg/pr127039.c
> > new file mode 100644
> > index 00000000000..fb3672ce55e
> > --- /dev/null
> > +++ b/gcc/testsuite/gcc.dg/pr127039.c
> > @@ -0,0 +1,23 @@
> > +/* PR tree-optimization/127039 */
> > +/* { dg-do compile { target { aarch64*-*-* || riscv64*-*-* } } } */
> > +/* { dg-options "-O3 -fdump-tree-vect-details" } */
> > +/* { dg-additional-options "-march=armv8.2-a+sve
> > --param=vect-partial-vector-usage=0" { target aarch64*-*-* } } */
> > +/* { dg-additional-options "-march=rv64im_zve64f -mabi=lp64" { target
> > riscv64*-*-* } } */
> > +/* { dg-timeout 10 } */
> > +
> > +char a;
> > +int b;
> > +unsigned c;
> > +short d;
> > +
> > +void
> > +foo (void)
> > +{
> > + for (short f = 0; f < c; f += 3)
> > + {
> > + a ^= d;
> > + b = b < 0 ? b : 0;
> > + }
> > +}
> > +
> > +/* { dg-final { scan-tree-dump "LOOP VECTORIZED" "vect" } } */
> > --
> > 2.50.1 (Apple Git-155)
> >