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
>

Reply via email to