This patch implements an optimization to transform (a * b) == 0 to
(a == 0) || (b == 0) for signed and unsigned integer.

gcc/ChangeLog:

        * match.pd: New patterns.

gcc/testsuite/ChangeLog:

        * gcc.target/riscv/mul-eq-zero-1.c: New test.
        * gcc.target/riscv/mul-eq-zero-2.c: New test.
---
 gcc/match.pd                                   | 15 +++++++++++++++
 gcc/testsuite/gcc.target/riscv/mul-eq-zero-1.c | 17 +++++++++++++++++
 gcc/testsuite/gcc.target/riscv/mul-eq-zero-2.c | 12 ++++++++++++
 3 files changed, 44 insertions(+)
 create mode 100644 gcc/testsuite/gcc.target/riscv/mul-eq-zero-1.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/mul-eq-zero-2.c

diff --git a/gcc/match.pd b/gcc/match.pd
index 05c8b59eb9e..0ed297f90f9 100644
--- a/gcc/match.pd
+++ b/gcc/match.pd
@@ -320,6 +320,21 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
    @0)))
 #endif
 
+/* Fold (a * b == 0) to (a == 0) || (b == 0) for signed and unsigned integer */
+(simplify
+ (eq (mult (convert?@2 @0) (convert?@3 @1)) integer_zerop)
+ (if (!optimize_size
+      && INTEGRAL_TYPE_P (TREE_TYPE (@2)))
+  (with {
+    tree zero0 = build_zero_cst (TREE_TYPE (@0));
+    tree zero1 = build_zero_cst (TREE_TYPE (@1));
+   }
+   (if (TYPE_OVERFLOW_UNDEFINED (TREE_TYPE (@2))
+        || (TYPE_PRECISION (TREE_TYPE (@2)) >= TYPE_PRECISION (TREE_TYPE (@0))
+                                             + TYPE_PRECISION (TREE_TYPE 
(@1))))
+    (bit_ior (eq @0 { zero0; }) 
+             (eq @1 { zero1; }))))))
+           
 /* -x == x -> x == 0 */
 (for cmp (eq ne)
  (simplify
diff --git a/gcc/testsuite/gcc.target/riscv/mul-eq-zero-1.c 
b/gcc/testsuite/gcc.target/riscv/mul-eq-zero-1.c
new file mode 100644
index 00000000000..4af602bfa9e
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/mul-eq-zero-1.c
@@ -0,0 +1,17 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv64gc -mabi=lp64" { target { rv64} } } */
+/* { dg-skip-if "" { *-*-* } { "-Oz" } } */
+
+#include <stdbool.h>
+#include <stdint.h>
+
+bool foo(int32_t a, int32_t b) {
+    return ((int32_t)a * b) == 0;
+}
+
+bool foo2(uint8_t a, uint8_t b) {
+    return ((uint32_t)a * b) == 0;
+}
+
+/* { dg-final { scan-assembler-times {seqz} } } */
+/* { dg-final { scan-assembler-not {mulw} } } */
diff --git a/gcc/testsuite/gcc.target/riscv/mul-eq-zero-2.c 
b/gcc/testsuite/gcc.target/riscv/mul-eq-zero-2.c
new file mode 100644
index 00000000000..e8a406e6519
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/mul-eq-zero-2.c
@@ -0,0 +1,12 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv64gc -mabi=lp64" { target { rv64} } } */
+/* { dg-skip-if "" { *-*-* } { "-Oz" } } */
+
+#include <stdbool.h>
+#include <stdint.h>
+
+bool foo(uint32_t a, uint32_t b) {
+    return ((uint32_t)a * b) == 0;
+}
+
+/* { dg-final { scan-assembler-times {mulw} } } */
-- 
2.43.0

Reply via email to