rs6000: Fix extendsfdf2 for signaling NaNs
authorSegher Boessenkool <segher@kernel.crashing.org>
Fri, 17 Feb 2017 15:00:37 +0000 (16:00 +0100)
committerSegher Boessenkool <segher@gcc.gnu.org>
Fri, 17 Feb 2017 15:00:37 +0000 (16:00 +0100)
A cast from float to double should turn a signaling NaN into a quiet
NaN, if using -fsignaling-nans.  On PowerPC single-precision floats are
stored as double precision in registers, and so, the cast normally does
nothing.  This causes gcc.dg/pr59833.c to fail (it does such a cast,
and expects a quiet NaN as output).

This patch adds a new pattern, used with -fsignaling-nans in effect,
that creates an frsp instruction (or xsrsp) in this case.  Since the
input already is SFmode, that instruction turns signaling NaNs into
quiet NaNs and does nothing more.

* config/rs6000/rs6000.md (extendsfdf2): Remove default arguments.
If HONOR_SNANS (SFmode) force the input to a register.
(*extendsfdf2_fpr): Add !HONOR_SNANS (SFmode) condition.
(*extendsfdf2_snan): New pattern, used when using SNaNs; it generates
an frsp or similar insn.

From-SVN: r245534

gcc/ChangeLog
gcc/config/rs6000/rs6000.md

index 2960c7d284be28cedd781dbb51362996157356bd..0339ac9c5d3d66aec401760d85b3a80fcda33e2f 100644 (file)
@@ -1,3 +1,11 @@
+2017-02-17  Segher Boessenkool  <segher@kernel.crashing.org>
+
+       * config/rs6000/rs6000.md (extendsfdf2): Remove default arguments.
+       If HONOR_SNANS (SFmode) force the input to a register.
+       (*extendsfdf2_fpr): Add !HONOR_SNANS (SFmode) condition.
+       (*extendsfdf2_snan): New pattern, used when using SNaNs; it generates
+       an frsp or similar insn.
+
 2017-02-17  Martin Liska  <mliska@suse.cz>
 
        PR rtl-optimization/79577
index fca6de04b4cac1de3e03d9313757395d6e7db7fa..58e63c18f00b575efd7227e3a12b0655a4e282fa 100644 (file)
 
 ;; Floating point conversions
 (define_expand "extendsfdf2"
-  [(set (match_operand:DF 0 "gpc_reg_operand" "")
-       (float_extend:DF (match_operand:SF 1 "reg_or_none500mem_operand" "")))]
+  [(set (match_operand:DF 0 "gpc_reg_operand")
+       (float_extend:DF (match_operand:SF 1 "reg_or_none500mem_operand")))]
   "TARGET_HARD_FLOAT && ((TARGET_FPRS && TARGET_DOUBLE_FLOAT) || TARGET_E500_DOUBLE)"
-  "")
+{
+  if (HONOR_SNANS (SFmode))
+    operands[1] = force_reg (SFmode, operands[1]);
+})
 
 (define_insn_and_split "*extendsfdf2_fpr"
   [(set (match_operand:DF 0 "gpc_reg_operand" "=d,?d,d,ws,?ws,wu,wb")
        (float_extend:DF (match_operand:SF 1 "reg_or_mem_operand" "0,f,m,0,wy,Z,wY")))]
-  "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT"
+  "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT
+   && !HONOR_SNANS (SFmode)"
   "@
    #
    fmr %0,%1
 }
   [(set_attr "type" "fp,fpsimple,fpload,fp,fpsimple,fpload,fpload")])
 
+(define_insn "*extendsfdf2_snan"
+  [(set (match_operand:DF 0 "gpc_reg_operand" "=d,ws")
+       (float_extend:DF (match_operand:SF 1 "gpc_reg_operand" "f,wy")))]
+  "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT
+   && HONOR_SNANS (SFmode)"
+  "@
+   frsp %0,%1
+   xsrsp %x0,%x1"
+  [(set_attr "type" "fp")])
+
 (define_expand "truncdfsf2"
   [(set (match_operand:SF 0 "gpc_reg_operand" "")
        (float_truncate:SF (match_operand:DF 1 "gpc_reg_operand" "")))]