在 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_sizeWhy 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
