Ordered / Unordered FP compare are not handled properly on X86

I found that there is no diff in code generator for Ordered / Unordered FP compare instructions.
FUCOMISS, FUCOMISD are generated in the both cases.

  • Elena

-Eli

Should I open a ticket for this?

  • Elena

I think he was saying this is intended behaviour. Isn't the difference
between ucomiss and comiss just whether an exception is raised for
NaN?

If so, a compare that used that instruction would have to become more
like an "invoke" with a landingpad for the exception and so on,
wouldn't it? The current fcmp can already distinguish between ordered
and unordered, because ucomiss provides that information.

Tim.

There are currently lots of limitations in the expressiveness of LLVM IR for floating point operations (e.g. distinguishing between trapping and non-trapping cases and representing the floating point environment). If anyone wants to fully implement the floating point part of C99 (or Fortran!) then they will quickly hit problems. I believe that this kind of thing is usually implemented on-demand, and so until someone (maybe those nice folks at Argonne National Laboratory) who cares about numerical accuracy makes it a priority.

David

But this is another case. LLVM IR distinguishes between ordered and unordered compare and X86 backend has appropriate instructions.
But during DAG selection we just lose this information and always generate unordered fcmp.
I.e. in case of ordered fcmp the vcomiss should be generated, and in case of unordered - vucomiss.

- Elena

I think LLVM uses ordered/unordered compare to mean something
different to what the x86 instructions do. For example, "not equal":

    fcmp une == unordered not equal == A is NaN, B is NaN, or A != B
    fcmp one == ordered and equal == A is not NaN, B is not NaN, and A != B

Both of these can be implemented with the x86 unordered comparison
instruction by performing certain tests on the EFLAGS result. But if
we used the comiss instruction (and exceptions weren't masked) then
we'd take an exception if either A or B was a NaN.

Look at the C file I've attached, where I start by unmasking
exceptions and then perform what's essentially an "one" comparison.
LLVM implements this with ucomiss, and gets the result correct. If you
change this to "comiss" then instead the program terminates with a
floating point exception.

So there seem to be 2 cases:
1. Exception is masked. ucomiss is identical to comiss, why bother
complicating things by emitting comiss?
2. Exception is not masked: they're different and LLVM's IR has
specifically asked for the ucomiss behaviour: fcmp wants to know that
they're ordered, not abort if they're unordered.

Of course, as David says, we may need more intrinsics or instructions
to implement the stricter parts of IEEE-754 that C can expose, but
normal fcmp instructions aren't the place for that.

Tim.

tmp.c (344 Bytes)

Hi Tim,

I checked again, you are right. Ordered / unordered of X86 arch and LLVM fcmp have the different meaning.
Thank you for the detailed explanation.

- Elena