-
Notifications
You must be signed in to change notification settings - Fork 12.1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Bad floating-point "optimizations" #43070
Comments
Currently clang and llvm assume that floating point generates no side effects. There is work in progress to teach llvm and clang to be strict with floating point so many optimizations don't fire. If you want to follow the progress the tickets at reviews.llvm.org tend to have "[FPEnv]" in the name somewhere, and this is sometimes true for the mailing lists as well. See also the "constrained floating point intrinsics" in the Language Reference: https://llvm.org/docs/LangRef.html#constrained-floating-point-intrinsics |
I am glad to see that some work is being done on this issue. However, it appears to me that those intrinsics would not work for integer bit fields with respect to raising invalid for FP numbers too big to fit. |
It is a work in progress. I haven't looked at bitfields, but this ticket may get us closer: "Add constrained int->FP intrinsics" |
Command line options for clang to try to get good floating-point conformance |
With those command line options, the test case I tried those options after reading bug 8100. |
For what it's worth, I don't think this is enough to justify turning If you want to justify this transformation, you need to also treat all NaNs as quiet NaNs. This is a reasonable simplifying assumption for LLVM to make, but it should be made explicitly. |
The Language Reference says this about the default FP env: https://llvm.org/docs/LangRef.html#floatenv Suggestions welcome if that text is not clear. Otherwise, I think we can close this bug now. "Strict" FP is supported for multiple targets. If anything is still broken in that mode, there should be narrower bugs filed with examples to show a problem. |
The only thing that's a little weird for non-strict FP is that if we optimize |
This was in fact exactly my point; if reducing FWIW,
Personally, I'm perfectly agreeable with a resolution of clarifying that non- Additional but unnecessary nice-to-haves:
I'll probably make a fresh issue for all of the NaN clarifications that I'm aware of us (Rust) wanting from LLVM, since it's not just the sNaN semantics covered by this issue. |
Regarding I suspect the reason alive2 considers this valid is because the SMT-LIB floating-point theory does not differentiate between different kinds of NaNs. Also @CAD97 your last example link points to the alive2 run. |
To be clear, this is about more than "x * 1.0" alone. As noted in the original problem report, we allow several FP simplifications that ignore converting SNaN to QNaN. Here's an incomplete sampling of FP transforms that are allowed in LLVM's default FP environment: Proposal to update the LangRef text to make it clearer that those are expected transforms: "The default LLVM floating-point environment assumes IEEE754-compliant operations except that floating-point instructions do not have side effects. Results assume the round-to-nearest rounding mode. No floating-point exception state is maintained in this environment. Therefore, there is no guarantee that exceptions or their associated state (signaling NaN values) are created, cleared, or preserved. All NaN values are treated as quiet values, but otherwise they are propagated according to IEEE754 rules. The benefit of this exception-free assumption is that floating-point operations may be speculated freely without any other fast-math relaxations to the floating-point model." |
There seems to be some confusion about how exceptions and signaling NaNs relate there. An sNaN is a NaN value that always causes the "invalid operation" exception to be raised when you try to operate on it, not a kind of NaN that is produced by things signaling exceptions. It's not associated state, and it can only be created by directly specifying it in the source code or casting the right value from an integer. (Under default exception handling, IEEE 754 mandates that a float-producing operation that signals an invalid operation exception must deliver a qNaN.) Note that the invalid operation exception is also raised whenever you compute 0/0 or ∞ - ∞, and it's the default handling of that exception that produces the qNaN. |
I'm not sure how to word it better, but here's an attempt: |
Make it explicit that SNaN is not handled differently than QNaN in the LLVM default floating-point environment. Note that an IEEE-754-compliant model disallows transforms like "X * 1.0 -> X". That is because math operations are expected to convert SNaN to QNaN (set the signaling bit). But LLVM has had those kinds of transforms from the beginning: https://alive2.llvm.org/ce/z/igb55y We should be IEEE-754-compliant under strict-FP (the logic is implemented with a helper named canIgnoreSNaN()), but I don't think there is any demand to do that with default optimization. See issue #43070 for earlier draft/discussion about this change. Differential Revision: https://reviews.llvm.org/D143074
We made the documentation clearer, so closing this. If there are still problems, please file new issues with specific examples/requests. |
Extended Description
Is there a way to disable ALL "optimizations" related to floating-point?
My testing has shown that clang does the following:
They are all invalid "optimizations" if x is a signaling NaN.
In addition, some are invalid if x is a signed zero or infinity.
In the above, 'x' can be either a variable or a constant.
It might matter if 'x' is float, double, or long double.
The text was updated successfully, but these errors were encountered: