aboutsummaryrefslogtreecommitdiff
path: root/gcc/builtins.c
diff options
context:
space:
mode:
authorRichard Sandiford <richard.sandiford@arm.com>2015-11-17 18:39:02 +0000
committerRichard Sandiford <rsandifo@gcc.gnu.org>2015-11-17 18:39:02 +0000
commit686ee9719a4dc70619da0a69a4357007406c9fbd (patch)
treea3ec02e033084a3f11a50a026441973f162ceda0 /gcc/builtins.c
parentab23f5d9742b8b1c7a80d8383a141f243f4198e6 (diff)
downloadgcc-686ee9719a4dc70619da0a69a4357007406c9fbd.zip
gcc-686ee9719a4dc70619da0a69a4357007406c9fbd.tar.gz
gcc-686ee9719a4dc70619da0a69a4357007406c9fbd.tar.bz2
Add internal math functions
This patch adds internal functions for simple FLT_FN built-in functions, in cases where an associated optab already exists. Unlike some of the built-in functions, these internal functions never set errno. LDEXP is an odd-one out in that its second operand is an integer. All the others operate on uniform types. The patch also adds a function to query the internal function associated with a built-in function (if any), and another to test whether a given gcall could be replaced by a call to an internal function on the current target (as long as the caller deals with errno appropriately). Tested on x86_64-linux-gnu, aarch64-linux-gnu and arm-linux-gnueabi. gcc/ * builtins.h (associated_internal_fn): Declare. (replacement_internal_fn): Likewise. * builtins.c: Include internal-fn.h (associated_internal_fn, replacement_internal_fn): New functions. * internal-fn.def (DEF_INTERNAL_FLT_FN): New macro. (ACOS, ASIN, ATAN, COS, EXP, EXP10, EXP2, EXPM1, LOG, LOG10, LOG1P) (LOG2, LOGB, SIGNIFICAND, SIN, SQRT, TAN, CEIL, FLOOR, NEARBYINT) (RINT, ROUND, TRUNC, ATAN2, COPYSIGN, FMOD, POW, REMAINDER, SCALB) (LDEXP): New functions. * internal-fn.c: Include recog.h. (unary_direct, binary_direct): New macros. (expand_direct_optab_fn): New function. (expand_unary_optab_fn): New macro. (expand_binary_optab_fn): Likewise. (direct_unary_optab_supported_p): Likewise. (direct_binary_optab_supported_p): Likewise. From-SVN: r230474
Diffstat (limited to 'gcc/builtins.c')
-rw-r--r--gcc/builtins.c58
1 files changed, 58 insertions, 0 deletions
diff --git a/gcc/builtins.c b/gcc/builtins.c
index 85b251a..0eef112 100644
--- a/gcc/builtins.c
+++ b/gcc/builtins.c
@@ -62,6 +62,7 @@ along with GCC; see the file COPYING3. If not see
#include "cilk.h"
#include "tree-chkp.h"
#include "rtl-chkp.h"
+#include "internal-fn.h"
struct target_builtins default_target_builtins;
@@ -1901,6 +1902,63 @@ mathfn_built_in (tree type, enum built_in_function fn)
return mathfn_built_in_1 (type, fn, /*implicit=*/ 1);
}
+/* If BUILT_IN_NORMAL function FNDECL has an associated internal function,
+ return its code, otherwise return IFN_LAST. Note that this function
+ only tests whether the function is defined in internals.def, not whether
+ it is actually available on the target. */
+
+internal_fn
+associated_internal_fn (tree fndecl)
+{
+ gcc_checking_assert (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL);
+ tree return_type = TREE_TYPE (TREE_TYPE (fndecl));
+ switch (DECL_FUNCTION_CODE (fndecl))
+ {
+#define DEF_INTERNAL_FLT_FN(NAME, FLAGS, OPTAB, TYPE) \
+ CASE_FLT_FN (BUILT_IN_##NAME): return IFN_##NAME;
+#include "internal-fn.def"
+
+ CASE_FLT_FN (BUILT_IN_POW10):
+ return IFN_EXP10;
+
+ CASE_FLT_FN (BUILT_IN_DREM):
+ return IFN_REMAINDER;
+
+ CASE_FLT_FN (BUILT_IN_SCALBN):
+ CASE_FLT_FN (BUILT_IN_SCALBLN):
+ if (REAL_MODE_FORMAT (TYPE_MODE (return_type))->b == 2)
+ return IFN_LDEXP;
+ return IFN_LAST;
+
+ default:
+ return IFN_LAST;
+ }
+}
+
+/* If CALL is a call to a BUILT_IN_NORMAL function that could be replaced
+ on the current target by a call to an internal function, return the
+ code of that internal function, otherwise return IFN_LAST. The caller
+ is responsible for ensuring that any side-effects of the built-in
+ call are dealt with correctly. E.g. if CALL sets errno, the caller
+ must decide that the errno result isn't needed or make it available
+ in some other way. */
+
+internal_fn
+replacement_internal_fn (gcall *call)
+{
+ if (gimple_call_builtin_p (call, BUILT_IN_NORMAL))
+ {
+ internal_fn ifn = associated_internal_fn (gimple_call_fndecl (call));
+ if (ifn != IFN_LAST)
+ {
+ tree_pair types = direct_internal_fn_types (ifn, call);
+ if (direct_internal_fn_supported_p (ifn, types))
+ return ifn;
+ }
+ }
+ return IFN_LAST;
+}
+
/* 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. */