diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 0ad4e901e1c..0d4e6f2decf 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,14 @@ +2015-12-05 David Edelsohn + + PR target/68609 + * config/rs6000/rs6000-protos.h (rs6000_emit_swsqrt): Rename and add + bool arguement. + * config/rs6000/rs6000.c (rs6000_emit_swsqrt): Rename. Add + non-reciporcal path. + * config/rs6000/rs6000.md (rsqrt2): Call new function name. + (sqrt2): Replace define_insn with define_expand that may call + rs6000_emit_swsqrt. + 2015-12-04 Aditya Kumar Sebastian Pop diff --git a/gcc/config/rs6000/rs6000-protos.h b/gcc/config/rs6000/rs6000-protos.h index 05007654787..d9c7a79af39 100644 --- a/gcc/config/rs6000/rs6000-protos.h +++ b/gcc/config/rs6000/rs6000-protos.h @@ -137,7 +137,7 @@ extern void rs6000_expand_atomic_compare_and_swap (rtx op[]); extern void rs6000_expand_atomic_exchange (rtx op[]); extern void rs6000_expand_atomic_op (enum rtx_code, rtx, rtx, rtx, rtx, rtx); extern void rs6000_emit_swdiv (rtx, rtx, rtx, bool); -extern void rs6000_emit_swrsqrt (rtx, rtx); +extern void rs6000_emit_swsqrt (rtx, rtx, bool); extern void output_toc (FILE *, rtx, int, machine_mode); extern rtx rs6000_longcall_ref (rtx); extern void rs6000_fatal_bad_address (rtx); diff --git a/gcc/config/rs6000/rs6000.c b/gcc/config/rs6000/rs6000.c index 2b2c170d6e9..6b22f93e0ff 100644 --- a/gcc/config/rs6000/rs6000.c +++ b/gcc/config/rs6000/rs6000.c @@ -32910,7 +32910,7 @@ rs6000_emit_swdiv (rtx dst, rtx n, rtx d, bool note_p) rsqrt. Assumes no trapping math and finite arguments. */ void -rs6000_emit_swrsqrt (rtx dst, rtx src) +rs6000_emit_swsqrt (rtx dst, rtx src, bool recip) { machine_mode mode = GET_MODE (src); rtx x0 = gen_reg_rtx (mode); @@ -32943,6 +32943,16 @@ rs6000_emit_swrsqrt (rtx dst, rtx src) emit_insn (gen_rtx_SET (x0, gen_rtx_UNSPEC (mode, gen_rtvec (1, src), UNSPEC_RSQRT))); + /* If (src == 0.0) filter infinity to prevent NaN for sqrt(0.0). */ + if (!recip) + { + rtx zero = force_reg (mode, CONST0_RTX (mode)); + rtx target = emit_conditional_move (x0, GT, src, zero, mode, + x0, zero, mode, 0); + if (target != x0) + emit_move_insn (x0, target); + } + /* y = 0.5 * src = 1.5 * src - src -> fewer constants */ rs6000_emit_msub (y, src, halfthree, src); @@ -32959,7 +32969,12 @@ rs6000_emit_swrsqrt (rtx dst, rtx src) x0 = x1; } - emit_move_insn (dst, x0); + /* If not reciprocal, multiply by src to produce sqrt. */ + if (!recip) + emit_insn (gen_mul (dst, src, x0)); + else + emit_move_insn (dst, x0); + return; } diff --git a/gcc/config/rs6000/rs6000.md b/gcc/config/rs6000/rs6000.md index 39e1b299a72..66a62ef4186 100644 --- a/gcc/config/rs6000/rs6000.md +++ b/gcc/config/rs6000/rs6000.md @@ -4301,7 +4301,7 @@ (match_operand:RECIPF 1 "gpc_reg_operand" "")] "RS6000_RECIP_HAVE_RSQRTE_P (mode)" { - rs6000_emit_swrsqrt (operands[0], operands[1]); + rs6000_emit_swsqrt (operands[0], operands[1], 1); DONE; }) @@ -4426,7 +4426,7 @@ [(set_attr "type" "div") (set_attr "fp_type" "fp_div_")]) -(define_insn "sqrt2" +(define_insn "*sqrt2_internal" [(set (match_operand:SFDF 0 "gpc_reg_operand" "=,") (sqrt:SFDF (match_operand:SFDF 1 "gpc_reg_operand" ",")))] "TARGET__FPR && !TARGET_SIMPLE_FPU @@ -4437,6 +4437,23 @@ [(set_attr "type" "sqrt") (set_attr "fp_type" "fp_sqrt_")]) +(define_expand "sqrt2" + [(set (match_operand:SFDF 0 "gpc_reg_operand" "") + (sqrt:SFDF (match_operand:SFDF 1 "gpc_reg_operand" "")))] + "TARGET__FPR && !TARGET_SIMPLE_FPU + && (TARGET_PPC_GPOPT || (mode == SFmode && TARGET_XILINX_FPU))" +{ + if (mode == SFmode + && RS6000_RECIP_HAVE_RSQRTE_P (mode) + && !optimize_function_for_size_p (cfun) + && flag_finite_math_only && !flag_trapping_math + && flag_unsafe_math_optimizations) + { + rs6000_emit_swsqrt (operands[0], operands[1], 0); + DONE; + } +}) + ;; Floating point reciprocal approximation (define_insn "fre" [(set (match_operand:SFDF 0 "gpc_reg_operand" "=,")