[arm64] float to double conversion does not silence sNaN

Bug #1327530 reported by Matthias Klose on 2014-06-07
This bug affects 1 person
Affects Status Importance Assigned to Milestone
Linaro GCC
Fix Released
gcc-4.8 (Ubuntu)
gcc-4.9 (Ubuntu)

Bug Description

see the upstream issue

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.

I see the same behaviour on x86_64-linux-gnu , there is nothing specific about this behaviour with respect to the AArch64 port.

I can see this is ccp that causes the propagation in the brief time I looked at it. What I haven't yet done is audit the options bits to work out what the issues here.

Changed in gcc:
importance: Unknown → Medium
status: Unknown → New
Changed in gcc:
status: New → Fix Released
To post a comment you must log in.
This report contains Public information  Edit
Everyone can see this information.

Other bug subscribers

Remote bug watches

Bug watches keep track of this bug in other bug trackers.