aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorRoger Sayle <roger@eyesopen.com>2003-02-11 19:34:11 +0000
committerRoger Sayle <sayle@gcc.gnu.org>2003-02-11 19:34:11 +0000
commitb5e01d4bec0c3cb5e3881cd2f110316e1a51a27f (patch)
tree7ceaf59c454cfc0fade6ccb54dfb5372b71cd8d1 /gcc
parent290a4db98103f24105c77df2e78396892ae3957f (diff)
downloadgcc-b5e01d4bec0c3cb5e3881cd2f110316e1a51a27f.zip
gcc-b5e01d4bec0c3cb5e3881cd2f110316e1a51a27f.tar.gz
gcc-b5e01d4bec0c3cb5e3881cd2f110316e1a51a27f.tar.bz2
optabs.h (enum optab_index): Add new OTI_pow and OTI_atan2.
* optabs.h (enum optab_index): Add new OTI_pow and OTI_atan2. (pow_optab, atan2_optab): Define corresponding macros. * optabs.c (init_optabs): Initialize pow_optab and atan2_optab. * genopinit.c (optabs): Implement pow_optab and atan2_optab using pow?f3 and atan2?f3 patterns. * builtins.c (expand_errno_check): New function to update errno if necessary, split out from expand_builtin_mathfn. (expand_builtin_mathfn): Use expand_errno_check. (expand_builtin_mathfn_2): New function to handle expanding binary math functions, reusing the code in expand_errno_check. (expand_builtin): Handle the pow and atan2 math built-ins, BUILT_IN_{POW,POWF,POWL,ATAN2,ATAN2F,ATAN2L} via the new function expand_builtin_mathfn_2. * doc/md.texi: Document new pow?f3 and atan2?f3 patterns. From-SVN: r62708
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog18
-rw-r--r--gcc/builtins.c175
-rw-r--r--gcc/doc/md.texi25
-rw-r--r--gcc/genopinit.c6
-rw-r--r--gcc/optabs.c2
-rw-r--r--gcc/optabs.h8
6 files changed, 203 insertions, 31 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index c5144a9..b162e12 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,21 @@
+2003-02-11 Roger Sayle <roger@eyesopen.com>
+
+ * optabs.h (enum optab_index): Add new OTI_pow and OTI_atan2.
+ (pow_optab, atan2_optab): Define corresponding macros.
+ * optabs.c (init_optabs): Initialize pow_optab and atan2_optab.
+ * genopinit.c (optabs): Implement pow_optab and atan2_optab
+ using pow?f3 and atan2?f3 patterns.
+ * builtins.c (expand_errno_check): New function to update errno
+ if necessary, split out from expand_builtin_mathfn.
+ (expand_builtin_mathfn): Use expand_errno_check.
+ (expand_builtin_mathfn_2): New function to handle expanding binary
+ math functions, reusing the code in expand_errno_check.
+ (expand_builtin): Handle the pow and atan2 math built-ins,
+ BUILT_IN_{POW,POWF,POWL,ATAN2,ATAN2F,ATAN2L} via the new function
+ expand_builtin_mathfn_2.
+
+ * doc/md.texi: Document new pow?f3 and atan2?f3 patterns.
+
Tue Feb 11 19:03:22 MET 2003 Jan Hubicka <jh@suse.cz>
* combine.c (combine_simplify_rtx): Fix folding of
diff --git a/gcc/builtins.c b/gcc/builtins.c
index e2ad1e8..9478808 100644
--- a/gcc/builtins.c
+++ b/gcc/builtins.c
@@ -99,7 +99,9 @@ static rtx expand_builtin_apply PARAMS ((rtx, rtx, rtx));
static void expand_builtin_return PARAMS ((rtx));
static enum type_class type_to_class PARAMS ((tree));
static rtx expand_builtin_classify_type PARAMS ((tree));
+static void expand_errno_check PARAMS ((tree, rtx));
static rtx expand_builtin_mathfn PARAMS ((tree, rtx, rtx));
+static rtx expand_builtin_mathfn_2 PARAMS ((tree, rtx, rtx));
static rtx expand_builtin_constant_p PARAMS ((tree));
static rtx expand_builtin_args_info PARAMS ((tree));
static rtx expand_builtin_next_arg PARAMS ((tree));
@@ -1655,6 +1657,50 @@ mathfn_built_in (type, fn)
return implicit_built_in_decls[fcode];
}
+/* If errno must be maintained, expand the RTL to check if the result,
+ TARGET, of a built-in function call, EXP, is NaN, and if so set
+ errno to EDOM. */
+
+static void
+expand_errno_check (exp, target)
+ tree exp;
+ rtx target;
+{
+ rtx lab;
+
+ if (flag_errno_math && errno_set && HONOR_NANS (GET_MODE (target)))
+ {
+ lab = gen_label_rtx ();
+
+ /* Test the result; if it is NaN, set errno=EDOM because
+ the argument was not in the domain. */
+ emit_cmp_and_jump_insns (target, target, EQ, 0, GET_MODE (target),
+ 0, lab);
+
+#ifdef TARGET_EDOM
+ {
+#ifdef GEN_ERRNO_RTX
+ rtx errno_rtx = GEN_ERRNO_RTX;
+#else
+ rtx errno_rtx
+ = gen_rtx_MEM (word_mode, gen_rtx_SYMBOL_REF (Pmode, "errno"));
+#endif
+
+ emit_move_insn (errno_rtx, GEN_INT (TARGET_EDOM));
+ }
+#else
+ /* We can't set errno=EDOM directly; let the library call do it.
+ Pop the arguments right away in case the call gets deleted. */
+ NO_DEFER_POP;
+ expand_call (exp, target, 0);
+ OK_DEFER_POP;
+#endif
+
+ emit_label (lab);
+ }
+}
+
+
/* Expand a call to one of the builtin math functions (sin, cos, or sqrt).
Return 0 if a normal call should be emitted rather than expanding the
function in-line. EXP is the expression that is a call to the builtin
@@ -1760,41 +1806,105 @@ expand_builtin_mathfn (exp, target, subtarget)
return 0;
}
- /* If errno must be maintained, we must set it to EDOM for NaN results. */
+ expand_errno_check (exp, target);
- if (flag_errno_math && errno_set && HONOR_NANS (argmode))
+ /* Output the entire sequence. */
+ insns = get_insns ();
+ end_sequence ();
+ emit_insn (insns);
+
+ return target;
+}
+
+/* Expand a call to the builtin binary math functions (pow and atan2).
+ Return 0 if a normal call should be emitted rather than expanding the
+ function in-line. EXP is the expression that is a call to the builtin
+ function; if convenient, the result should be placed in TARGET.
+ SUBTARGET may be used as the target for computing one of EXP's
+ operands. */
+
+static rtx
+expand_builtin_mathfn_2 (exp, target, subtarget)
+ tree exp;
+ rtx target, subtarget;
+{
+ optab builtin_optab;
+ rtx op0, op1, insns;
+ tree fndecl = TREE_OPERAND (TREE_OPERAND (exp, 0), 0);
+ tree arglist = TREE_OPERAND (exp, 1);
+ tree arg0, arg1;
+ enum machine_mode argmode;
+ bool errno_set = true;
+ bool stable = true;
+
+ if (!validate_arglist (arglist, REAL_TYPE, REAL_TYPE, VOID_TYPE))
+ return 0;
+
+ arg0 = TREE_VALUE (arglist);
+ arg1 = TREE_VALUE (TREE_CHAIN (arglist));
+
+ /* Stabilize the arguments. */
+ if (TREE_CODE (arg0) != VAR_DECL && TREE_CODE (arg0) != PARM_DECL)
+ {
+ arg0 = save_expr (arg0);
+ TREE_VALUE (arglist) = arg0;
+ stable = false;
+ }
+ if (TREE_CODE (arg1) != VAR_DECL && TREE_CODE (arg1) != PARM_DECL)
{
- rtx lab1;
+ arg1 = save_expr (arg1);
+ TREE_VALUE (TREE_CHAIN (arglist)) = arg1;
+ stable = false;
+ }
- lab1 = gen_label_rtx ();
+ if (! stable)
+ {
+ exp = copy_node (exp);
+ arglist = tree_cons (NULL_TREE, arg0,
+ build_tree_list (NULL_TREE, arg1));
+ TREE_OPERAND (exp, 1) = arglist;
+ }
- /* Test the result; if it is NaN, set errno=EDOM because
- the argument was not in the domain. */
- emit_cmp_and_jump_insns (target, target, EQ, 0, GET_MODE (target),
- 0, lab1);
+ op0 = expand_expr (arg0, subtarget, VOIDmode, 0);
+ op1 = expand_expr (arg1, 0, VOIDmode, 0);
-#ifdef TARGET_EDOM
- {
-#ifdef GEN_ERRNO_RTX
- rtx errno_rtx = GEN_ERRNO_RTX;
-#else
- rtx errno_rtx
- = gen_rtx_MEM (word_mode, gen_rtx_SYMBOL_REF (Pmode, "errno"));
-#endif
+ /* Make a suitable register to place result in. */
+ target = gen_reg_rtx (TYPE_MODE (TREE_TYPE (exp)));
- emit_move_insn (errno_rtx, GEN_INT (TARGET_EDOM));
- }
-#else
- /* We can't set errno=EDOM directly; let the library call do it.
- Pop the arguments right away in case the call gets deleted. */
- NO_DEFER_POP;
- expand_call (exp, target, 0);
- OK_DEFER_POP;
-#endif
+ emit_queue ();
+ start_sequence ();
+
+ switch (DECL_FUNCTION_CODE (fndecl))
+ {
+ case BUILT_IN_POW:
+ case BUILT_IN_POWF:
+ case BUILT_IN_POWL:
+ builtin_optab = pow_optab; break;
+ case BUILT_IN_ATAN2:
+ case BUILT_IN_ATAN2F:
+ case BUILT_IN_ATAN2L:
+ builtin_optab = atan2_optab; break;
+ default:
+ abort ();
+ }
+
+ /* Compute into TARGET.
+ Set TARGET to wherever the result comes back. */
+ argmode = TYPE_MODE (TREE_TYPE (arg0));
+ target = expand_binop (argmode, builtin_optab, op0, op1,
+ target, 0, OPTAB_DIRECT);
- emit_label (lab1);
+ /* If we were unable to expand via the builtin, stop the
+ sequence (without outputting the insns) and return 0, causing
+ a call to the library function. */
+ if (target == 0)
+ {
+ end_sequence ();
+ return 0;
}
+ expand_errno_check (exp, target);
+
/* Output the entire sequence. */
insns = get_insns ();
end_sequence ();
@@ -4047,6 +4157,19 @@ expand_builtin (exp, target, subtarget, mode, ignore)
return target;
break;
+ case BUILT_IN_POW:
+ case BUILT_IN_POWF:
+ case BUILT_IN_POWL:
+ case BUILT_IN_ATAN2:
+ case BUILT_IN_ATAN2F:
+ case BUILT_IN_ATAN2L:
+ if (! flag_unsafe_math_optimizations)
+ break;
+ target = expand_builtin_mathfn_2 (exp, target, subtarget);
+ if (target)
+ return target;
+ break;
+
case BUILT_IN_APPLY_ARGS:
return expand_builtin_apply_args ();
diff --git a/gcc/doc/md.texi b/gcc/doc/md.texi
index ce3eb14..da7e38b 100644
--- a/gcc/doc/md.texi
+++ b/gcc/doc/md.texi
@@ -1,5 +1,5 @@
-@c Copyright (C) 1988, 1989, 1992, 1993, 1994, 1996, 1998, 1999, 2000, 2001, 2002
-@c Free Software Foundation, Inc.
+@c Copyright (C) 1988, 1989, 1992, 1993, 1994, 1996, 1998, 1999, 2000, 2001,
+@c 2002, 2003 Free Software Foundation, Inc.
@c This is part of the GCC manual.
@c For copying conditions, see the file gcc.texi.
@@ -2607,6 +2607,27 @@ corresponds to the C data type @code{double} and the @code{logf}
built-in function uses the mode which corresponds to the C data
type @code{float}.
+@cindex @code{pow@var{m}3} instruction pattern
+@item @samp{pow@var{m}3}
+Store the value of operand 1 raised to the exponent operand 2
+into operand 0.
+
+The @code{pow} built-in function of C always uses the mode which
+corresponds to the C data type @code{double} and the @code{powf}
+built-in function uses the mode which corresponds to the C data
+type @code{float}.
+
+@cindex @code{atan2@var{m}3} instruction pattern
+@item @samp{atan2@var{m}3}
+Store the arc tangent (inverse tangent) of operand 1 divided by
+operand 2 into operand 0, using the signs of both arguments to
+determine the quadrant of the result.
+
+The @code{atan2} built-in function of C always uses the mode which
+corresponds to the C data type @code{double} and the @code{atan2f}
+built-in function uses the mode which corresponds to the C data
+type @code{float}.
+
@cindex @code{floor@var{m}2} instruction pattern
@item @samp{floor@var{m}2}
Store the largest integral value not greater than argument.
diff --git a/gcc/genopinit.c b/gcc/genopinit.c
index 1a0070d..5d996b5 100644
--- a/gcc/genopinit.c
+++ b/gcc/genopinit.c
@@ -1,6 +1,6 @@
/* Generate code to initialize optabs from machine description.
- Copyright (C) 1993, 1994, 1995, 1996, 1997, 1998,
- 1999, 2000 Free Software Foundation, Inc.
+ Copyright (C) 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
+ 2001, 2002, 2003 Free Software Foundation, Inc.
This file is part of GCC.
@@ -105,6 +105,8 @@ static const char * const optabs[] =
"smax_optab->handlers[$A].insn_code = CODE_FOR_$(max$F$a3$)",
"umin_optab->handlers[$A].insn_code = CODE_FOR_$(umin$I$a3$)",
"umax_optab->handlers[$A].insn_code = CODE_FOR_$(umax$I$a3$)",
+ "pow_optab->handlers[$A].insn_code = CODE_FOR_$(pow$a3$)",
+ "atan2_optab->handlers[$A].insn_code = CODE_FOR_$(atan2$a3$)",
"neg_optab->handlers[$A].insn_code = CODE_FOR_$(neg$P$a2$)",
"negv_optab->handlers[(int) $A].insn_code =\n\
neg_optab->handlers[(int) $A].insn_code = CODE_FOR_$(neg$F$a2$)",
diff --git a/gcc/optabs.c b/gcc/optabs.c
index fbd7bdf..93b1498 100644
--- a/gcc/optabs.c
+++ b/gcc/optabs.c
@@ -5512,6 +5512,8 @@ init_optabs ()
smax_optab = init_optab (SMAX);
umin_optab = init_optab (UMIN);
umax_optab = init_optab (UMAX);
+ pow_optab = init_optab (UNKNOWN);
+ atan2_optab = init_optab (UNKNOWN);
/* These three have codes assigned exclusively for the sake of
have_insn_for. */
diff --git a/gcc/optabs.h b/gcc/optabs.h
index 5fda4da..e9f95fa 100644
--- a/gcc/optabs.h
+++ b/gcc/optabs.h
@@ -1,5 +1,5 @@
/* Definitions for code generation pass of GNU compiler.
- Copyright (C) 2001, 2002 Free Software Foundation, Inc.
+ Copyright (C) 2001, 2002, 2003 Free Software Foundation, Inc.
This file is part of GCC.
@@ -108,6 +108,10 @@ enum optab_index
OTI_umin,
/* Unsigned maximum value */
OTI_umax,
+ /* Power */
+ OTI_pow,
+ /* Arc tangent of y/x */
+ OTI_atan2,
/* Move instruction. */
OTI_mov,
@@ -202,6 +206,8 @@ extern GTY(()) optab optab_table[OTI_MAX];
#define smax_optab (optab_table[OTI_smax])
#define umin_optab (optab_table[OTI_umin])
#define umax_optab (optab_table[OTI_umax])
+#define pow_optab (optab_table[OTI_pow])
+#define atan2_optab (optab_table[OTI_atan2])
#define mov_optab (optab_table[OTI_mov])
#define movstrict_optab (optab_table[OTI_movstrict])