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.

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