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

--- Comment #22 from rguenther at suse dot de <rguenther at suse dot de> ---
On Tue, 4 Jun 2019, tkoenig at gcc dot gnu.org wrote:

> https://gcc.gnu.org/bugzilla/show_bug.cgi?id=77278
> 
> --- Comment #19 from Thomas Koenig <tkoenig at gcc dot gnu.org> ---
> (In reply to rguent...@suse.de from comment #15)
>   Btw, I wonder what happens at
> > the call boundary inside a single fortran module where
> > the caller passes a dim[2] array to a subroutine
> > handling arbitrary dimension arrays?  I suspect the
> > IL would have the very same TBAA issue.  Can you produce
> > a fortran testcase that exposes such a case so we can have a
> > look into the details?
> 
> Here is a test case:
> 
> module x
>   implicit none
> contains
>   subroutine foo(a)
>     real, dimension(..) :: a
>     print *,shape(a)
>   end subroutine foo
>   subroutine bar
>     real, dimension(2,2) :: a
>     real, dimension(3,3,3) :: b
>     call foo(a)
>     call foo(b)
>   end subroutine bar
> end module x
> 
> program main
>   use x
>   call bar
> end program main
> 
> Looking at the *.original tree dump, we have
> 
> bar ()
> {
>   real(kind=4) a[4];
>   real(kind=4) b[27];
> 
>   {
>     struct array02_real(kind=4) parm.0;
> 
> [...]
> 
>     foo (&parm.0);
>   }
> 
>   {
>     struct array03_real(kind=4) parm.1;
> 
> [...]
> 
>     foo (&parm.1);
>   }
> 
> and
> 
> foo (struct array15_real(kind=4) & restrict a)
> {
>   {
>     struct __st_parameter_dt dt_parm.2;
> 
> This does not really look very healthy (but it is not warned about).

OK, so changing the testcase to

module x
  implicit none
contains
  subroutine foo(a)
    real, dimension(..) :: a
    if (rank(a) < 2) STOP 3
  end subroutine foo
  subroutine bar
    real, dimension(2,2) :: a
    real, dimension(3,3,3) :: b
    call foo(a)
    call foo(b)
  end subroutine bar
end module x

program main
  use x
  call bar
end program main

makes us inline foo() where we then see

  struct array03_real(kind=4) parm.1;
  struct array02_real(kind=4) parm.0;
...
  parm.0.dtype.rank = 2;
...
  _15 = MEM[(struct array15_real(kind=4) &)&parm.0].dtype.rank;
  if (_15 <= 1)

which shows a possible wrong-code issue because the store
to rank is via array02 but the read uses array15.  We don't
miscompile this because we try to be forgiving if we see
a must-alias.

The frontend should create a descriptor type mimicing the one
in the library API and emit

  MEM[(struct arrayN_real(kind=4) &)&param.0].dtype.rank = 2;
...
  _15 = MEM[(struct arrayN_real(kind=4) &)&param.0].dtype.rank;
  if (_15 <= 1)

that is, all accesses to array descriptors should be as-if
they were indirect accesses through the assumed rank descriptor
type with the flex-array dim member.

Note this would no longer allow TBAA disambiguation of
different rank array descriptor accesses.  So alternatively
we would have to arrange accesses via structs with a flex
array member alias accesses via structs with fixed-array
members.  Still functions accessing assumed rank arrays
like foo() above then need to use the flexarray descriptor
type to access dtype.rank, not as it does at the moment
the max-rank descriptor type.  I suppose that would be
the first thing to fix (maybe also the easiest).

Honza and me can then think about ways to make
struct { int ndim; int dim[]; } accesses conflict with
struct { int ndim; int dim[N]; } with arbitrary N.
Like in record-component-aliases if it sees a trailing
fixed-size array member, build the corresponding flex-array
record and record a subset of that (ugh).

Reply via email to