aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorUros Bizjak <ubizjak@gmail.com>2007-01-30 12:20:07 +0100
committerUros Bizjak <uros@gcc.gnu.org>2007-01-30 12:20:07 +0100
commiteaee4464778034db0c3f27640c98bdfb8584ef17 (patch)
tree942a2e626dc40e269d296c1c97e6a8efef92aff0
parent9b1959ffcaa3fab49a90eb25f32a815ac22c2a85 (diff)
downloadgcc-eaee4464778034db0c3f27640c98bdfb8584ef17.zip
gcc-eaee4464778034db0c3f27640c98bdfb8584ef17.tar.gz
gcc-eaee4464778034db0c3f27640c98bdfb8584ef17.tar.bz2
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
-rw-r--r--gcc/ChangeLog14
-rw-r--r--gcc/builtins.c92
-rw-r--r--gcc/config/i386/i386.md39
3 files changed, 129 insertions, 16 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 90c826f..cc30009 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -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>
PR middle-end/27657
diff --git a/gcc/builtins.c b/gcc/builtins.c
index a2f540a..5ba1eae 100644
--- a/gcc/builtins.c
+++ b/gcc/builtins.c
@@ -95,6 +95,7 @@ static void expand_errno_check (tree, rtx);
static rtx expand_builtin_mathfn (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_interclass_mathfn (tree, rtx, rtx);
static rtx expand_builtin_sincos (tree);
static rtx expand_builtin_cexpi (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;
CASE_FLT_FN (BUILT_IN_LOGB):
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):
errno_set = true; builtin_optab = log_optab; break;
CASE_FLT_FN (BUILT_IN_LOG10):
@@ -2170,6 +2169,86 @@ expand_builtin_mathfn_3 (tree exp, rtx target, rtx subtarget)
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.
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
@@ -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_EXPM1):
CASE_FLT_FN (BUILT_IN_LOGB):
- CASE_FLT_FN (BUILT_IN_ILOGB):
CASE_FLT_FN (BUILT_IN_LOG):
CASE_FLT_FN (BUILT_IN_LOG10):
CASE_FLT_FN (BUILT_IN_LOG2):
@@ -5842,6 +5920,14 @@ expand_builtin (tree exp, rtx target, rtx subtarget, enum machine_mode mode,
return target;
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_LLCEIL):
CASE_FLT_FN (BUILT_IN_LFLOOR):
diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md
index 21d1c2b..a9620e2 100644
--- a/gcc/config/i386/i386.md
+++ b/gcc/config/i386/i386.md
@@ -16261,7 +16261,7 @@
DONE;
})
-(define_insn "*fxtractxf3_i387"
+(define_insn "fxtractxf3_i387"
[(set (match_operand:XF 0 "register_operand" "=f")
(unspec:XF [(match_operand:XF 2 "register_operand" "0")]
UNSPEC_XTRACT_FRACT))
@@ -16316,21 +16316,34 @@
DONE;
})
-(define_expand "ilogbsi2"
- [(parallel [(set (match_dup 2)
- (unspec:XF [(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))])]
+(define_expand "ilogbxf2"
+ [(use (match_operand:SI 0 "register_operand" ""))
+ (use (match_operand:XF 1 "register_operand" ""))]
"TARGET_USE_FANCY_MATH_387
- && (!TARGET_SSE_MATH || TARGET_MIX_SSE_I387)
&& flag_unsafe_math_optimizations && !optimize_size"
{
- operands[2] = gen_reg_rtx (XFmode);
- operands[3] = gen_reg_rtx (XFmode);
+ rtx op0 = 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"