Skip to content

@llvm.minimumnum.f32 returns sNaN instead of qNaN on x86_64 #123263

Open
@sunfishcode

Description

@sunfishcode

LLVM's documentation for @llvm.minimumnum.f32 says "If both operands are NaNs (including sNaN), returns qNaN". However, on x86_64, it actually returns sNaN.

Specifically, with this test.c:

#include <stdio.h>
#include <string.h>

float f32_minnumber(float x, float y);

int main() {
    float f = __builtin_nansf("");
    float g = f32_minnumber(f, f);
    float h = g + 0;

    unsigned uf, ug, uh;
    memcpy(&uf, &f, sizeof(f));
    memcpy(&ug, &g, sizeof(f));
    memcpy(&uh, &h, sizeof(f));

    printf("%x\n%x\n%x\n", uf, ug, uh);
    return 0;
}

and this minnumber.ll:

target triple = "x86_64-pc-linux-gnu"

define float @f32_minnumber(float %x, float %y) {
  %t = call float @llvm.minimumnum.f32(float %x, float %y)
  ret float %t
}
define double @f64_minnumber(double %x, double %y) {
  %t = call double @llvm.minimumnum.f32(double %x, double %y)
  ret double %t
}
define float @f32_maxnumber(float %x, float %y) {
  %t = call float @llvm.maximumnum.f32(float %x, float %y)
  ret float %t
}
define double @f64_maxnumber(double %x, double %y) {
  %t = call double @llvm.maximumnum.f32(double %x, double %y)
  ret double %t
}

Compiling for x86_64 gets this output:

$ clang test.c minnumber.ll 
$ ./a.out 
7fa00000
7fa00000
7fe00000
$ 

This shows that the operands of the f32.minimumnum are sNaN and the result is incorrectly also sNaN.

IEEE 754-2019 says of its corresponding minimumNumber operattion "If both operands are NaNs, a quiet NaN is returned".

I have not tested similar variants for f64, maximumnum, or other architectures.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions