Examining performance in Instruments, I found a hot spot calling x.isNaN, and timing showed a significant improvement in a performance-sensitive section replacing that with x != x.
Is there any difference if nothing creates signalling NaNs?
Does anything in Swift create signalling NaNs?
The specific code was in an interval value type, replacing var isNaN: Bool { min.isNaN || max.isNaN }
with var isNaN: Bool { min != min || max != max }
I encountered this tracking down a performance problem in a generic function which did not inline Interval.isNaN when specialized on Interval. Separately, how can I encourage the compiler to inline Interval.isNaN in the specialization?
Thank you. That "fixes" the issue with it not being inlined in the specialization. Though, as discussed in When should both @inlinable and @inline(__always) be used? - #2 by scanon, I need to consider whether the particular test case I'm looking at is representative or whether the code expansion of forcing inline will hurt performance elsewhere.
Yeah n != n will generate a UCOMISD instruction, which signals for SNANs. It exactly matches what Clang and GCC produce using isnan from math.h, with -fsignaling-nans (I don't think GCC actually supports it - really, isnan shouldn't signal).
Swift does a lot more work, but doesn't use any FP instructions so correctly doesn't signal.
IIRC, no normal math operations should ever produce a signalling NaN. It should always be something the user explicitly creates.