On Mon, Jun 18, 2018 at 4:58 PM Richard Sandiford <richard.sandif...@arm.com> wrote: > > This patch adds a helper for pattern code that wants to find an > internal (vectorisable) definition of an SSA name. > > A later patch will make more use of this, and alter the definition. > > 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-vect-patterns.c (vect_get_internal_def): New function. > (vect_recog_dot_prod_pattern, vect_recog_sad_pattern) > (vect_recog_vector_vector_shift_pattern, check_bool_pattern) > (search_type_for_mask_1): Use it. > > Index: gcc/tree-vect-patterns.c > =================================================================== > --- gcc/tree-vect-patterns.c 2018-06-18 15:41:33.000000000 +0100 > +++ gcc/tree-vect-patterns.c 2018-06-18 15:41:33.332272879 +0100 > @@ -155,6 +155,22 @@ vect_single_imm_use (gimple *def_stmt) > return use_stmt; > } > > +/* If OP is defined by a statement that's being considered for vectorization, > + return information about that statement, otherwise return NULL. */ > + > +static stmt_vec_info > +vect_get_internal_def (vec_info *vinfo, tree op) > +{ > + vect_def_type dt; > + gimple *def_stmt; > + if (TREE_CODE (op) != SSA_NAME > + || !vect_is_simple_use (op, vinfo, &def_stmt, &dt) > + || dt != vect_internal_def) > + return NULL; > + > + return vinfo_for_stmt (def_stmt); > +} > + > /* Check whether NAME, an ssa-name used in USE_STMT, > is a result of a type promotion, such that: > DEF_STMT: NAME = NOP (name0) > @@ -288,6 +304,7 @@ vect_recog_dot_prod_pattern (vec<gimple > tree oprnd0, oprnd1; > tree oprnd00, oprnd01; > stmt_vec_info stmt_vinfo = vinfo_for_stmt (last_stmt); > + vec_info *vinfo = stmt_vinfo->vinfo; > tree type, half_type; > gimple *pattern_stmt; > tree prod_type; > @@ -367,36 +384,29 @@ vect_recog_dot_prod_pattern (vec<gimple > return NULL; > > prod_type = half_type; > - stmt = SSA_NAME_DEF_STMT (oprnd0); > - > - /* It could not be the dot_prod pattern if the stmt is outside the loop. > */ > - if (!gimple_bb (stmt) || !flow_bb_inside_loop_p (loop, gimple_bb (stmt))) > + stmt_vec_info mult_vinfo = vect_get_internal_def (vinfo, oprnd0); > + if (!mult_vinfo) > return NULL; > > /* FORNOW. Can continue analyzing the def-use chain when this stmt in a > phi > inside the loop (in case we are analyzing an outer-loop). */ > - if (!is_gimple_assign (stmt)) > + gassign *mult = dyn_cast <gassign *> (mult_vinfo->stmt); > + if (!mult || gimple_assign_rhs_code (mult) != MULT_EXPR) > return NULL; > - stmt_vinfo = vinfo_for_stmt (stmt); > - gcc_assert (stmt_vinfo); > - if (STMT_VINFO_DEF_TYPE (stmt_vinfo) != vect_internal_def) > - return NULL; > - if (gimple_assign_rhs_code (stmt) != MULT_EXPR) > - return NULL; > - if (STMT_VINFO_IN_PATTERN_P (stmt_vinfo)) > + if (STMT_VINFO_IN_PATTERN_P (mult_vinfo)) > { > /* Has been detected as a widening multiplication? */ > > - stmt = STMT_VINFO_RELATED_STMT (stmt_vinfo); > - if (gimple_assign_rhs_code (stmt) != WIDEN_MULT_EXPR) > + mult = dyn_cast <gassign *> (STMT_VINFO_RELATED_STMT (mult_vinfo)); > + if (!mult || gimple_assign_rhs_code (mult) != WIDEN_MULT_EXPR) > return NULL; > - STMT_VINFO_PATTERN_DEF_SEQ (vinfo_for_stmt (last_stmt)) > - = STMT_VINFO_PATTERN_DEF_SEQ (stmt_vinfo); > - stmt_vinfo = vinfo_for_stmt (stmt); > - gcc_assert (stmt_vinfo); > - gcc_assert (STMT_VINFO_DEF_TYPE (stmt_vinfo) == vect_internal_def); > - oprnd00 = gimple_assign_rhs1 (stmt); > - oprnd01 = gimple_assign_rhs2 (stmt); > + STMT_VINFO_PATTERN_DEF_SEQ (stmt_vinfo) > + = STMT_VINFO_PATTERN_DEF_SEQ (mult_vinfo); > + mult_vinfo = vinfo_for_stmt (mult); > + gcc_assert (mult_vinfo); > + gcc_assert (STMT_VINFO_DEF_TYPE (mult_vinfo) == vect_internal_def); > + oprnd00 = gimple_assign_rhs1 (mult); > + oprnd01 = gimple_assign_rhs2 (mult); > } > else > { > @@ -404,14 +414,14 @@ vect_recog_dot_prod_pattern (vec<gimple > gimple *def_stmt; > tree oprnd0, oprnd1; > > - oprnd0 = gimple_assign_rhs1 (stmt); > - oprnd1 = gimple_assign_rhs2 (stmt); > - if (!type_conversion_p (oprnd0, stmt, true, &half_type0, &def_stmt, > + oprnd0 = gimple_assign_rhs1 (mult); > + oprnd1 = gimple_assign_rhs2 (mult); > + if (!type_conversion_p (oprnd0, mult, true, &half_type0, &def_stmt, > &promotion) > || !promotion) > return NULL; > oprnd00 = gimple_assign_rhs1 (def_stmt); > - if (!type_conversion_p (oprnd1, stmt, true, &half_type1, &def_stmt, > + if (!type_conversion_p (oprnd1, mult, true, &half_type1, &def_stmt, > &promotion) > || !promotion) > return NULL; > @@ -488,6 +498,7 @@ vect_recog_sad_pattern (vec<gimple *> *s > gimple *last_stmt = (*stmts)[0]; > tree sad_oprnd0, sad_oprnd1; > stmt_vec_info stmt_vinfo = vinfo_for_stmt (last_stmt); > + vec_info *vinfo = stmt_vinfo->vinfo; > tree half_type; > loop_vec_info loop_info = STMT_VINFO_LOOP_VINFO (stmt_vinfo); > struct loop *loop; > @@ -567,23 +578,16 @@ vect_recog_sad_pattern (vec<gimple *> *s > return NULL; > > tree abs_type = half_type; > - gimple *abs_stmt = SSA_NAME_DEF_STMT (plus_oprnd0); > - > - /* It could not be the sad pattern if the abs_stmt is outside the loop. */ > - if (!gimple_bb (abs_stmt) || !flow_bb_inside_loop_p (loop, gimple_bb > (abs_stmt))) > + stmt_vec_info abs_stmt_vinfo = vect_get_internal_def (vinfo, plus_oprnd0); > + if (!abs_stmt_vinfo) > return NULL; > > /* FORNOW. Can continue analyzing the def-use chain when this stmt in a > phi > inside the loop (in case we are analyzing an outer-loop). */ > - if (!is_gimple_assign (abs_stmt)) > - return NULL; > - > - stmt_vec_info abs_stmt_vinfo = vinfo_for_stmt (abs_stmt); > - gcc_assert (abs_stmt_vinfo); > - if (STMT_VINFO_DEF_TYPE (abs_stmt_vinfo) != vect_internal_def) > - return NULL; > - if (gimple_assign_rhs_code (abs_stmt) != ABS_EXPR > - && gimple_assign_rhs_code (abs_stmt) != ABSU_EXPR) > + gassign *abs_stmt = dyn_cast <gassign *> (abs_stmt_vinfo->stmt); > + if (!abs_stmt > + || (gimple_assign_rhs_code (abs_stmt) != ABS_EXPR > + && gimple_assign_rhs_code (abs_stmt) != ABSU_EXPR)) > return NULL; > > tree abs_oprnd = gimple_assign_rhs1 (abs_stmt); > @@ -595,23 +599,14 @@ vect_recog_sad_pattern (vec<gimple *> *s > if (TREE_CODE (abs_oprnd) != SSA_NAME) > return NULL; > > - gimple *diff_stmt = SSA_NAME_DEF_STMT (abs_oprnd); > - > - /* It could not be the sad pattern if the diff_stmt is outside the loop. > */ > - if (!gimple_bb (diff_stmt) > - || !flow_bb_inside_loop_p (loop, gimple_bb (diff_stmt))) > + stmt_vec_info diff_stmt_vinfo = vect_get_internal_def (vinfo, abs_oprnd); > + if (!diff_stmt_vinfo) > return NULL; > > /* FORNOW. Can continue analyzing the def-use chain when this stmt in a > phi > inside the loop (in case we are analyzing an outer-loop). */ > - if (!is_gimple_assign (diff_stmt)) > - return NULL; > - > - stmt_vec_info diff_stmt_vinfo = vinfo_for_stmt (diff_stmt); > - gcc_assert (diff_stmt_vinfo); > - if (STMT_VINFO_DEF_TYPE (diff_stmt_vinfo) != vect_internal_def) > - return NULL; > - if (gimple_assign_rhs_code (diff_stmt) != MINUS_EXPR) > + gassign *diff_stmt = dyn_cast <gassign *> (diff_stmt_vinfo->stmt); > + if (!diff_stmt || gimple_assign_rhs_code (diff_stmt) != MINUS_EXPR) > return NULL; > > tree half_type0, half_type1; > @@ -2076,11 +2071,10 @@ vect_recog_vector_vector_shift_pattern ( > { > gimple *last_stmt = stmts->pop (); > tree oprnd0, oprnd1, lhs, var; > - gimple *pattern_stmt, *def_stmt; > + gimple *pattern_stmt; > enum tree_code rhs_code; > stmt_vec_info stmt_vinfo = vinfo_for_stmt (last_stmt); > vec_info *vinfo = stmt_vinfo->vinfo; > - enum vect_def_type dt; > > if (!is_gimple_assign (last_stmt)) > return NULL; > @@ -2111,10 +2105,8 @@ vect_recog_vector_vector_shift_pattern ( > != TYPE_PRECISION (TREE_TYPE (oprnd0))) > return NULL; > > - if (!vect_is_simple_use (oprnd1, vinfo, &def_stmt, &dt)) > - return NULL; > - > - if (dt != vect_internal_def) > + stmt_vec_info def_vinfo = vect_get_internal_def (vinfo, oprnd1); > + if (!def_vinfo) > return NULL; > > *type_in = get_vectype_for_scalar_type (TREE_TYPE (oprnd0)); > @@ -2123,8 +2115,10 @@ vect_recog_vector_vector_shift_pattern ( > return NULL; > > tree def = NULL_TREE; > - stmt_vec_info def_vinfo = vinfo_for_stmt (def_stmt); > - if (!STMT_VINFO_IN_PATTERN_P (def_vinfo) && gimple_assign_cast_p > (def_stmt)) > + gassign *def_stmt = dyn_cast <gassign *> (def_vinfo->stmt); > + if (!STMT_VINFO_IN_PATTERN_P (def_vinfo) > + && def_stmt > + && gimple_assign_cast_p (def_stmt)) > { > tree rhs1 = gimple_assign_rhs1 (def_stmt); > if (TYPE_MODE (TREE_TYPE (rhs1)) == TYPE_MODE (TREE_TYPE (oprnd0)) > @@ -3180,18 +3174,15 @@ vect_recog_mixed_size_cond_pattern (vec< > static bool > check_bool_pattern (tree var, vec_info *vinfo, hash_set<gimple *> &stmts) > { > - gimple *def_stmt; > - enum vect_def_type dt; > tree rhs1; > enum tree_code rhs_code; > > - if (!vect_is_simple_use (var, vinfo, &def_stmt, &dt)) > - return false; > - > - if (dt != vect_internal_def) > + stmt_vec_info def_stmt_info = vect_get_internal_def (vinfo, var); > + if (!def_stmt_info) > return false; > > - if (!is_gimple_assign (def_stmt)) > + gassign *def_stmt = dyn_cast <gassign *> (def_stmt_info->stmt); > + if (!def_stmt) > return false; > > if (stmts.contains (def_stmt)) > @@ -3512,25 +3503,19 @@ adjust_bool_stmts (hash_set <gimple *> & > search_type_for_mask_1 (tree var, vec_info *vinfo, > hash_map<gimple *, tree> &cache) > { > - gimple *def_stmt; > - enum vect_def_type dt; > tree rhs1; > enum tree_code rhs_code; > tree res = NULL_TREE, res2; > > - if (TREE_CODE (var) != SSA_NAME) > - return NULL_TREE; > - > if (!VECT_SCALAR_BOOLEAN_TYPE_P (TREE_TYPE (var))) > return NULL_TREE; > > - if (!vect_is_simple_use (var, vinfo, &def_stmt, &dt)) > - return NULL_TREE; > - > - if (dt != vect_internal_def) > + stmt_vec_info def_stmt_info = vect_get_internal_def (vinfo, var); > + if (!def_stmt_info) > return NULL_TREE; > > - if (!is_gimple_assign (def_stmt)) > + gassign *def_stmt = dyn_cast <gassign *> (def_stmt_info->stmt); > + if (!def_stmt) > return NULL_TREE; > > tree *c = cache.get (def_stmt);