aboutsummaryrefslogtreecommitdiff
path: root/gcc/builtins.c
diff options
context:
space:
mode:
authorRichard Guenther <rguenth@gcc.gnu.org>2005-02-09 20:58:13 +0000
committerRichard Biener <rguenth@gcc.gnu.org>2005-02-09 20:58:13 +0000
commit17684d462957afd5011d71db40e9a96c63225d2c (patch)
tree347cc9d98b8029f4811e05bd8d3f3df4c5a4ced7 /gcc/builtins.c
parent8ca3515fbe765aef349c8d6f848539bf11d3d6df (diff)
downloadgcc-17684d462957afd5011d71db40e9a96c63225d2c.zip
gcc-17684d462957afd5011d71db40e9a96c63225d2c.tar.gz
gcc-17684d462957afd5011d71db40e9a96c63225d2c.tar.bz2
re PR middle-end/19402 (__builtin_powi? still missing)
2005-02-09 Richard Guenther <rguenth@gcc.gnu.org> PR middle-end/19402 * builtins.def: New __builtin_powi[lf]. * builtins.c (mathfn_built_in): Handle BUILT_IN_POWI. (expand_builtin_powi): New function. (expand_builtin): Dispatch to expand_builtin_powi. * libgcc2.h: Add prototypes for __builtin_powi[lf]. * libgcc2.c: Add __builtin_powi[lf] implementation. * mklibgcc.in: Add __builtin_powi[lf] to lib2funcs. * optabs.h: Add powi_optab. * optabs.c (init_optabs): Initialize powi_optab. * doc/extend.texi: Document __builtin_powi[lf]. * gcc.dg/pr19402-1.c: New testcase. * gcc.dg/pr19402-2.c: likewise. From-SVN: r94774
Diffstat (limited to 'gcc/builtins.c')
-rw-r--r--gcc/builtins.c69
1 files changed, 69 insertions, 0 deletions
diff --git a/gcc/builtins.c b/gcc/builtins.c
index 09c5b6b..3631615 100644
--- a/gcc/builtins.c
+++ b/gcc/builtins.c
@@ -1563,6 +1563,7 @@ mathfn_built_in (tree type, enum built_in_function fn)
CASE_MATHFN (BUILT_IN_NEXTAFTER)
CASE_MATHFN (BUILT_IN_NEXTTOWARD)
CASE_MATHFN (BUILT_IN_POW)
+ CASE_MATHFN (BUILT_IN_POWI)
CASE_MATHFN (BUILT_IN_POW10)
CASE_MATHFN (BUILT_IN_REMAINDER)
CASE_MATHFN (BUILT_IN_REMQUO)
@@ -2349,6 +2350,66 @@ expand_builtin_pow (tree exp, rtx target, rtx subtarget)
return expand_builtin_mathfn_2 (exp, target, subtarget);
}
+/* Expand a call to the powi built-in mathematical 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
+ function; if convenient, the result should be placed in TARGET. */
+
+static rtx
+expand_builtin_powi (tree exp, rtx target, rtx subtarget)
+{
+ tree arglist = TREE_OPERAND (exp, 1);
+ tree arg0, arg1;
+ rtx op0, op1;
+ enum machine_mode mode;
+
+ if (! validate_arglist (arglist, REAL_TYPE, INTEGER_TYPE, VOID_TYPE))
+ return 0;
+
+ arg0 = TREE_VALUE (arglist);
+ arg1 = TREE_VALUE (TREE_CHAIN (arglist));
+ mode = TYPE_MODE (TREE_TYPE (exp));
+
+ /* Handle constant power. */
+
+ if (TREE_CODE (arg1) == INTEGER_CST
+ && ! TREE_CONSTANT_OVERFLOW (arg1))
+ {
+ HOST_WIDE_INT n = TREE_INT_CST_LOW (arg1);
+
+ /* If the exponent is -1, 0, 1 or 2, then expand_powi is exact.
+ Otherwise, check the number of multiplications required. */
+ if ((TREE_INT_CST_HIGH (arg1) == 0
+ || TREE_INT_CST_HIGH (arg1) == -1)
+ && ((n >= -1 && n <= 2)
+ || (! optimize_size
+ && powi_cost (n) <= POWI_MAX_MULTS)))
+ {
+ op0 = expand_expr (arg0, subtarget, VOIDmode, 0);
+ op0 = force_reg (mode, op0);
+ return expand_powi (op0, mode, n);
+ }
+ }
+
+ /* Emit a libcall to libgcc. */
+
+ if (target == NULL_RTX)
+ target = gen_reg_rtx (mode);
+
+ op0 = expand_expr (arg0, subtarget, mode, 0);
+ if (GET_MODE (op0) != mode)
+ op0 = convert_to_mode (mode, op0, 0);
+ op1 = expand_expr (arg1, 0, word_mode, 0);
+ if (GET_MODE (op1) != word_mode)
+ op1 = convert_to_mode (word_mode, op1, 0);
+
+ target = emit_library_call_value (powi_optab->handlers[(int) mode].libfunc,
+ target, LCT_CONST_MAKE_BLOCK, mode, 2,
+ op0, mode, op1, word_mode);
+
+ return target;
+}
+
/* Expand expression EXP which is a call to the strlen builtin. Return 0
if we failed the caller should emit a normal call, otherwise
try to get the result in TARGET, if convenient. */
@@ -5186,6 +5247,14 @@ expand_builtin (tree exp, rtx target, rtx subtarget, enum machine_mode mode,
return target;
break;
+ case BUILT_IN_POWI:
+ case BUILT_IN_POWIF:
+ case BUILT_IN_POWIL:
+ target = expand_builtin_powi (exp, target, subtarget);
+ if (target)
+ return target;
+ break;
+
case BUILT_IN_ATAN2:
case BUILT_IN_ATAN2F:
case BUILT_IN_ATAN2L: