builtins.c (expand_builtin_int_roundingfn_2): New function.

2006-10-21  Richard Guenther  <rguenther@suse.de>

	* builtins.c (expand_builtin_int_roundingfn_2): New function.
	(expand_builtin): Use it to expand lrint instead of
	expand_builtin_mathfn.

From-SVN: r117936
This commit is contained in:
Richard Guenther 2006-10-21 19:55:07 +00:00 committed by Richard Biener
parent 962ef7fea2
commit 0bfa1541fa
2 changed files with 99 additions and 6 deletions

View File

@ -1,3 +1,9 @@
2006-10-21 Richard Guenther <rguenther@suse.de>
* builtins.c (expand_builtin_int_roundingfn_2): New function.
(expand_builtin): Use it to expand lrint instead of
expand_builtin_mathfn.
2006-10-21 Uros Bizjak <uros@kss-loka.si>
PR target/19398

View File

@ -95,6 +95,7 @@ static rtx expand_builtin_mathfn_2 (tree, rtx, rtx);
static rtx expand_builtin_mathfn_3 (tree, rtx, rtx);
static rtx expand_builtin_sincos (tree);
static rtx expand_builtin_int_roundingfn (tree, rtx, rtx);
static rtx expand_builtin_int_roundingfn_2 (tree, rtx, rtx);
static rtx expand_builtin_args_info (tree);
static rtx expand_builtin_next_arg (void);
static rtx expand_builtin_va_start (tree);
@ -1835,9 +1836,6 @@ expand_builtin_mathfn (tree exp, rtx target, rtx subtarget)
builtin_optab = nearbyint_optab; break;
CASE_FLT_FN (BUILT_IN_RINT):
builtin_optab = rint_optab; break;
CASE_FLT_FN (BUILT_IN_LRINT):
CASE_FLT_FN (BUILT_IN_LLRINT):
builtin_optab = lrint_optab; break;
default:
gcc_unreachable ();
}
@ -2210,7 +2208,9 @@ expand_builtin_sincos (tree exp)
return const0_rtx;
}
/* Expand a call to one of the builtin rounding functions (lfloor).
/* Expand a call to one of the builtin rounding functions gcc defines
as an extension (lfloor and lceil). As these are gcc extensions we
do not need to worry about setting errno to EDOM.
If expanding via optab fails, lower expression to (int)(floor(x)).
EXP is the expression that is a call to the builtin function;
if convenient, the result should be placed in TARGET. SUBTARGET may
@ -2309,6 +2309,88 @@ expand_builtin_int_roundingfn (tree exp, rtx target, rtx subtarget)
return target;
}
/* Expand a call to one of the builtin math functions doing integer
conversion (lrint).
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_int_roundingfn_2 (tree exp, rtx target, rtx subtarget)
{
optab builtin_optab;
rtx op0, insns;
tree fndecl = get_callee_fndecl (exp);
tree arglist = TREE_OPERAND (exp, 1);
enum machine_mode mode;
tree arg, narg;
/* There's no easy way to detect the case we need to set EDOM. */
if (flag_errno_math)
return NULL_RTX;
if (!validate_arglist (arglist, REAL_TYPE, VOID_TYPE))
return NULL_RTX;
arg = TREE_VALUE (arglist);
switch (DECL_FUNCTION_CODE (fndecl))
{
CASE_FLT_FN (BUILT_IN_LRINT):
CASE_FLT_FN (BUILT_IN_LLRINT):
builtin_optab = lrint_optab; break;
default:
gcc_unreachable ();
}
/* Make a suitable register to place result in. */
mode = TYPE_MODE (TREE_TYPE (exp));
/* Before working hard, check whether the instruction is available. */
if (builtin_optab->handlers[(int) mode].insn_code != CODE_FOR_nothing)
{
target = gen_reg_rtx (mode);
/* Wrap the computation of the argument in a SAVE_EXPR, as we may
need to expand the argument again. This way, we will not perform
side-effects more the once. */
narg = builtin_save_expr (arg);
if (narg != arg)
{
arg = narg;
arglist = build_tree_list (NULL_TREE, arg);
exp = build_function_call_expr (fndecl, arglist);
}
op0 = expand_expr (arg, subtarget, VOIDmode, 0);
start_sequence ();
/* Compute into TARGET.
Set TARGET to wherever the result comes back. */
target = expand_unop (mode, builtin_optab, op0, target, 0);
if (target != 0)
{
/* Output the entire sequence. */
insns = get_insns ();
end_sequence ();
emit_insn (insns);
return target;
}
/* If we were unable to expand via the builtin, stop the sequence
(without outputting the insns) and call to the library function
with the stabilized argument list. */
end_sequence ();
}
target = expand_call (exp, target, target == const0_rtx);
return target;
}
/* To evaluate powi(x,n), the floating point value x raised to the
constant integer exponent n, we use a hybrid algorithm that
combines the "window method" with look-up tables. For an
@ -5718,8 +5800,6 @@ expand_builtin (tree exp, rtx target, rtx subtarget, enum machine_mode mode,
CASE_FLT_FN (BUILT_IN_ROUND):
CASE_FLT_FN (BUILT_IN_NEARBYINT):
CASE_FLT_FN (BUILT_IN_RINT):
CASE_FLT_FN (BUILT_IN_LRINT):
CASE_FLT_FN (BUILT_IN_LLRINT):
target = expand_builtin_mathfn (exp, target, subtarget);
if (target)
return target;
@ -5734,6 +5814,13 @@ expand_builtin (tree exp, rtx target, rtx subtarget, enum machine_mode mode,
return target;
break;
CASE_FLT_FN (BUILT_IN_LRINT):
CASE_FLT_FN (BUILT_IN_LLRINT):
target = expand_builtin_int_roundingfn_2 (exp, target, subtarget);
if (target)
return target;
break;
CASE_FLT_FN (BUILT_IN_POW):
target = expand_builtin_pow (exp, target, subtarget);
if (target)