diff mbox

rs6000: Fix extendsfdf2 for signaling NaNs

Message ID 3a85a83ac5c57fbfb0a607c74d25876d1908ef62.1487341670.git.segher@kernel.crashing.org
State New
Headers show

Commit Message

Segher Boessenkool Feb. 17, 2017, 2:39 p.m. UTC
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.

Tested on powerpc64-linux {-m32,-m64}, committing to trunk.


Segher


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.

---
 gcc/config/rs6000/rs6000.md | 22 ++++++++++++++++++----
 1 file changed, 18 insertions(+), 4 deletions(-)
diff mbox

Patch

diff --git a/gcc/config/rs6000/rs6000.md b/gcc/config/rs6000/rs6000.md
index b784bca..ec93010 100644
--- a/gcc/config/rs6000/rs6000.md
+++ b/gcc/config/rs6000/rs6000.md
@@ -4648,15 +4648,19 @@  (define_insn "*cmp<mode>_fpr"
 
 ;; 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
@@ -4673,6 +4677,16 @@  (define_insn_and_split "*extendsfdf2_fpr"
 }
   [(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" "")))]