flang-21 produces NaN and Inf when it should not, randomly

2 min read Original article ↗

With flang-21, the code at the end of the post generates NaN and Inf unexpectedly and randomly.

The behavior can be reproduced by the following bash script.

rm -f a.out
uname -a
flang --version
flang -fstack-arrays -std=f2018 -O3 -ffast-math -g test_div_flang.f90
# Run a.out 5 times to demonstrate the random NaN/Inf generation behavior
for i in {1..5}; do
    echo "Run $i:"
    ./a.out
done

N.B.:
0. The -ffast-math flag is being used. I know, this is not recommended in practice, and it may give rise to un-mathematical results. However, the resutls should be deterministic.

  1. Keeping -ffast-math, different combinations of the compilation flags will lead to different results.

  2. Here are the results in my tests:

    **The results are not always the same across the runs. Look carefully :) **

  3. The above results can be reproduced by forking https://github.com/zequipe/flang_ranom_nan and running the GitHub Actions.

Thank you for taking a look.

Code:

! test_div_flang.f90
program test_div_flang
use iso_fortran_env, only : RP => REAL32

implicit none

! The code may behave differently depending on the dimension of the array. Try them.
real(RP) :: a(14), b(14), c
a =  [0., 0., 7.E-45, 7.E-45, 0., 5.E-45, 0., 5.E-45, 5.E-45, 0., 0., 0., 0., 5.E-45]

!real(RP) :: a(9), b(9), c
!a =  [5.E-45, 0., 5.E-45, 5.E-45, 0., 0., 0., 0., 5.E-45]
!
!real(RP) :: a(8), b(8), c
!a =  [0., 5.E-45, 5.E-45, 0., 0., 0., 0., 5.E-45]

b =  a / maxval(abs(a))
c =  maxval(abs(a))

print *,  '>>> Dimension = ', size(a)

print *, a/maxval(abs(a)), '|', b
print *, (a/maxval(abs(a)))**2, '|', b**2
print * , '------------------'
print *, a, '|', a/maxval(abs(a)), '|', b
print *, a, '|', (a/maxval(abs(a)))**2, '|', b**2

print * , '=================='

print *, a/c, '|', b
print *, (a/c)**2, '|', b**2
print * , '------------------'
print *, a, '|', a/c, '|', b
print *, a, '|', (a/c)**2, '|', b**2

end program test_div_flang