aboutsummaryrefslogtreecommitdiff
path: root/gcc/builtins.c
diff options
context:
space:
mode:
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. */