llvm.sqrt and undefined behavior

In llvm.sqrt, why is the penalty for negative operands undefined behavior,
as opposed to merely an unspecified result?

As an example, in code like this:
  %x = call float @llvm.sqrt.f32(float %y)
  %z = fcmp oge float %y, -0.0
Does LLVM intend to reserve the right to assume that %z is always true?
Or that %z is undef? Or even that any statement dominated by %x is
unreachable?

There's the issue of side-effects that many floating-point operations
can have, such as errno, FP status flags, and signals, depending on the
target and various other details. LangRef currently has no mention of
any of those things anywhere though, so it seems there are implicit
blanket permissions for floating-point error behavior.

Dan

As an example, in code like this:
%x = call float @llvm.sqrt.f32(float %y)
%z = fcmp oge float %y, -0.0
Does LLVM intend to reserve the right to assume that %z is always true?

Almost. llvm.sqrt is also defined for nan's and +inf like sqrt is.

Or that %z is undef? Or even that any statement dominated by %x is
unreachable?

Yep, that's is what is specified.

The big distinction between sqrt and llvm.sqrt is that sqrt (on most platforms) implicity sets errno on a negative result. This is problematic for many reasons: for example, you can't isel "sqrt" into the PPC fsqrt instruction, but you can isel llvm.sqrt into it. Also, this makes llvm.sqrt side-effect free, where sqrt potentially has side-effects (making it harder to CSE, hoist out of loops etc).

In llvm.sqrt, why is the penalty for negative operands undefined behavior,
as opposed to merely an unspecified result?

There are a couple of issues with doing this. The big thing that you lose is the ability to lower llvm.sqrt to sqrt on targets that don't have a hardware instruction. If the result of llvm.sqrt(-1) was just an undefined result, this lowering wouldn't be legal on targets where sqrt sets errno.

-Chris