I'm using Version 17.0.1.143 Build 20161005 with visual studio 2013. When floating point exceptions are unmasked, the following program produces the INVALID floating point exception when compiled with the given command line:
program m integer, parameter :: n = 2 real b(n) b = (/ 5.3359774e-5, 5.5001899e-5 /) call a( b, n ) end program m subroutine a ( b, n ) integer n real b(n) double precision t integer i do i = 1, n t = dble( -b(i) ) b(i) = sngl( exp(t) ) end do end subroutine a
Compile with:
ifort /fp:strict /QxAVX /Qvec-threshold0 /fpe0 /O2 /Z7 /MD well.F90 /link /map /nodefaultlib:libmmd
And run it:
> well forrtl: error (65): floating invalid Image PC Routine Line Source MSVCR120.dll 00007FFE1E27CADF Unknown Unknown Unknown well.exe 00007FF6CF18108D Unknown Unknown Unknown well.exe 00007FF6CF18258E Unknown Unknown Unknown well.exe 00007FF6CF183E87 Unknown Unknown Unknown KERNEL32.DLL 00007FFE2B8913D2 Unknown Unknown Unknown ntdll.dll 00007FFE2B9E54E4 Unknown Unknown Unknown
This set of options appears to cause two confounding things to happen: 1) the loop in subroutine a is vectorized and 2) instead of the implementation of exp() in the Intel libm, you get the exp() in MSVCRT. The vectorization of the loop involves loading two double values into an XMM register (say xmmX). Since exp() is not the vectorized version, it first loads the low quadword of xmmX into the argument register for exp() (namely xmm0). If there is more than one element in b, then it uses pshufd xmm0,xmmX,0eh to put the high quadword of xmmX in xmm0. This may also put some non-zero bits in the high quadword of xmm0. The MSVCRT implementation of exp() doesn't really like this; at some point it (pointlessly) tries to convert the high quadword of xmm0 into a 32-bit integer, which, depending on the exact bit pattern, may produce an invalid integer.
I think the code in MSVCRT exp() is clearly wrong; it shouldn't be converting unused values. But, I don't know that the Fortran should be supplying the argument in xmm0 with a non-zero high quadword either. What do you think? Is this a bug in the Fortran?
Thanks,
Allen