From 732a0ad314ba1603b9fd07199dd83518ed54ad4d Mon Sep 17 00:00:00 2001 From: Jakub Jelinek Date: Sun, 30 Oct 2011 13:16:01 +0100 Subject: [PATCH] tree-vectorizer.h (NUM_PATTERNS): Bump to 9. * tree-vectorizer.h (NUM_PATTERNS): Bump to 9. * tree-vect-patterns.c (vect_recog_vector_vector_shift_pattern): New function. (vect_vect_recog_func_ptrs): Add it. From-SVN: r180677 --- gcc/ChangeLog | 7 +++ gcc/tree-vect-patterns.c | 130 +++++++++++++++++++++++++++++++++++++++ gcc/tree-vectorizer.h | 2 +- 3 files changed, 138 insertions(+), 1 deletion(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index e9bda2b793a..c089100b689 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,10 @@ +2011-10-30 Jakub Jelinek + + * tree-vectorizer.h (NUM_PATTERNS): Bump to 9. + * tree-vect-patterns.c (vect_recog_vector_vector_shift_pattern): New + function. + (vect_vect_recog_func_ptrs): Add it. + 2011-10-30 David S. Miller * reorg.c (label_before_next_insn): New function. diff --git a/gcc/tree-vect-patterns.c b/gcc/tree-vect-patterns.c index 1386a747955..19b75e9e465 100644 --- a/gcc/tree-vect-patterns.c +++ b/gcc/tree-vect-patterns.c @@ -51,6 +51,8 @@ static gimple vect_recog_over_widening_pattern (VEC (gimple, heap) **, tree *, tree *); static gimple vect_recog_widen_shift_pattern (VEC (gimple, heap) **, tree *, tree *); +static gimple vect_recog_vector_vector_shift_pattern (VEC (gimple, heap) **, + tree *, tree *); static gimple vect_recog_mixed_size_cond_pattern (VEC (gimple, heap) **, tree *, tree *); static gimple vect_recog_bool_pattern (VEC (gimple, heap) **, tree *, tree *); @@ -61,6 +63,7 @@ static vect_recog_func_ptr vect_vect_recog_func_ptrs[NUM_PATTERNS] = { vect_recog_pow_pattern, vect_recog_over_widening_pattern, vect_recog_widen_shift_pattern, + vect_recog_vector_vector_shift_pattern, vect_recog_mixed_size_cond_pattern, vect_recog_bool_pattern}; @@ -1439,6 +1442,133 @@ vect_recog_widen_shift_pattern (VEC (gimple, heap) **stmts, return pattern_stmt; } +/* Detect a vector by vector shift pattern that wouldn't be otherwise + vectorized: + + type a_t; + TYPE b_T, res_T; + + S1 a_t = ; + S2 b_T = ; + S3 res_T = b_T op a_t; + + where type 'TYPE' is a type with different size than 'type', + and op is <<, >> or rotate. + + Also detect cases: + + type a_t; + TYPE b_T, c_T, res_T; + + S0 c_T = ; + S1 a_t = (type) c_T; + S2 b_T = ; + S3 res_T = b_T op a_t; + + Input/Output: + + * STMTS: Contains a stmt from which the pattern search begins, + i.e. the shift/rotate stmt. The original stmt (S3) is replaced + with a shift/rotate which has same type on both operands, in the + second case just b_T op c_T, in the first case with added cast + from a_t to c_T in STMT_VINFO_PATTERN_DEF_STMT. + + 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, heap) **stmts, + tree *type_in, tree *type_out) +{ + gimple last_stmt = VEC_pop (gimple, *stmts); + tree oprnd0, oprnd1, lhs, var; + gimple pattern_stmt, def_stmt; + enum tree_code rhs_code; + stmt_vec_info stmt_vinfo = vinfo_for_stmt (last_stmt); + loop_vec_info loop_vinfo = STMT_VINFO_LOOP_VINFO (stmt_vinfo); + enum vect_def_type dt; + tree def; + + if (!is_gimple_assign (last_stmt)) + return NULL; + + rhs_code = gimple_assign_rhs_code (last_stmt); + switch (rhs_code) + { + case LSHIFT_EXPR: + case RSHIFT_EXPR: + case LROTATE_EXPR: + case RROTATE_EXPR: + break; + default: + return NULL; + } + + if (STMT_VINFO_IN_PATTERN_P (stmt_vinfo)) + return NULL; + + lhs = gimple_assign_lhs (last_stmt); + oprnd0 = gimple_assign_rhs1 (last_stmt); + oprnd1 = gimple_assign_rhs2 (last_stmt); + if (TREE_CODE (oprnd0) != SSA_NAME + || TREE_CODE (oprnd1) != SSA_NAME + || TYPE_MODE (TREE_TYPE (oprnd0)) == TYPE_MODE (TREE_TYPE (oprnd1)) + || TYPE_PRECISION (TREE_TYPE (oprnd1)) + != GET_MODE_PRECISION (TYPE_MODE (TREE_TYPE (oprnd1))) + || TYPE_PRECISION (TREE_TYPE (lhs)) + != TYPE_PRECISION (TREE_TYPE (oprnd0))) + return NULL; + + if (!vect_is_simple_use (oprnd1, loop_vinfo, NULL, &def_stmt, &def, &dt)) + return NULL; + + if (dt != vect_internal_def) + return NULL; + + *type_in = get_vectype_for_scalar_type (TREE_TYPE (oprnd0)); + *type_out = *type_in; + if (*type_in == NULL_TREE) + return NULL; + + def = NULL_TREE; + if (gimple_assign_cast_p (def_stmt)) + { + tree rhs1 = gimple_assign_rhs1 (def_stmt); + if (TYPE_MODE (TREE_TYPE (rhs1)) == TYPE_MODE (TREE_TYPE (oprnd0)) + && TYPE_PRECISION (TREE_TYPE (rhs1)) + == TYPE_PRECISION (TREE_TYPE (oprnd0))) + def = rhs1; + } + + if (def == NULL_TREE) + { + def = vect_recog_temp_ssa_var (TREE_TYPE (oprnd0), NULL); + def_stmt = gimple_build_assign_with_ops (NOP_EXPR, def, oprnd1, + NULL_TREE); + STMT_VINFO_PATTERN_DEF_STMT (stmt_vinfo) = def_stmt; + } + + /* Pattern detected. */ + if (vect_print_dump_info (REPORT_DETAILS)) + fprintf (vect_dump, "vect_recog_vector_vector_shift_pattern: detected: "); + + /* Pattern supported. Create a stmt to be used to replace the pattern. */ + var = vect_recog_temp_ssa_var (TREE_TYPE (oprnd0), NULL); + pattern_stmt = gimple_build_assign_with_ops (rhs_code, var, oprnd0, def); + + if (vect_print_dump_info (REPORT_DETAILS)) + print_gimple_stmt (vect_dump, pattern_stmt, 0, TDF_SLIM); + + VEC_safe_push (gimple, heap, *stmts, last_stmt); + return pattern_stmt; +} + /* Function vect_recog_mixed_size_cond_pattern Try to find the following pattern: diff --git a/gcc/tree-vectorizer.h b/gcc/tree-vectorizer.h index b0142e2ba7f..6703edb5ee0 100644 --- a/gcc/tree-vectorizer.h +++ b/gcc/tree-vectorizer.h @@ -902,7 +902,7 @@ extern void vect_slp_transform_bb (basic_block); Additional pattern recognition functions can (and will) be added in the future. */ typedef gimple (* vect_recog_func_ptr) (VEC (gimple, heap) **, tree *, tree *); -#define NUM_PATTERNS 8 +#define NUM_PATTERNS 9 void vect_pattern_recog (loop_vec_info); /* In tree-vectorizer.c. */