On Sun, Aug 22, 2021 at 7:32 PM Jan Hubicka <hubi...@ucw.cz> wrote:
>
> > Thanks for looking into this bug - it is interesting that ipa-pta
> > requires !EAF_NOCLOBBER when function is called...
> >
> > I have some work done on teaching ipa-modref (and other propagation
> > passes) to use ipa-devirt info when the full set of callees is known.
> > This goes oposite way.
> >
> > You can drop flags only when callee == NAME and you can just frop
> > EAF_NOCLOBBER.  For example in testcase
> >
> > struct a {
> >   void (*foo)();
> >   void *bar;
> > }
> >
> > void wrap (struct a *a)
> > {
> >   a->foo ();
> > }
> >
> > will prevent us from figuring out that bar can not be modified when you
> > pass non-ecaping instance of struct a to wrap.
> >
>
> I am testing this updated patch which implements that.  I am not very
> happy about this (it punishes -fno-ipa-pta path for not very good
> reason), but we need bugfix for release branch.

Why does it "punish" -fno-ipa-pta?  It merely "punishes" modref of
no longer claiming that we do not alter the instruction stream pointed
to by a->foo, sth that shouldn't be very common.

Note that IPA PTA doesn't really know whether the passed argument
is a function or not, also 'wrap' could just receive a void * pointer and
still call the function.  So we're very much relying on how this all
plays out ...

> It is very easy now to add now EAF flags at modref side
> so we can track EAF_NOT_CALLED.
> tree-ssa-structalias side is always bit anoying wrt new EAF flags
> because it has three copies of the code building constraints for call
> (for normal, pure and const).
>
> Modref is already tracking if function can read/modify global memory.  I
> plan to add flags for NRC and link chain and then we can represent
> effect of ECF_CONST and PURE by simply adding flags.  I would thus would
> like to merge that code.  We do various optimizations to reduce amount
> of constriants produced, but hopefully this is not very important (or
> can be implemented by special casing in unified code).
>
> Honza
>
> gcc/ChangeLog:
>
> 2021-08-22  Jan Hubicka  <hubi...@ucw.cz>
>             Martin Liska  <mli...@suse.cz>
>
>         * ipa-modref.c (analyze_ssa_name_flags): Indirect call implies
>         ~EAF_NOCLOBBER.
>
> gcc/testsuite/ChangeLog:
>
> 2021-08-22  Jan Hubicka  <hubi...@ucw.cz>
>             Martin Liska  <mli...@suse.cz>
>
>         * gcc.dg/lto/pr101949_0.c: New test.
>         * gcc.dg/lto/pr101949_1.c: New test.
>
> diff --git a/gcc/ipa-modref.c b/gcc/ipa-modref.c
> index fafd804d4ba..549153865b8 100644
> --- a/gcc/ipa-modref.c
> +++ b/gcc/ipa-modref.c
> @@ -1700,6 +1700,15 @@ analyze_ssa_name_flags (tree name, vec<modref_lattice> 
> &lattice, int depth,
>        else if (gcall *call = dyn_cast <gcall *> (use_stmt))
>         {
>           tree callee = gimple_call_fndecl (call);
> +
> +         /* IPA PTA internally it treats calling a function as "writing" to
> +            the argument space of all functions the function pointer points 
> to
> +            (PR101949).  We can not drop EAF_NOCLOBBER only when ipa-pta
> +            is on since that would allow propagation of this from 
> -fno-ipa-pta
> +            to -fipa-pta functions.  */
> +         if (gimple_call_fn (use_stmt) == name)
> +           lattice[index].merge (~EAF_NOCLOBBER);
> +
>           /* Return slot optimization would require bit of propagation;
>              give up for now.  */
>           if (gimple_call_return_slot_opt_p (call)
> diff --git a/gcc/testsuite/gcc.dg/lto/pr101949_0.c 
> b/gcc/testsuite/gcc.dg/lto/pr101949_0.c
> new file mode 100644
> index 00000000000..142dffe8780
> --- /dev/null
> +++ b/gcc/testsuite/gcc.dg/lto/pr101949_0.c
> @@ -0,0 +1,20 @@
> +/* { dg-lto-do run } */
> +/* { dg-lto-options { "-O2 -fipa-pta -flto -flto-partition=1to1" } } */
> +
> +extern int bar (int (*)(int *), int *);
> +
> +static int x;
> +
> +static int __attribute__ ((noinline)) foo (int *p)
> +{
> +  *p = 1;
> +  x = 0;
> +  return *p;
> +}
> +
> +int main ()
> +{
> +  if (bar (foo, &x) != 0)
> +    __builtin_abort ();
> +  return 0;
> +}
> diff --git a/gcc/testsuite/gcc.dg/lto/pr101949_1.c 
> b/gcc/testsuite/gcc.dg/lto/pr101949_1.c
> new file mode 100644
> index 00000000000..871d15c9bfb
> --- /dev/null
> +++ b/gcc/testsuite/gcc.dg/lto/pr101949_1.c
> @@ -0,0 +1,4 @@
> +int __attribute__((noinline,noclone)) bar (int (*fn)(int *), int *p)
> +{
> +  return fn (p);
> +}

Reply via email to