+2013-05-28 Eric Botcazou <ebotcazou@adacore.com>
+
+ * doc/invoke.texi (SPARC Options): Document -mfix-ut699.
+ * builtins.c (expand_builtin_mathfn) <BUILT_IN_SQRT>: Try to widen the
+ mode if the instruction isn't available in the original mode.
+ * config/sparc/sparc.opt (mfix-ut699): New option.
+ * config/sparc/sparc.md (muldf3_extend): Disable if -mfix-ut699.
+ (divdf3): Turn into expander.
+ (divdf3_nofix): New insn.
+ (divdf3_fix): Likewise.
+ (divsf3): Disable if -mfix-ut699.
+ (sqrtdf2): Turn into expander.
+ (sqrtdf2_nofix): New insn.
+ (sqrtdf2_fix): Likewise.
+ (sqrtsf2): Disable if -mfix-ut699.
+
2013-05-27 Richard Biener <rguenther@suse.de>
PR middle-end/57412
tree fndecl = get_callee_fndecl (exp);
enum machine_mode mode;
bool errno_set = false;
+ bool try_widening = false;
tree arg;
if (!validate_arglist (exp, REAL_TYPE, VOID_TYPE))
{
CASE_FLT_FN (BUILT_IN_SQRT):
errno_set = ! tree_expr_nonnegative_p (arg);
+ try_widening = true;
builtin_optab = sqrt_optab;
break;
CASE_FLT_FN (BUILT_IN_EXP):
if (! flag_errno_math || ! HONOR_NANS (mode))
errno_set = false;
- /* Before working hard, check whether the instruction is available. */
- if (optab_handler (builtin_optab, mode) != CODE_FOR_nothing
+ /* Before working hard, check whether the instruction is available, but try
+ to widen the mode for specific operations. */
+ if ((optab_handler (builtin_optab, mode) != CODE_FOR_nothing
+ || (try_widening && !excess_precision_type (TREE_TYPE (exp))))
&& (!errno_set || !optimize_insn_for_size_p ()))
{
rtx result = gen_reg_rtx (mode);
[(set (match_operand:DF 0 "register_operand" "=e")
(mult:DF (float_extend:DF (match_operand:SF 1 "register_operand" "f"))
(float_extend:DF (match_operand:SF 2 "register_operand" "f"))))]
- "(TARGET_V8 || TARGET_V9) && TARGET_FPU"
+ "(TARGET_V8 || TARGET_V9) && TARGET_FPU && !sparc_fix_ut699"
"fsmuld\t%1, %2, %0"
[(set_attr "type" "fpmul")
(set_attr "fptype" "double")])
"fdivq\t%1, %2, %0"
[(set_attr "type" "fpdivd")])
-(define_insn "divdf3"
+(define_expand "divdf3"
[(set (match_operand:DF 0 "register_operand" "=e")
(div:DF (match_operand:DF 1 "register_operand" "e")
(match_operand:DF 2 "register_operand" "e")))]
"TARGET_FPU"
+ "")
+
+(define_insn "*divdf3_nofix"
+ [(set (match_operand:DF 0 "register_operand" "=e")
+ (div:DF (match_operand:DF 1 "register_operand" "e")
+ (match_operand:DF 2 "register_operand" "e")))]
+ "TARGET_FPU && !sparc_fix_ut699"
"fdivd\t%1, %2, %0"
[(set_attr "type" "fpdivd")
(set_attr "fptype" "double")])
+(define_insn "*divdf3_fix"
+ [(set (match_operand:DF 0 "register_operand" "=e")
+ (div:DF (match_operand:DF 1 "register_operand" "e")
+ (match_operand:DF 2 "register_operand" "e")))]
+ "TARGET_FPU && sparc_fix_ut699"
+ "fdivd\t%1, %2, %0\n\tstd\t%0, [%%sp-8]"
+ [(set_attr "type" "fpdivd")
+ (set_attr "fptype" "double")
+ (set_attr "length" "2")])
+
(define_insn "divsf3"
[(set (match_operand:SF 0 "register_operand" "=f")
(div:SF (match_operand:SF 1 "register_operand" "f")
(match_operand:SF 2 "register_operand" "f")))]
- "TARGET_FPU"
+ "TARGET_FPU && !sparc_fix_ut699"
"fdivs\t%1, %2, %0"
[(set_attr "type" "fpdivs")])
"fsqrtq\t%1, %0"
[(set_attr "type" "fpsqrtd")])
-(define_insn "sqrtdf2"
+(define_expand "sqrtdf2"
[(set (match_operand:DF 0 "register_operand" "=e")
(sqrt:DF (match_operand:DF 1 "register_operand" "e")))]
"TARGET_FPU"
+ "")
+
+(define_insn "*sqrtdf2_nofix"
+ [(set (match_operand:DF 0 "register_operand" "=e")
+ (sqrt:DF (match_operand:DF 1 "register_operand" "e")))]
+ "TARGET_FPU && !sparc_fix_ut699"
"fsqrtd\t%1, %0"
[(set_attr "type" "fpsqrtd")
(set_attr "fptype" "double")])
+(define_insn "*sqrtdf2_fix"
+ [(set (match_operand:DF 0 "register_operand" "=e")
+ (sqrt:DF (match_operand:DF 1 "register_operand" "e")))]
+ "TARGET_FPU && sparc_fix_ut699"
+ "fsqrtd\t%1, %0\n\tstd\t%0, [%%sp-8]"
+ [(set_attr "type" "fpsqrtd")
+ (set_attr "fptype" "double")
+ (set_attr "length" "2")])
+
(define_insn "sqrtsf2"
[(set (match_operand:SF 0 "register_operand" "=f")
(sqrt:SF (match_operand:SF 1 "register_operand" "f")))]
- "TARGET_FPU"
+ "TARGET_FPU && !sparc_fix_ut699"
"fsqrts\t%1, %0"
[(set_attr "type" "fpsqrts")])