diff options
author | Richard Sandiford <richard.sandiford@arm.com> | 2015-11-17 18:47:44 +0000 |
---|---|---|
committer | Richard Sandiford <rsandifo@gcc.gnu.org> | 2015-11-17 18:47:44 +0000 |
commit | c9e926ce2bdc8bdce5fd9892443cf6147868e7f6 (patch) | |
tree | 85646c7ff97526585c06596877a86bf8c493a6b3 /gcc/tree.c | |
parent | b03ff92e67280a98ab1587e0460069eea0fd5a8b (diff) | |
download | gcc-c9e926ce2bdc8bdce5fd9892443cf6147868e7f6.zip gcc-c9e926ce2bdc8bdce5fd9892443cf6147868e7f6.tar.gz gcc-c9e926ce2bdc8bdce5fd9892443cf6147868e7f6.tar.bz2 |
Add genmatch support for internal functions
This patch makes genmatch match calls based on combined_fn rather
than built_in_function and extends the matching to internal functions.
It also uses fold_const_call to fold the calls to a constant, rather
than going through fold_builtin_n.
In order to slightly simplify the code and remove potential
ambiguity, the patch enforces lower case for tree codes
(foo->FOO_EXPR), caps for functions (no built_in_hypot->BUILT_IN_HYPOT)
and requires an exact match for user-defined identifiers. The first two
were already met in practice but there were a couple of cases where
operator lists were defined in one case and used in another.
Tested on x86_64-linux-gnu, aarch64-linux-gnu and arm-linux-gnueabi.
gcc/
* match.pd: Use HYPOT and COS rather than hypot and cos.
Use CASE_CFN_* macros. Guard log/exp folds with
SCALAR_FLOAT_TYPE_P.
* genmatch.c (internal_fn): New enum.
(fn_id::fn): Change to an unsigned int.
(fn_id::fn_id): Accept internal_fn too.
(add_builtin): Rename to...
(add_function): ...this and turn into a template.
(get_operator): Only try one variation if the original name fails.
Only add _EXPR if the original name was all lower case.
Try converting internal and built-in function names to their
CFN equivalents.
(expr::gen_transform): Use maybe_build_call_expr_loc for generic.
(dt_simplify::gen_1): Likewise.
(dt_node::gen_kids_1): Use gimple_call_combined_fn for gimple
and get_call_combined_fn for generic.
(dt_simplify::gen): Use combined_fn as the type of fn_ids.
(decision_tree::gen): Likewise.
(main): Use lower case in the strings for {VIEW_,}CONVERT[012].
Use add_function rather than add_builtin. Register internal
functions too.
* generic-match-head.c: Include case-cfn-macros.h.
* gimple-fold.c (replace_stmt_with_simplification): Use
gimple_call_combined_fn to test whether we can keep an
existing call.
* gimple-match.h (code_helper): Replace built_in_function
with combined_fn.
* gimple-match-head.c: Include fold-const-call.h, internal-fn.h
and case-fn-macros.h.
(gimple_resimplify1): Use fold_const_call.
(gimple_resimplify2, gimple_resimplify3): Likewise.
(build_call_internal, build_call): New functions.
(maybe_push_res_to_seq): Use them.
(gimple_simplify): Use fold_const_call. Set *rcode to a combined_fn
rather than a built-in function.
* tree.h (build_call_expr_internal_loc): Declare.
(maybe_build_call_expr_loc): Likewise.
* tree.c (build_call_expr_internal_loc_array): New function.
(maybe_build_call_expr_loc): Likewise.
From-SVN: r230484
Diffstat (limited to 'gcc/tree.c')
-rw-r--r-- | gcc/tree.c | 62 |
1 files changed, 57 insertions, 5 deletions
@@ -11063,6 +11063,22 @@ build_call_expr (tree fndecl, int n, ...) return build_call_expr_loc_array (UNKNOWN_LOCATION, fndecl, n, argarray); } +/* Build an internal call to IFN, with arguments ARGS[0:N-1] and with return + type TYPE. This is just like CALL_EXPR, except its CALL_EXPR_FN is NULL. + It will get gimplified later into an ordinary internal function. */ + +tree +build_call_expr_internal_loc_array (location_t loc, internal_fn ifn, + tree type, int n, const tree *args) +{ + tree t = build_call_1 (type, NULL_TREE, n); + for (int i = 0; i < n; ++i) + CALL_EXPR_ARG (t, i) = args[i]; + SET_EXPR_LOCATION (t, loc); + CALL_EXPR_IFN (t) = ifn; + return t; +} + /* Build internal call expression. This is just like CALL_EXPR, except its CALL_EXPR_FN is NULL. It will get gimplified later into ordinary internal function. */ @@ -11072,16 +11088,52 @@ build_call_expr_internal_loc (location_t loc, enum internal_fn ifn, tree type, int n, ...) { va_list ap; + tree *argarray = XALLOCAVEC (tree, n); int i; - tree fn = build_call_1 (type, NULL_TREE, n); va_start (ap, n); for (i = 0; i < n; i++) - CALL_EXPR_ARG (fn, i) = va_arg (ap, tree); + argarray[i] = va_arg (ap, tree); va_end (ap); - SET_EXPR_LOCATION (fn, loc); - CALL_EXPR_IFN (fn) = ifn; - return fn; + return build_call_expr_internal_loc_array (loc, ifn, type, n, argarray); +} + +/* Return a function call to FN, if the target is guaranteed to support it, + or null otherwise. + + N is the number of arguments, passed in the "...", and TYPE is the + type of the return value. */ + +tree +maybe_build_call_expr_loc (location_t loc, combined_fn fn, tree type, + int n, ...) +{ + va_list ap; + tree *argarray = XALLOCAVEC (tree, n); + int i; + + va_start (ap, n); + for (i = 0; i < n; i++) + argarray[i] = va_arg (ap, tree); + va_end (ap); + if (internal_fn_p (fn)) + { + internal_fn ifn = as_internal_fn (fn); + if (direct_internal_fn_p (ifn)) + { + tree_pair types = direct_internal_fn_types (ifn, type, argarray); + if (!direct_internal_fn_supported_p (ifn, types)) + return NULL_TREE; + } + return build_call_expr_internal_loc_array (loc, ifn, type, n, argarray); + } + else + { + tree fndecl = builtin_decl_implicit (as_builtin_fn (fn)); + if (!fndecl) + return NULL_TREE; + return build_call_expr_loc_array (loc, fndecl, n, argarray); + } } /* Create a new constant string literal and return a char* pointer to it. |