3

My colleague showed me the following macro from the LLVM source code:

#define IMPLEMENT_UNORDERED(TY, X,Y)                                         \
    if (TY->isFloatTy()) {                                                   \
        if (X.FloatVal != X.FloatVal || Y.FloatVal != Y.FloatVal) {          \
            return Dest;                                                     \
        }                                                                    \
    } else if (X.DoubleVal != X.DoubleVal || Y.DoubleVal != Y.DoubleVal) {   \
            Dest.IntVal = APInt(1,true);                                     \
            return Dest;                                                     \
}

Here's how they use this macro:

static GenericValue executeFCMP_UEQ(GenericValue Src1, GenericValue Src2,
                                    Type *Ty) {
    GenericValue Dest;
    IMPLEMENT_UNORDERED(Ty, Src1, Src2)
    return executeFCMP_OEQ(Src1, Src2, Ty);
}

Below you can see the definition of GenericValue:

struct GenericValue {
    union {
        double          DoubleVal;
        float           FloatVal;
        PointerTy       PointerVal;
        struct { unsigned int first; unsigned int second; } UIntPairVal;
        unsigned char   Untyped[8];
    };
    APInt IntVal;   // also used for long doubles

    GenericValue() : DoubleVal(0.0), IntVal(1,0) {}
    explicit GenericValue(void *V) : PointerVal(V), IntVal(1,0) { }
};

My question is why there's the following inequality test inside the macro:

X.FloatVal != X.FloatVal
w3lcome
  • 33
  • 3
  • 2
    So what is the question? Note that NaN is not equal to itself (which is the above test). So it first test to see if either value is NaN. If neither are NaN then we call `executeFCMP_OEQ()` otherwise some simple value of Dest. – Martin York Nov 02 '12 at 21:03
  • 1
    This is a perfect example of why we should write functions in place of duplicated code. Had they simply defined a `bool is_nan(const float x) { return x != x; }`, the code would be much easier to understand: `if (is_nan(X.FloatVal) || is_nan(Y.FloatVal))` – GManNickG Nov 02 '12 at 21:30

1 Answers1

5

I'd guess they test for NaN (not a number): if x has a NaN value, x != x yields true.

Dietmar Kühl
  • 150,225
  • 13
  • 225
  • 380
  • Yup, `NaN` is the only floating-point value which doesn't compare equal to itself – Useless Nov 02 '12 at 21:12
  • 1
    @Useless: when you say "`NaN` *is* the only floating-point value" you surely meant to say that "`NaN`s *are* the only floating-point values"! After all, there are quite a few NaNs you may get, potentially indicating some useful information (and I don't even mean NaN-boxing). – Dietmar Kühl Nov 02 '12 at 21:18