On 28 October 2011 20:44, Jakub Jelinek <ja...@redhat.com> wrote: > Hi!
Hi, > > This patch implements what I've talked about, with this we can now > with -mavx2 as well as -mxop vectorize long long/unsigned long long > shifts by int or long long/unsigned long long shifts by long long > (where the FE casts it to int first). Already covered by the *vshift-* > testcases I've committed recently (eyeballed for -mxop plus link tested, > for -mavx2 tested on sde). > > Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk? OK. Thanks, Ira > > 2011-10-28 Jakub Jelinek <ja...@redhat.com> > > * 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. > > --- gcc/tree-vectorizer.h.jj 2011-10-27 08:42:51.000000000 +0200 > +++ gcc/tree-vectorizer.h 2011-10-28 16:26:30.000000000 +0200 > @@ -902,7 +902,7 @@ extern void vect_slp_transform_bb (basic > 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. */ > --- gcc/tree-vect-patterns.c.jj 2011-10-26 14:19:11.000000000 +0200 > +++ gcc/tree-vect-patterns.c 2011-10-28 17:41:26.000000000 +0200 > @@ -51,6 +51,8 @@ static gimple vect_recog_over_widening_p > 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_rec > 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 (gim > 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: > > Jakub >