[8/n] PR85694: Make patterns check for target support
Richard Biener
richard.guenther@gmail.com
Tue Jun 19 10:03:00 GMT 2018
On Mon, Jun 18, 2018 at 5:01 PM Richard Sandiford
<richard.sandiford@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.sandiford@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 ())
> {
More information about the Gcc-patches
mailing list