Indeed GCC does not enable -ffast-math by default. Unfortunately, -ffast-math and -funsafe-math-optimizations (despite the name) are
not the only options that prevent bit-for-bit-reproducible floating point. For example, -ffp-contract=fast is enabled by default [1], and it will lead to different floating-point roundings: Compare [2] which generates an FMA instruction, to [3] when -std=c99 is specified. As another example, -fexcess-precision=fast is also enabled by default. Similarly, [4] does intermediate calculations in the 80-bit x87 registers, while [5] has additional loads and stores to reduce the precision of intermediate results to 64 bits. In both examples, GCC generates code that does not conform to IEEE-754, unless -std=c99 is specified.
[1] From the man page:
-ffp-contract=style
-ffp-contract=off disables floating-point expression
contraction. -ffp-contract=fast enables floating-point
expression contraction such as forming of fused multiply-
add operations if the target has native support for them.
-ffp-contract=on enables floating-point expression
contraction if allowed by the language standard. This is
currently not implemented and treated equal to
-ffp-contract=off.
The default is -ffp-contract=fast.
[2]
https://godbolt.org/z/GKb7G4nW9[3] https://godbolt.org/z/KTnqcT6aW
[4] https://godbolt.org/z/4q31oEe14
[5] https://godbolt.org/z/qdf4hceca