http://gcc.gnu.org/bugzilla/show_bug.cgi?id=48636

--- Comment #11 from Janne Blomqvist <jb at gcc dot gnu.org> 2011-04-20 
18:14:20 UTC ---
(In reply to comment #9)
> > But do we actually do this? I did some tests a while ago, and IIRC for 
> > assumed
> > shape dummy arguments the procedure always calculates new bounds such that 
> > they
> > start from 1. That is, the procedure assumes that the actual argument
> > descriptor may have lower bounds != 1. 
> > So my argument is basically that with the new descriptor it might make 
> > sense to
> > switch the responsibility around such that it's the caller who makes sure 
> > that
> > all lower bounds are 0 (as we must have the capability to do this anyway in
> > order to call inter-operable procedures, no?) instead of the callee.
> 
> No, the conversion is already done in the caller:
> 
> subroutine bar(B)
>   interface;   subroutine foo(a); integer :: a(:); end subroutine foo
>   end interface
> integer :: B(:)
> call foo(B)
> end subroutine bar
> 
> Shows:
>     parm.4.dim[0].lbound = 1;
>     [...]
>     foo (&parm.4);
> For assumed-shape actual arguments, creating a new descriptor is actually not
> needed - only for deferred shape ones - or if one does not have a full array
> ref.
> Cf. gfc_conv_array_parameter, which is called by gfc_conv_procedure_call.
> 
> However, some additional calculation is also done in the the callee to
> determine the stride and offset; e.g.
>   ubound.0 = (b->dim[0].ubound - b->dim[0].lbound) + 1;
> again, if the dummy argument is not deferred-shaped (allocatable or pointer),
> one actually knows that "b->dim[0].lbound" == 1. I think we have some
> redundancy here -> missed optimization.

Yes, there seems to be some redundancy indeed in that case. I dug up my
testcase:

module asstest
  implicit none
contains
  subroutine assub(a, r)
    real, intent(in) :: a(:,:)
    real, intent(out) :: r

    r = a(42,43)
  end subroutine assub

  subroutine assub2(a, r)
    real, intent(in), allocatable :: a(:,:)
    real, intent(out) :: r

    r = a(42,43)
  end subroutine assub2
end module asstest

The -fdump-tree-original tree for this module is:

assub2 (struct array2_real(kind=4) & a, real(kind=4) & r)
{
  *r = (*(real(kind=4)[0:] *) a->data)[(a->dim[0].stride * 42 +
a->dim[1].stride * 43) + a->offset];
}


assub (struct array2_real(kind=4) & a, real(kind=4) & r)
{
  integer(kind=8) ubound.0;
  integer(kind=8) stride.1;
  integer(kind=8) ubound.2;
  integer(kind=8) stride.3;
  integer(kind=8) offset.4;
  integer(kind=8) size.5;
  real(kind=4)[0:D.1567] * a.0;
  integer(kind=8) D.1567;
  bit_size_type D.1568;
  <unnamed-unsigned:64> D.1569;

  {
    integer(kind=8) D.1566;

    D.1566 = a->dim[0].stride;
    stride.1 = D.1566 != 0 ? D.1566 : 1;
    a.0 = (real(kind=4)[0:D.1567] *) a->data;
    ubound.0 = (a->dim[0].ubound - a->dim[0].lbound) + 1;
    stride.3 = a->dim[1].stride;
    ubound.2 = (a->dim[1].ubound - a->dim[1].lbound) + 1;
    size.5 = stride.3 * NON_LVALUE_EXPR <ubound.2>;
    offset.4 = -stride.1 - NON_LVALUE_EXPR <stride.3>;
    D.1567 = size.5 + -1;
    D.1568 = (bit_size_type) size.5 * 32;
    D.1569 = (<unnamed-unsigned:64>) size.5 * 4;
  }
  *r = (*a.0)[(stride.1 * 42 + stride.3 * 43) + offset.4];
}

So if we make sure that the caller fixes up the descriptor so that bounds are
correct for assumed-shape parameters (as the TR requires for inter-operable
procedures), then assub could be as simple as assub2.

Reply via email to