From: Richard Sandiford Date: Wed, 20 Jun 2018 08:16:08 +0000 (+0000) Subject: [8/n] PR85694: Make patterns check for target support X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=1cbfeccc8d5ddade3a1727e18fe31c1e83e81701;p=gcc.git [8/n] PR85694: Make patterns check for target support This patch makes pattern recognisers do their own checking for vector types and target support. Previously some recognisers did this themselves and some left it to vect_pattern_recog_1. Doing this means we can get rid of the type_in argument, which was ignored if the recogniser did its own checking. It also means we create fewer junk statements. 2018-06-20 Richard Sandiford gcc/ * tree-vectorizer.h (NUM_PATTERNS, vect_recog_func_ptr): Move to tree-vect-patterns.c. * tree-vect-patterns.c (vect_supportable_direct_optab_p): New function. (vect_recog_dot_prod_pattern): Use it. Remove the type_in argument. (vect_recog_sad_pattern): Likewise. (vect_recog_widen_sum_pattern): Likewise. (vect_recog_pow_pattern): Likewise. Check for a null vectype. (vect_recog_widen_shift_pattern): Remove the type_in argument. (vect_recog_rotate_pattern): Likewise. (vect_recog_mult_pattern): Likewise. (vect_recog_vector_vector_shift_pattern): Likewise. (vect_recog_divmod_pattern): Likewise. (vect_recog_mixed_size_cond_pattern): Likewise. (vect_recog_bool_pattern): Likewise. (vect_recog_mask_conversion_pattern): Likewise. (vect_try_gather_scatter_pattern): Likewise. (vect_recog_widen_mult_pattern): Likewise. Check for a null vectype. (vect_recog_over_widening_pattern): Likewise. (vect_recog_gather_scatter_pattern): Likewise. (vect_recog_func_ptr): Move from tree-vectorizer.h (vect_vect_recog_func_ptrs): Move further down the file. (vect_recog_func): Likewise. Remove the third argument. (NUM_PATTERNS): Define based on vect_vect_recog_func_ptrs. (vect_pattern_recog_1): Expect the pattern function to do any necessary target tests. Also expect it to provide a vector type. Remove the type_in handling. From-SVN: r261791 --- diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 384c6ad49f6..ff47deb5e5b 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,32 @@ +2018-06-20 Richard Sandiford + + * tree-vectorizer.h (NUM_PATTERNS, vect_recog_func_ptr): Move to + tree-vect-patterns.c. + * tree-vect-patterns.c (vect_supportable_direct_optab_p): New function. + (vect_recog_dot_prod_pattern): Use it. Remove the type_in argument. + (vect_recog_sad_pattern): Likewise. + (vect_recog_widen_sum_pattern): Likewise. + (vect_recog_pow_pattern): Likewise. Check for a null vectype. + (vect_recog_widen_shift_pattern): Remove the type_in argument. + (vect_recog_rotate_pattern): Likewise. + (vect_recog_mult_pattern): Likewise. + (vect_recog_vector_vector_shift_pattern): Likewise. + (vect_recog_divmod_pattern): Likewise. + (vect_recog_mixed_size_cond_pattern): Likewise. + (vect_recog_bool_pattern): Likewise. + (vect_recog_mask_conversion_pattern): Likewise. + (vect_try_gather_scatter_pattern): Likewise. + (vect_recog_widen_mult_pattern): Likewise. Check for a null vectype. + (vect_recog_over_widening_pattern): Likewise. + (vect_recog_gather_scatter_pattern): Likewise. + (vect_recog_func_ptr): Move from tree-vectorizer.h + (vect_vect_recog_func_ptrs): Move further down the file. + (vect_recog_func): Likewise. Remove the third argument. + (NUM_PATTERNS): Define based on vect_vect_recog_func_ptrs. + (vect_pattern_recog_1): Expect the pattern function to do any + necessary target tests. Also expect it to provide a vector type. + Remove the type_in handling. + 2018-06-20 Richard Sandiford * tree-vect-patterns.c (vect_pattern_detected): New function. diff --git a/gcc/tree-vect-patterns.c b/gcc/tree-vect-patterns.c index 3d7f866fe37..a07b1a99159 100644 --- a/gcc/tree-vect-patterns.c +++ b/gcc/tree-vect-patterns.c @@ -47,66 +47,6 @@ along with GCC; see the file COPYING3. If not see #include "omp-simd-clone.h" #include "predict.h" -/* Pattern recognition functions */ -static gimple *vect_recog_widen_sum_pattern (vec *, tree *, - tree *); -static gimple *vect_recog_widen_mult_pattern (vec *, tree *, - tree *); -static gimple *vect_recog_dot_prod_pattern (vec *, tree *, - tree *); -static gimple *vect_recog_sad_pattern (vec *, tree *, - tree *); -static gimple *vect_recog_pow_pattern (vec *, tree *, tree *); -static gimple *vect_recog_over_widening_pattern (vec *, tree *, - tree *); -static gimple *vect_recog_widen_shift_pattern (vec *, - tree *, tree *); -static gimple *vect_recog_rotate_pattern (vec *, tree *, tree *); -static gimple *vect_recog_vector_vector_shift_pattern (vec *, - tree *, tree *); -static gimple *vect_recog_divmod_pattern (vec *, - tree *, tree *); - -static gimple *vect_recog_mult_pattern (vec *, - tree *, tree *); - -static gimple *vect_recog_mixed_size_cond_pattern (vec *, - tree *, tree *); -static gimple *vect_recog_bool_pattern (vec *, tree *, tree *); -static gimple *vect_recog_mask_conversion_pattern (vec *, tree *, tree *); -static gimple *vect_recog_gather_scatter_pattern (vec *, tree *, - tree *); - -struct vect_recog_func -{ - vect_recog_func_ptr fn; - const char *name; -}; - -/* Note that ordering matters - the first pattern matching on a stmt - is taken which means usually the more complex one needs to preceed - the less comples onex (widen_sum only after dot_prod or sad for example). */ -static vect_recog_func vect_vect_recog_func_ptrs[NUM_PATTERNS] = { - { vect_recog_widen_mult_pattern, "widen_mult" }, - { vect_recog_dot_prod_pattern, "dot_prod" }, - { vect_recog_sad_pattern, "sad" }, - { vect_recog_widen_sum_pattern, "widen_sum" }, - { vect_recog_pow_pattern, "pow" }, - { vect_recog_widen_shift_pattern, "widen_shift" }, - { vect_recog_over_widening_pattern, "over_widening" }, - { vect_recog_rotate_pattern, "rotate" }, - { vect_recog_vector_vector_shift_pattern, "vector_vector_shift" }, - { vect_recog_divmod_pattern, "divmod" }, - { vect_recog_mult_pattern, "mult" }, - { vect_recog_mixed_size_cond_pattern, "mixed_size_cond" }, - { vect_recog_bool_pattern, "bool" }, - /* This must come before mask conversion, and includes the parts - of mask conversion that are needed for gather and scatter - internal functions. */ - { vect_recog_gather_scatter_pattern, "gather_scatter" }, - { vect_recog_mask_conversion_pattern, "mask_conversion" } -}; - /* Report that we've found an instance of pattern PATTERN in statement STMT. */ @@ -134,6 +74,49 @@ new_pattern_def_seq (stmt_vec_info stmt_info, gimple *stmt) append_pattern_def_seq (stmt_info, stmt); } +/* Return true if the target supports a vector version of CODE, + where CODE is known to map to a direct optab. ITYPE specifies + the type of (some of) the scalar inputs and OTYPE specifies the + type of the scalar result. + + If CODE allows the inputs and outputs to have different type + (such as for WIDEN_SUM_EXPR), it is the input mode rather + than the output mode that determines the appropriate target pattern. + Operand 0 of the target pattern then specifies the mode that the output + must have. + + When returning true, set *VECOTYPE_OUT to the vector version of OTYPE. + Also set *VECITYPE_OUT to the vector version of ITYPE if VECITYPE_OUT + is nonnull. */ + +static bool +vect_supportable_direct_optab_p (tree otype, tree_code code, + tree itype, tree *vecotype_out, + tree *vecitype_out = NULL) +{ + tree vecitype = get_vectype_for_scalar_type (itype); + if (!vecitype) + return false; + + tree vecotype = get_vectype_for_scalar_type (otype); + if (!vecotype) + return false; + + optab optab = optab_for_tree_code (code, vecitype, optab_default); + if (!optab) + return false; + + insn_code icode = optab_handler (optab, TYPE_MODE (vecitype)); + if (icode == CODE_FOR_nothing + || insn_data[icode].operand[0].mode != TYPE_MODE (vecotype)) + return false; + + *vecotype_out = vecotype; + if (vecitype_out) + *vecitype_out = vecitype; + return true; +} + /* Check whether STMT2 is in the same loop or basic block as STMT1. Which of the two applies depends on whether we're currently doing loop-based or basic-block-based vectorization, as determined by @@ -293,8 +276,6 @@ vect_reassociating_reduction_p (stmt_vec_info stmt_vinfo) Output: - * TYPE_IN: The type of the input arguments to the pattern. - * TYPE_OUT: The type of the output of this pattern. * Return value: A new stmt that will be used to replace the sequence of @@ -310,8 +291,7 @@ vect_reassociating_reduction_p (stmt_vec_info stmt_vinfo) inner-loop nested in an outer-loop that us being vectorized). */ static gimple * -vect_recog_dot_prod_pattern (vec *stmts, tree *type_in, - tree *type_out) +vect_recog_dot_prod_pattern (vec *stmts, tree *type_out) { gimple *stmt, *last_stmt = (*stmts)[0]; tree oprnd0, oprnd1; @@ -448,8 +428,9 @@ vect_recog_dot_prod_pattern (vec *stmts, tree *type_in, vect_pattern_detected ("vect_recog_dot_prod_pattern", last_stmt); half_type = TREE_TYPE (oprnd00); - *type_in = half_type; - *type_out = type; + if (!vect_supportable_direct_optab_p (type, DOT_PROD_EXPR, half_type, + type_out)) + return NULL; var = vect_recog_temp_ssa_var (type, NULL); pattern_stmt = gimple_build_assign (var, DOT_PROD_EXPR, @@ -489,8 +470,6 @@ vect_recog_dot_prod_pattern (vec *stmts, tree *type_in, Output: - * TYPE_IN: The type of the input arguments to the pattern. - * TYPE_OUT: The type of the output of this pattern. * Return value: A new stmt that will be used to replace the sequence of @@ -499,8 +478,7 @@ vect_recog_dot_prod_pattern (vec *stmts, tree *type_in, */ static gimple * -vect_recog_sad_pattern (vec *stmts, tree *type_in, - tree *type_out) +vect_recog_sad_pattern (vec *stmts, tree *type_out) { gimple *last_stmt = (*stmts)[0]; tree sad_oprnd0, sad_oprnd1; @@ -641,8 +619,9 @@ vect_recog_sad_pattern (vec *stmts, tree *type_in, vect_pattern_detected ("vect_recog_sad_pattern", last_stmt); - *type_in = TREE_TYPE (sad_oprnd0); - *type_out = sum_type; + if (!vect_supportable_direct_optab_p (sum_type, SAD_EXPR, + TREE_TYPE (sad_oprnd0), type_out)) + return NULL; tree var = vect_recog_temp_ssa_var (sum_type, NULL); gimple *pattern_stmt = gimple_build_assign (var, SAD_EXPR, sad_oprnd0, @@ -778,8 +757,6 @@ vect_handle_widen_op_by_const (gimple *stmt, enum tree_code code, Output: - * TYPE_IN: The type of the input arguments to the pattern. - * TYPE_OUT: The type of the output of this pattern. * Return value: A new stmt that will be used to replace the sequence of @@ -790,8 +767,7 @@ vect_handle_widen_op_by_const (gimple *stmt, enum tree_code code, */ static gimple * -vect_recog_widen_mult_pattern (vec *stmts, - tree *type_in, tree *type_out) +vect_recog_widen_mult_pattern (vec *stmts, tree *type_out) { gimple *last_stmt = stmts->pop (); gimple *def_stmt0, *def_stmt1; @@ -933,8 +909,9 @@ vect_recog_widen_mult_pattern (vec *stmts, &dummy_int, &dummy_vec)) return NULL; - *type_in = vectype; *type_out = get_vectype_for_scalar_type (type); + if (!*type_out) + return NULL; /* Pattern supported. Create a stmt to be used to replace the pattern: */ var = vect_recog_temp_ssa_var (itype, NULL); @@ -989,8 +966,6 @@ vect_recog_widen_mult_pattern (vec *stmts, Output: - * TYPE_IN: The type of the input arguments to the pattern. - * TYPE_OUT: The type of the output of this pattern. * Return value: A new stmt that will be used to replace the sequence of @@ -1001,8 +976,7 @@ vect_recog_widen_mult_pattern (vec *stmts, */ static gimple * -vect_recog_pow_pattern (vec *stmts, tree *type_in, - tree *type_out) +vect_recog_pow_pattern (vec *stmts, tree *type_out) { gimple *last_stmt = (*stmts)[0]; tree base, exp; @@ -1072,12 +1046,13 @@ vect_recog_pow_pattern (vec *stmts, tree *type_in, if (node->simd_clones == NULL) return NULL; } + *type_out = get_vectype_for_scalar_type (TREE_TYPE (base)); + if (!*type_out) + return NULL; stmt_vec_info stmt_vinfo = vinfo_for_stmt (last_stmt); tree def = vect_recog_temp_ssa_var (TREE_TYPE (base), NULL); gimple *g = gimple_build_assign (def, MULT_EXPR, exp, logc); new_pattern_def_seq (stmt_vinfo, g); - *type_in = TREE_TYPE (base); - *type_out = NULL_TREE; tree res = vect_recog_temp_ssa_var (TREE_TYPE (base), NULL); g = gimple_build_call (exp_decl, 1, def); gimple_call_set_lhs (g, res); @@ -1091,15 +1066,15 @@ vect_recog_pow_pattern (vec *stmts, tree *type_in, /* We now have a pow or powi builtin function call with a constant exponent. */ - *type_out = NULL_TREE; - /* Catch squaring. */ if ((tree_fits_shwi_p (exp) && tree_to_shwi (exp) == 2) || (TREE_CODE (exp) == REAL_CST && real_equal (&TREE_REAL_CST (exp), &dconst2))) { - *type_in = TREE_TYPE (base); + if (!vect_supportable_direct_optab_p (TREE_TYPE (base), MULT_EXPR, + TREE_TYPE (base), type_out)) + return NULL; var = vect_recog_temp_ssa_var (TREE_TYPE (base), NULL); stmt = gimple_build_assign (var, MULT_EXPR, base, base); @@ -1110,9 +1085,9 @@ vect_recog_pow_pattern (vec *stmts, tree *type_in, if (TREE_CODE (exp) == REAL_CST && real_equal (&TREE_REAL_CST (exp), &dconsthalf)) { - *type_in = get_vectype_for_scalar_type (TREE_TYPE (base)); - if (*type_in - && direct_internal_fn_supported_p (IFN_SQRT, *type_in, + *type_out = get_vectype_for_scalar_type (TREE_TYPE (base)); + if (*type_out + && direct_internal_fn_supported_p (IFN_SQRT, *type_out, OPTIMIZE_FOR_SPEED)) { gcall *stmt = gimple_build_call_internal (IFN_SQRT, 1, base); @@ -1150,8 +1125,6 @@ vect_recog_pow_pattern (vec *stmts, tree *type_in, Output: - * TYPE_IN: The type of the input arguments to the pattern. - * TYPE_OUT: The type of the output of this pattern. * Return value: A new stmt that will be used to replace the sequence of @@ -1167,8 +1140,7 @@ vect_recog_pow_pattern (vec *stmts, tree *type_in, inner-loop nested in an outer-loop that us being vectorized). */ static gimple * -vect_recog_widen_sum_pattern (vec *stmts, tree *type_in, - tree *type_out) +vect_recog_widen_sum_pattern (vec *stmts, tree *type_out) { gimple *stmt, *last_stmt = (*stmts)[0]; tree oprnd0, oprnd1; @@ -1223,14 +1195,15 @@ vect_recog_widen_sum_pattern (vec *stmts, tree *type_in, if (!type_conversion_p (oprnd0, last_stmt, true, &half_type, &stmt, &promotion) || !promotion) - return NULL; + return NULL; oprnd0 = gimple_assign_rhs1 (stmt); vect_pattern_detected ("vect_recog_widen_sum_pattern", last_stmt); - *type_in = half_type; - *type_out = type; + if (!vect_supportable_direct_optab_p (type, WIDEN_SUM_EXPR, half_type, + type_out)) + return NULL; var = vect_recog_temp_ssa_var (type, NULL); pattern_stmt = gimple_build_assign (var, WIDEN_SUM_EXPR, oprnd0, oprnd1); @@ -1473,8 +1446,7 @@ vect_operation_fits_smaller_type (gimple *stmt, tree def, tree *new_type, demotion operation. We also check that S3 and S4 have only one use. */ static gimple * -vect_recog_over_widening_pattern (vec *stmts, - tree *type_in, tree *type_out) +vect_recog_over_widening_pattern (vec *stmts, tree *type_out) { gimple *stmt = stmts->pop (); gimple *pattern_stmt = NULL, *new_def_stmt, *prev_stmt = NULL, @@ -1562,14 +1534,15 @@ vect_recog_over_widening_pattern (vec *stmts, if (TYPE_UNSIGNED (new_type) != TYPE_UNSIGNED (use_type) || TYPE_PRECISION (new_type) != TYPE_PRECISION (use_type)) { + *type_out = get_vectype_for_scalar_type (use_type); + if (!*type_out) + return NULL; + /* Create NEW_TYPE->USE_TYPE conversion. */ new_oprnd = make_ssa_name (use_type); pattern_stmt = gimple_build_assign (new_oprnd, NOP_EXPR, var); STMT_VINFO_RELATED_STMT (vinfo_for_stmt (use_stmt)) = pattern_stmt; - *type_in = get_vectype_for_scalar_type (new_type); - *type_out = get_vectype_for_scalar_type (use_type); - /* We created a pattern statement for the last statement in the sequence, so we don't need to associate it with the pattern statement created for PREV_STMT. Therefore, we add PREV_STMT @@ -1583,8 +1556,7 @@ vect_recog_over_widening_pattern (vec *stmts, STMT_VINFO_PATTERN_DEF_SEQ (vinfo_for_stmt (use_stmt)) = STMT_VINFO_PATTERN_DEF_SEQ (vinfo_for_stmt (prev_stmt)); - *type_in = vectype; - *type_out = NULL_TREE; + *type_out = vectype; } stmts->safe_push (use_stmt); @@ -1648,8 +1620,6 @@ vect_recog_over_widening_pattern (vec *stmts, Output: - * TYPE_IN: The type of the input arguments to the pattern. - * TYPE_OUT: The type of the output of this pattern. * Return value: A new stmt that will be used to replace the sequence of @@ -1657,8 +1627,7 @@ vect_recog_over_widening_pattern (vec *stmts, WIDEN_LSHIFT_EXPR . */ static gimple * -vect_recog_widen_shift_pattern (vec *stmts, - tree *type_in, tree *type_out) +vect_recog_widen_shift_pattern (vec *stmts, tree *type_out) { gimple *last_stmt = stmts->pop (); gimple *def_stmt0; @@ -1740,7 +1709,6 @@ vect_recog_widen_shift_pattern (vec *stmts, &dummy_int, &dummy_vec)) return NULL; - *type_in = vectype; *type_out = vectype_out; /* Pattern supported. Create a stmt to be used to replace the pattern. */ @@ -1783,15 +1751,13 @@ vect_recog_widen_shift_pattern (vec *stmts, Output: - * TYPE_IN: The type of the input arguments to the pattern. - * TYPE_OUT: The type of the output of this pattern. * Return value: A new stmt that will be used to replace the rotate S0 stmt. */ static gimple * -vect_recog_rotate_pattern (vec *stmts, tree *type_in, tree *type_out) +vect_recog_rotate_pattern (vec *stmts, tree *type_out) { gimple *last_stmt = stmts->pop (); tree oprnd0, oprnd1, lhs, var, var1, var2, vectype, type, stype, def, def2; @@ -1876,10 +1842,7 @@ vect_recog_rotate_pattern (vec *stmts, tree *type_in, tree *type_out) return NULL; } - *type_in = vectype; *type_out = vectype; - if (*type_in == NULL_TREE) - return NULL; if (dt == vect_external_def && TREE_CODE (oprnd1) == SSA_NAME @@ -2034,16 +1997,13 @@ vect_recog_rotate_pattern (vec *stmts, tree *type_in, tree *type_out) Output: - * TYPE_IN: The type of the input arguments to the pattern. - * TYPE_OUT: The type of the output of this pattern. * Return value: A new stmt that will be used to replace the shift/rotate S3 stmt. */ static gimple * -vect_recog_vector_vector_shift_pattern (vec *stmts, - tree *type_in, tree *type_out) +vect_recog_vector_vector_shift_pattern (vec *stmts, tree *type_out) { gimple *last_stmt = stmts->pop (); tree oprnd0, oprnd1, lhs, var; @@ -2085,9 +2045,8 @@ vect_recog_vector_vector_shift_pattern (vec *stmts, if (!def_vinfo) return NULL; - *type_in = get_vectype_for_scalar_type (TREE_TYPE (oprnd0)); - *type_out = *type_in; - if (*type_in == NULL_TREE) + *type_out = get_vectype_for_scalar_type (TREE_TYPE (oprnd0)); + if (*type_out == NULL_TREE) return NULL; tree def = NULL_TREE; @@ -2449,16 +2408,13 @@ vect_synth_mult_by_constant (tree op, tree val, Output: - * TYPE_IN: The type of the input arguments to the pattern. - * TYPE_OUT: The type of the output of this pattern. * Return value: A new stmt that will be used to replace the multiplication. */ static gimple * -vect_recog_mult_pattern (vec *stmts, - tree *type_in, tree *type_out) +vect_recog_mult_pattern (vec *stmts, tree *type_out) { gimple *last_stmt = stmts->pop (); tree oprnd0, oprnd1, vectype, itype; @@ -2504,7 +2460,6 @@ vect_recog_mult_pattern (vec *stmts, vect_pattern_detected ("vect_recog_mult_pattern", last_stmt); stmts->safe_push (last_stmt); - *type_in = vectype; *type_out = vectype; return pattern_stmt; @@ -2543,16 +2498,13 @@ vect_recog_mult_pattern (vec *stmts, Output: - * TYPE_IN: The type of the input arguments to the pattern. - * TYPE_OUT: The type of the output of this pattern. * Return value: A new stmt that will be used to replace the division S1 or modulo S4 stmt. */ static gimple * -vect_recog_divmod_pattern (vec *stmts, - tree *type_in, tree *type_out) +vect_recog_divmod_pattern (vec *stmts, tree *type_out) { gimple *last_stmt = stmts->pop (); tree oprnd0, oprnd1, vectype, itype, cond; @@ -2703,7 +2655,6 @@ vect_recog_divmod_pattern (vec *stmts, stmts->safe_push (last_stmt); - *type_in = vectype; *type_out = vectype; return pattern_stmt; } @@ -2955,7 +2906,6 @@ vect_recog_divmod_pattern (vec *stmts, stmts->safe_push (last_stmt); - *type_in = vectype; *type_out = vectype; return pattern_stmt; } @@ -2980,8 +2930,6 @@ vect_recog_divmod_pattern (vec *stmts, Output: - * TYPE_IN: The type of the input arguments to the pattern. - * TYPE_OUT: The type of the output of this pattern. * Return value: A new stmt that will be used to replace the pattern. @@ -2991,8 +2939,7 @@ vect_recog_divmod_pattern (vec *stmts, a_T = (TYPE) a_it; */ static gimple * -vect_recog_mixed_size_cond_pattern (vec *stmts, tree *type_in, - tree *type_out) +vect_recog_mixed_size_cond_pattern (vec *stmts, tree *type_out) { gimple *last_stmt = (*stmts)[0]; tree cond_expr, then_clause, else_clause; @@ -3108,7 +3055,6 @@ vect_recog_mixed_size_cond_pattern (vec *stmts, tree *type_in, def_stmt_info = new_stmt_vec_info (def_stmt, vinfo); set_vinfo_for_stmt (def_stmt, def_stmt_info); STMT_VINFO_VECTYPE (def_stmt_info) = vecitype; - *type_in = vecitype; *type_out = vectype; vect_pattern_detected ("vect_recog_mixed_size_cond_pattern", last_stmt); @@ -3581,8 +3527,6 @@ search_type_for_mask (tree var, vec_info *vinfo) Output: - * TYPE_IN: The type of the input arguments to the pattern. - * TYPE_OUT: The type of the output of this pattern. * Return value: A new stmt that will be used to replace the pattern. @@ -3602,8 +3546,7 @@ search_type_for_mask (tree var, vec_info *vinfo) but the above is more efficient. */ static gimple * -vect_recog_bool_pattern (vec *stmts, tree *type_in, - tree *type_out) +vect_recog_bool_pattern (vec *stmts, tree *type_out) { gimple *last_stmt = stmts->pop (); enum tree_code rhs_code; @@ -3679,7 +3622,6 @@ vect_recog_bool_pattern (vec *stmts, tree *type_in, } *type_out = vectype; - *type_in = vectype; stmts->safe_push (last_stmt); vect_pattern_detected ("vect_recog_bool_pattern", last_stmt); @@ -3718,7 +3660,6 @@ vect_recog_bool_pattern (vec *stmts, tree *type_in, gimple_assign_rhs2 (last_stmt), gimple_assign_rhs3 (last_stmt)); *type_out = vectype; - *type_in = vectype; stmts->safe_push (last_stmt); vect_pattern_detected ("vect_recog_bool_pattern", last_stmt); @@ -3775,7 +3716,6 @@ vect_recog_bool_pattern (vec *stmts, tree *type_in, STMT_VINFO_DR_WRT_VEC_LOOP (pattern_stmt_info) = STMT_VINFO_DR_WRT_VEC_LOOP (stmt_vinfo); *type_out = vectype; - *type_in = vectype; stmts->safe_push (last_stmt); vect_pattern_detected ("vect_recog_bool_pattern", last_stmt); @@ -3839,8 +3779,7 @@ build_mask_conversion (tree mask, tree vectype, stmt_vec_info stmt_vinfo, S4' c_1' = m_3'' ? c_2 : c_3; */ static gimple * -vect_recog_mask_conversion_pattern (vec *stmts, tree *type_in, - tree *type_out) +vect_recog_mask_conversion_pattern (vec *stmts, tree *type_out) { gimple *last_stmt = stmts->pop (); enum tree_code rhs_code; @@ -3911,7 +3850,6 @@ vect_recog_mask_conversion_pattern (vec *stmts, tree *type_in, = STMT_VINFO_DR_WRT_VEC_LOOP (stmt_vinfo); *type_out = vectype1; - *type_in = vectype1; stmts->safe_push (last_stmt); vect_pattern_detected ("vect_recog_mask_conversion_pattern", last_stmt); @@ -4035,7 +3973,6 @@ vect_recog_mask_conversion_pattern (vec *stmts, tree *type_in, gimple_assign_rhs3 (last_stmt)); *type_out = vectype1; - *type_in = vectype1; stmts->safe_push (last_stmt); vect_pattern_detected ("vect_recog_mask_conversion_pattern", last_stmt); @@ -4081,7 +4018,6 @@ vect_recog_mask_conversion_pattern (vec *stmts, tree *type_in, pattern_stmt = gimple_build_assign (lhs, rhs_code, rhs1, rhs2); *type_out = vectype1; - *type_in = vectype1; stmts->safe_push (last_stmt); vect_pattern_detected ("vect_recog_mask_conversion_pattern", last_stmt); @@ -4180,14 +4116,14 @@ vect_add_conversion_to_patterm (tree type, tree value, /* Try to convert STMT into a call to a gather load or scatter store internal function. Return the final statement on success and set - *TYPE_IN and *TYPE_OUT to the vector type being loaded or stored. + *TYPE_OUT to the vector type being loaded or stored. This function only handles gathers and scatters that were recognized as such from the outset (indicated by STMT_VINFO_GATHER_SCATTER_P). */ static gimple * vect_try_gather_scatter_pattern (gimple *stmt, stmt_vec_info last_stmt_info, - tree *type_in, tree *type_out) + tree *type_out) { /* Currently we only support this for loop vectorization. */ stmt_vec_info stmt_info = vinfo_for_stmt (stmt); @@ -4264,7 +4200,6 @@ vect_try_gather_scatter_pattern (gimple *stmt, stmt_vec_info last_stmt_info, tree vectype = STMT_VINFO_VECTYPE (stmt_info); *type_out = vectype; - *type_in = vectype; vect_pattern_detected ("gather/scatter pattern", stmt); return pattern_stmt; @@ -4273,19 +4208,52 @@ vect_try_gather_scatter_pattern (gimple *stmt, stmt_vec_info last_stmt_info, /* Pattern wrapper around vect_try_gather_scatter_pattern. */ static gimple * -vect_recog_gather_scatter_pattern (vec *stmts, tree *type_in, - tree *type_out) +vect_recog_gather_scatter_pattern (vec *stmts, tree *type_out) { gimple *last_stmt = stmts->pop (); stmt_vec_info last_stmt_info = vinfo_for_stmt (last_stmt); gimple *pattern_stmt = vect_try_gather_scatter_pattern (last_stmt, last_stmt_info, - type_in, type_out); + type_out); if (pattern_stmt) stmts->safe_push (last_stmt); return pattern_stmt; } +typedef gimple *(*vect_recog_func_ptr) (vec *, tree *); + +struct vect_recog_func +{ + vect_recog_func_ptr fn; + const char *name; +}; + +/* Note that ordering matters - the first pattern matching on a stmt is + taken which means usually the more complex one needs to preceed the + less comples onex (widen_sum only after dot_prod or sad for example). */ +static vect_recog_func vect_vect_recog_func_ptrs[] = { + { vect_recog_widen_mult_pattern, "widen_mult" }, + { vect_recog_dot_prod_pattern, "dot_prod" }, + { vect_recog_sad_pattern, "sad" }, + { vect_recog_widen_sum_pattern, "widen_sum" }, + { vect_recog_pow_pattern, "pow" }, + { vect_recog_widen_shift_pattern, "widen_shift" }, + { vect_recog_over_widening_pattern, "over_widening" }, + { vect_recog_rotate_pattern, "rotate" }, + { vect_recog_vector_vector_shift_pattern, "vector_vector_shift" }, + { vect_recog_divmod_pattern, "divmod" }, + { vect_recog_mult_pattern, "mult" }, + { vect_recog_mixed_size_cond_pattern, "mixed_size_cond" }, + { vect_recog_bool_pattern, "bool" }, + /* This must come before mask conversion, and includes the parts + of mask conversion that are needed for gather and scatter + internal functions. */ + { vect_recog_gather_scatter_pattern, "gather_scatter" }, + { vect_recog_mask_conversion_pattern, "mask_conversion" } +}; + +const unsigned int NUM_PATTERNS = ARRAY_SIZE (vect_vect_recog_func_ptrs); + /* Mark statements that are involved in a pattern. */ static inline void @@ -4337,17 +4305,13 @@ vect_mark_pattern_stmts (gimple *orig_stmt, gimple *pattern_stmt, computation pattern. STMT: A stmt from which the pattern search should start. - If PATTERN_RECOG_FUNC successfully detected the pattern, it creates an - expression that computes the same functionality and can be used to - replace the sequence of stmts that are involved in the pattern. - - Output: - This function checks if the expression returned by PATTERN_RECOG_FUNC is - supported in vector form by the target. We use 'TYPE_IN' to obtain the - relevant vector type. If 'TYPE_IN' is already a vector type, then this - indicates that target support had already been checked by PATTERN_RECOG_FUNC. - If 'TYPE_OUT' is also returned by PATTERN_RECOG_FUNC, we check that it fits - to the available target pattern. + If PATTERN_RECOG_FUNC successfully detected the pattern, it creates + a sequence of statements that has the same functionality and can be + used to replace STMT. It returns the last statement in the sequence + and adds any earlier statements to STMT's STMT_VINFO_PATTERN_DEF_SEQ. + PATTERN_RECOG_FUNC also sets *TYPE_OUT to the vector type of the final + statement, having first checked that the target supports the new operation + in that type. This function also does some bookkeeping, as explained in the documentation for vect_recog_pattern. */ @@ -4361,13 +4325,11 @@ vect_pattern_recog_1 (vect_recog_func *recog_func, stmt_vec_info stmt_info; loop_vec_info loop_vinfo; tree pattern_vectype; - tree type_in, type_out; - enum tree_code code; int i; stmts_to_replace->truncate (0); stmts_to_replace->quick_push (stmt); - pattern_stmt = recog_func->fn (stmts_to_replace, &type_in, &type_out); + pattern_stmt = recog_func->fn (stmts_to_replace, &pattern_vectype); if (!pattern_stmt) { /* Clear related stmt info that analysis might have noted for @@ -4385,43 +4347,8 @@ vect_pattern_recog_1 (vect_recog_func *recog_func, stmt = stmts_to_replace->last (); stmt_info = vinfo_for_stmt (stmt); loop_vinfo = STMT_VINFO_LOOP_VINFO (stmt_info); + gcc_assert (pattern_vectype); - if (VECTOR_BOOLEAN_TYPE_P (type_in) - || VECTOR_TYPE_P (type_in)) - { - /* No need to check target support (already checked by the pattern - recognition function). */ - pattern_vectype = type_out ? type_out : type_in; - } - else - { - /* Check target support */ - type_in = get_vectype_for_scalar_type (type_in); - if (!type_in) - return false; - if (type_out) - type_out = get_vectype_for_scalar_type (type_out); - else - type_out = type_in; - if (!type_out) - return false; - pattern_vectype = type_out; - - if (is_gimple_assign (pattern_stmt)) - { - enum insn_code icode; - code = gimple_assign_rhs_code (pattern_stmt); - optab optab = optab_for_tree_code (code, type_in, optab_default); - machine_mode vec_mode = TYPE_MODE (type_in); - if (!optab - || (icode = optab_handler (optab, vec_mode)) == CODE_FOR_nothing - || (insn_data[icode].operand[0].mode != TYPE_MODE (type_out))) - return false; - } - else - gcc_assert (is_gimple_call (pattern_stmt)); - } - /* Found a vectorizable pattern. */ if (dump_enabled_p ()) { diff --git a/gcc/tree-vectorizer.h b/gcc/tree-vectorizer.h index fce3238ff64..0d4657b1b42 100644 --- a/gcc/tree-vectorizer.h +++ b/gcc/tree-vectorizer.h @@ -1628,8 +1628,6 @@ extern int vect_get_place_in_interleaving_chain (gimple *, gimple *); /* Pattern recognition functions. Additional pattern recognition functions can (and will) be added in the future. */ -typedef gimple *(* vect_recog_func_ptr) (vec *, tree *, tree *); -#define NUM_PATTERNS 15 void vect_pattern_recog (vec_info *); /* In tree-vectorizer.c. */