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))))
+
+/* 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)