On Tue, Aug 25, 2026 at 10:59 PM <[email protected]> wrote:
>
> From: Kyrylo Tkachov <[email protected]>
>
> The PR 127039 fix requires a generated constant reduction to fold for
> the operations that have an inverse reduction-pair rule.  It leaves
> FMAX and FMIN unchanged because they cannot form that cycle.
>
> The cycle is not the only concern.  When the constant reduction does
> not fold, the rule changes one runtime reduction:
>
>   r = .REDUC_FMAX (.FMAX (v, C));
>
> into two:
>
>   r1 = .REDUC_FMAX (v);
>   r2 = .REDUC_FMAX (C);
>   r = .FMAX (r1, r2);
>
> Require the constant reduction to fold for FMAX and FMIN too.  All
> eight reductions can then share one rule.  The transform is rejected
> when it would introduce a second runtime reduction.
>
> Bootstrapped and tested on aarch64-unknown-linux-gnu.
> Ok for trunk?
> Thanks,
> Kyrill
>
> gcc/ChangeLog:
>
>         PR tree-optimization/127039
>         * match.pd (REDUC (@0 op VECTOR_CST)): Require FMAX and FMIN
>         constant reductions to simplify.
>
> gcc/testsuite/ChangeLog:
>
>         PR tree-optimization/127039
>         * gcc.target/aarch64/vec-reduc-fmax-const-1.c: New test.

Ok

>
> Signed-off-by: Kyrylo Tkachov <[email protected]>
> ---
>  gcc/match.pd                                  | 17 ++---
>  .../aarch64/vec-reduc-fmax-const-1.c          | 62 +++++++++++++++++++
>  2 files changed, 67 insertions(+), 12 deletions(-)
>  create mode 100644 gcc/testsuite/gcc.target/aarch64/vec-reduc-fmax-const-1.c
>
> diff --git a/gcc/match.pd b/gcc/match.pd
> index 283e2313db6..c7841cab459 100644
> --- a/gcc/match.pd
> +++ b/gcc/match.pd
> @@ -12243,21 +12243,14 @@ and,
>            && !HONOR_SIGNED_ZEROS (type))
>         { elt; }))))
>
> -/* 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)
> +/* Fold REDUC (@0 op VECTOR_CST) as REDUC (@0) op REDUC (VECTOR_CST)
> +   when the constant reduction simplifies to a scalar operand.  */
> +(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)
>    (simplify (reduc (op @0 VECTOR_CST@1))
>      (op (reduc:type @0) (reduc!:type @1))))
>
> -/* 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))))
> -
>  /* Fold REDUC_PLUS (@0) +- REDUC_PLUS (@1) as REDUC_PLUS (@0 +- @1).  This
>     trades one lane-crossing reduction for one elementwise operation.  The
>     elementwise operation is done in the unsigned type because the reduction
> diff --git a/gcc/testsuite/gcc.target/aarch64/vec-reduc-fmax-const-1.c 
> b/gcc/testsuite/gcc.target/aarch64/vec-reduc-fmax-const-1.c
> new file mode 100644
> index 00000000000..42f5087db44
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/aarch64/vec-reduc-fmax-const-1.c
> @@ -0,0 +1,62 @@
> +/* { dg-do compile } */
> +/* { dg-options "-O2 -fgimple -fdump-tree-forwprop1" } */
> +/* { dg-additional-options "-march=armv8.2-a+sve -msve-vector-bits=scalable" 
> } */
> +
> +typedef float v4sf __attribute__ ((vector_size (16)));
> +
> +float __GIMPLE ()
> +reduc_fmax (v4sf x)
> +{
> +  v4sf c;
> +  v4sf v;
> +  float res;
> +
> +  c = _Literal (v4sf) { 1.0f, 1.0f, 1.0f, 1.0f };
> +  v = .FMAX (x, c);
> +  res = .REDUC_FMAX (v);
> +  return res;
> +}
> +
> +float __GIMPLE ()
> +reduc_fmin (v4sf x)
> +{
> +  v4sf c;
> +  v4sf v;
> +  float res;
> +
> +  c = _Literal (v4sf) { 1.0f, 1.0f, 1.0f, 1.0f };
> +  v = .FMIN (x, c);
> +  res = .REDUC_FMIN (v);
> +  return res;
> +}
> +
> +float __GIMPLE ()
> +reduc_fmax_scalable (__SVFloat32_t x)
> +{
> +  __SVFloat32_t c;
> +  __SVFloat32_t v;
> +  float res;
> +
> +  c = _Literal (__SVFloat32_t) 0;
> +  v = .FMAX (x, c);
> +  res = .REDUC_FMAX (v);
> +  return res;
> +}
> +
> +float __GIMPLE ()
> +reduc_fmin_scalable (__SVFloat32_t x)
> +{
> +  __SVFloat32_t c;
> +  __SVFloat32_t v;
> +  float res;
> +
> +  c = _Literal (__SVFloat32_t) 0;
> +  v = .FMIN (x, c);
> +  res = .REDUC_FMIN (v);
> +  return res;
> +}
> +
> +/* Do not introduce a second reduction when the constant reduction cannot
> +   fold.  */
> +/* { dg-final { scan-tree-dump-times {\.REDUC_FMAX} 2 "forwprop1" } } */
> +/* { dg-final { scan-tree-dump-times {\.REDUC_FMIN} 2 "forwprop1" } } */
> --
> 2.50.1 (Apple Git-155)
>

Reply via email to