On Wed, Jan 4, 2017 at 8:24 PM, Jeff Law <[email protected]> wrote:
> On 01/04/2017 11:55 AM, Jeff Law wrote:
>>
>> On 12/09/2016 01:28 AM, Richard Biener wrote:
>>>
>>> On Wed, Dec 7, 2016 at 12:18 AM, Jeff Law <[email protected]> wrote:
>>>>
>>>>
>>>>
>>>> So I was going through the various DSE related bugs as stumbled across
>>>> 67955.
>>>>
>>>> The basic issue in 67955 is that DSE is too simplistic when trying to
>>>> determine if two writes hit the same memory address. There are cases
>>>> were
>>>> PTA analysis can get us that information.
>>>>
>>>> The unfortunate problem is that PTA can generate a single points-to
>>>> set for
>>>> pointers to different elements in the same array. So we can only
>>>> exploit a
>>>> special case. Namely when we get a PTA singleton and the size of the
>>>> store
>>>> is the same size of the pointed-to object.
>>>>
>>>> That doesn't happen in a bootstrap, but it does happen for the
>>>> testcase in
>>>> the BZ as well as a handful of tests in the testsuite -- Tom reported 6
>>>> unique tests where it triggered, I ran my own tests where two more
>>>> were spit
>>>> out. Not huge. But the cost is low.
>>>>
>>>> All that I've done with Tom's patch is update the call into the PTA
>>>> system.
>>>> It's very clearly Tom's work.
>>>>
>>>> Bootstrapped and regression tested on x86_64-linux-gnu. Installing
>>>> on the
>>>> trunk.
>>>
>>>
>>> Just double-checked it doesn't break
>>>
>>> int foo (int *p, int b)
>>> {
>>> int *q;
>>> int i = 1;
>>> if (b)
>>> q = &i;
>>> else
>>> q = (void *)0;
>>> *q = 2;
>>> return i;
>>> }
>>
>> Right. ISTM this shouldn't have a singleton points-to set and thus
>> shouldn't change behavior. But looking at things more closely, it
>> looks like points-to-null is distinct from the points-to variables. ie,
>> we want to know if its a singleton and ! null. Thus we have to check
>> pt_solution_singleton_or_null_p (pi->pt, &pt_uid) && !pi->pt->null
>>
>> I think it's working for you because the path isolation code splits off
>> the NULL dereference path. Adding
>> -fno-isolate-erroneous-paths-dereference to the switches shows DSE2,
>> incorrectly IMHO, removing the i = 1 store.
>>
>> Thoughts?
>
> 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.
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;
}
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).
So for
int foo (int *p, int b)
{
int i = 1;
try {
int *q;
if (b)
q = &i;
else
q = (int *)0;
*q = 2;
} catch (...) {
return 0;
}
return i;
}
we do not remove the store to i with -fnon-call-exceptions. Which means we are
fine not testing for pt.null != 1.
?
Richard.
> Thanks,
>
> Jeff
>
>
> diff --git a/gcc/ChangeLog b/gcc/ChangeLog
> index d43c9bc..3a7ad9d 100644
> --- a/gcc/ChangeLog
> +++ b/gcc/ChangeLog
> @@ -1,3 +1,11 @@
> +2017-01-04 Jeff Law <[email protected]>
> +
> + PR tree-optimizatin/67955
> + * tree-ssa-alias.c (same_addr_size_stores_p): Check offsets first.
> + Allow any SSA_VAR_P as the base objects. Use integer_zerop. Verify
> + the points-to solution does not include pt_null. Use DECL_PT_UID
> + unconditionally.
> +
> 2017-01-04 Uros Bizjak <[email protected]>
>
> * config/i386/i386.md (HI/SImode test with imm to QImode splitters):
> diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
> index d8ff32f..0cbc8cc 100644
> --- a/gcc/testsuite/ChangeLog
> +++ b/gcc/testsuite/ChangeLog
> @@ -1,3 +1,8 @@
> +2017-01-03 Jeff Law <[email protected]>
> +
> + PR tree-optimization/67955
> + * gcc.dg/tree-ssa/ssa-dse-28.c: New test.
> +
> 2017-01-04 Marek Polacek <[email protected]>
>
> PR c++/77545
> diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-dse-28.c
> b/gcc/testsuite/gcc.dg/tree-ssa/ssa-dse-28.c
> new file mode 100644
> index 0000000..d35377b
> --- /dev/null
> +++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-dse-28.c
> @@ -0,0 +1,20 @@
> +/* { dg-do compile } */
> +/* { dg-options "-O2 -fdump-tree-dse-details -fexceptions
> -fnon-call-exceptions -fno-isolate-erroneous-paths-dereference" } */
> +
> +
> +int foo (int *p, int b)
> +{
> + int *q;
> + int i = 1;
> + if (b)
> + q = &i;
> + else
> + q = (void *)0;
> + *q = 2;
> + return i;
> +}
> +
> +/* { dg-final { scan-tree-dump-not "Deleted dead store" "dse1"} } */
> +/* { dg-final { scan-tree-dump-not "Deleted dead store" "dse2"} } */
> +/* { dg-final { scan-tree-dump-not "Deleted dead store" "dse3"} } */
> +
> diff --git a/gcc/tree-ssa-alias.c b/gcc/tree-ssa-alias.c
> index 0a9fc74..871fa12 100644
> --- a/gcc/tree-ssa-alias.c
> +++ b/gcc/tree-ssa-alias.c
> @@ -2326,9 +2326,13 @@ same_addr_size_stores_p (tree base1, HOST_WIDE_INT
> offset1, HOST_WIDE_INT size1,
> tree base2, HOST_WIDE_INT offset2, HOST_WIDE_INT
> size2,
> HOST_WIDE_INT max_size2)
> {
> - /* For now, just handle VAR_DECL. */
> - bool base1_obj_p = VAR_P (base1);
> - bool base2_obj_p = VAR_P (base2);
> + /* Offsets need to be 0. */
> + if (offset1 != 0
> + || offset2 != 0)
> + return false;
> +
> + bool base1_obj_p = SSA_VAR_P (base1);
> + bool base2_obj_p = SSA_VAR_P (base2);
>
> /* We need one object. */
> if (base1_obj_p == base2_obj_p)
> @@ -2356,13 +2360,9 @@ same_addr_size_stores_p (tree base1, HOST_WIDE_INT
> offset1, HOST_WIDE_INT size1,
> if (size1 != size2)
> return false;
>
> - /* Offsets need to be 0. */
> - if (offset1 != 0
> - || offset2 != 0)
> - return false;
>
> /* Check that memref is a store to pointer with singleton points-to info.
> */
> - if (!tree_int_cst_equal (TREE_OPERAND (memref, 1), integer_zero_node))
> + if (!integer_zerop (TREE_OPERAND (memref, 1)))
> return false;
> tree ptr = TREE_OPERAND (memref, 0);
> if (TREE_CODE (ptr) != SSA_NAME)
> @@ -2373,10 +2373,13 @@ same_addr_size_stores_p (tree base1, HOST_WIDE_INT
> offset1, HOST_WIDE_INT size1,
> || !pt_solution_singleton_or_null_p (&pi->pt, &pt_uid))
> return false;
>
> + /* If the solution has a singleton and NULL, then we can not
> + be sure that the two stores hit the same address. */
> + if (pi->pt.null)
> + return false;
> +
> /* Check that ptr points relative to obj. */
> - unsigned int obj_uid = (DECL_PT_UID_SET_P (obj)
> - ? DECL_PT_UID (obj)
> - : DECL_UID (obj));
> + unsigned int obj_uid = DECL_PT_UID (obj);
> if (obj_uid != pt_uid)
> return false;
>
>