On Sun, 8 Nov 2020, Jan Hubicka wrote:
> Hi,
> I implemented simple propagation of EAF arguments for ipa-modref (that is not
> hard to do). My main aim was to detect cases where THIS parameter does not
> escape but is used to read/write pointed to memory. This is meant to
> avoid poor code produced when we i.e. offline destructors on cold path.
>
> Unfortunately detecting EAF_NOESCAPE for such parameters breaks. This is
> already
> visible on memcpy if we let it to be be handled via its fnspec
> attribute. If I disable special handling in structalias:
>
> diff --git a/gcc/tree-ssa-structalias.c b/gcc/tree-ssa-structalias.c
> index a4832b75436..2b614913b57 100644
> --- a/gcc/tree-ssa-structalias.c
> +++ b/gcc/tree-ssa-structalias.c
> @@ -4389,7 +4389,6 @@ find_func_aliases_for_builtin_call (struct function
> *fn, gcall *t)
> case BUILT_IN_STRCPY:
> case BUILT_IN_STRNCPY:
> case BUILT_IN_BCOPY:
> - case BUILT_IN_MEMCPY:
> case BUILT_IN_MEMMOVE:
> case BUILT_IN_MEMPCPY:
> case BUILT_IN_STPCPY:
>
> In the following testcase we miss the fact that memcpy may merge i4p PTA
> set to i3p.
>
> extern void exit (int);
> extern void abort (void);
> int size = 8;
>
> int main (void)
> {
> int i3 = -1, i4 = 55;
> int *i3p = &i3;
> int *i4p = &i4;
>
> memcpy(&i3p, &i4p, size);
> if (i3p != i4p)
> abort ();
> exit (0);
> }
>
> This seems to be documented for some degree:
>
> /* Add *tem = nonlocal, do not add *tem = callused as
> EAF_NOESCAPE parameters do not escape to other parameters
> and all other uses appear in NONLOCAL as well. */
>
> But it also means that some of our FNSPECs are wrong now. I wonder if we can
> split this porperty to two different flags like EAF_NOEASCAPE and
> EAF_INDIRECT_NOESCAPE?
Note that EAF_NOESCAPE allows "escaping" to the return value (see
handle_rhs_call). I guess for simplicity we could allow escaping
of not escaped but USED params to other written to params. I think
we also don't handle "escaping" of a parameter indirectly to itself, thus
int i;
int *p = &i;
int **q = &p;
foo (&q);
if (*q != i)
abort ();
and
foo (int ***p)
{
*p = **p;
}
or so with foos param EAF_NOESCAPE (but not EAF_DIRECT).
Splitting up EAF_NOESCAPE makes it quite difficult to understand.
Arguably explicit handling of memcpy and friends _does_ pay off
for points-to analysis since I'd say modelling all possible and useful
things in fnspec would make it a monster ... you'd basically want
to have a way to specify additional constraints in the fnspec itself,
like *1 = *2, but then also distinguish points-to effects from
may-alias ones.
I wonder if we should teach the GIMPLE FE to parse 'fn spec'
so we can write unit tests for the attribute ... or maybe simply
add this to the __GIMPLE spec string.
> Auto-detecting EAF_INDIRECT_NOESCAPE seems bit harder at least assuming
> that any read can actually load few bits of pointer possibly written
> there beause if simple member functions accesses values pointer by THIS
> and return them we lose a track if the returned value is an escape point
> I would say.
>
> The difference in constraints are:
>
> --- good/a.c.035t.ealias 2020-11-08 13:34:04.397499515 +0100
> +++ a.c.035t.ealias 2020-11-08 13:39:15.483438469 +0100
> @@ -106,7 +106,15 @@
> size = NONLOCAL
> size.0_1 = size
> _2 = size.0_1
> -i3p = i4p
> +callarg(18) = &i3p
> +callarg(18) = callarg(18) + UNKNOWN
> +CALLUSED(16) = callarg(18)
> +CALLCLOBBERED(17) = callarg(18)
> +*callarg(18) = NONLOCAL
> +callarg(19) = &i4p
> +callarg(19) = callarg(19) + UNKNOWN
> +CALLUSED(16) = callarg(19)
> +ESCAPED = _2
> i3p.1_3 = i3p
> i4p.2_4 = i4p
> ESCAPED = &NULL
>
> ...
>
> Call clobber information
>
> -ESCAPED, points-to NULL, points-to vars: { }
> +ESCAPED, points-to non-local, points-to NULL, points-to vars: { }
>
> Flow-insensitive points-to information
>
> -i3p.1_3, points-to NULL, points-to vars: { D.1947 D.1948 }
> +i3p.1_3, points-to non-local, points-to escaped, points-to NULL, points-to
> vars: { D.1947 }
> i4p.2_4, points-to NULL, points-to vars: { D.1948 }
>
> main ()
>
> Honza
>
--
Richard Biener <[email protected]>
SUSE Software Solutions Germany GmbH, Maxfeldstrasse 5, 90409 Nuernberg,
Germany; GF: Felix Imend