This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Re: [PATCH] Fix inconsistent pruning of aliases
- From: Richard Guenther <rguenther at suse dot de>
- To: gcc-patches at gcc dot gnu dot org
- Cc: Daniel Berlin <dberlin at dberlin dot org>, dnovillo at google dot com
- Date: Tue, 20 Nov 2007 12:13:45 +0100 (CET)
- Subject: Re: [PATCH] Fix inconsistent pruning of aliases
- References: <Pine.LNX.4.64.0711201125330.4148@zhemvz.fhfr.qr>
On Tue, 20 Nov 2007, Richard Guenther wrote:
>
> This fixes an inconsistency in alias pruning. The situation is as
> follows. Consider two pointers, p_1 and p_2, p_1 has a NMT which aliases
> a global integer var X and SMT.1, p_2 points to anything (no NMT). The
> SMT.1 has X as its only alias.
>
> p_1->x = 0;
>
> p_2->x = 0;
>
> at the moment we prune X and so use SMT.1 for p_1->x because
> access_can_touch_variable correctly figures that p_1->x cannot access
> a bare global integer variable.
>
> for p_2->x we add SMT.1s aliases, but do not prune X here because as we
> don't know what p_2 points to, we disregard base/offset information and
> do not ask access_can_touch_variable:
>
> /* If we do not know the full reference tree or if the access is
> unspecified [0, -1], we cannot prune it. Otherwise try doing
> so using access_can_touch_variable. */
> if (full_ref
> && !(offset == 0 && size == -1)
> && !access_can_touch_variable (full_ref, al, offset, size))
> continue;
>
> the fix is to make the behavior consistent and let access_can_touch_variable
> prune also in the case of offset == 0 && size == -1 where it will now
> prune the alias to X and cause the SMT itself to be added to the VOPs.
>
> [It looks like one still could construct a case where we point to the SMT
> but otoh use SMTs aliases for when we have a pt_anything pointer, which
> would result in a missing link between both memory accesses -- don't we
> want to add the SMT itself in any case in get_addr_dereference_operands:
>
> /* If we don't know what this pointer points to then we have
> to make sure to not prune virtual operands based on offset
> and size. */
> if (v_ann->symbol_mem_tag)
> add_virtual_operand (v_ann->symbol_mem_tag, s_ann, flags,
> full_ref, 0, -1, false);
>
> ? That is, not only add the aliases of the SMT, but the SMT itself?]
What I see with the testcase is that a pointer that was not dereferenced
at the point aliasing computed the points-to set (and thus it became
pt_anything) became dereferenced as result of propagation. So we have
now no flow-sensitive information left for the memory access and use
at one point in the program the SMT and at another the NMT (of a different
SSA_NAME of the pointer, which was derefed, both pointers point to the
same memory though). The inconsistency I see is that for the VOP
computation using the NMT we don't add aliases of pointed-to SMTs, but
for the fallback using the SMT, we _only_ add aliases of the SMT.
A testcase is actually simple to construct (-O -fstrict-aliasing
-fno-early-inlining):
int *p;
int inline bar(void) { return 0; }
int foo(int x)
{
int i;
int *q;
if (bar())
q = &i;
else
q = p;
return *q + *p;
}
after the CCP pass after inlining q will be known to be p, but:
<bb 2>:
D.1549_10 = 0;
D.1549_2 = 0;
# VUSE <p_13(D)>
q_4 = p;
# VUSE <i_11(D)>
D.1551_5 = *q_4;
# VUSE <p_13(D)>
p.0_6 = p;
# VUSE <SMT.10_12(D)>
D.1553_7 = *p.0_6;
D.1550_8 = D.1551_5 + D.1553_7;
return D.1550_8;
that is, one access has VUSE <i> and one VUSE <SMT.10> - because
q_4 was set to pt_anything and uses the SMT aliases (which aliases i) and
the access through p.0_6 uses its NMT which points to SMT.10 only.
Funnily, if I add a store through q or p the points-to vars of the NMT
have i added, so maybe while the above looks "interesting" it is actually
an optimization? (If I initialize 'i', the alias also does appear)
Well, I'm slightly confused here ;) (but can't construct a miscompilation
with the above)
Richard.