https://gcc.gnu.org/g:2c0a9b7fb7902522fb8484342fcc19fd44df53e6

commit r15-7313-g2c0a9b7fb7902522fb8484342fcc19fd44df53e6
Author: Jeff Law <j...@ventanamicro.com>
Date:   Fri Jan 31 16:59:35 2025 -0700

    [committed][PR tree-optimization/114277] Fix missed optimization for 
multiplication against boolean value
    
    Andrew, Raphael and I have all poked at it in various ways over the last 
year
    or so.  I think when Raphael and I first looked at it I sent us down a bit 
of
    rathole.
    
    In particular it's odd that we're using a multiply to implement a select 
and it
    seemed like recognizing the idiom and rewriting into a conditional move was 
the
    right path.  That looked reasonably good for the test, but runs into 
problems
    with min/max detection elsewhere.
    
    I think that initial investigation somewhat polluted our thinking.  The
    regression can be fixed with a fairly simple match.pd pattern.
    
    Essentially we want to handle
    
    x * (x || b) -> x
    x * !(x || b) -> 0
    
    There's simplifications that can be made for "&&" cases, but I haven't seen
    them in practice.  Rather than drop in untested patterns, I'm leaving that 
as a
    future todo.
    
    My original was two match.pd patterns.  Andrew combined them into a single
    pattern.  I've made this conditional on GIMPLE as an earlier version that
    simplified to a conditional move showed that when applied on GENERIC we 
could
    drop an operand with a side effect which is clearly not good.
    
    I've bootstrapped and regression tested this on x86.  I've also tested on 
the
    various embedded targets in my tester.
    
            PR tree-optimization/114277
    gcc/
            * match.pd (a * (a || b) -> a): New pattern.
            (a * !(a || b) -> 0): Likewise.
    
    gcc/testsuite
            * gcc.target/i386/pr114277.c: New test.
            * gcc.target/riscv/pr114277.c: Likewise.
    
            Co-author:  Andrew Pinski <quic_apin...@quicinc.com>

Diff:
---
 gcc/match.pd                              | 17 +++++++++++++++++
 gcc/testsuite/gcc.target/i386/pr114277.c  | 10 ++++++++++
 gcc/testsuite/gcc.target/riscv/pr114277.c |  9 +++++++++
 3 files changed, 36 insertions(+)

diff --git a/gcc/match.pd b/gcc/match.pd
index 6991868fbe29..97e0bafdda4b 100644
--- a/gcc/match.pd
+++ b/gcc/match.pd
@@ -303,6 +303,23 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
  (mult @0 integer_zerop@1)
  @1)
 
+#if GIMPLE
+/* When multiplying a value by a boolean involving the value, we may
+   be able to simplify further.
+     a * ((a || b) != 0) -> a
+     a * ((a || b) == 0) -> 0
+
+   There are also bit-and cases which don't show up in practice yet.
+     a * ((a && b) != 0) -> a * b
+     a * ((a && b) == 0) -> b != 0 ? a : b */
+(for neeq (ne eq)
+ (simplify
+  (mult:c (convert? (neeq (bit_ior:c @0 @1) integer_zerop@2)) @0)
+  (if (neeq == EQ_EXPR)
+   { build_zero_cst (type); }
+   @0)))
+#endif
+
 /* -x == x -> x == 0 */
 (for cmp (eq ne)
  (simplify
diff --git a/gcc/testsuite/gcc.target/i386/pr114277.c 
b/gcc/testsuite/gcc.target/i386/pr114277.c
new file mode 100644
index 000000000000..eb611d26d6af
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr114277.c
@@ -0,0 +1,10 @@
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+
+int a,b;
+void func0(int x) { a=x * (x || b); }
+void func1(int x) { a=x * !(x || b); }
+
+/* { dg-final { scan-assembler-not "or" } } */
+/* { dg-final { scan-assembler-not "cmove" } } */
+
diff --git a/gcc/testsuite/gcc.target/riscv/pr114277.c 
b/gcc/testsuite/gcc.target/riscv/pr114277.c
new file mode 100644
index 000000000000..cc1db19ee4c5
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/pr114277.c
@@ -0,0 +1,9 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -march=rv64gc_zicond -mabi=lp64d" { target rv64 } } */
+/* { dg-options "-O2 -march=rv32gc_zicond -mabi=ilp32" { target rv32 } } */
+/* { dg-skip-if "" { *-*-* } { "-O0" "-O1" "-Os" "-Oz" "-O3" "-Og" } } */
+
+#include "../i386/pr114277.c"
+
+/* { dg-final { scan-assembler-not "czero" } } */
+

Reply via email to