On Thu, Jul 8, 2021 at 2:48 PM Richard Sandiford via Gcc-patches <gcc-patches@gcc.gnu.org> wrote: > > This patch generalises the interface to neutral_op_for_slp_reduction > so that it can be used for non-SLP reductions too. This isn't much > of a win on its own, but it helps later patches.
I guess that makes sense - OK. Richard. > gcc/ > * tree-vect-loop.c (neutral_op_for_slp_reduction): Replace with... > (neutral_op_for_reduction): ...this, providing a more general > interface. > (vect_create_epilog_for_reduction): Update accordingly. > (vectorizable_reduction): Likewise. > (vect_transform_cycle_phi): Likewise. > --- > gcc/tree-vect-loop.c | 59 +++++++++++++++++++------------------------- > 1 file changed, 26 insertions(+), 33 deletions(-) > > diff --git a/gcc/tree-vect-loop.c b/gcc/tree-vect-loop.c > index a67036f92e0..744645d8bad 100644 > --- a/gcc/tree-vect-loop.c > +++ b/gcc/tree-vect-loop.c > @@ -3248,23 +3248,15 @@ reduction_fn_for_scalar_code (enum tree_code code, > internal_fn *reduc_fn) > } > } > > -/* If there is a neutral value X such that SLP reduction NODE would not > - be affected by the introduction of additional X elements, return that X, > - otherwise return null. CODE is the code of the reduction and VECTOR_TYPE > - is the vector type that would hold element X. REDUC_CHAIN is true if > - the SLP statements perform a single reduction, false if each statement > - performs an independent reduction. */ > +/* If there is a neutral value X such that a reduction would not be affected > + by the introduction of additional X elements, return that X, otherwise > + return null. CODE is the code of the reduction and SCALAR_TYPE is type > + of the scalar elements. If the reduction has just a single initial value > + then INITIAL_VALUE is that value, otherwise it is null. */ > > static tree > -neutral_op_for_slp_reduction (slp_tree slp_node, tree vector_type, > - tree_code code, bool reduc_chain) > +neutral_op_for_reduction (tree scalar_type, tree_code code, tree > initial_value) > { > - vec<stmt_vec_info> stmts = SLP_TREE_SCALAR_STMTS (slp_node); > - stmt_vec_info stmt_vinfo = stmts[0]; > - tree scalar_type = TREE_TYPE (vector_type); > - class loop *loop = gimple_bb (stmt_vinfo->stmt)->loop_father; > - gcc_assert (loop); > - > switch (code) > { > case WIDEN_SUM_EXPR: > @@ -3284,12 +3276,7 @@ neutral_op_for_slp_reduction (slp_tree slp_node, tree > vector_type, > > case MAX_EXPR: > case MIN_EXPR: > - /* For MIN/MAX the initial values are neutral. A reduction chain > - has only a single initial value, so that value is neutral for > - all statements. */ > - if (reduc_chain) > - return vect_phi_initial_value (stmt_vinfo); > - return NULL_TREE; > + return initial_value; > > default: > return NULL_TREE; > @@ -5535,10 +5522,11 @@ vect_create_epilog_for_reduction (loop_vec_info > loop_vinfo, > tree neutral_op = NULL_TREE; > if (slp_node) > { > - stmt_vec_info first = REDUC_GROUP_FIRST_ELEMENT (stmt_info); > - neutral_op > - = neutral_op_for_slp_reduction (slp_node_instance->reduc_phis, > - vectype, code, first != NULL); > + tree initial_value = NULL_TREE; > + if (REDUC_GROUP_FIRST_ELEMENT (stmt_info)) > + initial_value = vect_phi_initial_value (orig_phis[0]); > + neutral_op = neutral_op_for_reduction (TREE_TYPE (vectype), code, > + initial_value); > } > if (neutral_op) > vector_identity = gimple_build_vector_from_val (&seq, vectype, > @@ -6935,9 +6923,13 @@ vectorizable_reduction (loop_vec_info loop_vinfo, > /* For SLP reductions, see if there is a neutral value we can use. */ > tree neutral_op = NULL_TREE; > if (slp_node) > - neutral_op = neutral_op_for_slp_reduction > - (slp_node_instance->reduc_phis, vectype_out, orig_code, > - REDUC_GROUP_FIRST_ELEMENT (stmt_info) != NULL); > + { > + tree initial_value = NULL_TREE; > + if (REDUC_GROUP_FIRST_ELEMENT (stmt_info) != NULL) > + initial_value = vect_phi_initial_value (reduc_def_phi); > + neutral_op = neutral_op_for_reduction (TREE_TYPE (vectype_out), > + orig_code, initial_value); > + } > > if (double_reduc && reduction_type == FOLD_LEFT_REDUCTION) > { > @@ -7501,15 +7493,16 @@ vect_transform_cycle_phi (loop_vec_info loop_vinfo, > else > { > gcc_assert (slp_node == slp_node_instance->reduc_phis); > - stmt_vec_info first = REDUC_GROUP_FIRST_ELEMENT (reduc_stmt_info); > - tree neutral_op > - = neutral_op_for_slp_reduction (slp_node, vectype_out, > - STMT_VINFO_REDUC_CODE > (reduc_info), > - first != NULL); > + tree initial_value = NULL_TREE; > + if (REDUC_GROUP_FIRST_ELEMENT (reduc_stmt_info)) > + initial_value = vect_phi_initial_value (phi); > + tree_code code = STMT_VINFO_REDUC_CODE (reduc_info); > + tree neutral_op = neutral_op_for_reduction (TREE_TYPE (vectype_out), > + code, initial_value); > get_initial_defs_for_reduction (loop_vinfo, reduc_info, > slp_node_instance->reduc_phis, > &vec_initial_defs, vec_num, > - first != NULL, neutral_op); > + initial_value != NULL, neutral_op); > } > } > else