On Thu, Sep 14, 2017 at 1:20 PM, Richard Sandiford <richard.sandif...@linaro.org> wrote: > This patch adds gimple-fold.h equivalents of build_vector and > build_vector_from_val. Like the other gimple-fold.h routines > they always return a valid gimple value and add any new > statements to a given gimple_seq. In combination with later > patches this reduces the number of force_gimple_operands. > > Tested on aarch64-linux-gnu, x86_64-linux-gnu and powerpc64le-linux-gnu. > OK to install?
Ok. Thanks, Richard. > Richard > > > 2017-09-14 Richard Sandiford <richard.sandif...@linaro.org> > Alan Hayward <alan.hayw...@arm.com> > David Sherwood <david.sherw...@arm.com> > > gcc/ > * gimple-fold.h (gimple_build_vector_from_val): Declare, and provide > an inline wrapper that provides a location. > (gimple_build_vector): Likewise. > * gimple-fold.c (gimple_build_vector_from_val): New function. > (gimple_build_vector): Likewise. > * tree-vect-loop.c (get_initial_def_for_reduction): Use the new > functions to build the initial value. Always return a gimple value. > (get_initial_defs_for_reduction): Likewise. Only compute > neutral_vec once. > (vect_create_epilog_for_reduction): Don't call force_gimple_operand or > vect_init_vector on the results from get_initial_def(s)_for_reduction. > (vectorizable_induction): Use gimple_build_vector rather than > vect_init_vector. > > Index: gcc/gimple-fold.h > =================================================================== > --- gcc/gimple-fold.h 2017-07-08 11:37:46.573465901 +0100 > +++ gcc/gimple-fold.h 2017-09-14 11:26:37.598804415 +0100 > @@ -127,6 +127,21 @@ gimple_convert_to_ptrofftype (gimple_seq > return gimple_convert_to_ptrofftype (seq, UNKNOWN_LOCATION, op); > } > > +extern tree gimple_build_vector_from_val (gimple_seq *, location_t, tree, > + tree); > +inline tree > +gimple_build_vector_from_val (gimple_seq *seq, tree type, tree op) > +{ > + return gimple_build_vector_from_val (seq, UNKNOWN_LOCATION, type, op); > +} > + > +extern tree gimple_build_vector (gimple_seq *, location_t, tree, vec<tree>); > +inline tree > +gimple_build_vector (gimple_seq *seq, tree type, vec<tree> elts) > +{ > + return gimple_build_vector (seq, UNKNOWN_LOCATION, type, elts); > +} > + > extern bool gimple_stmt_nonnegative_warnv_p (gimple *, bool *, int = 0); > extern bool gimple_stmt_integer_valued_real_p (gimple *, int = 0); > > Index: gcc/gimple-fold.c > =================================================================== > --- gcc/gimple-fold.c 2017-09-14 11:24:42.666088258 +0100 > +++ gcc/gimple-fold.c 2017-09-14 11:26:37.598804415 +0100 > @@ -7058,6 +7058,58 @@ gimple_convert_to_ptrofftype (gimple_seq > return gimple_convert (seq, loc, sizetype, op); > } > > +/* Build a vector of type TYPE in which each element has the value OP. > + Return a gimple value for the result, appending any new statements > + to SEQ. */ > + > +tree > +gimple_build_vector_from_val (gimple_seq *seq, location_t loc, tree type, > + tree op) > +{ > + tree res, vec = build_vector_from_val (type, op); > + if (is_gimple_val (vec)) > + return vec; > + if (gimple_in_ssa_p (cfun)) > + res = make_ssa_name (type); > + else > + res = create_tmp_reg (type); > + gimple *stmt = gimple_build_assign (res, vec); > + gimple_set_location (stmt, loc); > + gimple_seq_add_stmt_without_update (seq, stmt); > + return res; > +} > + > +/* Build a vector of type TYPE in which the elements have the values > + given by ELTS. Return a gimple value for the result, appending any > + new instructions to SEQ. */ > + > +tree > +gimple_build_vector (gimple_seq *seq, location_t loc, tree type, > + vec<tree> elts) > +{ > + unsigned int nelts = elts.length (); > + gcc_assert (nelts == TYPE_VECTOR_SUBPARTS (type)); > + for (unsigned int i = 0; i < nelts; ++i) > + if (!TREE_CONSTANT (elts[i])) > + { > + vec<constructor_elt, va_gc> *v; > + vec_alloc (v, nelts); > + for (i = 0; i < nelts; ++i) > + CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, elts[i]); > + > + tree res; > + if (gimple_in_ssa_p (cfun)) > + res = make_ssa_name (type); > + else > + res = create_tmp_reg (type); > + gimple *stmt = gimple_build_assign (res, build_constructor (type, v)); > + gimple_set_location (stmt, loc); > + gimple_seq_add_stmt_without_update (seq, stmt); > + return res; > + } > + return build_vector (type, elts); > +} > + > /* Return true if the result of assignment STMT is known to be non-negative. > If the return value is based on the assumption that signed overflow is > undefined, set *STRICT_OVERFLOW_P to true; otherwise, don't change > Index: gcc/tree-vect-loop.c > =================================================================== > --- gcc/tree-vect-loop.c 2017-09-14 11:25:32.164167193 +0100 > +++ gcc/tree-vect-loop.c 2017-09-14 11:26:37.599804415 +0100 > @@ -4044,33 +4044,18 @@ get_initial_def_for_reduction (gimple *s > else > def_for_init = build_int_cst (scalar_type, int_init_val); > > - /* Create a vector of '0' or '1' except the first element. */ > - auto_vec<tree, 32> elts (nunits); > - elts.quick_grow (nunits); > - for (i = nunits - 2; i >= 0; --i) > - elts[i + 1] = def_for_init; > - > - /* Option1: the first element is '0' or '1' as well. */ > if (adjustment_def) > + /* Option1: the first element is '0' or '1' as well. */ > + init_def = gimple_build_vector_from_val (&stmts, vectype, > + def_for_init); > + else > { > - elts[0] = def_for_init; > - > - init_def = build_vector (vectype, elts); > - break; > - } > - > - /* Option2: the first element is INIT_VAL. */ > - elts[0] = init_val; > - if (TREE_CONSTANT (init_val)) > - init_def = build_vector (vectype, elts); > - else > - { > - vec<constructor_elt, va_gc> *v; > - vec_alloc (v, nunits); > - CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, init_val); > + /* Option2: the first element is INIT_VAL. */ > + auto_vec<tree, 32> elts (nunits); > + elts.quick_push (init_val); > for (i = 1; i < nunits; ++i) > - CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, elts[i]); > - init_def = build_constructor (vectype, v); > + elts.quick_push (def_for_init); > + init_def = gimple_build_vector (&stmts, vectype, elts); > } > } > break; > @@ -4089,9 +4074,7 @@ get_initial_def_for_reduction (gimple *s > } > } > init_val = gimple_convert (&stmts, TREE_TYPE (vectype), init_val); > - if (! gimple_seq_empty_p (stmts)) > - gsi_insert_seq_on_edge_immediate (loop_preheader_edge (loop), > stmts); > - init_def = build_vector_from_val (vectype, init_val); > + init_def = gimple_build_vector_from_val (&stmts, vectype, init_val); > } > break; > > @@ -4099,6 +4082,8 @@ get_initial_def_for_reduction (gimple *s > gcc_unreachable (); > } > > + if (stmts) > + gsi_insert_seq_on_edge_immediate (loop_preheader_edge (loop), stmts); > return init_def; > } > > @@ -4115,7 +4100,6 @@ get_initial_defs_for_reduction (slp_tree > gimple *stmt = stmts[0]; > stmt_vec_info stmt_vinfo = vinfo_for_stmt (stmt); > unsigned nunits; > - tree vec_cst; > unsigned j, number_of_places_left_in_vector; > tree vector_type, scalar_type; > tree vop; > @@ -4124,10 +4108,8 @@ get_initial_defs_for_reduction (slp_tree > unsigned number_of_copies = 1; > vec<tree> voprnds; > voprnds.create (number_of_vectors); > - bool constant_p; > tree neutral_op = NULL; > struct loop *loop; > - gimple_seq ctor_seq = NULL; > > vector_type = STMT_VINFO_VECTYPE (stmt_vinfo); > scalar_type = TREE_TYPE (vector_type); > @@ -4137,6 +4119,7 @@ get_initial_defs_for_reduction (slp_tree > > loop = (gimple_bb (stmt))->loop_father; > gcc_assert (loop); > + edge pe = loop_preheader_edge (loop); > > /* op is the reduction operand of the first stmt already. */ > /* For additional copies (see the explanation of NUMBER_OF_COPIES below) > @@ -4170,8 +4153,7 @@ get_initial_defs_for_reduction (slp_tree > if (! reduc_chain) > neutral_op = NULL; > else > - neutral_op = PHI_ARG_DEF_FROM_EDGE (stmt, > - loop_preheader_edge (loop)); > + neutral_op = PHI_ARG_DEF_FROM_EDGE (stmt, pe); > break; > > default: > @@ -4198,7 +4180,6 @@ get_initial_defs_for_reduction (slp_tree > number_of_copies = nunits * number_of_vectors / group_size; > > number_of_places_left_in_vector = nunits; > - constant_p = true; > auto_vec<tree, 32> elts (nunits); > elts.quick_grow (nunits); > for (j = 0; j < number_of_copies; j++) > @@ -4213,42 +4194,21 @@ get_initial_defs_for_reduction (slp_tree > && neutral_op) > op = neutral_op; > else > - op = PHI_ARG_DEF_FROM_EDGE (stmt, > - loop_preheader_edge (loop)); > + op = PHI_ARG_DEF_FROM_EDGE (stmt, pe); > > /* Create 'vect_ = {op0,op1,...,opn}'. */ > number_of_places_left_in_vector--; > elts[number_of_places_left_in_vector] = op; > - if (!CONSTANT_CLASS_P (op)) > - constant_p = false; > > if (number_of_places_left_in_vector == 0) > { > - if (constant_p) > - vec_cst = build_vector (vector_type, elts); > - else > - { > - vec<constructor_elt, va_gc> *v; > - unsigned k; > - vec_alloc (v, nunits); > - for (k = 0; k < nunits; ++k) > - CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, elts[k]); > - vec_cst = build_constructor (vector_type, v); > - } > - tree init; > - gimple_stmt_iterator gsi; > - init = vect_init_vector (stmt, vec_cst, vector_type, NULL); > + gimple_seq ctor_seq = NULL; > + tree init = gimple_build_vector (&ctor_seq, vector_type, elts); > if (ctor_seq != NULL) > - { > - gsi = gsi_for_stmt (SSA_NAME_DEF_STMT (init)); > - gsi_insert_seq_before_without_update (&gsi, ctor_seq, > - GSI_SAME_STMT); > - ctor_seq = NULL; > - } > + gsi_insert_seq_on_edge_immediate (pe, ctor_seq); > voprnds.quick_push (init); > > number_of_places_left_in_vector = nunits; > - constant_p = true; > } > } > } > @@ -4268,15 +4228,19 @@ get_initial_defs_for_reduction (slp_tree > group of stmts, NUMBER_OF_VECTORS to be created is greater than > NUMBER_OF_SCALARS/NUNITS or NUNITS/NUMBER_OF_SCALARS, and hence we have > to replicate the vectors. */ > + tree neutral_vec = NULL; > while (number_of_vectors > vec_oprnds->length ()) > { > - tree neutral_vec = NULL; > - > if (neutral_op) > { > if (!neutral_vec) > - neutral_vec = build_vector_from_val (vector_type, neutral_op); > - > + { > + gimple_seq ctor_seq = NULL; > + neutral_vec = gimple_build_vector_from_val > + (&ctor_seq, vector_type, neutral_op); > + if (ctor_seq != NULL) > + gsi_insert_seq_on_edge_immediate (pe, ctor_seq); > + } > vec_oprnds->quick_push (neutral_vec); > } > else > @@ -4455,14 +4419,8 @@ vect_create_epilog_for_reduction (vec<tr > /* Set phi nodes arguments. */ > FOR_EACH_VEC_ELT (reduction_phis, i, phi) > { > - tree vec_init_def, def; > - gimple_seq stmts; > - vec_init_def = force_gimple_operand (vec_initial_defs[i], &stmts, > - true, NULL_TREE); > - if (stmts) > - gsi_insert_seq_on_edge_immediate (loop_preheader_edge (loop), stmts); > - > - def = vect_defs[i]; > + tree vec_init_def = vec_initial_defs[i]; > + tree def = vect_defs[i]; > for (j = 0; j < ncopies; j++) > { > if (j != 0) > @@ -5405,7 +5363,7 @@ vect_create_epilog_for_reduction (vec<tr > { > stmt_vec_info use_stmt_vinfo; > stmt_vec_info new_phi_vinfo; > - tree vect_phi_init, preheader_arg, vect_phi_res, init_def; > + tree vect_phi_init, preheader_arg, vect_phi_res; > basic_block bb = gimple_bb (use_stmt); > gimple *use; > > @@ -5438,10 +5396,8 @@ vect_create_epilog_for_reduction (vec<tr > /* Create vs0 - initial def of the double reduction phi. > */ > preheader_arg = PHI_ARG_DEF_FROM_EDGE (use_stmt, > loop_preheader_edge > (outer_loop)); > - init_def = get_initial_def_for_reduction (stmt, > - preheader_arg, > NULL); > - vect_phi_init = vect_init_vector (use_stmt, init_def, > - vectype, NULL); > + vect_phi_init = get_initial_def_for_reduction > + (stmt, preheader_arg, NULL); > > /* Update phi node arguments with vs0 and vs2. */ > add_phi_arg (vect_phi, vect_phi_init, > @@ -6738,36 +6694,21 @@ vectorizable_induction (gimple *phi, > for (ivn = 0; ivn < nivs; ++ivn) > { > auto_vec<tree, 32> elts (nunits); > - bool constant_p = true; > + stmts = NULL; > for (unsigned eltn = 0; eltn < nunits; ++eltn) > { > if (ivn*nunits + eltn >= group_size > && (ivn*nunits + eltn) % group_size == 0) > - { > - stmts = NULL; > - elt = gimple_build (&stmts, PLUS_EXPR, TREE_TYPE (elt), > - elt, step_expr); > - if (stmts) > - { > - new_bb = gsi_insert_seq_on_edge_immediate (pe, stmts); > - gcc_assert (!new_bb); > - } > - } > - if (! CONSTANT_CLASS_P (elt)) > - constant_p = false; > + elt = gimple_build (&stmts, PLUS_EXPR, TREE_TYPE (elt), > + elt, step_expr); > elts.quick_push (elt); > } > - if (constant_p) > - new_vec = build_vector (vectype, elts); > - else > + vec_init = gimple_build_vector (&stmts, vectype, elts); > + if (stmts) > { > - vec<constructor_elt, va_gc> *v; > - vec_alloc (v, nunits); > - for (i = 0; i < nunits; ++i) > - CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, elts[i]); > - new_vec = build_constructor (vectype, v); > + new_bb = gsi_insert_seq_on_edge_immediate (pe, stmts); > + gcc_assert (!new_bb); > } > - vec_init = vect_init_vector (phi, new_vec, vectype, NULL); > > /* Create the induction-phi that defines the induction-operand. */ > vec_dest = vect_get_new_vect_var (vectype, vect_simple_var, > "vec_iv_"); > @@ -6864,37 +6805,28 @@ vectorizable_induction (gimple *phi, > } > else > { > - vec<constructor_elt, va_gc> *v; > - > /* iv_loop is the loop to be vectorized. Create: > vec_init = [X, X+S, X+2*S, X+3*S] (S = step_expr, X = init_expr) */ > stmts = NULL; > new_name = gimple_convert (&stmts, TREE_TYPE (vectype), init_expr); > > - vec_alloc (v, nunits); > - bool constant_p = is_gimple_min_invariant (new_name); > - CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, new_name); > + auto_vec<tree, 32> elts (nunits); > + elts.quick_push (new_name); > for (i = 1; i < nunits; i++) > { > /* Create: new_name_i = new_name + step_expr */ > new_name = gimple_build (&stmts, PLUS_EXPR, TREE_TYPE (new_name), > new_name, step_expr); > - if (!is_gimple_min_invariant (new_name)) > - constant_p = false; > - CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, new_name); > + elts.quick_push (new_name); > } > + /* Create a vector from [new_name_0, new_name_1, ..., > + new_name_nunits-1] */ > + vec_init = gimple_build_vector (&stmts, vectype, elts); > if (stmts) > { > new_bb = gsi_insert_seq_on_edge_immediate (pe, stmts); > gcc_assert (!new_bb); > } > - > - /* Create a vector from [new_name_0, new_name_1, ..., > new_name_nunits-1] */ > - if (constant_p) > - new_vec = build_vector_from_ctor (vectype, v); > - else > - new_vec = build_constructor (vectype, v); > - vec_init = vect_init_vector (phi, new_vec, vectype, NULL); > } > >