This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: [PR tree-optimization/67955] Exploit PTA in DSE


On 01/05/2017 01:34 AM, Richard Biener wrote:
On Wed, Jan 4, 2017 at 8:24 PM, Jeff Law <law@redhat.com> wrote:

The more I think about this the more I'm sure we need to verify pt.null is
not in the points-to set.    I've taken the above testcase and added it as a
negative test.  Bootstrapped, regression tested and committed to the trunk
along with the other minor cleanups you pointed out.

Note disabling this for pt.null == 1 makes it pretty useless given we compute
that conservatively to always 1 in points-to analysis (and only VRP ever sets
it to zero).  See PTAs find_what_p_points_to.  This is because PTA does
not conservatively compute whether a pointer may be NULL (all bugs, I have
partly fixed some and have an incomplete patch to fix others -- at the point
I looked into this we had no users of pt.null info and thus I decided the
extra constraints and complexity wasn't worth the compile-time/memory-use).

Without -fnon-call-exceptions removing the *0 = 2 store is IMHO ok, so we
only have to make sure to not break the exception case.
I spent a goodly amount of time thinking about this... I think the key point is whether or not removing the store is observable in a conforming program.

Essentially if we get a non-call exception or receive a signal between the "dead" store and the subsequent store, then we could observe that the "dead" store was removed if the object being stored escapes.

This seems to have larger implications than just the cases we're looking at (assume "a" is something in memory, of course).


a = 1;
<trigger non-call exception>
a = 2;


If "a" escapes such that its value can be queried in the exception handler, then the exception handler would be able to observe the first store and thus it should not be removed.

We also have to be cognizant of systems where there is memory mapped at location 0. When that is true, we must check pt.null and honor it, even if it pessimizes code.



For

int foo (int *p, int b)
{
  int *q;
  int i = 1;
  if (b)
    q = &i;
  else
    q = (void *)0;
  *q = 2;
  i = 3;
  return *q;
}
So on a system where *0 is a valid memory address, *q = 2 does not make anything dead, nor does i = 3 unless we were to isolate the THEN/ELSE blocks.

On a system where *0 traps, there is no way to observe the value of "i" in the handler. Thus i = 1 is a dead store. I believe we must keep the *q = 2 store because it can trigger a signal/exception which is itself an observable side effect? Right?










we remove all stores but the last store to i and the load from q (but we don't
replace q with &i here, a missed optimization if removing the other stores is
valid).
But if we remove the *q = 2 store, we remove an observable side effect, the trap/exception itself if we reach that statement via the ELSE path.

Jeff


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]