-ffast-math' [...] this option should never be turned on together with any `-O' option since it can result in incorrect output for programs which depend on an exact implementation of IEEE or ISO rules/specifications for math functions.
That is not quite right. The documentation says that no
-O option should ever turn this switch on (i.e. if you specify
-O3, then this will not enable
-ffast-math behind your back, unless there is an error in gcc), and indeed you can use
-O3 with
-ffast-math without any problems. It is just that a program compiled with any
-O options is still standard-conformant and guarantees a certain behaviour under clearly defined conditions, while a program compiled with unsafe options makes no such claims.
However, it is noteworthy that
-funsafe-math cannot produce, but
will always produce incorrect results/behaviours. Whether or not those wrong results/behaviours really matter or not depends on the situation, but they are always wrong.
For example, the compiler may simply assume that any input given to a mathematical function is always good and valid, even though if your actual input possibly produces nonsense output.
Or, the compiler may truncate floating point numbers instead of rounding, or it will tell the CPU to treat non-normalized numbers simply as zero.
For some applications this is utterly bad. For many others, it does not matter at all, even though it is technically wrong.
Similar issues arise with floating point numbers every day (even without optimisations), as a certain kind of "uncertainity" is always inherent to floating point numbers. For example, a floating point value in a register is usually not the same as a floating point value in memory that has gone through the same calculations,
and the value in a register will generally not be the same after storing the register to memory and reading it back. Even though common sense tells you that writing a register to memory and reading it back must yield the identical value, that's not the case.
This is because floating point numbers in memory are 32 or 64 bits wide, but FPU registers are internally 80, 96, or 112 bits (or can be 32 bits, if you use SSE math).
Thus, with
-funsafe-math, you only make a thing that's blurry already a bit more blurry