diff options
-rw-r--r-- | gcc/ChangeLog | 18 | ||||
-rw-r--r-- | gcc/builtins.c | 175 | ||||
-rw-r--r-- | gcc/doc/md.texi | 25 | ||||
-rw-r--r-- | gcc/genopinit.c | 6 | ||||
-rw-r--r-- | gcc/optabs.c | 2 | ||||
-rw-r--r-- | gcc/optabs.h | 8 |
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]) |