Skip to content

Use of simd_reduce_max/min for floats is suspicious #1971

@RalfJung

Description

@RalfJung

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.)

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions