fortrancompiler-optimizationgfortrando-loops

How does gfortran with optimization flags interpret nested implied do loops?


I have an issue with gfortran that I am trying to understand on a general level to avoid encountering it again in the future. Specifically, I am trying to understand the behavior of nested implied do loops when reading in data and how this is affected by gfortran optimization flags.

As part of a larger program that I am modifying, I am trying to read in some data and store them in a matrix, sttheight, which in my specific case is a vector given the dimensions of the variables used when allocating it. A minimum working example showing the issue is given below.

The problem is pertaining to the nested implied do loop construct used when reading the variable from the input-file. When compiling the program with gfortran Read_fct.f90 -o Read, and running it, it produces the desired output, which is printing the 8 floating point variables in Input.txt:

   0.00000000       14370.0117       14370.0117       14370.0117       14370.0117       14370.0117       14370.0117       14370.0117  

I'm using: "GNU Fortran (GCC) 12.2.0 20220819 (HPE)"

However, if I compile it with gfortran -O2 Read_fct.f90 -o Read, the output is "0.00000000" printed 8 times. The same is obtained with -O1 or higer optimization flags (-O3 to -O5). The program does not throw any errors or warnings which means that the issue can easily be overlooked. Further debugging by gfortran -O2 -g -fcheck=bounds Read_fct.f90 -o Read reveals the source of the error:

At line 18 of file Read_fct.f90
Fortran runtime error: Index '0' of dimension 1 of array 'noheight' below lower bound of 1

I.e. it seems that the program attempts to initialize noheight(jpuff), before assigning a value to jpuff. So for this specific case, I can easily resolve the issue, but that would make my code less general, possibly introducing other issues down the line. Also, having spent several hours trying to locate the problem, I would like to understand the underlying issue to reduce my chances of encountering this problem again.

Compiling with -O3 with both: "Cray Fortran : Version 16.0.1" and "ifort (IFORT) 2021.7.1 20221019" leads to the intended behavior of printing the correct floating point values.

So in short: 1) Is something wrong with my code, 2) is this the expected behavior with gfortran's optimization flags or 3) is this a bug in gfortran? The latter seems unlikely to me, but I guess that nothing is impossible.

I hope someone will be able to point me in the right direction here.

MWE:

Read_fct.f90:

program Read_fct
implicit none
integer ::  ntraj, mpuff
integer :: jheight, jt, jpuff
real,allocatable :: sttheight(:,:,:)

integer, dimension(:), allocatable :: noheight

open(1, file='Input.txt')
ntraj = 8
mpuff = 1

allocate(noheight(mpuff))
noheight(1) = 1

allocate(sttheight(noheight(1), ntraj, mpuff))

read (1,*) (((sttheight(jheight,jt,jpuff),jheight=1,noheight(jpuff)),jt=1,ntraj),jpuff=1,mpuff)
write(*,*) sttheight
close(1)
end program

The file "Input.txt" has only a single line with the data I am trying to read:

0.00000000,14370.01149861,14370.01149861,14370.01149861,14370.01149861,14370.01149861,14370.01149861,14370.01149861     ! sttheight

Edit: implicit none included and ierr removed accordingly


Solution

  • The program can be greatly simplified, this is the MRE I came up with

    program implied_do_bug
    implicit none
    integer :: i,j,k
    real :: arr(1,1,1)
    integer :: ni(1)
    
    ni(1) = 1
    arr = 1
    
    write(*,*) (((arr(i,j,k), i=1,ni(k)), j=1,1), k=1,1)
    end program
    

    I have submitted this into the GCC Bugzilla as a likely compiler bug that is a regression as bug 111837.

    According to the replies, a workaround is to disable frontend optimizations by -fno-frontend-optimize.