From 5249ee4d79855edda91b26bb07c9c8737cdfc96c Mon Sep 17 00:00:00 2001 From: Richard Sandiford Date: Thu, 12 Jul 2018 13:02:17 +0000 Subject: Implement SLP of internal functions SLP of calls was previously restricted to built-in functions. This patch extends it to internal functions. 2018-07-12 Richard Sandiford gcc/ * internal-fn.h (vectorizable_internal_fn_p): New function. * tree-vect-slp.c (compatible_calls_p): Likewise. (vect_build_slp_tree_1): Remove nops argument. Handle calls to internal functions. (vect_build_slp_tree_2): Update call to vect_build_slp_tree_1. gcc/testsuite/ * gcc.dg/vect/vect-cond-arith-6.c: New test. * gcc.target/aarch64/sve/cond_arith_4.c: Likewise. * gcc.target/aarch64/sve/cond_arith_4_run.c: Likewise. * gcc.target/aarch64/sve/cond_arith_5.c: Likewise. * gcc.target/aarch64/sve/cond_arith_5_run.c: Likewise. * gcc.target/aarch64/sve/slp_14.c: Likewise. * gcc.target/aarch64/sve/slp_14_run.c: Likewise. From-SVN: r262590 --- gcc/tree-vect-slp.c | 53 +++++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 43 insertions(+), 10 deletions(-) (limited to 'gcc/tree-vect-slp.c') diff --git a/gcc/tree-vect-slp.c b/gcc/tree-vect-slp.c index 528e1d5..8dc5763 100644 --- a/gcc/tree-vect-slp.c +++ b/gcc/tree-vect-slp.c @@ -562,6 +562,41 @@ again: return 0; } +/* Return true if call statements CALL1 and CALL2 are similar enough + to be combined into the same SLP group. */ + +static bool +compatible_calls_p (gcall *call1, gcall *call2) +{ + unsigned int nargs = gimple_call_num_args (call1); + if (nargs != gimple_call_num_args (call2)) + return false; + + if (gimple_call_combined_fn (call1) != gimple_call_combined_fn (call2)) + return false; + + if (gimple_call_internal_p (call1)) + { + if (!types_compatible_p (TREE_TYPE (gimple_call_lhs (call1)), + TREE_TYPE (gimple_call_lhs (call2)))) + return false; + for (unsigned int i = 0; i < nargs; ++i) + if (!types_compatible_p (TREE_TYPE (gimple_call_arg (call1, i)), + TREE_TYPE (gimple_call_arg (call2, i)))) + return false; + } + else + { + if (!operand_equal_p (gimple_call_fn (call1), + gimple_call_fn (call2), 0)) + return false; + + if (gimple_call_fntype (call1) != gimple_call_fntype (call2)) + return false; + } + return true; +} + /* A subroutine of vect_build_slp_tree for checking VECTYPE, which is the caller's attempt to find the vector type in STMT with the narrowest element type. Return true if VECTYPE is nonnull and if it is valid @@ -650,8 +685,8 @@ vect_two_operations_perm_ok_p (vec stmts, unsigned int group_size, static bool vect_build_slp_tree_1 (vec_info *vinfo, unsigned char *swap, vec stmts, unsigned int group_size, - unsigned nops, poly_uint64 *max_nunits, - bool *matches, bool *two_operators) + poly_uint64 *max_nunits, bool *matches, + bool *two_operators) { unsigned int i; gimple *first_stmt = stmts[0], *stmt = stmts[0]; @@ -727,7 +762,9 @@ vect_build_slp_tree_1 (vec_info *vinfo, unsigned char *swap, if (gcall *call_stmt = dyn_cast (stmt)) { rhs_code = CALL_EXPR; - if (gimple_call_internal_p (call_stmt) + if ((gimple_call_internal_p (call_stmt) + && (!vectorizable_internal_fn_p + (gimple_call_internal_fn (call_stmt)))) || gimple_call_tail_p (call_stmt) || gimple_call_noreturn_p (call_stmt) || !gimple_call_nothrow_p (call_stmt) @@ -873,11 +910,8 @@ vect_build_slp_tree_1 (vec_info *vinfo, unsigned char *swap, if (rhs_code == CALL_EXPR) { gimple *first_stmt = stmts[0]; - if (gimple_call_num_args (stmt) != nops - || !operand_equal_p (gimple_call_fn (first_stmt), - gimple_call_fn (stmt), 0) - || gimple_call_fntype (first_stmt) - != gimple_call_fntype (stmt)) + if (!compatible_calls_p (as_a (first_stmt), + as_a (stmt))) { if (dump_enabled_p ()) { @@ -1193,8 +1227,7 @@ vect_build_slp_tree_2 (vec_info *vinfo, bool two_operators = false; unsigned char *swap = XALLOCAVEC (unsigned char, group_size); - if (!vect_build_slp_tree_1 (vinfo, swap, - stmts, group_size, nops, + if (!vect_build_slp_tree_1 (vinfo, swap, stmts, group_size, &this_max_nunits, matches, &two_operators)) return NULL; -- cgit v1.1