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

--- Comment #4 from Feng Xue <fxue at os dot amperecomputing.com> ---
(In reply to Richard Biener from comment #3)
> (In reply to Feng Xue from comment #2)
> > (In reply to Richard Biener from comment #1)
> > > Yes, it's not possible to implement the standards restrict qualification
> > > constraints reliably for pointers not in the outermost scope of a function
> > > and after the compiler was allowed to do CSE or other code transforms.
> > > 
> > > For simplicity only function parameters (and select "global" cases)
> > > are handled in the implementation which resides in points-to analysis.
> > > 
> > > In principle 'restrict' should be handled in the C/C++ language frontends
> > > instead.
> > 
> > Maybe, I caught your point, w/o front-end scope information, we do not know
> > the effective lifetime of "__restrict__" pointer merely from def/use chain
> > in the gimple. An example:
> > 
> >   void foo (int *p)
> >   {
> >      int *a_escaped;
> > 
> >      {
> >        int * __restrict__ a = ...;
> > 
> >        /* no alias between "a" and "p" */
> >        *a = ...;
> > 
> >        /* Make "a" escaped from block scope */
> >        a_escaped = a + offset;
> >      }
> > 
> >     /* By source-level declaration syntax, "a_escaped" and "p" may be
> > aliased. But in the gimple, we do not know usage of "a_escaped" does not
> > belongs to lifetime constrainted by "__restrict__", and could lead to an
> > incorrect conclusion that "a_escaped" and "p" are alias-free. */
> > 
> >     *a_escaped = ...;
> > 
> >     ...
> >   }
> > 
> > But for the 2nd case, all pointers are defined in the outermost scope of
> > function. How about an enhancement? Besides parameters, we could also mark
> > all __restrict__ pointers declared in the outermost scope, and ignore others
> > in any enclosed scopes, as you said, probably this could be done that at the
> > front-end stage.
> 
> Outermost scope would work as long as there is no inlining or optimization
> happening before since we happily elide scopes and "globalize" variables.

 inline void goo()
 {
   int * __restrict__ p;

   ...
 } 

 void foo()
  {
     goo();
  }

 ->

 void foo()
  {

     // goo();
     {

       // Would DECL_CONTEXT(p) become "foo" from "goo" after inline?
       int * __restrict__ p; 

       ...

     }
  }

I do not deep dive into related code how DECL_CONTEXT() varies with inline or
optimization. If this is quite compilicated to track, my thought is to
introduce  another DECL_CONTEXT_RAW() or similar stuff, that is set to its
original function, when analyzing alias for a restrict var, we would also check
if DECL_CONTEXT and DECL_CONTEXT_RAW is matched or not.

> That is, it's quite difficult to prove handling user(!) variables in the
> outermost scope is correct.  You'd check that DECL_CONTEXT of a variable
> is the same as DECL_INITIAL (cfun->decl), but I'm not sure this will
> never "break".  Depending on frontends there might or might not be an
> additional "outer" scope from DECL_INITIAL IIRC.
> 
> Does handling variables in the outermost scope matter in practice?

In reality, we encounter an application with a hot loop containing lots of
memory accesses, whose pointers are defined as __restrict__ variables
initialized in the outermost scope, and those fake aliasing relations prevent
vectorization.

Reply via email to