Hi Richard,

>> I wonder if reviewers could take a look (or a second look) at some of 
>> my outstanding patches.
>> PR middle-end/100810: Penalize IV candidates with undefined value 
>> bases 
>> https://gcc.gnu.org/pipermail/gcc-patches/2021-August/578441.html
>
> I did comment on this one, noting the more general issue.
> My opinion is still that doing heavy lifting in IVOPTs is misplaced.

I wasn't sure whether you'd had the opportunity to give this bug some more
thought.

You're completely right, that it is theoretically possible for GCC to upgrade
its data flow (CCP/VRP) passes to use a finer grained definition of undefined/
uninitialized/indeterminate values; an indeterminate-value numbering pass
if you will.  Under the constraints that the automatic variables are not 
volatile,
and the types don't supporting a trapping values, the compiler could determine
that "undef1 - undef1", or "undef2 ^ undef2" have defined values, but that 
"undef1 - undef2" and "undef3 ^ undef4" remain indeterminate.  Like
traditional value numbering, it may be possible to track "t1 = undef3 ^ undef4",
"t2 = t1 ^ undef4", "t3 = t2 - undef3".   Conceptually, the same applies to 
(floating point) mathematics and its numerous infinities, sometimes "+Inf - 
+Inf"
is known to be zero, provided that it is the exact same infinity (omega) that is
being subtracted.

The two counter arguments for this solution as a fix for PR 100810, is that such
a pass doesn't yet exist, and it still (probably) falls foul of C/C++'s 
undefined
behaviour from use of an uninitialized automatic variable.  From an engineering
perspective, it's a lot of effort to support poorly written code.

Quick question to the language lawyers:

int foo()
{
  int undef;
  return undef ^ undef;
}

int bar()
{
  volatile int undef;
  return undef ^ undef;
}

Do the above functions invoke undefined behaviour?

The approach taken by the proposed patch is that it's the pass/transformation 
that
introduces more undefined behaviour than was present in the original code, that 
is
at fault.  Even if later passes, decided not to take advantage of UB, is there 
any benefit
for replacing an induction variable with a well-defined value (evolution) and 
substituting
it with one that depends upon indefinite values.  I'd argue the correct fix is 
to go the other
way, and attempt to reduce the instances of undefined behaviour.

So transform

        int undef;
        while (cond())
          undef++;
        ...

which invokes UB on each iteration with:

        int undef;
        unsigned int count = 0;
        while (cond())
          count++;
        undef += count;
        ...

which now only invokes UB after the loop.

Consider:
        int undef;
        int result = 0;
        while (cond())
          result ^= undef;
        return result;

where the final value of result may be well-defined if the loop iterates
an even number of times.

        int undef;
        int result = 0;
        while (cond())
          result ^= 1;
        return result ? undef : 0;


Has anyone proposed an alternate fix to PR middle-end/100810?
We can always revert my proposed fix (for this P1 regression), once IV opts
is able to confirm that it is safe to make the substitution that it is 
proposing.


I'm curious to hear your (latest) thoughts.

Thanks again for thinking about this.

Best regards,
Roger
--


Reply via email to