On Sun, May 17, 2026 at 6:26 AM Shivam Gupta <[email protected]> wrote:
>
> This is a follow-up to the -O1 patch for PR112533.
>
> At -O2, GCC lowers (~a & 1) == (~b & 1) via inlining into:
>   _14 = ~a;
>   _12 = (bool) _14;
>   _13 = ~b;
>   _9  = (bool) _13;
>   _8  = _9 == _12;
>
> At -O2, the ne case of (bool)(~x) != (bool)(~y) is already handled
> by CCP1 before forwprop runs.
> However the eq case was missing from match.pd.
>
> Add match.pd rule for the eq form:
>
>   (bool)(~x) == (bool)(~y) -> (bool)(~(x ^ y))
>
> The NOTs cancel on both sides, reducing the equality comparison
> to XNOR.
>
> Bootstrapped and regression tested on aarch64-linux-gnu with
> RUNTESTFLAGS="tree-ssa.exp".
>
> PR tree-optimization/112533
>
> gcc/ChangeLog:
>         * match.pd: Add eq case for (bool)(~x)==(bool)(~y),
>         the ne case was already handled by CCP1.
>
> gcc/testsuite/ChangeLog:
>         * gcc.dg/tree-ssa/bool-eq-simplify-O2.c: New test.
>
> Signed-off-by: Shivam Gupta <[email protected]>
> ---
>  gcc/match.pd                                  |  8 +++++
>  .../gcc.dg/tree-ssa/bool-eq-simplify-O2.c     | 30 +++++++++++++++++++
>  2 files changed, 38 insertions(+)
>  create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/bool-eq-simplify-O2.c
>
> diff --git a/gcc/match.pd b/gcc/match.pd
> index ff13a07ea94..85a8d1cba50 100644
> --- a/gcc/match.pd
> +++ b/gcc/match.pd
> @@ -2033,6 +2033,14 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
>        && element_precision (type) <= element_precision (TREE_TYPE (@1)))
>    (bit_xor (convert @0) (convert @1))))
>
> +/* (bool)(~X) == (bool)(~Y) -> (bool)(~(X ^ Y)).  */
> +(simplify
> + (eq (convert (bit_not @0))
> +     (convert (bit_not @1)))
> + (if (TREE_CODE (type) == BOOLEAN_TYPE
> +      && types_match (@0, @1))
> + (convert (bit_not (bit_xor @0 @1)))))

I think we can do better and be more generic here.
Take:
```
int f(int a, int b)
{
 // a = ~a;
//  b = ~b;
  short  sa = a;
  short  sb = b;
  return sa == sb;
}
```

This should just be:
```
int f(int a, int b)
{
 // a = ~a;
//  b = ~b;
  int t = a ^ b;
  short t1 = t;
  return t1 == 0;
}
```
Which means adding another case to the simplify pattern for `(cmp
(convert@0 @00) (convert?@1 @10))`
I think it only works for eq/ne. Here we already handle outer > inner
precision. We need to add outer < inner.
And the result becomes `(cmp (convert (bit_xor @00 @10)) 0)` and that
will optimize the rest of the way to what you have above.

Thanks,
Andrea

> +
>  /* Convert ~X ^ C to X ^ ~C.  */
>  (simplify
>   (bit_xor (convert? (bit_not @0)) INTEGER_CST@1)
> diff --git a/gcc/testsuite/gcc.dg/tree-ssa/bool-eq-simplify-O2.c 
> b/gcc/testsuite/gcc.dg/tree-ssa/bool-eq-simplify-O2.c
> new file mode 100644
> index 00000000000..7e096828be8
> --- /dev/null
> +++ b/gcc/testsuite/gcc.dg/tree-ssa/bool-eq-simplify-O2.c
> @@ -0,0 +1,30 @@
> +/* { dg-do compile } */
> +/* { dg-options "-O2 -fdump-tree-optimized" } */
> +
> +/* Verify the fix for PR112533 at -O2:
> +   (~a & 1) == (~b & 1) is lowered to (bool)(~a) == (bool)(~b)
> +   which should be simplified to (bool)(~(a ^ b)).  */
> +
> +typedef unsigned int u32;
> +
> +/* Source-level form from the bug report.  */
> +static _Bool
> +is_even (u32 a)
> +{
> +  return a % 2 == 0;
> +}
> +
> +_Bool
> +same_evenness (u32 a, u32 b)
> +{
> +  return is_even (a) == is_even (b);
> +}
> +
> +_Bool
> +diff_evenness (u32 a, u32 b)
> +{
> +  return is_even (a) != is_even (b);
> +}
> +
> +/* Verify the XOR form is produced.  */
> +/* { dg-final { scan-tree-dump-times "\\\^" 2 "optimized" } } */
> --
> 2.34.1
>

Reply via email to