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 <rguent...@suse.de> SUSE Software Solutions Germany GmbH, Maxfeldstrasse 5, 90409 Nuernberg, Germany; GF: Felix Imend