-
-
Notifications
You must be signed in to change notification settings - Fork 273
Description
The compiler can unexpectedly rearrange floating point operations and access to the floating point status flags when optimizing. This means std.math ieeeFlags cannot be reliably checked in optimized code. Consider:
void main()
{
import std.math;
static real zero = 0.0;
real x = 3.5;
resetIeeeFlags();
assert(!ieeeFlags.invalid);
x /= zero;
x *= zero;
assert(ieeeFlags.invalid); // optimizer may moves this before div and mult
assert(isNaN(x));
}Here, optimizer moves function call ieeeFlags() before math ops, and invalid is not set as expected.
This has been observed with LLVM 3.6 targeting arm and x86-64, and other combinations may be affected to. Right now it is cause a new 2.067 unittest in std.math to fail.
C99 invented "#pragma STDC FENV_ACCESS ON" to prevent optimizer from reordering instructions that affect float environment. See note [2] here: http://en.wikipedia.org/wiki/C99#Example
clang does not support this pragma and LLVM IR has no way of expressing:
https://llvm.org/bugs/show_bug.cgi?id=10409
This also could be an issue for gdc as this reference says gcc doesn't support pragma FENV_ACCESS:
http://wiki.musl-libc.org/wiki/Mathematical_Library#Fenv_and_error_handling
Work around in C is to use volatile vars to force ordering and libm.h has a FORCE_EVAL macro to do that.