Array temporaries for double re-indexing of arrays

We came across some interesting behavior of GFortran while compiling our code with the -Warray-temporaries option. Arrays which are accessed by two composed index functions cause GFortran to create a temporary array.

Here’s a simplified version:

program test
implicit none
integer, parameter :: n=10
integer a(n),b(n),idx(n),i

do i=1,n
  a(i)=i
  idx(i)=n-i+1
end do

b(1:n)=a(idx(idx(1:n)))

print *,b(1:n)

end program

Compiling with

gfortran -O3 -Warray-temporaries -fdump-tree-original test.f90

gives the warning

   12 | b(1:n)=a(idx(idx(1:n)))
      |         1
Warning: Creating array temporary at (1) [-Warray-temporaries]

An inspection of the intermediate representation reveals that GFortran has indeed created a temporary array. The runtime compiler check for the creation of temporary arrays (-fcheck=array-temps) fails to flag this, which has also been reported here and here.

One would hope that the above code would be equivalent to:

program test
implicit none
integer, parameter :: n=10
integer a(n),b(n),idx(n),i

do i=1,n
  a(i)=i
  idx(i)=n-i+1
end do

do i=1,n
  b(i)=a(idx(idx(i)))
end do

print *,b(1:n)

end program

but it appears not to be the case.

In summary, it may be worthwhile checking code with the -Warray-temporaries option and replacing double re-indexing instances with explicit loops.

3 Likes

What happens when you multistep the nested line?

eg;

temp1 = idx(i)
temp2 = idx(temp1)
b(i) = a(temp2)

I’ll wager it does not have to create a temp array because there is no potential to be acting on the array while looking up values.

Have fun!

knarfnarF