I've run into an issue with floating-point comparisons. When comparing a value with NaN using the < operator, I expect the FE_INVALID flag to be set. The < operator should raise the flag according to the C11 standard (and also according to IEEE-754):
The
islessmacro determines whether its first argument is less than its second argument. The value ofisless(x, y)is always equal to(x) < (y); however, unlike(x) < (y),isless(x, y)does not raise the "invalid" floating-point exception whenxandyare unordered.
Here is an example program to reproduce my issue:
#include <stdio.h>
#include <math.h>
#include <fenv.h>
#pragma STDC FENV_ACCESS ON
int main()
{
    volatile float a = 12.0f;
    volatile float b = NAN;
    volatile int   c;
    feclearexcept(FE_ALL_EXCEPT);
    c = (a < b);
    if (fetestexcept(FE_INVALID))
        printf("FE_INVALID\n");
    else
        printf("Not invalid\n");
    return 0;
}
On my machine (Linux, march=broadwell) it returns "Not invalid".
I compiled it using GCC v7.2.0, using the -std=c11 option (not using it didn't change anything in the result). The emitted x86 instruction is UCOMISS which is only raising exceptions for signalling NaNs - I would expect to see COMISS as that would raise the exception on all NaN comparisons, as NaNs are unordered no matter whether they're signalling or not.
Did I make a mistake in my code or forget some compiler option to make the behavior IEEE-compliant? Could it be a bug (or performance optimization) in the compiler to ignore the need to raise an exception here?
