在 2025/11/27 21:16, Jakub Jelinek 写道:
On Thu, Nov 27, 2025 at 09:02:20PM +0800, Dongyan Chen wrote:
This patch implements an optimization to transform (a * b) == 0 to
(a == 0) || (b == 0) for signed and unsigned integer.
Shouldn't that just optimize to (a | b) == 0
instead? At least when a and b have the same type.
Thanks for the review. I think that would be incorrect.
(a | b) == 0 implies both a and b are zero (a==0 && b==0),
but (a * b) == 0 implies that at least one of them is zero.
For example, if a=0 and b=1, a * b is 0, but a | b is 1.
gcc/ChangeLog:
* match.pd: New patterns.
Usually one writes in () what the patterns are (and there is just one
in this case).
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)
It should also handle the negation, i.e. also (a * b) != 0 to (a | b) != 0.
And the converts look dangerous to me.
Consider
long long x = 0x7fffffff00000000LL;
int y = 24;
...
return ((int) x) * y == 0;
This is surely true but (x == 0) || (y == 0) is false.
So, you'd need to check that the conversions aren't throwing away any bits.
Plus, blindly comparing TYPE_PRECISION of TREE_TYPE (@2) (which is
INTEGRAL_TYPE_P, so it has meaningful precision) with
the others which aren't verified to be integral at all, could be floating
with completely different meaning of TYPE_PRECISION and issues whether
non-zero floating when converted to integer is converted to 0 or not, or
various other types which might not even have sensible TYPE_PRECISION.
+ (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; }))))))
+
Furthermore, tests for generic tree-ssa transformations don't belong
to target specific tests, they should be somewhere in gcc.dg/ or
gcc.dg/tree-ssa/.
Jakub
I understand the issues you pointed out and the need
for INTEGRAL_TYPE_P checks. I'm working on the fixes now
and will submit a v2 patch once I've verified everything with thorough
testing. It might take a little time to ensure correctness.
Thanks
Dongyan