3 ms·
FTA: As a workaround, the following function should do: bool rounds_to_nearest() noexcept { static volatile float fmin = 1e-38; return (fmin + 1.0f =
by Someone 4y ago
FTA: As a workaround, the following function should do:
bool rounds_to_nearest() noexcept {
static volatile float fmin = 1e-38;
return (fmin + 1.0f == 1.0f - fmin);
}
We declare the small value to be volatile: this asks the C/C++ compiler to load the variable each time it needs to access it. It prevents the compiler from optimizing away the function at compile time. The compiler is forced to recompute the function each time.
I don’t think that, technically, is true. Yes, the compiler must load the variable, but I don’t see how it is required to do the addition, the subtraction, or the comparison.
I think the compiler could, in theory, detect that fmin never gets changed from its initial value (not too hard, given that it is local to that small function), do some constant folding, and compile the function as (in pseudocode):
load fmin
load fmin
return true
- deleted 4y ago[deleted]
- mwalcott3 4y agoIt cant "detect that fmin never gets changed from its initial value". The standard: "C11 § 6.7.3 Type qualifiers ¶ 7 An object that has volatile-qualified type may be modified in ways unknown to the implementation or have other unknown side effects." Just a note but http://eel.is/c++draft/dcl.type.cv#6 http://eel.is/c++draft/dcl.type.cv#6: "volatile is a hint to the implementation to avoid aggressive optimization involving the object because the value of the object might be changed by means undetectable by an implementation." So it doesn't matter if it can prove nothing in the code could modify the variable. volatile tells it has no way of knowing what the value is because something external to the program may change it aka "undetectable/unknown by an implementation". It is true that it can optimize away calculations using a volatile variable while keeping the accesses if the result is not used. But it cannot fully optimize away calculations using volatile variables if the result is used because it cannot assume the volatile value doesn't change. You can see this in practice with the following code on a modern compiler like clang with O3 #include <cfenv> #include <iostream> #include <limits> inline bool rounds_nearest() { volatile static float fmin = std::numeric_limits<float>::min(); auto a = fmin + 2.0f; return (fmin + 1.0f == 1.0f - fmin); } int main() { std::cout << rounds_nearest() << std::endl; } https://godbolt.org/z/TPKWGa3sM https://godbolt.org/z/TPKWGa3sM (fmin + 2.0f) never gets calculated because a never gets used but an extra movss gets added to preserve the access of the volatile variable. If the compiler can prove you never use the result of a calculation using a volatile it could optimize the calculation away. But if you use the result it will not get optimized away. If you remove cout but still call the rounds_nearest function then you will see all calculations get removed but the accesses will remain.