[RFC] Explicitly specifying NaN and signed zero semantics for minf and maxf

A different example that I think illustrates the same point you tried to make:

bool x = isNaN(minf(a, b));
bool y = isNaN(minf(a, b));
assert(x == y);

I would expect this to hold for all a and b, whether this comes from the source program or was introduced by the compiler.

So I think I agree with you, Any/Undefined prohibits duplication.

Sorry, I shouldn’t have used a cast. I meant re-interpreting the bits as an integer. That is always defined.

Yes your last example is better. :slight_smile:

Specifically, this can fail with Any:

bool x = isNaN(minf(a, b));
bool y = isNaN(minf(a, b));
assert(x == y);

but this cannot:

bool x = isNaN(minf(a, b));
assert(x == x);

Wouldn’t it be more pragmatic to define Any/Undefined with NaN as truly undefined (immediate UB or poison)? If we expect the lowering target to be able to detect NaN, then it could always expand minf/maxf if it does not provide a matching Propagate* ops. This should work for SPIR-V/GLSL.

That feels equivalent to have Unknown being setting the “input won’t be NaN” fastmath flag, which doesn’t seem right. I’d think “there exists a consistent semantics, but we don’t know what they are” is more useful than poison.

@antiagainst pointed me to an earlier discussion on this: Adding min/max (int/float) ops to standard dialect - #4 by awpr

I think we have to be extra clear and careful when deciding what ‘consistent semantics’ mean for Unknown/Undefined. Based on:

I understood that:

  1. It’s either PropagateNaN or PropagateOther globally in the whole module.
  2. minf/maxf are Pure (speculatable, no implicit memory effects)
  3. Duplication, CSE, DCE are all fine. This should not fail:
  1. We can only constant-fold when we know arguments to be non-NaN.

Without either a strict notion of consistency or disallowing NaN arguments, I don’t see how we would be able to do basic transformations like scalarization, vectorization, loop unrolling, etc.