https://gcc.gnu.org/bugzilla/show_bug.cgi?id=126130

--- Comment #8 from Richard Biener <rguenth at gcc dot gnu.org> ---
(In reply to Richard Biener from comment #7)
> (In reply to Richard Biener from comment #5)
> [...]
> > diff --git a/gcc/pta-andersen.cc b/gcc/pta-andersen.cc
> > index bba34b3c9a0..7adf4f53579 100644
> > --- a/gcc/pta-andersen.cc
> > +++ b/gcc/pta-andersen.cc
> > @@ -394,7 +394,8 @@ solution_set_expand (bitmap set, bitmap *expanded)
> >      {
> >        varinfo_t v = get_varinfo (j);
> >        if (v->is_artificial_var
> > -         || v->is_full_var)
> > +         || v->is_full_var
> > +         || v->is_fn_info)
> >         continue;
> >        if (v->head != prev_head)
> >         {
> 
> causes
> 
[...]
> +FAIL: gcc.dg/torture/pr43879_1.c   -O1  execution test
> +FAIL: gcc.dg/torture/pr43879_1.c   -O2  execution test
> +FAIL: gcc.dg/torture/pr43879_1.c   -O3 -g  execution test
> +FAIL: gcc.dg/torture/pr43879_1.c   -Os  execution test

shows that in pr43879_2.c which has

static int foo(int *i)
{
        bar(*i);
        baz(i);
        bar(*i);
        return *i;
}

struct TBL tbl = { foo };

-ESCAPED = { ESCAPED NONLOCAL foo foo.clobber foo.use foo.result foo.arg0 }
+ESCAPED = { foo }
...
-foo.result = { ESCAPED NONLOCAL }
-foo.arg0 = { ESCAPED NONLOCAL }
+foo.result = { }
+foo.arg0 = { }

so when a function pointer escapes we rely on the

ESCAPED = *ESCAPED
ESCAPED = ESCAPED + UNKNOWN
*ESCAPED = NONLOCAL

constraints to populate the arguments (and static chain) with NONLOCAL.

+FAIL: gcc.dg/torture/pr94947-1.c   -O1  execution test
+FAIL: gcc.dg/torture/pr94947-1.c   -O2  execution test
+FAIL: gcc.dg/torture/pr94947-1.c   -O3 -g  execution test
+FAIL: gcc.dg/torture/pr94947-1.c   -Os  execution test

is the more interesting case where we have

static int *p;

static void foo ()
{
  if (*p != 1)
    abort ();
}

int main()
{
  int x = 1;
  p = &x;
  baz_call = foo;
  baz ();

and baz () in another TU calling foo ().  With the patch we elide 'x = 1'
because the baz () call only uses escaped/global vars.  'x' does not
escape the unit, but with expanding to USE/CLOBBER we get 'x' escaped
via the escape of 'foo' and thus escaping what foo uses.
Removing use/clobber from the expansion makes this no longer work,
but I have not yet made up my mind whether this is the correct way
to deal with this -- I'd have expected this to only have an effect on
the baz () uses/clobbers, but there we have patched/unpatched

  # USE = nonlocal unit-escaped 
  # CLB = nonlocal unit-escaped 
  bazD.2966 ();

we treat 'baz' "classical" (it's extern, no body available), but still
use unit-escaped here (we do not compute the classical function escaped
in IPA PTA).

Steensgard-wise we'd "unify" USE/CLB of classical function calls and
all escaped function USE/CLB.

Reply via email to