x86: lowering of `llvm.minnum` and `llvm.maxnum` does not handle signed zeroes correctly
- Dominant language
- LLVM
- Stars
- 40.5k
- Forks
- 18.7k
- PR merge metrics
- PR metrics pending
Description
https://github.com/llvm/llvm-project/pull/112852 updated the documentation and semantics around the `llvm.minnum` and `llvm.maxnum` intrinsics. The langref for e.g. `llvm.minnum` now says (emphasis mine):
> Follows the semantics of minNum in IEEE-754-2008, **except that -0.0 < +0.0 for the purposes of this intrinsic.**
[...]
> **If the intrinsic is marked with the nsz attribute,** then the effect is as in the definition in C and IEEE-754-2008: the result of `minnum(-0.0, +0.0)` may be either -0.0 or +0.0.
However, this is not respected for x86. It lowers these operations to a `minps`/`minpd` plus a `cmpunord` to handle NaN, but makes no effort to handle signed zeroes if the nsz attribute is absent.
You can see this behavior in [this godbolt example](https://godbolt.org/z/Wz39s5czr). Note that the Rust `min` intrinsic is lowered to `llvm.minnum` (without any nsz attribute), which is then compiled into a `minps`+`cmpunordps` sequence.
Contributor guide
Research direction
Start by reading the linked PR 112852 and reproducing the behavior in the linked Godbolt example. Then trace the x86 lowering of llvm.minnum and llvm.maxnum, comparing minps/minpd plus cmpunord behavior with the documented signed-zero semantics; done means both intrinsic forms lower correctly with and without nsz.
Written by the indexing model from the issue text.
Assessment
- Domain
- compilers
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 45/100