aboutsummaryrefslogtreecommitdiff
path: root/gcc/tree.c
diff options
context:
space:
mode:
authorRichard Sandiford <richard.sandiford@arm.com>2015-11-17 18:47:44 +0000
committerRichard Sandiford <rsandifo@gcc.gnu.org>2015-11-17 18:47:44 +0000
commitc9e926ce2bdc8bdce5fd9892443cf6147868e7f6 (patch)
tree85646c7ff97526585c06596877a86bf8c493a6b3 /gcc/tree.c
parentb03ff92e67280a98ab1587e0460069eea0fd5a8b (diff)
downloadgcc-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.c62
1 files changed, 57 insertions, 5 deletions
diff --git a/gcc/tree.c b/gcc/tree.c
index 29c5f4c..d5a71a3 100644
--- a/gcc/tree.c
+++ b/gcc/tree.c
@@ -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.