+2015-12-05 David Edelsohn <dje.gcc@gmail.com>
+
+ 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 (rsqrt<mode>2): Call new function name.
+ (sqrt<mode>2): Replace define_insn with define_expand that may call
+ rs6000_emit_swsqrt.
+
2015-12-04 Aditya Kumar <aditya.k7@samsung.com>
Sebastian Pop <s.pop@samsung.com>
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);
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);
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);
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;
}
(match_operand:RECIPF 1 "gpc_reg_operand" "")]
"RS6000_RECIP_HAVE_RSQRTE_P (<MODE>mode)"
{
- rs6000_emit_swrsqrt (operands[0], operands[1]);
+ rs6000_emit_swsqrt (operands[0], operands[1], 1);
DONE;
})
\f
[(set_attr "type" "<Fs>div")
(set_attr "fp_type" "fp_div_<Fs>")])
-(define_insn "sqrt<mode>2"
+(define_insn "*sqrt<mode>2_internal"
[(set (match_operand:SFDF 0 "gpc_reg_operand" "=<Ff>,<Fv2>")
(sqrt:SFDF (match_operand:SFDF 1 "gpc_reg_operand" "<Ff>,<Fv2>")))]
"TARGET_<MODE>_FPR && !TARGET_SIMPLE_FPU
[(set_attr "type" "<Fs>sqrt")
(set_attr "fp_type" "fp_sqrt_<Fs>")])
+(define_expand "sqrt<mode>2"
+ [(set (match_operand:SFDF 0 "gpc_reg_operand" "")
+ (sqrt:SFDF (match_operand:SFDF 1 "gpc_reg_operand" "")))]
+ "TARGET_<MODE>_FPR && !TARGET_SIMPLE_FPU
+ && (TARGET_PPC_GPOPT || (<MODE>mode == SFmode && TARGET_XILINX_FPU))"
+{
+ if (<MODE>mode == SFmode
+ && RS6000_RECIP_HAVE_RSQRTE_P (<MODE>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<Fs>"
[(set (match_operand:SFDF 0 "gpc_reg_operand" "=<Ff>,<Fv2>")