On 3/17/23 04:31, Richard Biener wrote:
On Thu, Mar 16, 2023 at 4:27 PM Manolis Tsamis <manolis.tsa...@vrull.eu> wrote:
For this C testcase:

void g();
void f(unsigned int *a)
{
   if (++*a == 1)
     g();
}

GCC will currently emit a comparison with 1 by using the value
of *a after the increment. This can be improved by comparing
against 0 and using the value before the increment. As a result
there is a potentially shorter dependancy chain (no need to wait
for the result of +1) and on targets with compare zero instructions
the generated code is one instruction shorter.
The downside is we now need two registers and their lifetime overlaps.

Your patch mixes changing / inverting a parameter (which seems unneeded
for the actual change) with preferring compares against zero.

What's the reason to specifically prefer compares against zero?  On x86
we have add that sets flags, so ++*a == 0 would be preferred, but
for your sequence we'd need a test reg, reg; branch on zero, so we do
not save any instruction.

We do have quite some number of bugreports with regards to making VRPs
life harder when splitting things this way.  It's easier for VRP to handle

   _1 = _2 + 1;
   if (_1 == 1)

than it is

   _1 = _2 + 1;
   if (_2 == 0)

where VRP fails to derive a range for _1 on the _2 == 0 branch.  So besides


Heh?

    _1 = *a_5(D);
    b_6 = _1 + 1;
    if (_1 == 0)
      goto <bb 3>; [INV]
    else
      goto <bb 4>; [INV]

2->3  (T) _1 :  [irange] unsigned int [0, 0] NONZERO 0x0
2->3  (T) b_6 :         [irange] unsigned int [1, 1] NONZERO 0x1
2->4  (F) _1 :  [irange] unsigned int [1, +INF]
2->4  (F) b_6 :         [irange] unsigned int [0, 0][2, +INF]

I will grant you that if the definition of b_6 is in a different basic block that if (_1 == 0) we may not always get a range for it,  but generally this should be OK?  especialyl within a basic block.

I do have a few re-computation cases to improve upon of course :-P

Andrew



Reply via email to