You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
This example is miscompiled by reordering the call to f(j, a) between two fesetround calls. There are at least two different bugs here (for the testcase with inlining disabled and the testcase with inlining enabled):
With inlining disabled, the call to function f is reordered past a call to function fesetround. 'f' is attributed as 'readnone' (plus 'willreturn nounwind'), so this transform superficially appears correct, but is not: we can't reorder a function that reads the FP environment past a function that changes the FP environment (at least, not within a 'strictfp' function). It's not clear to me whether it's wrong to mark 'f' as 'readnone', or whether we should track the FP environment separately from reads of memory, but I suspect the latter might be a better choice.
With inlining enabled, the inliner adds an 'fadd' instruction to 'g'. That's wrong: 'fadd' can be freely reordered past function calls, but we certainly don't want to allow 'fadd' to be reordered past a call to 'fesetround'. I think the right approach here is that the inliner should produce constrained FP intrinsic calls (assuming the default rounding mode) when inlining into a 'strictfp' function.
As a complementary problem to (2), we also have:
Inlining a constrained FP intrinsic call into a non-'strictfp' function should convert the constrained FP intrinsic call into an unconstrained instruction. This is important because we need to emit the libc++ wrapper functions around C math functions as 'strictfp', and don't want that to be a pessimization.
... produces wrong results with Clang+libc++ (and also with Clang+libstdc++), because std::rint is built with FENV_ACCESS OFF, so its call to rint is treated as unconstrained. We could fix that by using FENV_ACCESS ON in libc++'s <math.h> wrapper, but that will pessimize all FENV_ACCESS OFF calls unless the inliner is able to undo that when inlining into non-strictfp functions.
The text was updated successfully, but these errors were encountered:
Extended Description
Testcase:
https://godbolt.org/z/E8Kje7
This example is miscompiled by reordering the call to f(j, a) between two fesetround calls. There are at least two different bugs here (for the testcase with inlining disabled and the testcase with inlining enabled):
With inlining disabled, the call to function f is reordered past a call to function fesetround. 'f' is attributed as 'readnone' (plus 'willreturn nounwind'), so this transform superficially appears correct, but is not: we can't reorder a function that reads the FP environment past a function that changes the FP environment (at least, not within a 'strictfp' function). It's not clear to me whether it's wrong to mark 'f' as 'readnone', or whether we should track the FP environment separately from reads of memory, but I suspect the latter might be a better choice.
With inlining enabled, the inliner adds an 'fadd' instruction to 'g'. That's wrong: 'fadd' can be freely reordered past function calls, but we certainly don't want to allow 'fadd' to be reordered past a call to 'fesetround'. I think the right approach here is that the inliner should produce constrained FP intrinsic calls (assuming the default rounding mode) when inlining into a 'strictfp' function.
As a complementary problem to (2), we also have:
Right now:
#include
#pragma STDC FENV_ACCESS ON
float f() { return std::rint(10.5); }
... produces wrong results with Clang+libc++ (and also with Clang+libstdc++), because std::rint is built with FENV_ACCESS OFF, so its call to rint is treated as unconstrained. We could fix that by using FENV_ACCESS ON in libc++'s <math.h> wrapper, but that will pessimize all FENV_ACCESS OFF calls unless the inliner is able to undo that when inlining into non-strictfp functions.
The text was updated successfully, but these errors were encountered: