Efficiency of different ways representing temporary arrays for derived types

Harald Anlauf anlauf@gmx.de
Tue Jan 29 21:15:00 GMT 2013


As I was curious to find out which way was more efficient in
representing a temporary array of a derived type being passed
to a subroutine, I looked at the dump of the following code:

module test
   implicit none
   type t
      integer :: i
   end type t
   interface
      subroutine bla (y)
        import
        type(t) :: y(:)
      end subroutine bla
   end interface
contains
   subroutine foo (x)
     type(t) :: x                ! Scalar instance

     type(t) :: z(1)             ! Temporary 1
     z(1) = x
     call bla (    z    )        ! Use temporary 1
     call bla ( (/ x /) )        ! Create temporary on the fly
   end subroutine foo
end module test


With trunk (4.8), but also 4.7 and 4.6 I get (-fdump-tree-original):

foo (struct t & restrict x)
{
   struct t z[1];

   z[0] = *x;
   {
     struct array1_t parm.0;

     parm.0.dtype = 297;
     parm.0.dim[0].lbound = 1;
     parm.0.dim[0].ubound = 1;
     parm.0.dim[0].stride = 1;
     parm.0.data = (void *) &z[0];
     parm.0.offset = -1;
     bla (&parm.0);
   }
   {
     struct t A.5[1];
     struct array1_t atmp.4;
     struct t A.2[1];
     struct array1_t atmp.1;

     atmp.1.dtype = 297;
     atmp.1.dim[0].stride = 1;
     atmp.1.dim[0].lbound = 0;
     atmp.1.dim[0].ubound = 0;
     atmp.1.data = (void * restrict) &A.2;
     atmp.1.offset = 0;
     (*(struct t[1] * restrict) atmp.1.data)[0] = *x;
     atmp.4.dtype = 297;
     atmp.4.dim[0].stride = 1;
     atmp.4.dim[0].lbound = 0;
     atmp.4.dim[0].ubound = 0;
     atmp.4.data = (void * restrict) &A.5;
     atmp.4.offset = 0;
     {
       integer(kind=4) S.6;

       S.6 = 0;
       while (1)
         {
           if (S.6 > 0) goto L.1;
           (*(struct t[1] * restrict) atmp.4.data)[S.6] = (*(struct t[1] 
* restrict) atmp.1.data)[S.6];
           S.6 = S.6 + 1;
         }
       L.1:;
     }
     bla (&atmp.4);
   }
}


It appears that the second case, where the temporary is created
"on the fly", does more work than necessary, i.e. apparently twice
as much as in the first case.  Should I expect this?

Another funny finding: if I comment out the declaration of "i" in
the derived type, so that it is empty, I get some additional code
calling __builtin_free which looks interesting.  I hadn't expected
that.  Why should this additional code appear in the dump?
Maybe some cleanup, but why only in this case?

Cheers,
Harald



More information about the Fortran mailing list