Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Floating-point min and max that prefer numbers #1548

Open
sunfishcode opened this issue Jan 9, 2025 · 2 comments
Open

Floating-point min and max that prefer numbers #1548

sunfishcode opened this issue Jan 9, 2025 · 2 comments

Comments

@sunfishcode
Copy link
Member

sunfishcode commented Jan 9, 2025

Wasm's current f32.min and f32.max, correspond to IEEE 754-2019's minimum and maximum operations. When exactly one of their two operands is a NaN, they pick the NaN. Wasm may wish to consider adding instructions corresponding to IEEE 754-2019's minimumNumber and maximumNumber operations, which would pick the non-NaN.

In LLVM, the corresponding operations are minimumnum and maximumnum. In C23, the corresponding functions are fminimum_num and fmaximum_num.

These are similar to the now-removed minNum and maxNum operators from IEEE 754-2008, but specify that negative zero is to be treated as less than zero rather than being nondeterministic, and that signaling NaN is to be handled more like quiet NaN so that the operators are associative.

Implementations

Looking at current major CPU ISAs, it appears only PowerPC has direct support for these instructions. However, as can be seen on aarch64, CPUs with instructions implementing 754-2008's minNum and maxNum can implement it with three instructions, and as can be seen on x86_64, AVX enables significant optimizations, so adding these new instructions would at least be an improvement over the status quo on most architectures for code that would use them.

Naming

Given that IEEE 754-2019's minimum corresponds to Wasm's min, it's tempting to map minimumNumber to minnum in Wasm, however this risks confusion with the old and removed minNum and maxNum operators.

Consequently, I suggest the names minnumber and maxnumber for Wasm. The full set would be:

  • f32.minnumber
  • f32.maxnumber
  • f64.minnumber
  • f64.maxnumber

Next steps

If anyone has information about source languages, compilers, or libraries using IEEE 754-2019's minumNumber and maximumNumber, or CPUs implementing them, or use cases that would benefit from them, please post about it here!

@ppenzin
Copy link

ppenzin commented Jan 16, 2025

How are you proposing to handle canonical vs non-canonical NaNs? Currently we are supposed to preserve exact NaN value if it is canonical (in this case if both arguments are NaNs). Implementation examples don't seem to have canonical NaN handling.

@sunfishcode
Copy link
Member Author

Looking at the code more closely, I believe I found a bug in LLVM here. LLVM's documentation for @llvm.minimumnum.f32 says "If both operands are NaNs (including sNaN), returns qNaN", however looking at the non-AVX x86-64 version at least, it does not do this. I've now filed llvm/llvm-project#123263 to report this bug.

Fixing that bug may require LLVM to use a significantly different code sequence, so we'll see where canonical NaN handling ends up.

However, in general, it tends to be the case on architectures that implement the recommendations in IEEE 754-2019 6.2.3 NaN propagation, eg.:

If two or more inputs are NaN, then the payload of the resulting NaN should be identical to the payload of
one of the input NaNs if representable in the destination format.

as most architectures do, that Wasm-compatible canonical NaN handling happens without any additional instructions.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants