Optimization of gfortran for execution speed

THOMAS Paul Richard 169137 prthomas@drfccad.cea.fr
Fri Oct 21 07:54:00 GMT 2005


Tobi,

> instead of being translated to a function call
> - don't forget to check that you don't break stuff like
>    a(1:N-1) = a(2:N)
> 
I cannot break it because it has not been fixed.  Inspection of dependency.c
will convince you of that but in the meantime let the example below suffice.
For N variable, the dependency cannot be resolved but it works fine if it is
a constant.

What I am doing will permit this to work for cases like i(N-1:N) = i(N:N+1),
which is resolvable because the number of elements is constant.

Note also that the case mentioned by Dominique i(N:N+1) = i(N-1:N) produces
a temporary, even when N is a parameter.  Again, examination of dependency.c
will show that there is no attempt made to treat this case. I would just as
soon leave it as a TODO until either I come to grips with how to reverse the
order of a scalarizer loop or one of the adepts intervenes. It would be easy
to signal a reverse dependency overlap, however.

I am beginning to wonder if some warnings might not be in order for cases
that cannot be treated, where a remedy can be effected by modification of
the source code?

Paul

  integer, dimension(10)  ::  i = (/0,1,2,3,4,5,6,7,8,9/)
  integer                 ::  j, N = 6
  do j = 1, 4
    i(1:N) = i(2:N+1)
  end do
end
 
produces the following code:-

MAIN__ ()
{
  int4 j;
  static int4 i[10] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
  static int4 n = 6;

  j = 1;
  if (j <= 4)
    {
      while (1)
        {
          {
            logical4 D.575;

            {
              void * D.571;
              int4 D.570;
              struct array1_int4 atmp.0; /*   <= Note the temporary.  */

              atmp.0.dtype = 265;
              atmp.0.dim[0].stride = 1;
              atmp.0.dim[0].lbound = 0;
              atmp.0.dim[0].ubound = n - 1;
              D.570 = NON_LVALUE_EXPR <n>;
              D.571 = _gfortran_internal_malloc (D.570 * 4);
              atmp.0.data = D.571;
              atmp.0.offset = 0;
              {
                int4 S.1;

                S.1 = 0;
                while (1)
                  {
                    if (S.1 > n - 1) goto L.3; else (void) 0;
                    (*(int4[0:] *) atmp.0.data)[NON_LVALUE_EXPR <S.1>] =
i[NON_LVALUE_EXPR <S.1> + 1];
                    S.1 = S.1 + 1;
                  }
                L.3:;
                S.1 = 0;
                while (1)
                  {
                    if (S.1 > n - 1) goto L.4; else (void) 0;
                    i[NON_LVALUE_EXPR <S.1>] = (*(int4[0:] *)
atmp.0.data)[NON_LVALUE_EXPR <S.1>];
                    S.1 = S.1 + 1;
                  }
                L.4:;
              }
              _gfortran_internal_free (atmp.0.data);
            }
            L.1:;
            D.575 = j == 4;
            j = j + 1;
            if (D.575) goto L.2; else (void) 0;
          }
        }
    }
  else
    {
      (void) 0;
    }
  L.2:;
}

changing N to a parameter gets rid of the temporary; thus:

MAIN__ ()
{
  int4 j;
  static int4 i[10] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};

  j = 1;
  if (j <= 4)
    {
      while (1)
        {
          {
            logical4 D.561;

            {
              int4 S.0;

              S.0 = 1;
              while (1)
                {
                  if (S.0 > 6) goto L.3; else (void) 0;
                  i[NON_LVALUE_EXPR <S.0> + -1] = i[NON_LVALUE_EXPR <S.0>];
                  S.0 = S.0 + 1;
                }
              L.3:;
            }
            L.1:;
            D.561 = j == 4;
            j = j + 1;
            if (D.561) goto L.2; else (void) 0;
          }
        }
    }
  else
    {
      (void) 0;
    }
  L.2:;
}



More information about the Fortran mailing list