I found a way to “break” do
-loops.
Consider this example, which approximates a loop from 1
to infinity:
integer :: i
do i=1, huge(i)
! ...
The do
-loop should calculate the iteration count, decrease it until it reaches zero and then exit the loop (11.1.7.4.5 j3).
This shouldn’t be a problem, because the iteration count starts at huge(i)
which is the largest possible integer of the given type. It is decreased until it reaches zero, so there cannot be any over- or underflow.
However with gfortran
, ifort
and nagfor
such a loop never exits. Only with pgfortran
it terminates.
To round things up, I tested another loop, which goes from -1
till huge(i)-1
. Here gfortran
, ifort
and nagfor
had no problem, although an iteration count with the same kind like i
would overflow (11.1.7.4.1(3) m2 - m1
). In contrast pgfortran
immediately stopped the loop.
Therefore I assume that pgfortran
is the only compiler (of the four I tested) which behaves exactly like the specification defines a do
-loop.
Interestingly the assembly of the gfortran
reveals, that there is an unconditional jump (jmp). So it isn’t even an overflow, but the compiler translates do i=1,huge(i)
to an endless loop:
assembly
# a.f90:7: do i=1,huge(i)
movl $1, -4(%rbp) #, i
.L4:
# a.f90:7: do i=1,huge(i)
movl -4(%rbp), %eax # i, i.5_4
addl $1, %eax #, _5
movl %eax, -4(%rbp) # _5, i
jmp .L4 #
.cfi_endproc
test program
integer :: i
do i=-1,huge(i)-1
end do
print "(a,i0)", "'do i=-1,huge(i)-1' exits with i=", i
do i=1,huge(i)
end do
print"(a,i0)", "'do i=1,huge(i)' exits with i=", i
end
Output
Output (gfortran
, ifort
, nagfor
):
'do i=-1,huge(i)-1' exits with i=2147483647
second loop does not exit
Output(pgfortran
):
'do i=-1,huge(i)-1' exits with i=-1
'do i=1,huge(i)' exits with i=-2147483648
Compiler Versions
gcc version 7.4.0 & 11.2.0
ifort version 19.0.2.187
nag 7.0
pgfortran 20.1-0