signbit returns false for negative NaN

Hello,

When compiling with a recent version of Clang, the following code

std::signbit(-std::numeric_limits::quiet_NaN())

returns true with optimizations disabled and false with optimizations enabled. Other compilers like GCC and older versions of Clang always return true as expected. Is it a bug or a feature?

I’m using Apple LLVM version 5.1 (clang-503.0.38) (based on LLVM 3.4svn).

Thanks,
Victor

I believe this is likely a bug. std::signbit is defined to behave the
same as the C macro of the same name, which has the footnote, "The
signbit macro reports the sign of all values, including infinities,
zeros, and NaNs. If zero is unsigned, it is treated as positive."

~Aaron

I’ve checked and the same happens with the signbit macro.

Victor

This appears to have nothing to do with signbit, but rather that we are somehow “optimizing” –NaN —> NaN.

int main(int argc, char *argv[]) {
double x = -__builtin_nan("");
printf("%d\t%d\n", signbit(x));
return 0;
}

this prints zero on recent clang (should print 1). Stepping through, x is being set to a positive NaN.– Steve

The standards for C and C++, and consequentially Clang and LLVM, are
terribly underspecified w.r.t. things like NaN behavior. =/ We have seen
this before, and even if we fix it in Clang/LLVM I worry that it will
regress as there are many places where we model NaNs in a manner slightly
too aggressive to be strictly IEEE-754 conforming. =[

Is being IEEE-754 conforming a worthwhile goal? If so, we could talk about how to improve testing to prevent such regressions and find other latent bugs. I would generally argue in favour of conformance, but am not familiar with exactly what the C/C++ rules are. To say this differently, are there important optimizations we don’t want to loose which aren’t conforming? Philip

Is being IEEE-754 conforming a worthwhile goal? If so, we could talk about how to improve testing to prevent such regressions and find other latent bugs. I would generally argue in favour of conformance, but am not familiar with exactly what the C/C++ rules are in this area. Do they even allow full conformance? To say this differently, are there important optimizations we don’t want to loose which aren’t conforming? Philip

The standards for C and C++, and consequentially Clang and LLVM, are terribly underspecified w.r.t. things like NaN behavior. =/ We have seen this before, and even if we fix it in Clang/LLVM I worry that it will regress as there are many places where we model NaNs in a manner slightly too aggressive to be strictly IEEE-754 conforming. =[

Is being IEEE-754 conforming a worthwhile goal? If so, we could talk about how to improve testing to prevent such regressions and find other latent bugs.

I would generally argue in favour of conformance, but am not familiar with exactly what the C/C++ rules are.

C and C++ recommend but do not require IEEE-754 conformance (they define a means for a platform to claim conformance, but do not require that it do so). At least within Apple, we’ve historically put a fair bit of effort into maintaining IEEE-754 conformance, at least when it comes to the semantics of basic arithmetic in default rounding (like this case does).

To say this differently, are there important optimizations we don't want to loose which aren't conforming?

We have relaxed modes (-ffast-math and friends) that license those optimizations. The default mode should conform as much as reasonably possible.

– Steve

This turns out to be a bug in APFloat. I'll post a patch to llvm-commits in a minute.

– Steve

Thanks for fixing this.

  • Victor

No problem, thanks for the simple report.

– Steve