On Sat, Sep 24, 2011 at 01:26:36PM +0200, Richard Guenther wrote: > > +int > > +f3 (S &__restrict x, S &__restrict y) > > +{ > > + x.p[0] = 3; > > + y.p[0] = 0; > > +// { dg-final { scan-tree-dump-times "return 3" 1 "optimized" } } > > + return x.p[0]; > > +} > > + > > +int > > +f4 (S &x, S &y) > > +{ > > + x.p[0] = 4; > > + y.p[0] = 0; > > +// { dg-final { scan-tree-dump-times "return 4" 0 "optimized" } } > > + return x.p[0]; > > +}
> I don't see why > > f4 (s, s) > > would be invalid. But you would miscompile it. f3 (s, s) you mean? I believe it is invalid. For f4 it would be valid and not optimized out. > (I'm not sure that a restrict qualified component is properly defined > by the C standard - we're just making this extension in a very constrained > case to allow Fortran array descriptors to work). Well, C standard doesn't have references, and C++ doesn't have restrict. So it is all about extensions. But what else would be & __restrict for than similar to *__restrict to say that the pointed (resp. referenced) object must not be accessed through other means than the reference or references/pointers derived from it, in the spirit of ISO C99 6.7.3.1. So, before jumping to __restrict fields, consider int a[10], b[10]; int * f8 (S &__restrict x, S &__restrict y) { x.p = a; y.p = b; return x.p; } which we already optimize even before the patch. It is certainly invalid to call f8 (s, s). And the restricted fields, it is a straightforward extension to the restrict definition of ISO C99. We don't use it just for Fortran descriptors, but e.g. std::valarray uses __restrict fields too and has that backed up by the C++ standard requirements. Two different std::valarray objects will have different pointers inside of the structure. My intent currently is to be able to vectorize: #include <valarray> std::valarray<int> f9 (std::valarray<int> a, std::valarray<int> b, std::valarray<int> c, int z) { int i; for (i = 0; i < z; i++) { a[i] = b[i] + c[i]; a[i] += b[i] * c[i]; } return a; } void f10 (std::valarray<int> &__restrict a, std::valarray<int> &__restrict b, std::valarray<int> &__restrict c, int z) { int i; for (i = 0; i < z; i++) { a[i] = b[i] + c[i]; a[i] += b[i] * c[i]; } } In f9 we currently handle it differently than in f10, while IMHO it should be the same thing, a is guaranteed in both cases not to alias b nor c and b is guaranteed not to alias c, furthermore, a._M_data[0] through a._M_data[z-1] is guaranteed not to alias b._M_data[0] through b._M_data[z-1] and c._M_data[0] through c._M_data[z-1] and similarly for b vs. c. The __restrict on the _M_data field in std::valarray is a hint that different std::valarray objects will have different pointers. In f9 we have: size_tD.1850 D.53593; intD.9 * restrict D.53592; intD.9 & D.53591; ... D.53592_7 = MEM[(struct valarrayD.50086 *)aD.50087_6(D) + 8B]; D.53593_42 = D.53456_5 * 4; # PT = nonlocal escaped { D.53660 } (restr) D.53591_43 = D.53592_7 + D.53593_42; ... *D.53591_43 = D.53462_19; and while PTA computes the restricted property here, we unfortunately still don't use it, because D.53591 (which comes from all the inlined wrappers) isn't TYPE_RESTRICT. Shouldn't we propagate that property to either SSA_NAMEs initialized from restricted pointers resp. POINTER_PLUS_EXPRs, or if it is common to all VAR_DECLs underlying such SSA_NAMEs, to the VAR_DECLs? But in f10 we don't get even that far, the a._M_data (which is actually a->_M_data, since a is a (restricted) reference) load is already itself not considered as restricted by PTA. It is nice that we optimize Fortran arrays well, but it would be nice if we did the same for C++ too. Jakub