On Mon, May 18, 2026 at 10:01 AM Shivam Gupta <[email protected]> wrote:
>
>
>
> On Mon, May 18, 2026 at 12:49 PM Andrew Pinski
> <[email protected]> wrote:
>>
>> On Mon, May 18, 2026 at 12:11 AM Shivam Gupta <[email protected]> wrote:
>> >
>> > This is a follow-up to the -O1 patch for PR112533.
>> >
>> > At -O2, GCC lowers (~x & 1) == (~y & 1) via inlining into:
>> > _14 = ~x;
>> > _12 = (bool) _14;
>> > _13 = ~y;
>> > _9 = (bool) _13;
>> > _8 = _9 == _12;
>> >
>> > The NOT cancellation (~x == ~y -> x == y) is handled by existing
>> > forwprop rules before this rule fires.
>> >
>> > Add match.pd rule for eq and ne:
>> >
>> > (T)(x) == (T)(y) -> (T)(x ^ y) == 0
>> > (T)(x) != (T)(y) -> (T)(x ^ y) != 0
>> >
>> > Bootstrapped and regression tested on aarch64-linux-gnu with
>> > RUNTESTFLAGS="tree-ssa.exp".
>> >
>> > Changes since v1:
>> > * v2: Generalize the match rule to generic narrowing
>> > integral equality comparisons from bool equality.
>> >
>> > PR tree-optimization/112533
>> >
>> > gcc/ChangeLog:
>> > * match.pd: Add generic narrowing eq/ne to XOR-against-zero
>> > rule for (T)(x) == (T)(y) where precision(T) < precision(x).
>> >
>> > gcc/testsuite/ChangeLog:
>> > * gcc.dg/tree-ssa/narrow-eq-simplify.c: New test covering
>> > bool parity and short truncation cases.
>> >
>> > Signed-off-by: Shivam Gupta <[email protected]>
>> > ---
>> > gcc/match.pd | 16 +++++++
>> > .../gcc.dg/tree-ssa/narrow-eq-simplify.c | 47 +++++++++++++++++++
>> > 2 files changed, 63 insertions(+)
>> > create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/narrow-eq-simplify.c
>> >
>> > diff --git a/gcc/match.pd b/gcc/match.pd
>> > index ff13a07ea94..1fcf28044ee 100644
>> > --- a/gcc/match.pd
>> > +++ b/gcc/match.pd
>> > @@ -2033,6 +2033,22 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
>> > && element_precision (type) <= element_precision (TREE_TYPE (@1)))
>> > (bit_xor (convert @0) (convert @1))))
>> >
>> > +/* For narrowing conversations:
>> > + (T)(X) == (T)(Y) -> (T)(X ^ Y) == 0
>> > + (T)(X) != (T)(Y) -> (T)(X ^ Y) != 0 */
>> > +(for cmp (eq ne)
>> > + (simplify
>> > + (cmp (convert@0 @00) (convert@1 @10))
>> > + (if (INTEGRAL_TYPE_P (type)
>> > + && INTEGRAL_TYPE_P (TREE_TYPE (@00))
>> > + && types_match (@00, @10)
>> > + && types_match (@0, @1)
>> > + && TYPE_PRECISION (TREE_TYPE (@0))
>> > + < TYPE_PRECISION (TREE_TYPE (@00)))
>> > + (with { tree stype = TREE_TYPE (@0); }
>> > + (cmp (convert:stype (bit_xor @00 @10))
>> > + { build_zero_cst (stype); })))))
>>
>> You need to put this with the other ones that are already doing this
>> pattern; otherwise this and the other ones won't work. Also I don't
>> think you need to match the types of @0 and @1 here. Also
>> INTEGRAL_TYPE_P (type) will be true for INTEGRAL_TYPE_P (TREE_TYPE
>> (@00)).
>>
>> Also use itype rather than stype. s here usually stands for signed
>> while i would stand for inner.
>>
>> Thanks,
>> Andrea
>>
>
> Hello,
>
> I browsed the match.pd file but I am not sure where else to put this. Rest
> comments are addressed in v3 of patch.
See line 7738 and after that. It starts with:
/* From fold_sign_changed_comparison and fold_widened_comparison.
FIXME: the lack of symmetry is disturbing. */
Note simple_comparison expands via
(define_operator_list simple_comparison lt le eq ne ge gt)
So with your v2/v3 there are 2 patterns which will match eq/ne and I
don't think they will work together since they are almost exactly the
same.
Thanks,
Andrea
>
> Thanks,
> Shivam
>
>>
>> > +
>> > /* 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/narrow-eq-simplify.c
>> > b/gcc/testsuite/gcc.dg/tree-ssa/narrow-eq-simplify.c
>> > new file mode 100644
>> > index 00000000000..8b03954719a
>> > --- /dev/null
>> > +++ b/gcc/testsuite/gcc.dg/tree-ssa/narrow-eq-simplify.c
>> > @@ -0,0 +1,47 @@
>> > +/* { dg-do compile } */
>> > +/* { dg-options "-O2 -fdump-tree-optimized" } */
>> > +
>> > +/* Verify the fix for PR112533 at -O2.
>> > + (~a & 1) == (~a & 1) is lowered via inlining to
>> > + (bool)(~a) == (bool)(~b), then existing forwprop rules cancel
>> > + the NOTs giving (bool)(a) == (bool)(b), which this rule
>> > + simplifies to (bool)(a ^ b) == 0. */
>> > +
>> > +typedef unsigned int u32;
>> > +
>> > +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);
>> > +}
>> > +
>> > +short
>> > +eq_short_not (int a, int b)
>> > +{
>> > + short sa = ~a;
>> > + short sb = ~b;
>> > + return sa == sb;
>> > +}
>> > +
>> > +short
>> > +ne_short_not (int a, int b)
>> > +{
>> > + short sa = ~a;
>> > + short sb = ~b;
>> > + return sa != sb;
>> > +}
>> > +
>> > +/* Verify the XOR form is produced. */
>> > +/* { dg-final { scan-tree-dump-times "\\\^" 4 "optimized" } } */
>> > --
>> > 2.34.1
>> >