On Tue, Apr 15, 2025 at 8:27 AM Eikansh Gupta <quic_eikag...@quicinc.com> wrote: > > The patterns can be simplified as shown below: > > (a != b) & ((a|b) != 0) -> (a != b) > (a != b) | ((a|b) != 0) -> ((a|b) != 0) > > The similar simplification can be there for (a == b). This patch adds > simplification for above patterns. The forwprop pass was modifying the > patterns to some other form and they were not getting simplified. The > patch also adds simplification for those patterns. > > Bootstrapped and tested on x86_64-linux-gnu with no regressions. > > PR 117760 > > gcc/ChangeLog: > > * match.pd ((a != b) and/or ((a | b) != 0)): New pattern. > ((a == b) and/or (a | b) == 0): New pattern. > ((a == b) & (a | b) == 0): New pattern. > > gcc/testsuite/ChangeLog: > > * gcc.dg/tree-ssa/pr117760-1.c: New test. > * gcc.dg/tree-ssa/pr117760-2.c: New test. > * gcc.dg/tree-ssa/pr117760.c: New test. > > Signed-off-by: Eikansh Gupta <quic_eikag...@quicinc.com> > --- > gcc/match.pd | 58 ++++++++++++++++++++++ > gcc/testsuite/gcc.dg/tree-ssa/pr117760-1.c | 51 +++++++++++++++++++ > gcc/testsuite/gcc.dg/tree-ssa/pr117760-2.c | 37 ++++++++++++++ > gcc/testsuite/gcc.dg/tree-ssa/pr117760.c | 51 +++++++++++++++++++ > 4 files changed, 197 insertions(+) > create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/pr117760-1.c > create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/pr117760-2.c > create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/pr117760.c > > diff --git a/gcc/match.pd b/gcc/match.pd > index 5c679848bdf..291c08d5882 100644 > --- a/gcc/match.pd > +++ b/gcc/match.pd > @@ -4852,6 +4852,64 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT) > && expr_no_side_effects_p (@1)) > @2))) > > +(for cmp (eq ne) > + (for bitop (bit_ior bit_and) > + /* ((a != b) & ((a | b) != 0)) -> (a != b) */ > + /* ((a != b) | ((a | b) != 0)) -> ((a|b) != 0) */ > + /* ((a == b) & (a | b) == 0) -> ((a|b) == 0) */ > + /* ((a == b) | (a | b) == 0) -> (a == b) */ > + (simplify > + (bitop:c > + (cmp@3 @1 @2) > + (cmp@4 (bit_ior @1 @2) integer_zerop)) > + (if ((cmp == EQ_EXPR) ^ (bitop == BIT_IOR_EXPR)) > + @4 @3))
These two-level cases look OK to me, can you split this out to a separate patch please? > + > + /* ((a == b) | (a == 0) | (b == 0)) -> (a == b) */ a = 1, b = 0: 0 | 0 | 1 == 1 != (1 == 0) so this looks wrong? > + /* ((a == b) & ((a == 0) | (b == 0))) -> ((a|b) == 0) */ How often do these three-level cases happen? I wonder if they are not better handled in tree-ssa-reassoc.cc given that would handle an arbitrary number of cases. In fact it might already handle some? > + (simplify > + (bitop:c > + (eq:c@3 @1 @2) > + (bit_ior (eq @1 integer_zerop) (eq @2 integer_zerop))) > + (if (bitop == BIT_IOR_EXPR) > + @3 (eq (bit_ior @1 @2) { build_zero_cst (TREE_TYPE (@1)); })))) > + > + /* (((a == b) & (a == 0)) | (b == 0)) -> ((a|b) == 0) */ > + /* (((a != b) & (a != 0)) | (b != 0)) -> (a != b) */ > + (simplify > + (bit_ior:c (bit_and (cmp @1 integer_zerop) (cmp:c @1 @2)) > + (cmp @2 integer_zerop)) > + (if (cmp == EQ_EXPR) > + (eq (bit_ior @1 @2) { build_zero_cst (TREE_TYPE (@1)); }) > + (ne @1 @2)))) > + > +/* ((a != b) | (a != 0) | (b != 0)) -> ((a|b) != 0) */ > +(simplify > + (bit_ior:c > + (ne @1 @2) > + (bit_ior:c (ne @1 integer_zerop) (ne @2 integer_zerop))) > + (ne (bit_ior @1 @2) { build_zero_cst (TREE_TYPE (@1)); })) > + > +/* ((a != b) & ((a | b) == 0)) -> false */ > +(simplify > + (bit_and:c > + (ne @1 @2) > + (eq (bit_ior @1 @2) integer_zerop)) > + { constant_boolean_node (false, type); }) > + > +/* ((a != b) & ((a == 0) | (b == 0))) -> false */ > +(simplify > + (bit_and:c > + (ne:c@3 @1 @2) > + (bit_ior:c (eq @1 integer_zerop) (eq @2 integer_zerop))) > + { constant_boolean_node (false, type); }) > + > +/* (((a != b) & (a == 0)) | (b == 0)) -> false */ > +(simplify > + (bit_ior:c (bit_and:c (eq @1 integer_zerop) (ne:c @1 @2)) > + (eq @2 integer_zerop)) > + { constant_boolean_node (false, type); }) > + > /* Simplifications of shift and rotates. */ > > (for rotate (lrotate rrotate) > diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr117760-1.c > b/gcc/testsuite/gcc.dg/tree-ssa/pr117760-1.c > new file mode 100644 > index 00000000000..94a05f20ff0 > --- /dev/null > +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr117760-1.c > @@ -0,0 +1,51 @@ > +/* { dg-do compile } */ > +/* { dg-options "-O1 -fdump-tree-optimized-raw" } */ > + > +int f1(int a, int b) > +{ > + if (a == 0 || b == 0) > + return a == b; > + return 0; > +} > + > +int f2(int a, int b) > +{ > + int c = a == 0; > + int d = b == 0; > + int e = a == b; > + return c|d|e; > +} > + > +int f3(int a, int b) > +{ > + int c = a == 0; > + int d = b == 0; > + int e = a == b; > + return (c|d)&e; > +} > + > +int f4(int a, int b) > +{ > + int c = a == 0; > + int d = b == 0; > + int e = a == b; > + return c|d&e; > +} > + > +int f5(int a, int b) > +{ > + int c = (a|b) == 0; > + int e = a == b; > + return c|e; > +} > + > +int f6(int a, int b) > +{ > + int c = (a|b) == 0; > + int e = a == b; > + return c&e; > +} > + > +/* { dg-final { scan-tree-dump-times "eq_expr, " 6 "optimized" } } */ > +/* { dg-final { scan-tree-dump-times "nop_expr, " 6 "optimized" } } */ > +/* { dg-final { scan-tree-dump-times "bit_ior_expr, " 4 "optimized" } } */ > diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr117760-2.c > b/gcc/testsuite/gcc.dg/tree-ssa/pr117760-2.c > new file mode 100644 > index 00000000000..62c147cd6a4 > --- /dev/null > +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr117760-2.c > @@ -0,0 +1,37 @@ > +/* { dg-do compile } */ > +/* { dg-options "-O1 -fdump-tree-optimized-raw" } */ > + > +int f1(int a, int b) > +{ > + int c = a == 0; > + int d = b == 0; > + int e = a != b; > + return (c|d)&e; > +} > + > +int f2(int a, int b) > +{ > + int c = (a|b) == 0; > + int e = a != b; > + return c&e; > +} > + > +int f3(int a, int b) > +{ > + int c = a == 0; > + int d = b == 0; > + int e = a != b; > + return c|d&e; > +} > + > +int f4(int a, int b) > +{ > + if (a == 0 || b == 0) > + return a != b; > + return 0; > +} > + > +/* { dg-final { scan-tree-dump-not "ne_expr," "optimized" } } */ > +/* { dg-final { scan-tree-dump-not "eq_expr," "optimized" } } */ > +/* { dg-final { scan-tree-dump-not "bit_ior_expr," "optimized" } } */ > +/* { dg-final { scan-tree-dump-not "bit_and_expr," "optimized" } } */ > diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr117760.c > b/gcc/testsuite/gcc.dg/tree-ssa/pr117760.c > new file mode 100644 > index 00000000000..c5f5dbd6123 > --- /dev/null > +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr117760.c > @@ -0,0 +1,51 @@ > +/* { dg-do compile } */ > +/* { dg-options "-O1 -fdump-tree-optimized-raw" } */ > + > +int f1(int a, int b) > +{ > + if (a != 0 || b != 0) > + return a != b; > + return 0; > +} > + > +int f2(int a, int b) > +{ > + int c = a != 0; > + int d = b != 0; > + int e = a != b; > + return c|d|e; > +} > + > +int f3(int a, int b) > +{ > + int c = a != 0; > + int d = b != 0; > + int e = a != b; > + return (c|d)&e; > +} > + > +int f4(int a, int b) > +{ > + int c = a != 0; > + int d = b != 0; > + int e = a != b; > + return c|d&e; > +} > + > +int f5(int a, int b) > +{ > + int c = (a|b) != 0; > + int e = a != b; > + return c|e; > +} > + > +int f6(int a, int b) > +{ > + int c = (a|b) != 0; > + int e = a != b; > + return c&e; > +} > + > +/* { dg-final { scan-tree-dump-times "ne_expr, " 6 "optimized" } } */ > +/* { dg-final { scan-tree-dump-times "nop_expr, " 6 "optimized" } } */ > +/* { dg-final { scan-tree-dump-times "bit_ior_expr, " 2 "optimized" } } */ > -- > 2.17.1 >