On Mon, 7 Feb 2022, Joseph Myers wrote:

> On Fri, 4 Feb 2022, Richard Biener via Gcc-patches wrote:
> 
> > This adds explicit variable birth CLOBBERs in an attempt to fix
> > PR90348 and duplicates.  The birth / death CLOBBER pairs are
> > used to compute liveness and conflicts for stack variable
> > coalescing where the lack of an explicit birth but instead
> > use of first mention causes misrepresentation of variable life
> > ranges when optimization moves the first mention upwards the
> > original birth point at the variables bind expression start.
> 
> I'm not clear on exactly where you consider a variable to be born, but 
> note that non-VLA C variables have a lifetime that starts at the beginning 
> of their block, not at their declaration: it's valid to jump backward from 
> after the declaration to before it and then access the variable via a 
> pointer, or jump forward again over the declaration and access it by name.  
> (Most programs of course don't do that sort of thing.)

Oh, interesting.  So the following is valid

int foo(int always_true_at_runtime)
{
  {
    int *p;
    if (always_true_at_runtime)
      goto after;
lab:
    return *p;
after:
    int i = 0;
    p = &i;
    if (always_true_at_runtime)
      goto lab;
  }
  return 0;
}

For the implementation I considered starting lifetime at a DECL_EXPR
if it exists and otherwise at the start of the BIND_EXPR.  Note the
complication is that control flow has to reach the lifetime-start
clobber before the first access.  But that might also save us here,
since for the example above 'i' would be live via the backedge
from goto lab.

That said, the existing complication is that when the gimplifier
visits the BIND_EXPR it has no way to know whether there will be
a following DECL_EXPR or not (and the gimplifier notes there are
cases a DECL_EXPR variable is not in a BIND_EXPR).  My plan is to
compute this during one of the body walks the gimplifier performs
before gimplifying.

Another complication is that at least the C frontend + gimplifier
combination for

  switch (i)
  {
  case 1:
    int i;
    break;
  }

will end up having the BIND_EXPR mentioning 'i' containing the
case label, so just placing the birth at the BIND will make it
unreachable as

  i = BIRTH;
case_label_for_1:
  ...

conveniently at least the C frontend has a DECL_EXPR for 'i'
which avoids this and I did not find a way (yet) in the gimplifier
to rectify this when gimplifying switches.

So there's still work to do but I think that starting the lifetime
at a DECL_EXPR if it exists is the way to go?

Richard.

Reply via email to