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.
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)
>