-
Notifications
You must be signed in to change notification settings - Fork 13.4k
clang/llvm don't support C99 FP rounding mode pragmas (FENV_ACCESS etc) #8472
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
Comments
Lack of proper support for fp rounding has come up before, so I'm sure this bug |
The closest I could find is bug 3929 which asks for the FENV pragmas in llvm-gcc. Complete C99 fenv support in llvm+clang would be great, but an option like gcc's -frounding-math that disables some optimizations seems easier to achieve. (I may have missed a real duplicate, I am not good at using bugzilla) |
*** Bug llvm/llvm-bugzilla-archive#8241 has been marked as a duplicate of this bug. *** |
Note that this impacts properly building packages like ppl 0.11.2 which expect functional -frounding-math support. Currently the only viable workaround when using the clang compilers is to build ppl with --disable-fpmath which reduces the functionality of the package. |
Does even -O0 fail? In CGAL, every operation where rounding matters is done through macros which with clang go through volatile variables or asm statements to prevent broken optimizations. It is slow. |
*** Bug llvm/llvm-bugzilla-archive#10409 has been marked as a duplicate of this bug. *** |
*** Bug llvm/llvm-bugzilla-archive#12958 has been marked as a duplicate of this bug. *** |
*** Bug llvm/llvm-bugzilla-archive#16202 has been marked as a duplicate of this bug. *** |
*** Bug llvm/llvm-bugzilla-archive#17088 has been marked as a duplicate of this bug. *** |
*** Bug llvm/llvm-bugzilla-archive#22271 has been marked as a duplicate of this bug. *** |
*** Bug llvm/llvm-bugzilla-archive#22873 has been marked as a duplicate of this bug. *** |
*** Bug llvm/llvm-bugzilla-archive#23707 has been marked as a duplicate of this bug. *** |
Test cases using rint() and nearbyint() from <math.h> It looks to me like the compiler gets it right when the rounding mode is known at compile time. The attached test produced the following output for me:
The first time the rounding mode comes from an array, the second time it's set to a literal value. |
This violates both C99 and C++11/14. COMPILER PRODUCES INCORRECT CODE. Why is this not a release breaker? This is much worse than failing to compile valid code. This is compiling valid code into something unintended. |
You are mistaken. Setting the rounding mode without using #pragma STDC FENV_ACCESS ON invokes undefined behavior. See C11 7.6.1/2. (This pragma does not exist in C++, so is unusable, but that's not our fault...) Clang doesn't support that pragma, making this an unimplemented feature from C99, for which we will produce a warning or error. That's the subject of this enhancement request. |
*** Bug llvm/llvm-bugzilla-archive#26931 has been marked as a duplicate of this bug. *** |
I just hit this issue and I've attached a test case (interval.c) that Clang mis-compiles. It appears that when Clang is optimizing (-O3) it changes two separate fadd instructions that use a different rounding mode into a vectorized add using the wrong rounding modes. Correct
Incorrect
What surprised me a bit is that if I compile the test case with |
What's it going on? |
*** Bug llvm/llvm-bugzilla-archive#39112 has been marked as a duplicate of this bug. *** |
*** Bug llvm/llvm-bugzilla-archive#40954 has been marked as a duplicate of this bug. *** |
With regards to the resolution of Bug 40954, is this the intended duplicate bug? I'm confused as my reported bug report doesn't use rounding modes. It was a LICM miscompile as an fdiv (that can raise an exception) was moved with respect to its control-flow dependence. |
Hi, Eric. This bug is serving as a catch all for a general class of problems related to the fact that LLVM treats FP operations as not having side effects. I'll explain why below. We are working on a general solution to this problem which when fully implemented will fix the problem that you reported. The fact that LLVM treats FP operations as not having side effects is an intentional design decision. It enables better optimization of floating point code in the case where exceptions are not being unmasked and the status flags are not being checked, which we believe to be the case that the majority of clang and LLVM users care about. If you look at the LLVM language reference you will find intrinsics defined for constrained versions of the FP operations. This is the approach we are taking to solve the side effect problem. From the perspective of LLVM IR, it is undefined behavior to unmask FP exceptions, read FP status flags, or change FP control flags when you are not using these intrinsics. (More precisely, I think it is the interaction between the FP environment and the non-constrained FP operations that is undefined.) Similarly the C99 standard says that implementations are free to assume the default FP environment (round to nearest, no exceptions unmasked) and that the status flags will not be tested outside of scopes in which the FENV_ACCESS pragma state is "off". That's why your bug falls under the scope of this one. |
*** Bug llvm/llvm-bugzilla-archive#44302 has been marked as a duplicate of this bug. *** |
Clang does not need to support it to behave correctly, see below.
There are 2 ways to conform to C99:
|
Vincent, we are not lawyers trying to get our client off on a technicality, we want useful behavior for users.
Ok, this one would help, it is gcc's -frounding-math -ftrapping-math (although it doesn't really work in gcc), but implementing it properly is likely almost as hard as supporting the pragma.
This one would be counterproductive. We use rounded operations with clang every day, by placing optimization barriers (inline asm) around each such operation. Removing FE_UPWARD, while it would make the implementation conforming, would complicate things for us, we would have to reimplement the very platform-specific fesetround on every platform we support... |
Entirely agreed. But returning incorrect results is definitively not useful for users, and actually very bad.
AFAIK, -frounding-math works correctly in GCC if the user uses a single rounding mode in his code. At least, that's how it is documented.
Then perhaps this should be under the control of a compiler option, and the macros could be undefined by default at least in ISO C strict modes. I doubt that every developer who needs directed rounding modes places optimization barriers around each FP operation. This is error prone (it is very easy to forget one) and makes the code more tedious to write and difficult to read. Directed rounding modes are essentially there to get guaranteed results (interval arithmetic, error bounds...), so that even getting a slightly incorrect result is rather a critical issue. |
Yes.
Gcc's manpage says "This option should be specified for programs that change the FP rounding mode dynamically" and doesn't mention this restriction of "use a single rounding mode", or I didn't look in the right place.
I don't care about C (only C++) so I won't fight that, but I'd rather spend energy moving epsilon closer to an implementation of the pragma than spend it removing useful, if misleading, macros.
They do if they use clang and care about correctness...
With wrappers, it isn't that error prone.
Yes, but that's an argument for implementing the feature, not removing the little that is there. |
FWIW, I think we're close to having this working on several architectures and any other architectures that want to enable it have several examples to follow for the backend changes that are needed. The -fp-model=strict option puts us in a mode when FENV_ACCESS is on everywhere without the pragma. There's a patch up to support the pragma (https://reviews.llvm.org/D69272). There are problem a bunch of corner cases that we're missing, but for the most part I believe it is basically functional and in no place is it functionally worse than it was before. Try it out. File new bugs. The one big caveat is that we're not currently doing anything to optimize the constrained FP code well. The way it's implemented basically turns all FP operations into black boxes and optimizations will need to be taught to handle them in light of the constraints. We have some ideas for that, but I don't think much, if anything, has been done. |
*** Bug llvm/llvm-bugzilla-archive#45722 has been marked as a duplicate of this bug. *** |
*** Bug llvm/llvm-bugzilla-archive#46799 has been marked as a duplicate of this bug. *** |
mentioned in issue llvm/llvm-bugzilla-archive#8241 |
…Dylan-DPC Document rounding for floating-point primitive operations and string parsing The docs for floating point don't have much to say at present about either the precision of their results or rounding behaviour. As I understand it[^1][^2], Rust doesn't support operating with non-default rounding directions, so we need only describe roundTiesToEven. [^1]: rust-lang#41753 (comment) [^2]: llvm/llvm-project#8472 (comment) This PR makes a start by documenting that for primitive operations and `from_str()`.
Document rounding for floating-point primitive operations and string parsing The docs for floating point don't have much to say at present about either the precision of their results or rounding behaviour. As I understand it[^1][^2], Rust doesn't support operating with non-default rounding directions, so we need only describe roundTiesToEven. [^1]: rust-lang/rust#41753 (comment) [^2]: llvm/llvm-project#8472 (comment) This PR makes a start by documenting that for primitive operations and `from_str()`.
[lldb] Support frame variable for generic types in embedded Swift
LLVM bugzilla bug 8100 became issue #8472 with the migration to GitHub. llvm/llvm-project#8472
LLVM bugzilla bug 8100 became issue #8472 with the migration to GitHub. llvm/llvm-project#8472 (cherry picked from commit 92927b8)
LLVM bugzilla bug 8100 became issue #8472 with the migration to GitHub. llvm/llvm-project#8472 (cherry picked from commit 92927b8)
LLVM bugzilla bug 8100 became issue #8472 with the migration to GitHub. llvm/llvm-project#8472
LLVM bugzilla bug 8100 became issue #8472 with the migration to GitHub. llvm/llvm-project#8472 (cherry picked from commit 92927b8) (cherry picked from commit 6cd4450)
Extended Description
Hello,
consider this code:
#include <fenv.h>
#include <assert.h>
int main(){
double a=1.1;
double b=10.1;
fesetround(FE_UPWARD);
assert(-((-a)b)!=ab);
}
Excessive optimization will remove the double negation. gcc has option -frounding-math to help with this. Intel's -fp-model strict is not quite as good (it fails for this example) but it helps (for instance it lets the code work if I write 1.1 and 10.1 instead of a and b in the assertion). With llvm-gcc or clang, this always fails at -O1.
A similar option for llvm would be very welcome, there are applications where rounding in the appropriate direction is crucial (precision and speed come far behind).
The text was updated successfully, but these errors were encountered: