mercredi 11 septembre 2019

floating point comparison with quiet_NaN on GCC with "-ffast-math" always yields true(!)

Under certain circumstances, comparing a normal floating point number with std::numeric_limits<float>::quiet_NaN() always yields "true" when compiled with GCC + "-ffast-math" (tested on Linux and MinGW). On other circumstances it always yields "false" (which would be the IEEE compliant behavior).

If one of the values i known to be a quiet_NaN at compile time, then the behavior is IEEE compliant and branches get optimized away.

I know that "-ffast-math" allows to break IEEE rules and that it implies "-ffinite-math-only" which assumes that there are no NaNs. But even with "-ffast-math" the result of quiet_NaN() has a specific bit pattern (e.g. 7FF80000), so how can a comparison with a normal float like 0.5f possibly yield true?

Here's a code sample showing the different cases. Please compile with "g++ -O3 -ffast-math".

#include <iostream>
#include <limits>

int main() {
#if 1
    // make sure that the value of 'x' is not known at compile time
    bool isnan;
    std::cout << "use nan (0|1): ";
    std::cin >> isnan;
#else
    // otherwise GCC correctly applies IEEE rules for NaN and the branch below is optimized away accordingly
    bool isnan = true;
#endif
    float x = isnan ? std::numeric_limits<float>::quiet_NaN() : 0.5f;
    std::cout << "x: " << x << std::endl;
    float a;
    std::cout << "type a float: ";
    std::cin >> a;
#if 1
    // *always* prints 1 (!)
    std::cout << a << " equal to " << x << ": " << (x == a) << std::endl;
#else
    // always prints false - the opposite from above!
    std::cout << a << " equal to " << x << ": " << ((x == a) ? "true" : "false") << std::endl;
#endif
    return 0;
}

also, here's a godbolt link: https://godbolt.org/z/CKXSxB I guess the relevant part is at line 66 (with "-ffast-math") resp. 67 (without "-ffast-math"). can someone explain to me the difference between those instructions?

is this behavior of GCC acceptable or should I file a bug report?

Aucun commentaire:

Enregistrer un commentaire