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.

> 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

Reply via email to