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 <seg...@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 --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" "")))] -- 1.9.3