Optimizing compilers are usually used with flags that cause them to break IEEE754.
Still, it would be nice if results from low-optimization runs might be bit-exact.
Optimizing compilers are usually used with flags that cause them to break IEEE754.
Still, it would be nice if results from low-optimization runs might be bit-exact.
For languages that don't mandate IEEE-754. There are plenty of languages that do, like Java, JavaScript, C#, and WebAssembly.
It's worth noting that usually such optimizations are things like enabling algebraic reassociation and commutation (of primitives like +, -, /, ==, etc) operations, fused-multiply add, and others. It's really not clear to me how much disabling all those optimization costs in the real world.
Things get crazy when compilers want to do major reorganization of loops, optimizing stencils, polyhedral optimizations. I am not an expert here, but I think these rely on properties of float arithmetic that don't hold in all cases, i.e. they rely on UB.
I assure you that SPECcpu scores are a lot lower, if that's what you care about. And yes, it's extremely helpful to do major reorganization of loops if the program has multi-dimensional loops in the wrong order.
However, as far as I understand, specifying a proper language standard (for example -std=c99, -std=c++14, etc.) restores sane behavior (see -ffast-math, and more specifically -fexcess-precision).
Are there other cases where -O3 breaks IEEE754 on modern setups?
The dark underside of IEEE 754 is that full support for it also requires features that most languages don't provide access for: rounding mode and exception handling (aka sticky bits). In C/C++, using these features correctly requires STDC FENV_ACCESS support which is only in ICC and recent clang (neither GCC nor MSVC support it). And there's usually two hardware bits for handling denormals (flush-to-zero and denormals-are-zero) that aren't in IEEE 754, which tend to be on by default when you're compiling for some targets (most notably GPUs).
[1] https://software.intel.com/content/www/us/en/develop/documen... -- note fp-model=fast=[1|2]
E.g.:
void foo(int N) {
for (int i = 0; i < N; i++) {
#pragma STDC FENV_ACCESS ON
// This applies only to the for loop...
}
// But not here, for example!
}This is not always true. Some FMA operations round after the multiply, and some do not.