Quantcast
Viewing all articles
Browse latest Browse all 415

Floating point exception in MSVCRT

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


Viewing all articles
Browse latest Browse all 415

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>