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