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