> > Apologies if I was unclear or misunderstand, I believe that's exactly what 
> > I am
> > doing right now. I change the !='s' to =='s' and switch their true with 
> > their false
> > edge, from there we can simply find the equality edge by finding the TRUE 
> > edge.
> > If this is an unwelcome change however, it can easily be done without 
> > changing
> > the operator.

> Not modifying the comparisons and just taking it into account during pattern
> matching would be greatly appreciated I think.

> > > "The memcmp() function returns an integer less than, equal to, or greater
> > > than zero if the first n bytes of s1 is found, respectively, to be less
> > > than, to match, or be greater than the first n bytes of s2.
> >
> > > For a nonzero return value, the sign is determined by the sign of the
> > > difference between the first pair of bytes (interpreted as unsigned char)
> > > that differ in s1 and s2."
> >
> > Sorry for my wording, that is not the only thing memcmp gives us, but it
> > does not give us information regarding which fields mismatched. So we cannot
> > deal with (after !='s are converted to =='s) blocks where not all blocks in
> > a chain have the same node as their (eventual, possibly through fallthru's)
> > FALSE edge's destination, is what I was trying to say.

> That shouldn't matter, unless you want to pattern recognize random orders
> of the comparisons (and only verify all bits in the range are compared).
> For <=> it needs to bbe sequential like memcmp will be, i.e. first compare
> bytes with the smallest index, then the one above it etc.

Why does that it not matter that the destination of all the chain blocks'
FALSE edge is the same, if we have:
<bb 1> :
_1 = this_13(D)->a;
_2 = _14(D)->a;
if (_1 == _2)
  goto <bb 2>; [INV]
else
  goto <bb X>; [INV]
<bb 2> :
_3 = this_13(D)->b;
_4 = _14(D)->b;
if (_3 == _4)
  goto <bb 3>; [INV]
else
  goto <bb Y>; [INV]
...
Where X != B, and we replace bb 1 and 2 with, for example, a single bb:

<bb 4> :
_5 = &this_13(D)->a;
_6 = &_14(D)->a;
_7 = __builtin_memcmp(_5, _6, somelen)
if (_1 == _2)
  goto <bb 3>; [INV]
else
  goto <bb Z>; [INV]

How are we going to decide what block Z is, since <bb 1> and <bb 2> go somewhere
different when their respective field was found to not match, but in <bb 4> we
do not know which field caused the mismatch so we can only branch to 1 block.
But using either X or Y for Z will result in an "optimization" that changes the
program's behaviour.

> Also, note some comparisons could be using COMPONENT_REFs, so a->b.c
> kind of form, while others in the same chain could be MEM_REFs [a, 28].
> For what exactly is read one should use e.g. get_inner_reference
> to find if all the loads are from the same (2) bases at the right offsets.
I've been using get_addr_base_and_unit_offset for the COMPONENT_REF's and
for the MEM_REF's, just read the 0th operand into the base and the 1st
into the offset. I have not encountered the MEM_REF's anymore in the
defaulted == operator since moving this optimization to the early passes though.
> Punt for volatiles, punt or be very careful for reversep, etc.
> Note, for both == and != or even <=> some comparisons could have accesses
> using one base on the lhs and the other on rhs and in others have them
> swapped.> It can also handle bitfields, for ==/!= all that matters is that
> all bits are compared and the block starts and ends at a byte boundary.
> For <=> it needs the right ordering and for non-unsigned char accesses
> little endian.
Oh interesting I haven't encountered them being swapped yet so I didn't
really consider it, I'll add it, thanks.

>        Jakub



________________________________
From: Jakub Jelinek <ja...@redhat.com>
Sent: 06 August 2025 14:50:10
To: Thomas de Bock
Cc: Richard Biener; gcc@gcc.gnu.org
Subject: [ext] Re: Help with comparison-merging optimization pass

On Wed, Aug 06, 2025 at 01:32:07PM +0000, Thomas de Bock wrote:
> Apologies if I was unclear or misunderstand, I believe that's exactly what I 
> am
> doing right now. I change the !='s' to =='s' and switch their true with their 
> false
> edge, from there we can simply find the equality edge by finding the TRUE 
> edge.
> If this is an unwelcome change however, it can easily be done without changing
> the operator.

Not modifying the comparisons and just taking it into account during pattern
matching would be greatly appreciated I think.

> > "The memcmp() function returns an integer less than, equal to, or greater
> > than zero if the first n bytes of s1 is found, respectively, to be less
> > than, to match, or be greater than the first n bytes of s2.
>
> > For a nonzero return value, the sign is determined by the sign of the
> > difference between the first pair of bytes (interpreted as unsigned char)
> > that differ in s1 and s2."
>
> Sorry for my wording, that is not the only thing memcmp gives us, but it
> does not give us information regarding which fields mismatched. So we cannot
> deal with (after !='s are converted to =='s) blocks where not all blocks in
> a chain have the same node as their (eventual, possibly through fallthru's)
> FALSE edge's destination, is what I was trying to say.

That shouldn't matter, unless you want to pattern recognize random orders
of the comparisons (and only verify all bits in the range are compared).
For <=> it needs to bbe sequential like memcmp will be, i.e. first compare
bytes with the smallest index, then the one above it etc.

Also, note some comparisons could be using COMPONENT_REFs, so a->b.c
kind of form, while others in the same chain could be MEM_REFs [a, 28].
For what exactly is read one should use e.g. get_inner_reference
to find if all the loads are from the same (2) bases at the right offsets.
Punt for volatiles, punt or be very careful for reversep, etc.
Note, for both == and != or even <=> some comparisons could have accesses
using one base on the lhs and the other on rhs and in others have them
swapped.  It can also handle bitfields, for ==/!= all that matters is that
all bits are compared and the block starts and ends at a byte boundary.
For <=> it needs the right ordering and for non-unsigned char accesses
little endian.

        Jakub


This e-mail and any attachments may contain information that is confidential 
and proprietary and otherwise protected from disclosure. If you are not the 
intended recipient of this e-mail, do not read, duplicate or redistribute it by 
any means. Please immediately delete it and any attachments and notify the 
sender that you have received it by mistake. Unintended recipients are 
prohibited from taking action on the basis of information in this e-mail or any 
attachments. The DRW Companies make no representations that this e-mail or any 
attachments are free of computer viruses or other defects.

Reply via email to