go: cmd/compile: inconsistent signaling NaN behavior on mips64le

Compile and run the following C program:

#include <stdio.h>
#include <stdint.h>

double add0(double x) {
  return x+0;
}

int main(int argc, char *argv[]) {
  double snan64;
  *(uint64_t*)&snan64 = 0x7ff0000000000001;
  printf("snan64: %llx\n", *(uint64_t*)&snan64);
  double x = add0(snan64);
  printf("  add0: %llx\n", *(uint64_t*)&x);
}

On the linux-mips64le-mengzhuo builders, it prints

snan64: 7ff0000000000001
  add0: 7ff8000000000001

On the linux-mips64le-rtrk builders, it prints

snan64: 7ff0000000000001
  add0: 7ff0000000000001

Note that on the mengzhuo builder, the quiet bit gets set, whereas on the rtrk builder it does not.

This seems like a strange inconsistency. The assembly code for add0 is the same on both platforms.

It seems strange that the rtrk builder doesn’t convert the NaN from signaling to quiet. add0 quiets the NaN for all the other Go platforms we support (amd64, powerpc, etc.). There are also strange inconsistencies with how it handles float32 <-> float64 conversions of signaling NaNs, which is how I first noticed this (#36399).

Is this expected behavor? Is this allowed by the spec? Might it be a bug in the rtrk builder? Is there some floating-point-signal-interrupt-control-word thingy we might need to set?

@mengzhuo @milanknezevic

About this issue

  • Original URL
  • State: closed
  • Created 4 years ago
  • Comments: 17 (13 by maintainers)

Commits related to this issue

Most upvoted comments

I think it should generate a quiet NaN. The MIPS manual said

An SNaN is never produced as a result value.

Also

SNaN operands cause the Invalid Operation exception for arithmetic operations. … The result, when the exception condition occurs without a precise trap, is a quiet NaN.