builtins.c (expand_builtin_int_interclass_roundingfn): New function to handle optabs that operate on floating point input argument and...
* builtins.c (expand_builtin_int_interclass_roundingfn): New function to handle optabs that operate on floating point input argument and output to integer output. (expand_builtin_mathfn) [BUILT_IN_ILOGB]: Move from here ... (expand_builtin_interclass_mathfn) [BUILT_IN_ILOGB]: ... to here. (expand_builtin): Expand BUILT_IN_ILOGB{,F,L} using expand_builtin_interclass_mathfn (). * config/i386/i386.md (fxtractxf3_i387): Rename from *fxtractxf3_i387. (ilogbsi2): Remove. (ilogbxf2, ilogb<mode>2): New expanders to implement ilogb, ilogbf and ilogbl built-in functions as x87 intrinsics. From-SVN: r121336
This commit is contained in:
parent
9b1959ffca
commit
eaee446477
|
@ -1,3 +1,17 @@
|
||||||
|
2007-01-30 Uros Bizjak <ubizjak@gmail.com>
|
||||||
|
|
||||||
|
* builtins.c (expand_builtin_int_interclass_roundingfn): New function
|
||||||
|
to handle optabs that operate on floating point input argument and
|
||||||
|
output to integer output.
|
||||||
|
(expand_builtin_mathfn) [BUILT_IN_ILOGB]: Move from here ...
|
||||||
|
(expand_builtin_interclass_mathfn) [BUILT_IN_ILOGB]: ... to here.
|
||||||
|
(expand_builtin): Expand BUILT_IN_ILOGB{,F,L} using
|
||||||
|
expand_builtin_interclass_mathfn ().
|
||||||
|
* config/i386/i386.md (fxtractxf3_i387): Rename from *fxtractxf3_i387.
|
||||||
|
(ilogbsi2): Remove.
|
||||||
|
(ilogbxf2, ilogb<mode>2): New expanders to implement ilogb, ilogbf and
|
||||||
|
ilogbl built-in functions as x87 intrinsics.
|
||||||
|
|
||||||
2007-01-30 Richard Guenther <rguenther@suse.de>
|
2007-01-30 Richard Guenther <rguenther@suse.de>
|
||||||
|
|
||||||
PR middle-end/27657
|
PR middle-end/27657
|
||||||
|
|
|
@ -95,6 +95,7 @@ static void expand_errno_check (tree, rtx);
|
||||||
static rtx expand_builtin_mathfn (tree, rtx, rtx);
|
static rtx expand_builtin_mathfn (tree, rtx, rtx);
|
||||||
static rtx expand_builtin_mathfn_2 (tree, rtx, rtx);
|
static rtx expand_builtin_mathfn_2 (tree, rtx, rtx);
|
||||||
static rtx expand_builtin_mathfn_3 (tree, rtx, rtx);
|
static rtx expand_builtin_mathfn_3 (tree, rtx, rtx);
|
||||||
|
static rtx expand_builtin_interclass_mathfn (tree, rtx, rtx);
|
||||||
static rtx expand_builtin_sincos (tree);
|
static rtx expand_builtin_sincos (tree);
|
||||||
static rtx expand_builtin_cexpi (tree, rtx, rtx);
|
static rtx expand_builtin_cexpi (tree, rtx, rtx);
|
||||||
static rtx expand_builtin_int_roundingfn (tree, rtx, rtx);
|
static rtx expand_builtin_int_roundingfn (tree, rtx, rtx);
|
||||||
|
@ -1814,8 +1815,6 @@ expand_builtin_mathfn (tree exp, rtx target, rtx subtarget)
|
||||||
errno_set = true; builtin_optab = expm1_optab; break;
|
errno_set = true; builtin_optab = expm1_optab; break;
|
||||||
CASE_FLT_FN (BUILT_IN_LOGB):
|
CASE_FLT_FN (BUILT_IN_LOGB):
|
||||||
errno_set = true; builtin_optab = logb_optab; break;
|
errno_set = true; builtin_optab = logb_optab; break;
|
||||||
CASE_FLT_FN (BUILT_IN_ILOGB):
|
|
||||||
errno_set = true; builtin_optab = ilogb_optab; break;
|
|
||||||
CASE_FLT_FN (BUILT_IN_LOG):
|
CASE_FLT_FN (BUILT_IN_LOG):
|
||||||
errno_set = true; builtin_optab = log_optab; break;
|
errno_set = true; builtin_optab = log_optab; break;
|
||||||
CASE_FLT_FN (BUILT_IN_LOG10):
|
CASE_FLT_FN (BUILT_IN_LOG10):
|
||||||
|
@ -2170,6 +2169,86 @@ expand_builtin_mathfn_3 (tree exp, rtx target, rtx subtarget)
|
||||||
return target;
|
return target;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Expand a call to one of the builtin math functions that operate on
|
||||||
|
floating point argument and output an integer result (ilogb, isinf,
|
||||||
|
isnan, etc).
|
||||||
|
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_interclass_mathfn (tree exp, rtx target, rtx subtarget)
|
||||||
|
{
|
||||||
|
optab builtin_optab;
|
||||||
|
enum insn_code icode;
|
||||||
|
rtx op0;
|
||||||
|
tree fndecl = get_callee_fndecl (exp);
|
||||||
|
tree arglist = TREE_OPERAND (exp, 1);
|
||||||
|
enum machine_mode mode;
|
||||||
|
bool errno_set = false;
|
||||||
|
tree arg, narg;
|
||||||
|
|
||||||
|
if (!validate_arglist (arglist, REAL_TYPE, VOID_TYPE))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
arg = TREE_VALUE (arglist);
|
||||||
|
|
||||||
|
switch (DECL_FUNCTION_CODE (fndecl))
|
||||||
|
{
|
||||||
|
CASE_FLT_FN (BUILT_IN_ILOGB):
|
||||||
|
errno_set = true; builtin_optab = ilogb_optab; break;
|
||||||
|
default:
|
||||||
|
gcc_unreachable ();
|
||||||
|
}
|
||||||
|
|
||||||
|
/* There's no easy way to detect the case we need to set EDOM. */
|
||||||
|
if (flag_errno_math && errno_set)
|
||||||
|
return NULL_RTX;
|
||||||
|
|
||||||
|
/* Optab mode depends on the mode of the input argument. */
|
||||||
|
mode = TYPE_MODE (TREE_TYPE (arg));
|
||||||
|
|
||||||
|
icode = builtin_optab->handlers[(int) mode].insn_code;
|
||||||
|
|
||||||
|
/* Before working hard, check whether the instruction is available. */
|
||||||
|
if (icode != CODE_FOR_nothing)
|
||||||
|
{
|
||||||
|
/* Make a suitable register to place result in. */
|
||||||
|
if (!target
|
||||||
|
|| GET_MODE (target) != TYPE_MODE (TREE_TYPE (exp)))
|
||||||
|
target = gen_reg_rtx (TYPE_MODE (TREE_TYPE (exp)));
|
||||||
|
|
||||||
|
gcc_assert (insn_data[icode].operand[0].predicate
|
||||||
|
(target, GET_MODE (target)));
|
||||||
|
|
||||||
|
/* 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);
|
||||||
|
|
||||||
|
if (mode != GET_MODE (op0))
|
||||||
|
op0 = convert_to_mode (mode, op0, 0);
|
||||||
|
|
||||||
|
/* Compute into TARGET.
|
||||||
|
Set TARGET to wherever the result comes back. */
|
||||||
|
emit_unop_insn (icode, target, op0, UNKNOWN);
|
||||||
|
return target;
|
||||||
|
}
|
||||||
|
|
||||||
|
target = expand_call (exp, target, target == const0_rtx);
|
||||||
|
|
||||||
|
return target;
|
||||||
|
}
|
||||||
|
|
||||||
/* Expand a call to the builtin sincos math function.
|
/* Expand a call to the builtin sincos math function.
|
||||||
Return 0 if a normal call should be emitted rather than expanding the
|
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 in-line. EXP is the expression that is a call to the builtin
|
||||||
|
@ -5817,7 +5896,6 @@ expand_builtin (tree exp, rtx target, rtx subtarget, enum machine_mode mode,
|
||||||
CASE_FLT_FN (BUILT_IN_EXP2):
|
CASE_FLT_FN (BUILT_IN_EXP2):
|
||||||
CASE_FLT_FN (BUILT_IN_EXPM1):
|
CASE_FLT_FN (BUILT_IN_EXPM1):
|
||||||
CASE_FLT_FN (BUILT_IN_LOGB):
|
CASE_FLT_FN (BUILT_IN_LOGB):
|
||||||
CASE_FLT_FN (BUILT_IN_ILOGB):
|
|
||||||
CASE_FLT_FN (BUILT_IN_LOG):
|
CASE_FLT_FN (BUILT_IN_LOG):
|
||||||
CASE_FLT_FN (BUILT_IN_LOG10):
|
CASE_FLT_FN (BUILT_IN_LOG10):
|
||||||
CASE_FLT_FN (BUILT_IN_LOG2):
|
CASE_FLT_FN (BUILT_IN_LOG2):
|
||||||
|
@ -5842,6 +5920,14 @@ expand_builtin (tree exp, rtx target, rtx subtarget, enum machine_mode mode,
|
||||||
return target;
|
return target;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
CASE_FLT_FN (BUILT_IN_ILOGB):
|
||||||
|
if (! flag_unsafe_math_optimizations)
|
||||||
|
break;
|
||||||
|
target = expand_builtin_interclass_mathfn (exp, target, subtarget);
|
||||||
|
if (target)
|
||||||
|
return target;
|
||||||
|
break;
|
||||||
|
|
||||||
CASE_FLT_FN (BUILT_IN_LCEIL):
|
CASE_FLT_FN (BUILT_IN_LCEIL):
|
||||||
CASE_FLT_FN (BUILT_IN_LLCEIL):
|
CASE_FLT_FN (BUILT_IN_LLCEIL):
|
||||||
CASE_FLT_FN (BUILT_IN_LFLOOR):
|
CASE_FLT_FN (BUILT_IN_LFLOOR):
|
||||||
|
|
|
@ -16261,7 +16261,7 @@
|
||||||
DONE;
|
DONE;
|
||||||
})
|
})
|
||||||
|
|
||||||
(define_insn "*fxtractxf3_i387"
|
(define_insn "fxtractxf3_i387"
|
||||||
[(set (match_operand:XF 0 "register_operand" "=f")
|
[(set (match_operand:XF 0 "register_operand" "=f")
|
||||||
(unspec:XF [(match_operand:XF 2 "register_operand" "0")]
|
(unspec:XF [(match_operand:XF 2 "register_operand" "0")]
|
||||||
UNSPEC_XTRACT_FRACT))
|
UNSPEC_XTRACT_FRACT))
|
||||||
|
@ -16316,21 +16316,34 @@
|
||||||
DONE;
|
DONE;
|
||||||
})
|
})
|
||||||
|
|
||||||
(define_expand "ilogbsi2"
|
(define_expand "ilogbxf2"
|
||||||
[(parallel [(set (match_dup 2)
|
[(use (match_operand:SI 0 "register_operand" ""))
|
||||||
(unspec:XF [(match_operand:XF 1 "register_operand" "")]
|
(use (match_operand:XF 1 "register_operand" ""))]
|
||||||
UNSPEC_XTRACT_FRACT))
|
|
||||||
(set (match_dup 3)
|
|
||||||
(unspec:XF [(match_dup 1)] UNSPEC_XTRACT_EXP))])
|
|
||||||
(parallel [(set (match_operand:SI 0 "register_operand" "")
|
|
||||||
(fix:SI (match_dup 3)))
|
|
||||||
(clobber (reg:CC FLAGS_REG))])]
|
|
||||||
"TARGET_USE_FANCY_MATH_387
|
"TARGET_USE_FANCY_MATH_387
|
||||||
&& (!TARGET_SSE_MATH || TARGET_MIX_SSE_I387)
|
|
||||||
&& flag_unsafe_math_optimizations && !optimize_size"
|
&& flag_unsafe_math_optimizations && !optimize_size"
|
||||||
{
|
{
|
||||||
operands[2] = gen_reg_rtx (XFmode);
|
rtx op0 = gen_reg_rtx (XFmode);
|
||||||
operands[3] = gen_reg_rtx (XFmode);
|
rtx op1 = gen_reg_rtx (XFmode);
|
||||||
|
|
||||||
|
emit_insn (gen_fxtractxf3_i387 (op0, op1, operands[1]));
|
||||||
|
emit_insn (gen_fix_truncxfsi2 (operands[0], op1));
|
||||||
|
DONE;
|
||||||
|
})
|
||||||
|
|
||||||
|
(define_expand "ilogb<mode>2"
|
||||||
|
[(use (match_operand:SI 0 "register_operand" ""))
|
||||||
|
(use (match_operand:X87MODEF12 1 "register_operand" ""))]
|
||||||
|
"TARGET_USE_FANCY_MATH_387
|
||||||
|
&& (!(SSE_FLOAT_MODE_P (<MODE>mode) && TARGET_SSE_MATH)
|
||||||
|
|| TARGET_MIX_SSE_I387)
|
||||||
|
&& flag_unsafe_math_optimizations && !optimize_size"
|
||||||
|
{
|
||||||
|
rtx op0 = gen_reg_rtx (XFmode);
|
||||||
|
rtx op1 = gen_reg_rtx (XFmode);
|
||||||
|
|
||||||
|
emit_insn (gen_fxtract_extend<mode>xf3_i387 (op0, op1, operands[1]));
|
||||||
|
emit_insn (gen_fix_truncxfsi2 (operands[0], op1));
|
||||||
|
DONE;
|
||||||
})
|
})
|
||||||
|
|
||||||
(define_insn "*f2xm1xf2_i387"
|
(define_insn "*f2xm1xf2_i387"
|
||||||
|
|
Loading…
Reference in New Issue