https://gcc.gnu.org/bugzilla/show_bug.cgi?id=78655

--- Comment #16 from Andrew Macleod <amacleod at redhat dot com> ---
(In reply to rguent...@suse.de from comment #15)
> On Wed, 16 Nov 2022, amacleod at redhat dot com wrote:
> 
> > https://gcc.gnu.org/bugzilla/show_bug.cgi?id=78655
> > 
> > Andrew Macleod <amacleod at redhat dot com> changed:
> > 
> >            What    |Removed                     |Added
> > ----------------------------------------------------------------------------
> >              Status|NEW                         |ASSIGNED
> >            Assignee|unassigned at gcc dot gnu.org      |amacleod at redhat 
> > dot com
> > 
> > --- Comment #14 from Andrew Macleod <amacleod at redhat dot com> ---
> > Created attachment 53910 [details]
> >   --> https://gcc.gnu.org/bugzilla/attachment.cgi?id=53910&action=edit
> > patch to fix the problem
> > 
> > This patch fixes the PR, but exposes issues in other passes.  They introduce
> > undefined behaviour by hoisting POINTER_PLUS expressions into blocks in 
> > which
> > the operand is not known to be non-null.   (See PR 107709)
> > Until this can be audited fully, we put this patch on hold.
> 
> In fact the patch doesnt 'exploit the fact that the result of
> pointer addition can not be nullptr' but it exploits that if
> ptr + CST is performed then 'ptr' cannot be nullptr(?)
> 

GCC already exploits the title of the PR, when the code represents it with that
situation. 
The only case we don't get is if the code is reordered slightly as the testcase
in comment 4:

bool f(int* a)
{
  bool x = a == nullptr;
  a += 10;
  return x;
}

That testcase requires this patch.  


> That is, it assumes that there is a zero sized object at nullptr and
> thus the pointer increment to outside (but not one after it) invokes UB.
> 
> That's much more aggressive than optimizing
> 
>   ptr + 4 != nullptr
> 
> to true and I'm not sure the reasoning follows.  I think at 'nullptr'
> there is _no_ object and thus the restriction to pointer addition
> doesn't apply at all - if a pointer does not refer to an object then
> the rule that increment to outside of the object invokes UB doesn't 
> apply.

It implements comment 11, and comment 12 confirmed that 11 was accurate.

(1)
>> X + Y would be non-null if either X or Y is known to be non-null.
so if Y is non-zero, X + Y is non-zero.
(2)
>> If we know that X + Y is non-null via some mechanism (for example the result 
>> was dereferenced), then we know that X and Y are non-null.
X + Y is non-null based on (2)

Going back to the code generated for this:

    x_2 = a_1(D) == 0B;
    a_3 = a_1(D) + 40;
    return x_2;

The only way to to return 1 with this sequence is for a_3 = a_1(D) + 40 to
determine that a_1 is non-zero after this statement... which is what this patch
does.
It then reapplies this knowledge as a recomputation of x_2 based on this
knowledge after the defintion of a_3.

So yes, this is much more aggressive.  I suppose in theory we could close this
PR and open a new one to cover the more aggressive version.

Reply via email to