Commit 1cbfeccc by Richard Sandiford Committed by Richard Sandiford

[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  <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.

From-SVN: r261791
parent 49d8df1b
2018-06-20 Richard Sandiford <richard.sandiford@arm.com> 2018-06-20 Richard Sandiford <richard.sandiford@arm.com>
* 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 <richard.sandiford@arm.com>
* tree-vect-patterns.c (vect_pattern_detected): New function. * tree-vect-patterns.c (vect_pattern_detected): New function.
(vect_recog_dot_prod_patternm, vect_recog_sad_pattern) (vect_recog_dot_prod_patternm, vect_recog_sad_pattern)
(vect_recog_widen_mult_pattern, vect_recog_widen_sum_pattern) (vect_recog_widen_mult_pattern, vect_recog_widen_sum_pattern)
......
...@@ -47,66 +47,6 @@ along with GCC; see the file COPYING3. If not see ...@@ -47,66 +47,6 @@ along with GCC; see the file COPYING3. If not see
#include "omp-simd-clone.h" #include "omp-simd-clone.h"
#include "predict.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 /* Report that we've found an instance of pattern PATTERN in
statement STMT. */ statement STMT. */
...@@ -134,6 +74,49 @@ new_pattern_def_seq (stmt_vec_info stmt_info, gimple *stmt) ...@@ -134,6 +74,49 @@ new_pattern_def_seq (stmt_vec_info stmt_info, gimple *stmt)
append_pattern_def_seq (stmt_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. /* 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 Which of the two applies depends on whether we're currently doing
loop-based or basic-block-based vectorization, as determined by loop-based or basic-block-based vectorization, as determined by
...@@ -293,8 +276,6 @@ vect_reassociating_reduction_p (stmt_vec_info stmt_vinfo) ...@@ -293,8 +276,6 @@ vect_reassociating_reduction_p (stmt_vec_info stmt_vinfo)
Output: Output:
* TYPE_IN: The type of the input arguments to the pattern.
* TYPE_OUT: The type of the output of this 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 * 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) ...@@ -310,8 +291,7 @@ vect_reassociating_reduction_p (stmt_vec_info stmt_vinfo)
inner-loop nested in an outer-loop that us being vectorized). */ inner-loop nested in an outer-loop that us being vectorized). */
static gimple * static gimple *
vect_recog_dot_prod_pattern (vec<gimple *> *stmts, tree *type_in, vect_recog_dot_prod_pattern (vec<gimple *> *stmts, tree *type_out)
tree *type_out)
{ {
gimple *stmt, *last_stmt = (*stmts)[0]; gimple *stmt, *last_stmt = (*stmts)[0];
tree oprnd0, oprnd1; tree oprnd0, oprnd1;
...@@ -448,8 +428,9 @@ vect_recog_dot_prod_pattern (vec<gimple *> *stmts, tree *type_in, ...@@ -448,8 +428,9 @@ vect_recog_dot_prod_pattern (vec<gimple *> *stmts, tree *type_in,
vect_pattern_detected ("vect_recog_dot_prod_pattern", last_stmt); vect_pattern_detected ("vect_recog_dot_prod_pattern", last_stmt);
half_type = TREE_TYPE (oprnd00); half_type = TREE_TYPE (oprnd00);
*type_in = half_type; if (!vect_supportable_direct_optab_p (type, DOT_PROD_EXPR, half_type,
*type_out = type; type_out))
return NULL;
var = vect_recog_temp_ssa_var (type, NULL); var = vect_recog_temp_ssa_var (type, NULL);
pattern_stmt = gimple_build_assign (var, DOT_PROD_EXPR, pattern_stmt = gimple_build_assign (var, DOT_PROD_EXPR,
...@@ -489,8 +470,6 @@ vect_recog_dot_prod_pattern (vec<gimple *> *stmts, tree *type_in, ...@@ -489,8 +470,6 @@ vect_recog_dot_prod_pattern (vec<gimple *> *stmts, tree *type_in,
Output: Output:
* TYPE_IN: The type of the input arguments to the pattern.
* TYPE_OUT: The type of the output of this 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 * 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 *> *stmts, tree *type_in, ...@@ -499,8 +478,7 @@ vect_recog_dot_prod_pattern (vec<gimple *> *stmts, tree *type_in,
*/ */
static gimple * static gimple *
vect_recog_sad_pattern (vec<gimple *> *stmts, tree *type_in, vect_recog_sad_pattern (vec<gimple *> *stmts, tree *type_out)
tree *type_out)
{ {
gimple *last_stmt = (*stmts)[0]; gimple *last_stmt = (*stmts)[0];
tree sad_oprnd0, sad_oprnd1; tree sad_oprnd0, sad_oprnd1;
...@@ -641,8 +619,9 @@ vect_recog_sad_pattern (vec<gimple *> *stmts, tree *type_in, ...@@ -641,8 +619,9 @@ vect_recog_sad_pattern (vec<gimple *> *stmts, tree *type_in,
vect_pattern_detected ("vect_recog_sad_pattern", last_stmt); vect_pattern_detected ("vect_recog_sad_pattern", last_stmt);
*type_in = TREE_TYPE (sad_oprnd0); if (!vect_supportable_direct_optab_p (sum_type, SAD_EXPR,
*type_out = sum_type; TREE_TYPE (sad_oprnd0), type_out))
return NULL;
tree var = vect_recog_temp_ssa_var (sum_type, NULL); tree var = vect_recog_temp_ssa_var (sum_type, NULL);
gimple *pattern_stmt = gimple_build_assign (var, SAD_EXPR, sad_oprnd0, 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, ...@@ -778,8 +757,6 @@ vect_handle_widen_op_by_const (gimple *stmt, enum tree_code code,
Output: Output:
* TYPE_IN: The type of the input arguments to the pattern.
* TYPE_OUT: The type of the output of this 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 * 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, ...@@ -790,8 +767,7 @@ vect_handle_widen_op_by_const (gimple *stmt, enum tree_code code,
*/ */
static gimple * static gimple *
vect_recog_widen_mult_pattern (vec<gimple *> *stmts, vect_recog_widen_mult_pattern (vec<gimple *> *stmts, tree *type_out)
tree *type_in, tree *type_out)
{ {
gimple *last_stmt = stmts->pop (); gimple *last_stmt = stmts->pop ();
gimple *def_stmt0, *def_stmt1; gimple *def_stmt0, *def_stmt1;
...@@ -933,8 +909,9 @@ vect_recog_widen_mult_pattern (vec<gimple *> *stmts, ...@@ -933,8 +909,9 @@ vect_recog_widen_mult_pattern (vec<gimple *> *stmts,
&dummy_int, &dummy_vec)) &dummy_int, &dummy_vec))
return NULL; return NULL;
*type_in = vectype;
*type_out = get_vectype_for_scalar_type (type); *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: */ /* Pattern supported. Create a stmt to be used to replace the pattern: */
var = vect_recog_temp_ssa_var (itype, NULL); var = vect_recog_temp_ssa_var (itype, NULL);
...@@ -989,8 +966,6 @@ vect_recog_widen_mult_pattern (vec<gimple *> *stmts, ...@@ -989,8 +966,6 @@ vect_recog_widen_mult_pattern (vec<gimple *> *stmts,
Output: Output:
* TYPE_IN: The type of the input arguments to the pattern.
* TYPE_OUT: The type of the output of this 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 * Return value: A new stmt that will be used to replace the sequence of
...@@ -1001,8 +976,7 @@ vect_recog_widen_mult_pattern (vec<gimple *> *stmts, ...@@ -1001,8 +976,7 @@ vect_recog_widen_mult_pattern (vec<gimple *> *stmts,
*/ */
static gimple * static gimple *
vect_recog_pow_pattern (vec<gimple *> *stmts, tree *type_in, vect_recog_pow_pattern (vec<gimple *> *stmts, tree *type_out)
tree *type_out)
{ {
gimple *last_stmt = (*stmts)[0]; gimple *last_stmt = (*stmts)[0];
tree base, exp; tree base, exp;
...@@ -1072,12 +1046,13 @@ vect_recog_pow_pattern (vec<gimple *> *stmts, tree *type_in, ...@@ -1072,12 +1046,13 @@ vect_recog_pow_pattern (vec<gimple *> *stmts, tree *type_in,
if (node->simd_clones == NULL) if (node->simd_clones == NULL)
return 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); stmt_vec_info stmt_vinfo = vinfo_for_stmt (last_stmt);
tree def = vect_recog_temp_ssa_var (TREE_TYPE (base), NULL); tree def = vect_recog_temp_ssa_var (TREE_TYPE (base), NULL);
gimple *g = gimple_build_assign (def, MULT_EXPR, exp, logc); gimple *g = gimple_build_assign (def, MULT_EXPR, exp, logc);
new_pattern_def_seq (stmt_vinfo, g); 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); tree res = vect_recog_temp_ssa_var (TREE_TYPE (base), NULL);
g = gimple_build_call (exp_decl, 1, def); g = gimple_build_call (exp_decl, 1, def);
gimple_call_set_lhs (g, res); gimple_call_set_lhs (g, res);
...@@ -1091,15 +1066,15 @@ vect_recog_pow_pattern (vec<gimple *> *stmts, tree *type_in, ...@@ -1091,15 +1066,15 @@ vect_recog_pow_pattern (vec<gimple *> *stmts, tree *type_in,
/* We now have a pow or powi builtin function call with a constant /* We now have a pow or powi builtin function call with a constant
exponent. */ exponent. */
*type_out = NULL_TREE;
/* Catch squaring. */ /* Catch squaring. */
if ((tree_fits_shwi_p (exp) if ((tree_fits_shwi_p (exp)
&& tree_to_shwi (exp) == 2) && tree_to_shwi (exp) == 2)
|| (TREE_CODE (exp) == REAL_CST || (TREE_CODE (exp) == REAL_CST
&& real_equal (&TREE_REAL_CST (exp), &dconst2))) && 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); var = vect_recog_temp_ssa_var (TREE_TYPE (base), NULL);
stmt = gimple_build_assign (var, MULT_EXPR, base, base); stmt = gimple_build_assign (var, MULT_EXPR, base, base);
...@@ -1110,9 +1085,9 @@ vect_recog_pow_pattern (vec<gimple *> *stmts, tree *type_in, ...@@ -1110,9 +1085,9 @@ vect_recog_pow_pattern (vec<gimple *> *stmts, tree *type_in,
if (TREE_CODE (exp) == REAL_CST if (TREE_CODE (exp) == REAL_CST
&& real_equal (&TREE_REAL_CST (exp), &dconsthalf)) && real_equal (&TREE_REAL_CST (exp), &dconsthalf))
{ {
*type_in = get_vectype_for_scalar_type (TREE_TYPE (base)); *type_out = get_vectype_for_scalar_type (TREE_TYPE (base));
if (*type_in if (*type_out
&& direct_internal_fn_supported_p (IFN_SQRT, *type_in, && direct_internal_fn_supported_p (IFN_SQRT, *type_out,
OPTIMIZE_FOR_SPEED)) OPTIMIZE_FOR_SPEED))
{ {
gcall *stmt = gimple_build_call_internal (IFN_SQRT, 1, base); gcall *stmt = gimple_build_call_internal (IFN_SQRT, 1, base);
...@@ -1150,8 +1125,6 @@ vect_recog_pow_pattern (vec<gimple *> *stmts, tree *type_in, ...@@ -1150,8 +1125,6 @@ vect_recog_pow_pattern (vec<gimple *> *stmts, tree *type_in,
Output: Output:
* TYPE_IN: The type of the input arguments to the pattern.
* TYPE_OUT: The type of the output of this 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 * Return value: A new stmt that will be used to replace the sequence of
...@@ -1167,8 +1140,7 @@ vect_recog_pow_pattern (vec<gimple *> *stmts, tree *type_in, ...@@ -1167,8 +1140,7 @@ vect_recog_pow_pattern (vec<gimple *> *stmts, tree *type_in,
inner-loop nested in an outer-loop that us being vectorized). */ inner-loop nested in an outer-loop that us being vectorized). */
static gimple * static gimple *
vect_recog_widen_sum_pattern (vec<gimple *> *stmts, tree *type_in, vect_recog_widen_sum_pattern (vec<gimple *> *stmts, tree *type_out)
tree *type_out)
{ {
gimple *stmt, *last_stmt = (*stmts)[0]; gimple *stmt, *last_stmt = (*stmts)[0];
tree oprnd0, oprnd1; tree oprnd0, oprnd1;
...@@ -1223,14 +1195,15 @@ vect_recog_widen_sum_pattern (vec<gimple *> *stmts, tree *type_in, ...@@ -1223,14 +1195,15 @@ vect_recog_widen_sum_pattern (vec<gimple *> *stmts, tree *type_in,
if (!type_conversion_p (oprnd0, last_stmt, true, &half_type, &stmt, if (!type_conversion_p (oprnd0, last_stmt, true, &half_type, &stmt,
&promotion) &promotion)
|| !promotion) || !promotion)
return NULL; return NULL;
oprnd0 = gimple_assign_rhs1 (stmt); oprnd0 = gimple_assign_rhs1 (stmt);
vect_pattern_detected ("vect_recog_widen_sum_pattern", last_stmt); vect_pattern_detected ("vect_recog_widen_sum_pattern", last_stmt);
*type_in = half_type; if (!vect_supportable_direct_optab_p (type, WIDEN_SUM_EXPR, half_type,
*type_out = type; type_out))
return NULL;
var = vect_recog_temp_ssa_var (type, NULL); var = vect_recog_temp_ssa_var (type, NULL);
pattern_stmt = gimple_build_assign (var, WIDEN_SUM_EXPR, oprnd0, oprnd1); 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, ...@@ -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. */ demotion operation. We also check that S3 and S4 have only one use. */
static gimple * static gimple *
vect_recog_over_widening_pattern (vec<gimple *> *stmts, vect_recog_over_widening_pattern (vec<gimple *> *stmts, tree *type_out)
tree *type_in, tree *type_out)
{ {
gimple *stmt = stmts->pop (); gimple *stmt = stmts->pop ();
gimple *pattern_stmt = NULL, *new_def_stmt, *prev_stmt = NULL, gimple *pattern_stmt = NULL, *new_def_stmt, *prev_stmt = NULL,
...@@ -1562,14 +1534,15 @@ vect_recog_over_widening_pattern (vec<gimple *> *stmts, ...@@ -1562,14 +1534,15 @@ vect_recog_over_widening_pattern (vec<gimple *> *stmts,
if (TYPE_UNSIGNED (new_type) != TYPE_UNSIGNED (use_type) if (TYPE_UNSIGNED (new_type) != TYPE_UNSIGNED (use_type)
|| TYPE_PRECISION (new_type) != TYPE_PRECISION (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. */ /* Create NEW_TYPE->USE_TYPE conversion. */
new_oprnd = make_ssa_name (use_type); new_oprnd = make_ssa_name (use_type);
pattern_stmt = gimple_build_assign (new_oprnd, NOP_EXPR, var); pattern_stmt = gimple_build_assign (new_oprnd, NOP_EXPR, var);
STMT_VINFO_RELATED_STMT (vinfo_for_stmt (use_stmt)) = pattern_stmt; 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 /* We created a pattern statement for the last statement in the
sequence, so we don't need to associate it with the pattern sequence, so we don't need to associate it with the pattern
statement created for PREV_STMT. Therefore, we add PREV_STMT statement created for PREV_STMT. Therefore, we add PREV_STMT
...@@ -1583,8 +1556,7 @@ vect_recog_over_widening_pattern (vec<gimple *> *stmts, ...@@ -1583,8 +1556,7 @@ vect_recog_over_widening_pattern (vec<gimple *> *stmts,
STMT_VINFO_PATTERN_DEF_SEQ (vinfo_for_stmt (use_stmt)) STMT_VINFO_PATTERN_DEF_SEQ (vinfo_for_stmt (use_stmt))
= STMT_VINFO_PATTERN_DEF_SEQ (vinfo_for_stmt (prev_stmt)); = STMT_VINFO_PATTERN_DEF_SEQ (vinfo_for_stmt (prev_stmt));
*type_in = vectype; *type_out = vectype;
*type_out = NULL_TREE;
} }
stmts->safe_push (use_stmt); stmts->safe_push (use_stmt);
...@@ -1648,8 +1620,6 @@ vect_recog_over_widening_pattern (vec<gimple *> *stmts, ...@@ -1648,8 +1620,6 @@ vect_recog_over_widening_pattern (vec<gimple *> *stmts,
Output: Output:
* TYPE_IN: The type of the input arguments to the pattern.
* TYPE_OUT: The type of the output of this 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 * Return value: A new stmt that will be used to replace the sequence of
...@@ -1657,8 +1627,7 @@ vect_recog_over_widening_pattern (vec<gimple *> *stmts, ...@@ -1657,8 +1627,7 @@ vect_recog_over_widening_pattern (vec<gimple *> *stmts,
WIDEN_LSHIFT_EXPR <a_t, CONST>. */ WIDEN_LSHIFT_EXPR <a_t, CONST>. */
static gimple * static gimple *
vect_recog_widen_shift_pattern (vec<gimple *> *stmts, vect_recog_widen_shift_pattern (vec<gimple *> *stmts, tree *type_out)
tree *type_in, tree *type_out)
{ {
gimple *last_stmt = stmts->pop (); gimple *last_stmt = stmts->pop ();
gimple *def_stmt0; gimple *def_stmt0;
...@@ -1740,7 +1709,6 @@ vect_recog_widen_shift_pattern (vec<gimple *> *stmts, ...@@ -1740,7 +1709,6 @@ vect_recog_widen_shift_pattern (vec<gimple *> *stmts,
&dummy_int, &dummy_vec)) &dummy_int, &dummy_vec))
return NULL; return NULL;
*type_in = vectype;
*type_out = vectype_out; *type_out = vectype_out;
/* Pattern supported. Create a stmt to be used to replace the pattern. */ /* Pattern supported. Create a stmt to be used to replace the pattern. */
...@@ -1783,15 +1751,13 @@ vect_recog_widen_shift_pattern (vec<gimple *> *stmts, ...@@ -1783,15 +1751,13 @@ vect_recog_widen_shift_pattern (vec<gimple *> *stmts,
Output: Output:
* TYPE_IN: The type of the input arguments to the pattern.
* TYPE_OUT: The type of the output of this pattern. * TYPE_OUT: The type of the output of this pattern.
* Return value: A new stmt that will be used to replace the rotate * Return value: A new stmt that will be used to replace the rotate
S0 stmt. */ S0 stmt. */
static gimple * 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 (); gimple *last_stmt = stmts->pop ();
tree oprnd0, oprnd1, lhs, var, var1, var2, vectype, type, stype, def, def2; tree oprnd0, oprnd1, lhs, var, var1, var2, vectype, type, stype, def, def2;
...@@ -1876,10 +1842,7 @@ vect_recog_rotate_pattern (vec<gimple *> *stmts, tree *type_in, tree *type_out) ...@@ -1876,10 +1842,7 @@ vect_recog_rotate_pattern (vec<gimple *> *stmts, tree *type_in, tree *type_out)
return NULL; return NULL;
} }
*type_in = vectype;
*type_out = vectype; *type_out = vectype;
if (*type_in == NULL_TREE)
return NULL;
if (dt == vect_external_def if (dt == vect_external_def
&& TREE_CODE (oprnd1) == SSA_NAME && TREE_CODE (oprnd1) == SSA_NAME
...@@ -2034,16 +1997,13 @@ vect_recog_rotate_pattern (vec<gimple *> *stmts, tree *type_in, tree *type_out) ...@@ -2034,16 +1997,13 @@ vect_recog_rotate_pattern (vec<gimple *> *stmts, tree *type_in, tree *type_out)
Output: Output:
* TYPE_IN: The type of the input arguments to the pattern.
* TYPE_OUT: The type of the output of this 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 * Return value: A new stmt that will be used to replace the shift/rotate
S3 stmt. */ S3 stmt. */
static gimple * static gimple *
vect_recog_vector_vector_shift_pattern (vec<gimple *> *stmts, vect_recog_vector_vector_shift_pattern (vec<gimple *> *stmts, tree *type_out)
tree *type_in, tree *type_out)
{ {
gimple *last_stmt = stmts->pop (); gimple *last_stmt = stmts->pop ();
tree oprnd0, oprnd1, lhs, var; tree oprnd0, oprnd1, lhs, var;
...@@ -2085,9 +2045,8 @@ vect_recog_vector_vector_shift_pattern (vec<gimple *> *stmts, ...@@ -2085,9 +2045,8 @@ vect_recog_vector_vector_shift_pattern (vec<gimple *> *stmts,
if (!def_vinfo) if (!def_vinfo)
return NULL; return NULL;
*type_in = get_vectype_for_scalar_type (TREE_TYPE (oprnd0)); *type_out = get_vectype_for_scalar_type (TREE_TYPE (oprnd0));
*type_out = *type_in; if (*type_out == NULL_TREE)
if (*type_in == NULL_TREE)
return NULL; return NULL;
tree def = NULL_TREE; tree def = NULL_TREE;
...@@ -2449,16 +2408,13 @@ vect_synth_mult_by_constant (tree op, tree val, ...@@ -2449,16 +2408,13 @@ vect_synth_mult_by_constant (tree op, tree val,
Output: Output:
* TYPE_IN: The type of the input arguments to the pattern.
* TYPE_OUT: The type of the output of this pattern. * TYPE_OUT: The type of the output of this pattern.
* Return value: A new stmt that will be used to replace * Return value: A new stmt that will be used to replace
the multiplication. */ the multiplication. */
static gimple * static gimple *
vect_recog_mult_pattern (vec<gimple *> *stmts, vect_recog_mult_pattern (vec<gimple *> *stmts, tree *type_out)
tree *type_in, tree *type_out)
{ {
gimple *last_stmt = stmts->pop (); gimple *last_stmt = stmts->pop ();
tree oprnd0, oprnd1, vectype, itype; tree oprnd0, oprnd1, vectype, itype;
...@@ -2504,7 +2460,6 @@ vect_recog_mult_pattern (vec<gimple *> *stmts, ...@@ -2504,7 +2460,6 @@ vect_recog_mult_pattern (vec<gimple *> *stmts,
vect_pattern_detected ("vect_recog_mult_pattern", last_stmt); vect_pattern_detected ("vect_recog_mult_pattern", last_stmt);
stmts->safe_push (last_stmt); stmts->safe_push (last_stmt);
*type_in = vectype;
*type_out = vectype; *type_out = vectype;
return pattern_stmt; return pattern_stmt;
...@@ -2543,16 +2498,13 @@ vect_recog_mult_pattern (vec<gimple *> *stmts, ...@@ -2543,16 +2498,13 @@ vect_recog_mult_pattern (vec<gimple *> *stmts,
Output: Output:
* TYPE_IN: The type of the input arguments to the pattern.
* TYPE_OUT: The type of the output of this pattern. * TYPE_OUT: The type of the output of this pattern.
* Return value: A new stmt that will be used to replace the division * Return value: A new stmt that will be used to replace the division
S1 or modulo S4 stmt. */ S1 or modulo S4 stmt. */
static gimple * static gimple *
vect_recog_divmod_pattern (vec<gimple *> *stmts, vect_recog_divmod_pattern (vec<gimple *> *stmts, tree *type_out)
tree *type_in, tree *type_out)
{ {
gimple *last_stmt = stmts->pop (); gimple *last_stmt = stmts->pop ();
tree oprnd0, oprnd1, vectype, itype, cond; tree oprnd0, oprnd1, vectype, itype, cond;
...@@ -2703,7 +2655,6 @@ vect_recog_divmod_pattern (vec<gimple *> *stmts, ...@@ -2703,7 +2655,6 @@ vect_recog_divmod_pattern (vec<gimple *> *stmts,
stmts->safe_push (last_stmt); stmts->safe_push (last_stmt);
*type_in = vectype;
*type_out = vectype; *type_out = vectype;
return pattern_stmt; return pattern_stmt;
} }
...@@ -2955,7 +2906,6 @@ vect_recog_divmod_pattern (vec<gimple *> *stmts, ...@@ -2955,7 +2906,6 @@ vect_recog_divmod_pattern (vec<gimple *> *stmts,
stmts->safe_push (last_stmt); stmts->safe_push (last_stmt);
*type_in = vectype;
*type_out = vectype; *type_out = vectype;
return pattern_stmt; return pattern_stmt;
} }
...@@ -2980,8 +2930,6 @@ vect_recog_divmod_pattern (vec<gimple *> *stmts, ...@@ -2980,8 +2930,6 @@ vect_recog_divmod_pattern (vec<gimple *> *stmts,
Output: Output:
* TYPE_IN: The type of the input arguments to the pattern.
* TYPE_OUT: The type of the output of this pattern. * TYPE_OUT: The type of the output of this pattern.
* Return value: A new stmt that will be used to replace the pattern. * Return value: A new stmt that will be used to replace the pattern.
...@@ -2991,8 +2939,7 @@ vect_recog_divmod_pattern (vec<gimple *> *stmts, ...@@ -2991,8 +2939,7 @@ vect_recog_divmod_pattern (vec<gimple *> *stmts,
a_T = (TYPE) a_it; */ a_T = (TYPE) a_it; */
static gimple * static gimple *
vect_recog_mixed_size_cond_pattern (vec<gimple *> *stmts, tree *type_in, vect_recog_mixed_size_cond_pattern (vec<gimple *> *stmts, tree *type_out)
tree *type_out)
{ {
gimple *last_stmt = (*stmts)[0]; gimple *last_stmt = (*stmts)[0];
tree cond_expr, then_clause, else_clause; tree cond_expr, then_clause, else_clause;
...@@ -3108,7 +3055,6 @@ vect_recog_mixed_size_cond_pattern (vec<gimple *> *stmts, tree *type_in, ...@@ -3108,7 +3055,6 @@ vect_recog_mixed_size_cond_pattern (vec<gimple *> *stmts, tree *type_in,
def_stmt_info = new_stmt_vec_info (def_stmt, vinfo); def_stmt_info = new_stmt_vec_info (def_stmt, vinfo);
set_vinfo_for_stmt (def_stmt, def_stmt_info); set_vinfo_for_stmt (def_stmt, def_stmt_info);
STMT_VINFO_VECTYPE (def_stmt_info) = vecitype; STMT_VINFO_VECTYPE (def_stmt_info) = vecitype;
*type_in = vecitype;
*type_out = vectype; *type_out = vectype;
vect_pattern_detected ("vect_recog_mixed_size_cond_pattern", last_stmt); vect_pattern_detected ("vect_recog_mixed_size_cond_pattern", last_stmt);
...@@ -3581,8 +3527,6 @@ search_type_for_mask (tree var, vec_info *vinfo) ...@@ -3581,8 +3527,6 @@ search_type_for_mask (tree var, vec_info *vinfo)
Output: Output:
* TYPE_IN: The type of the input arguments to the pattern.
* TYPE_OUT: The type of the output of this pattern. * TYPE_OUT: The type of the output of this pattern.
* Return value: A new stmt that will be used to replace the 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) ...@@ -3602,8 +3546,7 @@ search_type_for_mask (tree var, vec_info *vinfo)
but the above is more efficient. */ but the above is more efficient. */
static gimple * static gimple *
vect_recog_bool_pattern (vec<gimple *> *stmts, tree *type_in, vect_recog_bool_pattern (vec<gimple *> *stmts, tree *type_out)
tree *type_out)
{ {
gimple *last_stmt = stmts->pop (); gimple *last_stmt = stmts->pop ();
enum tree_code rhs_code; enum tree_code rhs_code;
...@@ -3679,7 +3622,6 @@ vect_recog_bool_pattern (vec<gimple *> *stmts, tree *type_in, ...@@ -3679,7 +3622,6 @@ vect_recog_bool_pattern (vec<gimple *> *stmts, tree *type_in,
} }
*type_out = vectype; *type_out = vectype;
*type_in = vectype;
stmts->safe_push (last_stmt); stmts->safe_push (last_stmt);
vect_pattern_detected ("vect_recog_bool_pattern", last_stmt); vect_pattern_detected ("vect_recog_bool_pattern", last_stmt);
...@@ -3718,7 +3660,6 @@ vect_recog_bool_pattern (vec<gimple *> *stmts, tree *type_in, ...@@ -3718,7 +3660,6 @@ vect_recog_bool_pattern (vec<gimple *> *stmts, tree *type_in,
gimple_assign_rhs2 (last_stmt), gimple_assign_rhs2 (last_stmt),
gimple_assign_rhs3 (last_stmt)); gimple_assign_rhs3 (last_stmt));
*type_out = vectype; *type_out = vectype;
*type_in = vectype;
stmts->safe_push (last_stmt); stmts->safe_push (last_stmt);
vect_pattern_detected ("vect_recog_bool_pattern", last_stmt); vect_pattern_detected ("vect_recog_bool_pattern", last_stmt);
...@@ -3775,7 +3716,6 @@ vect_recog_bool_pattern (vec<gimple *> *stmts, tree *type_in, ...@@ -3775,7 +3716,6 @@ vect_recog_bool_pattern (vec<gimple *> *stmts, tree *type_in,
STMT_VINFO_DR_WRT_VEC_LOOP (pattern_stmt_info) STMT_VINFO_DR_WRT_VEC_LOOP (pattern_stmt_info)
= STMT_VINFO_DR_WRT_VEC_LOOP (stmt_vinfo); = STMT_VINFO_DR_WRT_VEC_LOOP (stmt_vinfo);
*type_out = vectype; *type_out = vectype;
*type_in = vectype;
stmts->safe_push (last_stmt); stmts->safe_push (last_stmt);
vect_pattern_detected ("vect_recog_bool_pattern", 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, ...@@ -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; */ S4' c_1' = m_3'' ? c_2 : c_3; */
static gimple * static gimple *
vect_recog_mask_conversion_pattern (vec<gimple *> *stmts, tree *type_in, vect_recog_mask_conversion_pattern (vec<gimple *> *stmts, tree *type_out)
tree *type_out)
{ {
gimple *last_stmt = stmts->pop (); gimple *last_stmt = stmts->pop ();
enum tree_code rhs_code; enum tree_code rhs_code;
...@@ -3911,7 +3850,6 @@ vect_recog_mask_conversion_pattern (vec<gimple *> *stmts, tree *type_in, ...@@ -3911,7 +3850,6 @@ vect_recog_mask_conversion_pattern (vec<gimple *> *stmts, tree *type_in,
= STMT_VINFO_DR_WRT_VEC_LOOP (stmt_vinfo); = STMT_VINFO_DR_WRT_VEC_LOOP (stmt_vinfo);
*type_out = vectype1; *type_out = vectype1;
*type_in = vectype1;
stmts->safe_push (last_stmt); stmts->safe_push (last_stmt);
vect_pattern_detected ("vect_recog_mask_conversion_pattern", last_stmt); vect_pattern_detected ("vect_recog_mask_conversion_pattern", last_stmt);
...@@ -4035,7 +3973,6 @@ vect_recog_mask_conversion_pattern (vec<gimple *> *stmts, tree *type_in, ...@@ -4035,7 +3973,6 @@ vect_recog_mask_conversion_pattern (vec<gimple *> *stmts, tree *type_in,
gimple_assign_rhs3 (last_stmt)); gimple_assign_rhs3 (last_stmt));
*type_out = vectype1; *type_out = vectype1;
*type_in = vectype1;
stmts->safe_push (last_stmt); stmts->safe_push (last_stmt);
vect_pattern_detected ("vect_recog_mask_conversion_pattern", last_stmt); vect_pattern_detected ("vect_recog_mask_conversion_pattern", last_stmt);
...@@ -4081,7 +4018,6 @@ vect_recog_mask_conversion_pattern (vec<gimple *> *stmts, tree *type_in, ...@@ -4081,7 +4018,6 @@ vect_recog_mask_conversion_pattern (vec<gimple *> *stmts, tree *type_in,
pattern_stmt = gimple_build_assign (lhs, rhs_code, rhs1, rhs2); pattern_stmt = gimple_build_assign (lhs, rhs_code, rhs1, rhs2);
*type_out = vectype1; *type_out = vectype1;
*type_in = vectype1;
stmts->safe_push (last_stmt); stmts->safe_push (last_stmt);
vect_pattern_detected ("vect_recog_mask_conversion_pattern", 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, ...@@ -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 /* Try to convert STMT into a call to a gather load or scatter store
internal function. Return the final statement on success and set 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 This function only handles gathers and scatters that were recognized
as such from the outset (indicated by STMT_VINFO_GATHER_SCATTER_P). */ as such from the outset (indicated by STMT_VINFO_GATHER_SCATTER_P). */
static gimple * static gimple *
vect_try_gather_scatter_pattern (gimple *stmt, stmt_vec_info last_stmt_info, 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. */ /* Currently we only support this for loop vectorization. */
stmt_vec_info stmt_info = vinfo_for_stmt (stmt); 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, ...@@ -4264,7 +4200,6 @@ vect_try_gather_scatter_pattern (gimple *stmt, stmt_vec_info last_stmt_info,
tree vectype = STMT_VINFO_VECTYPE (stmt_info); tree vectype = STMT_VINFO_VECTYPE (stmt_info);
*type_out = vectype; *type_out = vectype;
*type_in = vectype;
vect_pattern_detected ("gather/scatter pattern", stmt); vect_pattern_detected ("gather/scatter pattern", stmt);
return pattern_stmt; return pattern_stmt;
...@@ -4273,19 +4208,52 @@ vect_try_gather_scatter_pattern (gimple *stmt, stmt_vec_info last_stmt_info, ...@@ -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. */ /* Pattern wrapper around vect_try_gather_scatter_pattern. */
static gimple * static gimple *
vect_recog_gather_scatter_pattern (vec<gimple *> *stmts, tree *type_in, vect_recog_gather_scatter_pattern (vec<gimple *> *stmts, tree *type_out)
tree *type_out)
{ {
gimple *last_stmt = stmts->pop (); gimple *last_stmt = stmts->pop ();
stmt_vec_info last_stmt_info = vinfo_for_stmt (last_stmt); stmt_vec_info last_stmt_info = vinfo_for_stmt (last_stmt);
gimple *pattern_stmt = vect_try_gather_scatter_pattern (last_stmt, gimple *pattern_stmt = vect_try_gather_scatter_pattern (last_stmt,
last_stmt_info, last_stmt_info,
type_in, type_out); type_out);
if (pattern_stmt) if (pattern_stmt)
stmts->safe_push (last_stmt); stmts->safe_push (last_stmt);
return pattern_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. */ /* Mark statements that are involved in a pattern. */
static inline void static inline void
...@@ -4337,17 +4305,13 @@ vect_mark_pattern_stmts (gimple *orig_stmt, gimple *pattern_stmt, ...@@ -4337,17 +4305,13 @@ vect_mark_pattern_stmts (gimple *orig_stmt, gimple *pattern_stmt,
computation pattern. computation pattern.
STMT: A stmt from which the pattern search should start. STMT: A stmt from which the pattern search should start.
If PATTERN_RECOG_FUNC successfully detected the pattern, it creates an If PATTERN_RECOG_FUNC successfully detected the pattern, it creates
expression that computes the same functionality and can be used to a sequence of statements that has the same functionality and can be
replace the sequence of stmts that are involved in the pattern. 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.
Output: PATTERN_RECOG_FUNC also sets *TYPE_OUT to the vector type of the final
This function checks if the expression returned by PATTERN_RECOG_FUNC is statement, having first checked that the target supports the new operation
supported in vector form by the target. We use 'TYPE_IN' to obtain the in that type.
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.
This function also does some bookkeeping, as explained in the documentation This function also does some bookkeeping, as explained in the documentation
for vect_recog_pattern. */ for vect_recog_pattern. */
...@@ -4361,13 +4325,11 @@ vect_pattern_recog_1 (vect_recog_func *recog_func, ...@@ -4361,13 +4325,11 @@ vect_pattern_recog_1 (vect_recog_func *recog_func,
stmt_vec_info stmt_info; stmt_vec_info stmt_info;
loop_vec_info loop_vinfo; loop_vec_info loop_vinfo;
tree pattern_vectype; tree pattern_vectype;
tree type_in, type_out;
enum tree_code code;
int i; int i;
stmts_to_replace->truncate (0); stmts_to_replace->truncate (0);
stmts_to_replace->quick_push (stmt); 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) if (!pattern_stmt)
{ {
/* Clear related stmt info that analysis might have noted for /* Clear related stmt info that analysis might have noted for
...@@ -4385,43 +4347,8 @@ vect_pattern_recog_1 (vect_recog_func *recog_func, ...@@ -4385,43 +4347,8 @@ vect_pattern_recog_1 (vect_recog_func *recog_func,
stmt = stmts_to_replace->last (); stmt = stmts_to_replace->last ();
stmt_info = vinfo_for_stmt (stmt); stmt_info = vinfo_for_stmt (stmt);
loop_vinfo = STMT_VINFO_LOOP_VINFO (stmt_info); 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. */ /* Found a vectorizable pattern. */
if (dump_enabled_p ()) if (dump_enabled_p ())
{ {
......
...@@ -1628,8 +1628,6 @@ extern int vect_get_place_in_interleaving_chain (gimple *, gimple *); ...@@ -1628,8 +1628,6 @@ extern int vect_get_place_in_interleaving_chain (gimple *, gimple *);
/* Pattern recognition functions. /* Pattern recognition functions.
Additional pattern recognition functions can (and will) be added Additional pattern recognition functions can (and will) be added
in the future. */ in the future. */
typedef gimple *(* vect_recog_func_ptr) (vec<gimple *> *, tree *, tree *);
#define NUM_PATTERNS 15
void vect_pattern_recog (vec_info *); void vect_pattern_recog (vec_info *);
/* In tree-vectorizer.c. */ /* In tree-vectorizer.c. */
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment