Re: [PATCH v2] match.pd: Simplify XORs of zero_one_valued comparisons

Shivam Gupta <[email protected]>
Newsgroups gmane.comp.gcc.patches
Message-ID <CAHX=PX_CBUeHjf_amwBVd51h5j7zB9vbbRHsZyFaKcjjSpXOOw@mail.gmail.com>
On Thu, Aug 13, 2026 at 5:58 PM Richard Biener
<[email protected]> wrote:
>
> On Sun, May 31, 2026 at 5:33 PM Shivam Gupta <[email protected]> wrote:
> >
> > Recognize XOR patterns involving zero_one_valued operands compared
> > against zero and simplify them to direct equality or inequality tests.
> >
> > Specifically:
> >
> > (a == 0) ^ (b != 0)  -> a == b
> > (a != 0) ^ (b == 0)  -> a == b
> > (a == 0) ^ (b == 0)  -> a != b
> > (a != 0) ^ (b != 0)  -> a != b
> >
> > Also handle a specific case:
> > (a == 0) ^ b -> a == b
> >
> > Extend the simplifications to handle the corresponding boolean
> > equality forms as well:
> > (a == 0) == (b != 0) -> a != b
> > (a != 0) == (b == 0) -> a != b
> > (a == 0) == (b == 0) -> a == b
> > (a != 0) == (b != 0) -> a == b
> >
> > Regression tested on aarch64-linux-gnu.
> >
> > Changes since v1:
> > * v2: Simplify (a == 0) ^ b to a == b.
> >       Handle outer EQ as well as outer NE forms.
> >       Use convert:type to handle differing operand types.
> >
> > gcc/ChangeLog:
> >         * match.pd: Add simplifications for XORs and boolean
> >         comparisons of zero_one_valued comparisons against zero.
> >
> > gcc/testsuite/ChangeLog:
> >         * gcc.dg/tree-ssa/bool-eq-bitxor.c: Update expected number
> >         of optimized XOR forms.
> >         * gcc.dg/tree-ssa/bool-xor-zero-one-valued.c: New test.
> >
> > Signed-off-by: Shivam Gupta <[email protected]>
> > ---
> >  gcc/match.pd                                  | 29 +++++++++++++++
> >  .../gcc.dg/tree-ssa/bool-eq-bitxor.c          |  4 +-
> >  .../tree-ssa/bool-xor-zero-one-valued.c       | 37 +++++++++++++++++++
> >  3 files changed, 67 insertions(+), 3 deletions(-)
> >  create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/bool-xor-zero-one-valued.c
> >
> > diff --git a/gcc/match.pd b/gcc/match.pd
> > index 228bab78428..bed3ca23c6c 100644
> > --- a/gcc/match.pd
> > +++ b/gcc/match.pd
> > @@ -3765,6 +3765,35 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
> >      (if (types_match (type, TREE_TYPE (@0)))
> >       (bit_xor @0 { build_one_cst (type); } ))))))
> >
> > +/* For zero_one_valued operands:
> > +    (a == 0) != b -> a == b.  */
> > +(simplify
> > + (ne (convert:s (eq zero_one_valued_p@0 integer_zerop))
>
> Don't you need :c on the 'ne'?
>
> > +     (convert:s zero_one_valued_p@1))
>
> I'd drop the :s everywhere.
>
> > + (if (types_match (TREE_TYPE (@0), TREE_TYPE (@1)))
> > +  (convert (eq @0 @1))))
>
> Why the outer (convert ...)?
>
> > +
> > +/* For zero_one_valued operands:
> > +     (a op1 0) cmp (b op2 0) -> a icmp b
> > +   where op1 != op2.  */
> > +(for cmp (ne eq)
> > +     icmp (eq ne)
> > + (for op1 (eq ne)
> > +      op2 (ne eq)
> > +  (simplify
> > +   (cmp:c (op1 zero_one_valued_p@0 integer_zerop)
> > +            (op2 zero_one_valued_p@1 integer_zerop))
> > +   (icmp (convert:type @0) (convert:type @1)))))
> > +
> > +/* For zero_one_valued operands:
> > +     (a op 0) cmp (b op 0) -> a cmp b.  */
>
> This coud be merged into the above by appending
> cmp == icmp, op1 == op2 cases, no?
>
> All patterns are problematic for vector types I think,
> zero_one_valued_p currently never fires for those
> but I wonder if we should make this explicit in the
> users rather relying on that never changing?
>

Thank you for the review. I have address all the comments in v3 of patch.

Best regards,
Shivam

> Thanks,
> Richard.
>
> > +(for cmp (ne eq)
> > + (for op (eq ne)
> > +  (simplify
> > +   (cmp:c (op zero_one_valued_p@0 integer_zerop)
> > +            (op zero_one_valued_p@1 integer_zerop))
> > +   (cmp (convert:type @0) (convert:type @1)))))
> > +
> >  /* ((a ^ b) & c) cmp d || a != b --> (0 cmp d || a != b). */
> >  (for cmp (simple_comparison)
> >    (simplify
> > diff --git a/gcc/testsuite/gcc.dg/tree-ssa/bool-eq-bitxor.c b/gcc/testsuite/gcc.dg/tree-ssa/bool-eq-bitxor.c
> > index bc263e80977..e39e82589b6 100644
> > --- a/gcc/testsuite/gcc.dg/tree-ssa/bool-eq-bitxor.c
> > +++ b/gcc/testsuite/gcc.dg/tree-ssa/bool-eq-bitxor.c
> > @@ -36,7 +36,5 @@ xor_ne_ne (u32 a, u32 b)
> >  }
> >
> >  /* Verify all functions canonicalize to xor-mask tests.  */
> > -/* { dg-final { scan-tree-dump-times "a_\[0-9\]+\\(D\\) \\^ b_\[0-9\]+\\(D\\)" 3 "optimized" } } */
> > +/* { dg-final { scan-tree-dump-times "a_\[0-9\]+\\(D\\) \\^ b_\[0-9\]+\\(D\\)" 4 "optimized" } } */
> >
> > -/* xor_eq_ne not optimized yet due to zero_one_valued_p canonicalization.  */
> > -/* { dg-final { scan-tree-dump-times "& 1" 2 "optimized" { xfail *-*-* } } } */
> > diff --git a/gcc/testsuite/gcc.dg/tree-ssa/bool-xor-zero-one-valued.c b/gcc/testsuite/gcc.dg/tree-ssa/bool-xor-zero-one-valued.c
> > new file mode 100644
> > index 00000000000..2bc10db4e70
> > --- /dev/null
> > +++ b/gcc/testsuite/gcc.dg/tree-ssa/bool-xor-zero-one-valued.c
> > @@ -0,0 +1,37 @@
> > +/* { dg-do compile } */
> > +/* { dg-options "-O1 -fdump-tree-optimized" } */
> > +
> > +_Bool
> > +f1 (unsigned a, unsigned b)
> > +{
> > +  if (a != 0 && a != 1) __builtin_unreachable();
> > +  if (b != 0 && b != 1) __builtin_unreachable();
> > +  return (a == 0) ^ (b != 0);
> > +}
> > +
> > +_Bool
> > +f2 (unsigned a, unsigned b)
> > +{
> > +  if (a != 0 && a != 1) __builtin_unreachable();
> > +  if (b != 0 && b != 1) __builtin_unreachable();
> > +  return (a != 0) ^ (b == 0);
> > +}
> > +
> > +_Bool
> > +f3 (unsigned a, unsigned b)
> > +{
> > +  if (a != 0 && a != 1) __builtin_unreachable();
> > +  if (b != 0 && b != 1) __builtin_unreachable();
> > +  return (a == 0) ^ (b == 0);
> > +}
> > +
> > +_Bool
> > +f4 (unsigned a, unsigned b)
> > +{
> > +  if (a != 0 && a != 1) __builtin_unreachable();
> > +  if (b != 0 && b != 1) __builtin_unreachable();
> > +  return (a != 0) ^ (b != 0);
> > +}
> > +
> > +/* { dg-final { scan-tree-dump-times "== 0" 0 "optimized" } } */
> > +/* { dg-final { scan-tree-dump-times "!= 0" 0 "optimized" } } */
> > --
> > 2.34.1
> >
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.