On Mon, Jun 18, 2018 at 5:01 PM Richard Sandiford <richard.sandif...@arm.com> wrote: > > 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. > > Tested on aarch64-linux-gnu and x86_64-linux-gnu. OK to install?
OK. Richard. > Richard > > > 2018-06-18 Richard Sandiford <richard.sandif...@arm.com> > > 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. > > Index: gcc/tree-vectorizer.h > =================================================================== > --- gcc/tree-vectorizer.h 2018-06-14 12:27:34.104084473 +0100 > +++ gcc/tree-vectorizer.h 2018-06-18 15:43:52.951038712 +0100 > @@ -1616,8 +1616,6 @@ extern int vect_get_place_in_interleavin > /* Pattern recognition functions. > Additional pattern recognition functions can (and will) be added > in the future. */ > -typedef gimple *(* vect_recog_func_ptr) (vec<gimple *> *, tree *, tree *); > -#define NUM_PATTERNS 15 > void vect_pattern_recog (vec_info *); > > /* In tree-vectorizer.c. */ > Index: gcc/tree-vect-patterns.c > =================================================================== > --- gcc/tree-vect-patterns.c 2018-06-18 15:43:52.000000000 +0100 > +++ gcc/tree-vect-patterns.c 2018-06-18 15:43:52.951038712 +0100 > @@ -47,66 +47,6 @@ Software Foundation; either version 3, o > #include "omp-simd-clone.h" > #include "predict.h" > > -/* Pattern recognition functions */ > -static gimple *vect_recog_widen_sum_pattern (vec<gimple *> *, tree *, > - tree *); > -static gimple *vect_recog_widen_mult_pattern (vec<gimple *> *, tree *, > - tree *); > -static gimple *vect_recog_dot_prod_pattern (vec<gimple *> *, tree *, > - tree *); > -static gimple *vect_recog_sad_pattern (vec<gimple *> *, tree *, > - tree *); > -static gimple *vect_recog_pow_pattern (vec<gimple *> *, tree *, tree *); > -static gimple *vect_recog_over_widening_pattern (vec<gimple *> *, tree *, > - tree *); > -static gimple *vect_recog_widen_shift_pattern (vec<gimple *> *, > - tree *, tree *); > -static gimple *vect_recog_rotate_pattern (vec<gimple *> *, tree *, tree *); > -static gimple *vect_recog_vector_vector_shift_pattern (vec<gimple *> *, > - tree *, tree *); > -static gimple *vect_recog_divmod_pattern (vec<gimple *> *, > - tree *, tree *); > - > -static gimple *vect_recog_mult_pattern (vec<gimple *> *, > - tree *, tree *); > - > -static gimple *vect_recog_mixed_size_cond_pattern (vec<gimple *> *, > - tree *, tree *); > -static gimple *vect_recog_bool_pattern (vec<gimple *> *, tree *, tree *); > -static gimple *vect_recog_mask_conversion_pattern (vec<gimple *> *, tree *, > tree *); > -static gimple *vect_recog_gather_scatter_pattern (vec<gimple *> *, 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_ > 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 > > 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 > inner-loop nested in an outer-loop that us being vectorized). */ > > static gimple * > -vect_recog_dot_prod_pattern (vec<gimple *> *stmts, tree *type_in, > - tree *type_out) > +vect_recog_dot_prod_pattern (vec<gimple *> *stmts, tree *type_out) > { > gimple *stmt, *last_stmt = (*stmts)[0]; > tree oprnd0, oprnd1; > @@ -448,8 +428,9 @@ vect_recog_dot_prod_pattern (vec<gimple > 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<gimple > > 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<gimple > */ > > static gimple * > -vect_recog_sad_pattern (vec<gimple *> *stmts, tree *type_in, > - tree *type_out) > +vect_recog_sad_pattern (vec<gimple *> *stmts, tree *type_out) > { > gimple *last_stmt = (*stmts)[0]; > tree sad_oprnd0, sad_oprnd1; > @@ -641,8 +619,9 @@ vect_recog_sad_pattern (vec<gimple *> *s > > 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 *s > > 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 *s > */ > > static gimple * > -vect_recog_widen_mult_pattern (vec<gimple *> *stmts, > - tree *type_in, tree *type_out) > +vect_recog_widen_mult_pattern (vec<gimple *> *stmts, tree *type_out) > { > gimple *last_stmt = stmts->pop (); > gimple *def_stmt0, *def_stmt1; > @@ -933,8 +909,9 @@ vect_recog_widen_mult_pattern (vec<gimpl > &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<gimpl > > 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<gimpl > */ > > static gimple * > -vect_recog_pow_pattern (vec<gimple *> *stmts, tree *type_in, > - tree *type_out) > +vect_recog_pow_pattern (vec<gimple *> *stmts, tree *type_out) > { > gimple *last_stmt = (*stmts)[0]; > tree base, exp; > @@ -1072,12 +1046,13 @@ vect_recog_pow_pattern (vec<gimple *> *s > 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<gimple *> *s > /* 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<gimple *> *s > 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<gimple *> *s > > 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<gimple *> *s > inner-loop nested in an outer-loop that us being vectorized). */ > > static gimple * > -vect_recog_widen_sum_pattern (vec<gimple *> *stmts, tree *type_in, > - tree *type_out) > +vect_recog_widen_sum_pattern (vec<gimple *> *stmts, tree *type_out) > { > gimple *stmt, *last_stmt = (*stmts)[0]; > tree oprnd0, oprnd1; > @@ -1223,14 +1195,15 @@ vect_recog_widen_sum_pattern (vec<gimple > 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 > demotion operation. We also check that S3 and S4 have only one use. */ > > static gimple * > -vect_recog_over_widening_pattern (vec<gimple *> *stmts, > - tree *type_in, tree *type_out) > +vect_recog_over_widening_pattern (vec<gimple *> *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<gi > 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<gi > 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<gi > > 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<gi > WIDEN_LSHIFT_EXPR <a_t, CONST>. */ > > static gimple * > -vect_recog_widen_shift_pattern (vec<gimple *> *stmts, > - tree *type_in, tree *type_out) > +vect_recog_widen_shift_pattern (vec<gimple *> *stmts, tree *type_out) > { > gimple *last_stmt = stmts->pop (); > gimple *def_stmt0; > @@ -1740,7 +1709,6 @@ vect_recog_widen_shift_pattern (vec<gimp > &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<gimp > > 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<gimple *> *stmts, tree *type_in, tree > *type_out) > +vect_recog_rotate_pattern (vec<gimple *> *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<gimple *> > 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<gimple *> > > 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<gimple *> *stmts, > - tree *type_in, tree *type_out) > +vect_recog_vector_vector_shift_pattern (vec<gimple *> *stmts, tree *type_out) > { > gimple *last_stmt = stmts->pop (); > tree oprnd0, oprnd1, lhs, var; > @@ -2085,9 +2045,8 @@ vect_recog_vector_vector_shift_pattern ( > 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, tr > > 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<gimple *> *stmts, > - tree *type_in, tree *type_out) > +vect_recog_mult_pattern (vec<gimple *> *stmts, tree *type_out) > { > gimple *last_stmt = stmts->pop (); > tree oprnd0, oprnd1, vectype, itype; > @@ -2504,7 +2460,6 @@ vect_recog_mult_pattern (vec<gimple *> * > 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<gimple *> * > > 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<gimple *> *stmts, > - tree *type_in, tree *type_out) > +vect_recog_divmod_pattern (vec<gimple *> *stmts, tree *type_out) > { > gimple *last_stmt = stmts->pop (); > tree oprnd0, oprnd1, vectype, itype, cond; > @@ -2703,7 +2655,6 @@ vect_recog_divmod_pattern (vec<gimple *> > > stmts->safe_push (last_stmt); > > - *type_in = vectype; > *type_out = vectype; > return pattern_stmt; > } > @@ -2955,7 +2906,6 @@ vect_recog_divmod_pattern (vec<gimple *> > > stmts->safe_push (last_stmt); > > - *type_in = vectype; > *type_out = vectype; > return pattern_stmt; > } > @@ -2980,8 +2930,6 @@ vect_recog_divmod_pattern (vec<gimple *> > > 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<gimple *> > a_T = (TYPE) a_it; */ > > static gimple * > -vect_recog_mixed_size_cond_pattern (vec<gimple *> *stmts, tree *type_in, > - tree *type_out) > +vect_recog_mixed_size_cond_pattern (vec<gimple *> *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< > 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 > > 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 > but the above is more efficient. */ > > static gimple * > -vect_recog_bool_pattern (vec<gimple *> *stmts, tree *type_in, > - tree *type_out) > +vect_recog_bool_pattern (vec<gimple *> *stmts, tree *type_out) > { > gimple *last_stmt = stmts->pop (); > enum tree_code rhs_code; > @@ -3679,7 +3622,6 @@ vect_recog_bool_pattern (vec<gimple *> * > } > > *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<gimple *> * > 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<gimple *> * > 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 v > S4' c_1' = m_3'' ? c_2 : c_3; */ > > static gimple * > -vect_recog_mask_conversion_pattern (vec<gimple *> *stmts, tree *type_in, > - tree *type_out) > +vect_recog_mask_conversion_pattern (vec<gimple *> *stmts, tree *type_out) > { > gimple *last_stmt = stmts->pop (); > enum tree_code rhs_code; > @@ -3911,7 +3850,6 @@ vect_recog_mask_conversion_pattern (vec< > = 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< > 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< > 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 typ > > /* 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 > > 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 > /* Pattern wrapper around vect_try_gather_scatter_pattern. */ > > static gimple * > -vect_recog_gather_scatter_pattern (vec<gimple *> *stmts, tree *type_in, > - tree *type_out) > +vect_recog_gather_scatter_pattern (vec<gimple *> *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<gimple *> *, 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_st > 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,56 +4325,19 @@ vect_pattern_recog_1 (vect_recog_func *r > 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) > return false; > > 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 ()) > {