I know tanh returns an approximation, not a perfectly rounded answer for all inputs. So it's not surprising when the results vary by platform or by compiler implementation. That's fine.
Nonetheless, it's odd that opt-level alone causes this difference in behavior.
It doesn't seem too hard to make math behave consistently across opt-levels
It's certainly valuable for math to behave consistently
Looking at the assembly, both builds contain a call to tanhf, and both pass the same constant value! How can it be right that they get different answers? Or... is the release build ignoring the result??
Assembly release build has value worked out that it uses.
Why it still calls tanh seems weird. (My guess is whoever added the code for pre calculated result just forgot to remove it.)
OK, that at least seems like it has to be a minor bug. How does it make sense to constant-fold a function call if you're somehow not allowed to optimize the actual call away? Is it calling the function for its side effects?
If I change the method to .exp(), .tan(), .asin(), .sinh(), or .cosh(), the call out to libm is fully optimized away. For .atan(), it's not.
So the optimized one is exactly right (it's the only representable value within ±½ULP of the exact result), but the runtime one is the other answer within ±1ULP.
Thus for me it's not that dirty. I think it's more that I'm sad that the libm isn't doing better. (Though getting these accurate and fast is a seriously hard problem.)