Commit b5e01d4b by Roger Sayle Committed by Roger Sayle

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
parent 290a4db9
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
......
......@@ -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 ();
......
@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.
......
/* 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$)",
......
......@@ -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. */
......
/* 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])
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment