Comment 1 for bug 1327530

Revision history for this message
In , Aurelien Jarno (aurelien-aurel32) wrote :

Consider the following code:

#define _GNU_SOURCE
#include <stdio.h>
#include <math.h>

int main (void)
{
  float sNaN = __builtin_nansf ("");
  double x = (double) sNaN;
  return issignaling(x);
}

It correctly returns 0 at -O0 optimisation level, but returns 1 at -O1 and -O2 optimisation levels.

Here is the generated assembly code at -O0:
0000000000400630 <main>:
  400630: a9be7bfd stp x29, x30, [sp,#-32]!
  400634: 910003fd mov x29, sp
  400638: 18000160 ldr w0, 400664 <main+0x34>
  40063c: b9001fa0 str w0, [x29,#28]
  400640: b9401fa0 ldr w0, [x29,#28]
  400644: 1e270000 fmov s0, w0
  400648: 1e22c000 fcvt d0, s0
  40064c: 9e660000 fmov x0, d0
  400650: f9000ba0 str x0, [x29,#16]
  400654: fd400ba0 ldr d0, [x29,#16]
  400658: 97ffff8e bl 400490 <__issignaling@plt>
  40065c: a8c27bfd ldp x29, x30, [sp],#32
  400660: d65f03c0 ret
  400664: 7fa00000 .word 0x7fa00000

Here is the generated assembly code at -O1:
0000000000400630 <main>:
  400630: a9bf7bfd stp x29, x30, [sp,#-16]!
  400634: 910003fd mov x29, sp
  400638: 5c000080 ldr d0, 400648 <main+0x18>
  40063c: 97ffff95 bl 400490 <__issignaling@plt>
  400640: a8c17bfd ldp x29, x30, [sp],#16
  400644: d65f03c0 ret
  400648: 00000000 .word 0x00000000
  40064c: 7ff40000 .word 0x7ff40000

As you can see at -O1, the sNaN constant is propagated, and the propagated value is loaded and passed directly to issignaling. Quoting the IEEE Std 754 standard:
"Under default exception handling, any operation signaling an invalid operation exception and for which a floating-point result is to be delivered shall deliver a quiet NaN."

So it looks like the copy propagation is not done correctly, the sNaN should be silenced in the process.