-
Notifications
You must be signed in to change notification settings - Fork 306
Description
Some aarch64 vendor intrinsics seem to be implemented via simd_reduce_max/simd_reduce_min on float types (Cc @folkertdev). Is that truly the right thing to do? We currently codegen these to llvm.vector.reduce.fmax.*, which is documented to have the same semantics as llvm.maxnum, but the situation around the documented and actual semantics of these operations is extraordinarily messy at the moment. Our own documentation for the intrinsic disagrees with the LLVM documentation, and Miri implements yet another variant of these semantics.
- LLVM docs: SNaN behavior from IEEE-754-2008, signed zeros from IEEE-754-2019 (i.e.
-0.0 < +0.0) - LLVM implementation: ? (on x86, LLVM does not actually implement the documented behavior, but for stdarch we only care about aarch64)
- Rust intrinsic docs: everything like IEEE-754-2008
- Miri: SNaN from IEEE-754-2019, signed zeros from IEEE-754-2008 (i.e., non-deterministic)
As a start, it would be good to figure out the exact intended semantics wrt SNaN and signed zeros for aarch64 vmaxnmvq_f32 and friends. But we also have to take into account that simd_reduce_max/simd_reduce_min are meant to be portable, so designing their semantics around the aarch64 behavior is likely not the right call. By default, I would expect them to behave like f*::max, which is what Miri implements.
(I did not find any use of simd_reduce_max/simd_reduce_min for float types for other targets, but I may have missed some.)