rs6000: Fix extendsfdf2 for signaling NaNs

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
This commit is contained in:
Segher Boessenkool 2017-02-17 16:00:37 +01:00 committed by Segher Boessenkool
parent 3185712c77
commit 4bcd6597a3
2 changed files with 26 additions and 4 deletions

View 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

View File

@ -4648,15 +4648,19 @@
;; 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 @@
}
[(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" "")))]