> > 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

I see, missed that! 

> 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.

Yep, i am not arguing for eliminating special case of memcpy (because we
have the additional info that it only copies pointers from *src to
*dest).

However I find current definition of EAF_NOESCAPE bit hard to handle in
modref, since naturally it is quite reliable to track all uses of ssa
name that correspond to parameters, but it is harder to track where
values read from pointed-to memory can eventually go.

What I do is to walk all uses of SSA_NAME that correspond to parameter
and try to unerstand it.  If it is one of
 1) memory load via derefence of name
 2) memory store where name is base of LHS
 3) memory store where name is rhs
 4) name is passed as a value to function 
 5) dereferenced value from name is passed to funtion
 6) used as value normal gimple expression
 7) used in return (as RHS or base of memory dereference address)
 8) it is used only in reference but not as base (as array index or so)

Then I merge in (and) flags I determine as follow:

For 1) clear EAF_USED and recurse to LHS name. Based on its flags I
decide on:
  - EAF_DIRECT (if LHS has EAF_UNUSED),
  - EAF_NOCLOBBER (if LHS has EAF_NOCLOBBER)
  - EAF_NOESCAPE (if LHS has EAF_NOESCAPE). 

For 2) I clear EAF_NOCLOBBER and EAF_UNUSED flag

For 3) I give up (clear all flags) since I would need to track where the
memory is going.

For 4) I determine flag of function parameter

For 5) I need to do same handling as 1) where flag of "loaded value" is
flag of the function

For 6) I determine flags of LHS and merge them in

For 7) I clear NOESCAPE if rhs is name itself
and UNUSED + NOESCAPE if rhs is derefernece from name.

For 8) I do nothing.  Here the names are non-pointers that I track
because of earlier dereference.



So I think 7) can be relaxed.  Main problem is hoever that we often see 1)
and then 3) or 7) on LHS that makes us punt very often.

The fact that pointer directly does not escape but pointed to memory can
seems still very useful since one does not need to add *ptr to points-to
sets. But I will try relaxing 7).

If we allow values escaping to other parameters and itself, I think I
can relax 3) if base of the store is default def of PARM_DECL.
> 
> 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.

May be nice and also describe carefully that NOESCAPE and NOCLOBBER also
reffers to indirect references.  Current description
"Nonzero if the argument does not escape."
reads to me that it is about ptr itself, not about *ptr and also it does
not speak of the escaping to return value etc.

Honza

Reply via email to