在 2025/11/28 12:41, Andrew Pinski 写道:
On Thu, Nov 27, 2025 at 5:04 AM Dongyan Chen
<[email protected]> wrote:
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
Why not optimize_size? We don't have any patterns in match.pd that
depend on optimizing for size currently.
Could this instead be done in isel/expand?
And convert `(a == 0) || (b == 0)` into `(a*b == 0)` on the gimple
level and then doing the opposite in isel/expand and depending on the
cost there?

Also I see you don't handle `a*b != 0` which is `a != 0 && b != 0`.
I posted a limited form of the `!= 0` case before:
https://gcc.gnu.org/pipermail/gcc-patches/2023-September/630651.html
And it was rejected because the a*b  !=/== 0 is simpler than the other form.
This is why I asked about doing this in isel/expand instead.

Thanks,
Andrew

Thanks for the review and explanation. My primary motivation for this patch is 
to address a code generation discrepancy between LLVM and GCC on RISC-V 
(https://godbolt.org/z/5b81vbEEa). In certain scenarios (e.g., at -O3), 
splitting the multiplication into checks proves to be more performant on RISC-V 
hardware, and I plan to address the `!= 0` case as well.

I agree that `match.pd` is not the right place for this if it conflicts with 
the GIMPLE canonical form and lacks cost awareness.

Could you advise on the preferred approach?

Should I implement this transformation in the RISC-V backend (e.g., using 
define_split or generic expansion in `riscv.md`) to avoid affecting other 
targets?Or would you prefer a generic handling in isel / expand that queries 
the target costs?

I'm leaning towards handling it in the RISC-V backend to be safe and 
target-specific, and I'd appreciate your guidance.

Thanks,
Dongyan


Reply via email to