Message ID | 87vahj98uk.fsf_-_@linaro.org |
---|---|
State | New |
Headers | show |
Series | Make gimple_build_vector take a tree_vector_builder | expand |
On Wed, Dec 6, 2017 at 4:25 PM, Richard Sandiford <richard.sandiford@linaro.org> wrote: > This patch changes gimple_build_vector so that it takes a > tree_vector_builder instead of a size and a vector of trees. > > Tested on aarch64-linux-gnu, x86_64-linux-gnu and powerpc64le-linux-gnu. > Also spot-checked on sparc64-linux-gnu. OK to install? Ok. Richard. > Thanks, > Richard > > > 2017-12-06 Richard Sandiford <richard.sandiford@linaro.org> > > gcc/ > * vector-builder.h (vector_builder::derived): New const overload. > (vector_builder::elt): New function. > * tree-vector-builder.h (tree_vector_builder::type): New function. > (tree_vector_builder::apply_step): Declare. > * tree-vector-builder.c (tree_vector_builder::apply_step): New > function. > * gimple-fold.h (tree_vector_builder): Declare. > (gimple_build_vector): Take a tree_vector_builder instead of a > type and vector of elements. > * gimple-fold.c (gimple_build_vector): Likewise. > * tree-vect-loop.c (get_initial_def_for_reduction): Update call > accordingly. > (get_initial_defs_for_reduction): Likewise. > (vectorizable_induction): Likewise. > > Index: gcc/vector-builder.h > =================================================================== > --- gcc/vector-builder.h 2017-12-06 14:46:14.133599820 +0000 > +++ gcc/vector-builder.h 2017-12-06 14:49:04.289693414 +0000 > @@ -68,6 +68,10 @@ #define GCC_VECTOR_BUILDER_H > given integral_p (ELT1) && integral_p (ELT2). There is no fixed > choice of StepType. > > + T apply_step (T base, unsigned int factor, StepType step) const; > + > + Return a vector element with the value BASE + FACTOR * STEP. > + > bool can_elide_p (T elt) const; > > Return true if we can drop element ELT, even if the retained > @@ -91,6 +95,7 @@ #define GCC_VECTOR_BUILDER_H > unsigned int nelts_per_pattern () const { return m_nelts_per_pattern; } > unsigned int encoded_nelts () const; > bool encoded_full_vector_p () const; > + T elt (unsigned int) const; > > void finalize (); > > @@ -163,6 +168,38 @@ vector_builder<T, Derived>::new_vector ( > this->truncate (0); > } > > +/* Return the value of vector element I, which might or might not be > + encoded explicitly. */ > + > +template<typename T, typename Derived> > +T > +vector_builder<T, Derived>::elt (unsigned int i) const > +{ > + /* This only makes sense if the encoding has been fully populated. */ > + gcc_checking_assert (encoded_nelts () <= this->length ()); > + > + /* First handle elements that are already present in the underlying > + vector, regardless of whether they're part of the encoding or not. */ > + if (i < this->length ()) > + return (*this)[i]; > + > + /* Identify the pattern that contains element I and work out the index of > + the last encoded element for that pattern. */ > + unsigned int pattern = i % m_npatterns; > + unsigned int count = i / m_npatterns; > + unsigned int final_i = encoded_nelts () - m_npatterns + pattern; > + T final = (*this)[final_i]; > + > + /* If there are no steps, the final encoded value is the right one. */ > + if (m_nelts_per_pattern <= 2) > + return final; > + > + /* Otherwise work out the value from the last two encoded elements. */ > + T prev = (*this)[final_i - m_npatterns]; > + return derived ()->apply_step (final, count - 2, > + derived ()->step (prev, final)); > +} > + > /* Change the encoding to NPATTERNS patterns of NELTS_PER_PATTERN each, > but without changing the underlying vector. */ > > Index: gcc/tree-vector-builder.h > =================================================================== > --- gcc/tree-vector-builder.h 2017-12-06 14:49:00.386854068 +0000 > +++ gcc/tree-vector-builder.h 2017-12-06 14:49:04.289693414 +0000 > @@ -45,6 +45,7 @@ #define GCC_TREE_VECTOR_BUILDER_H > bool allow_steps_p () const; > bool integral_p (const_tree) const; > wide_int step (const_tree, const_tree) const; > + tree apply_step (tree, unsigned int, const wide_int &) const; > bool can_elide_p (const_tree) const; > void note_representative (tree *, tree); > > Index: gcc/tree-vector-builder.c > =================================================================== > --- gcc/tree-vector-builder.c 2017-12-06 14:49:00.386854068 +0000 > +++ gcc/tree-vector-builder.c 2017-12-06 14:49:04.289693414 +0000 > @@ -96,6 +96,16 @@ tree_vector_builder::new_binary_operatio > return true; > } > > +/* Return a vector element with the value BASE + FACTOR * STEP. */ > + > +tree > +tree_vector_builder::apply_step (tree base, unsigned int factor, > + const wide_int &step) const > +{ > + return wide_int_to_tree (TREE_TYPE (base), > + wi::to_wide (base) + factor * step); > +} > + > /* Return a VECTOR_CST for the current constant. */ > > tree > Index: gcc/gimple-fold.h > =================================================================== > --- gcc/gimple-fold.h 2017-11-29 11:06:33.003002371 +0000 > +++ gcc/gimple-fold.h 2017-12-06 14:49:04.288693455 +0000 > @@ -135,11 +135,13 @@ gimple_build_vector_from_val (gimple_seq > return gimple_build_vector_from_val (seq, UNKNOWN_LOCATION, type, op); > } > > -extern tree gimple_build_vector (gimple_seq *, location_t, tree, vec<tree>); > +class tree_vector_builder; > +extern tree gimple_build_vector (gimple_seq *, location_t, > + tree_vector_builder *); > inline tree > -gimple_build_vector (gimple_seq *seq, tree type, vec<tree> elts) > +gimple_build_vector (gimple_seq *seq, tree_vector_builder *builder) > { > - return gimple_build_vector (seq, UNKNOWN_LOCATION, type, elts); > + return gimple_build_vector (seq, UNKNOWN_LOCATION, builder); > } > > extern bool gimple_stmt_nonnegative_warnv_p (gimple *, bool *, int = 0); > Index: gcc/gimple-fold.c > =================================================================== > --- gcc/gimple-fold.c 2017-12-06 14:48:52.888162175 +0000 > +++ gcc/gimple-fold.c 2017-12-06 14:49:04.288693455 +0000 > @@ -7178,23 +7178,30 @@ gimple_build_vector_from_val (gimple_seq > 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. */ > +/* Build a vector from BUILDER, handling the case in which some elements > + are non-constant. Return a gimple value for the result, appending any > + new instructions to SEQ. > + > + BUILDER must not have a stepped encoding on entry. This is because > + the function is not geared up to handle the arithmetic that would > + be needed in the variable case, and any code building a vector that > + is known to be constant should use BUILDER->build () directly. */ > > tree > -gimple_build_vector (gimple_seq *seq, location_t loc, tree type, > - vec<tree> elts) > +gimple_build_vector (gimple_seq *seq, location_t loc, > + tree_vector_builder *builder) > { > - 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])) > + gcc_assert (builder->nelts_per_pattern () <= 2); > + unsigned int encoded_nelts = builder->encoded_nelts (); > + for (unsigned int i = 0; i < encoded_nelts; ++i) > + if (!TREE_CONSTANT ((*builder)[i])) > { > + tree type = builder->type (); > + unsigned int nelts = TYPE_VECTOR_SUBPARTS (type); > vec<constructor_elt, va_gc> *v; > vec_alloc (v, nelts); > for (i = 0; i < nelts; ++i) > - CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, elts[i]); > + CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, builder->elt (i)); > > tree res; > if (gimple_in_ssa_p (cfun)) > @@ -7206,7 +7213,7 @@ gimple_build_vector (gimple_seq *seq, lo > gimple_seq_add_stmt_without_update (seq, stmt); > return res; > } > - return build_vector (type, elts); > + return builder->build (); > } > > /* Return true if the result of assignment STMT is known to be non-negative. > Index: gcc/tree-vect-loop.c > =================================================================== > --- gcc/tree-vect-loop.c 2017-12-06 14:48:52.889162134 +0000 > +++ gcc/tree-vect-loop.c 2017-12-06 14:49:04.289693414 +0000 > @@ -3968,11 +3968,9 @@ get_initial_def_for_reduction (gimple *s > struct loop *loop = LOOP_VINFO_LOOP (loop_vinfo); > tree scalar_type = TREE_TYPE (init_val); > tree vectype = get_vectype_for_scalar_type (scalar_type); > - int nunits; > enum tree_code code = gimple_assign_rhs_code (stmt); > tree def_for_init; > tree init_def; > - int i; > bool nested_in_vect_loop = false; > REAL_VALUE_TYPE real_init_val = dconst0; > int int_init_val = 0; > @@ -3980,7 +3978,6 @@ get_initial_def_for_reduction (gimple *s > gimple_seq stmts = NULL; > > gcc_assert (vectype); > - nunits = TYPE_VECTOR_SUBPARTS (vectype); > > gcc_assert (POINTER_TYPE_P (scalar_type) || INTEGRAL_TYPE_P (scalar_type) > || SCALAR_FLOAT_TYPE_P (scalar_type)); > @@ -4053,11 +4050,10 @@ get_initial_def_for_reduction (gimple *s > else > { > /* Option2: the first element is INIT_VAL. */ > - auto_vec<tree, 32> elts (nunits); > + tree_vector_builder elts (vectype, 1, 2); > elts.quick_push (init_val); > - for (i = 1; i < nunits; ++i) > - elts.quick_push (def_for_init); > - init_def = gimple_build_vector (&stmts, vectype, elts); > + elts.quick_push (def_for_init); > + init_def = gimple_build_vector (&stmts, &elts); > } > } > break; > @@ -4182,7 +4178,7 @@ get_initial_defs_for_reduction (slp_tree > number_of_copies = nunits * number_of_vectors / group_size; > > number_of_places_left_in_vector = nunits; > - auto_vec<tree, 32> elts (nunits); > + tree_vector_builder elts (vector_type, nunits, 1); > elts.quick_grow (nunits); > for (j = 0; j < number_of_copies; j++) > { > @@ -4205,12 +4201,14 @@ get_initial_defs_for_reduction (slp_tree > if (number_of_places_left_in_vector == 0) > { > gimple_seq ctor_seq = NULL; > - tree init = gimple_build_vector (&ctor_seq, vector_type, elts); > + tree init = gimple_build_vector (&ctor_seq, &elts); > if (ctor_seq != NULL) > gsi_insert_seq_on_edge_immediate (pe, ctor_seq); > voprnds.quick_push (init); > > number_of_places_left_in_vector = nunits; > + elts.new_vector (vector_type, nunits, 1); > + elts.quick_grow (nunits); > } > } > } > @@ -6698,7 +6696,7 @@ vectorizable_induction (gimple *phi, > unsigned ivn; > for (ivn = 0; ivn < nivs; ++ivn) > { > - auto_vec<tree, 32> elts (nunits); > + tree_vector_builder elts (vectype, nunits, 1); > stmts = NULL; > for (unsigned eltn = 0; eltn < nunits; ++eltn) > { > @@ -6708,7 +6706,7 @@ vectorizable_induction (gimple *phi, > elt, step_expr); > elts.quick_push (elt); > } > - vec_init = gimple_build_vector (&stmts, vectype, elts); > + vec_init = gimple_build_vector (&stmts, &elts); > if (stmts) > { > new_bb = gsi_insert_seq_on_edge_immediate (pe, stmts); > @@ -6815,7 +6813,7 @@ vectorizable_induction (gimple *phi, > stmts = NULL; > new_name = gimple_convert (&stmts, TREE_TYPE (vectype), init_expr); > > - auto_vec<tree, 32> elts (nunits); > + tree_vector_builder elts (vectype, nunits, 1); > elts.quick_push (new_name); > for (i = 1; i < nunits; i++) > { > @@ -6826,7 +6824,7 @@ vectorizable_induction (gimple *phi, > } > /* Create a vector from [new_name_0, new_name_1, ..., > new_name_nunits-1] */ > - vec_init = gimple_build_vector (&stmts, vectype, elts); > + vec_init = gimple_build_vector (&stmts, &elts); > if (stmts) > { > new_bb = gsi_insert_seq_on_edge_immediate (pe, stmts);
Index: gcc/vector-builder.h =================================================================== --- gcc/vector-builder.h 2017-12-06 14:46:14.133599820 +0000 +++ gcc/vector-builder.h 2017-12-06 14:49:04.289693414 +0000 @@ -68,6 +68,10 @@ #define GCC_VECTOR_BUILDER_H given integral_p (ELT1) && integral_p (ELT2). There is no fixed choice of StepType. + T apply_step (T base, unsigned int factor, StepType step) const; + + Return a vector element with the value BASE + FACTOR * STEP. + bool can_elide_p (T elt) const; Return true if we can drop element ELT, even if the retained @@ -91,6 +95,7 @@ #define GCC_VECTOR_BUILDER_H unsigned int nelts_per_pattern () const { return m_nelts_per_pattern; } unsigned int encoded_nelts () const; bool encoded_full_vector_p () const; + T elt (unsigned int) const; void finalize (); @@ -163,6 +168,38 @@ vector_builder<T, Derived>::new_vector ( this->truncate (0); } +/* Return the value of vector element I, which might or might not be + encoded explicitly. */ + +template<typename T, typename Derived> +T +vector_builder<T, Derived>::elt (unsigned int i) const +{ + /* This only makes sense if the encoding has been fully populated. */ + gcc_checking_assert (encoded_nelts () <= this->length ()); + + /* First handle elements that are already present in the underlying + vector, regardless of whether they're part of the encoding or not. */ + if (i < this->length ()) + return (*this)[i]; + + /* Identify the pattern that contains element I and work out the index of + the last encoded element for that pattern. */ + unsigned int pattern = i % m_npatterns; + unsigned int count = i / m_npatterns; + unsigned int final_i = encoded_nelts () - m_npatterns + pattern; + T final = (*this)[final_i]; + + /* If there are no steps, the final encoded value is the right one. */ + if (m_nelts_per_pattern <= 2) + return final; + + /* Otherwise work out the value from the last two encoded elements. */ + T prev = (*this)[final_i - m_npatterns]; + return derived ()->apply_step (final, count - 2, + derived ()->step (prev, final)); +} + /* Change the encoding to NPATTERNS patterns of NELTS_PER_PATTERN each, but without changing the underlying vector. */ Index: gcc/tree-vector-builder.h =================================================================== --- gcc/tree-vector-builder.h 2017-12-06 14:49:00.386854068 +0000 +++ gcc/tree-vector-builder.h 2017-12-06 14:49:04.289693414 +0000 @@ -45,6 +45,7 @@ #define GCC_TREE_VECTOR_BUILDER_H bool allow_steps_p () const; bool integral_p (const_tree) const; wide_int step (const_tree, const_tree) const; + tree apply_step (tree, unsigned int, const wide_int &) const; bool can_elide_p (const_tree) const; void note_representative (tree *, tree); Index: gcc/tree-vector-builder.c =================================================================== --- gcc/tree-vector-builder.c 2017-12-06 14:49:00.386854068 +0000 +++ gcc/tree-vector-builder.c 2017-12-06 14:49:04.289693414 +0000 @@ -96,6 +96,16 @@ tree_vector_builder::new_binary_operatio return true; } +/* Return a vector element with the value BASE + FACTOR * STEP. */ + +tree +tree_vector_builder::apply_step (tree base, unsigned int factor, + const wide_int &step) const +{ + return wide_int_to_tree (TREE_TYPE (base), + wi::to_wide (base) + factor * step); +} + /* Return a VECTOR_CST for the current constant. */ tree Index: gcc/gimple-fold.h =================================================================== --- gcc/gimple-fold.h 2017-11-29 11:06:33.003002371 +0000 +++ gcc/gimple-fold.h 2017-12-06 14:49:04.288693455 +0000 @@ -135,11 +135,13 @@ gimple_build_vector_from_val (gimple_seq return gimple_build_vector_from_val (seq, UNKNOWN_LOCATION, type, op); } -extern tree gimple_build_vector (gimple_seq *, location_t, tree, vec<tree>); +class tree_vector_builder; +extern tree gimple_build_vector (gimple_seq *, location_t, + tree_vector_builder *); inline tree -gimple_build_vector (gimple_seq *seq, tree type, vec<tree> elts) +gimple_build_vector (gimple_seq *seq, tree_vector_builder *builder) { - return gimple_build_vector (seq, UNKNOWN_LOCATION, type, elts); + return gimple_build_vector (seq, UNKNOWN_LOCATION, builder); } extern bool gimple_stmt_nonnegative_warnv_p (gimple *, bool *, int = 0); Index: gcc/gimple-fold.c =================================================================== --- gcc/gimple-fold.c 2017-12-06 14:48:52.888162175 +0000 +++ gcc/gimple-fold.c 2017-12-06 14:49:04.288693455 +0000 @@ -7178,23 +7178,30 @@ gimple_build_vector_from_val (gimple_seq 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. */ +/* Build a vector from BUILDER, handling the case in which some elements + are non-constant. Return a gimple value for the result, appending any + new instructions to SEQ. + + BUILDER must not have a stepped encoding on entry. This is because + the function is not geared up to handle the arithmetic that would + be needed in the variable case, and any code building a vector that + is known to be constant should use BUILDER->build () directly. */ tree -gimple_build_vector (gimple_seq *seq, location_t loc, tree type, - vec<tree> elts) +gimple_build_vector (gimple_seq *seq, location_t loc, + tree_vector_builder *builder) { - 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])) + gcc_assert (builder->nelts_per_pattern () <= 2); + unsigned int encoded_nelts = builder->encoded_nelts (); + for (unsigned int i = 0; i < encoded_nelts; ++i) + if (!TREE_CONSTANT ((*builder)[i])) { + tree type = builder->type (); + unsigned int nelts = TYPE_VECTOR_SUBPARTS (type); vec<constructor_elt, va_gc> *v; vec_alloc (v, nelts); for (i = 0; i < nelts; ++i) - CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, elts[i]); + CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, builder->elt (i)); tree res; if (gimple_in_ssa_p (cfun)) @@ -7206,7 +7213,7 @@ gimple_build_vector (gimple_seq *seq, lo gimple_seq_add_stmt_without_update (seq, stmt); return res; } - return build_vector (type, elts); + return builder->build (); } /* Return true if the result of assignment STMT is known to be non-negative. Index: gcc/tree-vect-loop.c =================================================================== --- gcc/tree-vect-loop.c 2017-12-06 14:48:52.889162134 +0000 +++ gcc/tree-vect-loop.c 2017-12-06 14:49:04.289693414 +0000 @@ -3968,11 +3968,9 @@ get_initial_def_for_reduction (gimple *s struct loop *loop = LOOP_VINFO_LOOP (loop_vinfo); tree scalar_type = TREE_TYPE (init_val); tree vectype = get_vectype_for_scalar_type (scalar_type); - int nunits; enum tree_code code = gimple_assign_rhs_code (stmt); tree def_for_init; tree init_def; - int i; bool nested_in_vect_loop = false; REAL_VALUE_TYPE real_init_val = dconst0; int int_init_val = 0; @@ -3980,7 +3978,6 @@ get_initial_def_for_reduction (gimple *s gimple_seq stmts = NULL; gcc_assert (vectype); - nunits = TYPE_VECTOR_SUBPARTS (vectype); gcc_assert (POINTER_TYPE_P (scalar_type) || INTEGRAL_TYPE_P (scalar_type) || SCALAR_FLOAT_TYPE_P (scalar_type)); @@ -4053,11 +4050,10 @@ get_initial_def_for_reduction (gimple *s else { /* Option2: the first element is INIT_VAL. */ - auto_vec<tree, 32> elts (nunits); + tree_vector_builder elts (vectype, 1, 2); elts.quick_push (init_val); - for (i = 1; i < nunits; ++i) - elts.quick_push (def_for_init); - init_def = gimple_build_vector (&stmts, vectype, elts); + elts.quick_push (def_for_init); + init_def = gimple_build_vector (&stmts, &elts); } } break; @@ -4182,7 +4178,7 @@ get_initial_defs_for_reduction (slp_tree number_of_copies = nunits * number_of_vectors / group_size; number_of_places_left_in_vector = nunits; - auto_vec<tree, 32> elts (nunits); + tree_vector_builder elts (vector_type, nunits, 1); elts.quick_grow (nunits); for (j = 0; j < number_of_copies; j++) { @@ -4205,12 +4201,14 @@ get_initial_defs_for_reduction (slp_tree if (number_of_places_left_in_vector == 0) { gimple_seq ctor_seq = NULL; - tree init = gimple_build_vector (&ctor_seq, vector_type, elts); + tree init = gimple_build_vector (&ctor_seq, &elts); if (ctor_seq != NULL) gsi_insert_seq_on_edge_immediate (pe, ctor_seq); voprnds.quick_push (init); number_of_places_left_in_vector = nunits; + elts.new_vector (vector_type, nunits, 1); + elts.quick_grow (nunits); } } } @@ -6698,7 +6696,7 @@ vectorizable_induction (gimple *phi, unsigned ivn; for (ivn = 0; ivn < nivs; ++ivn) { - auto_vec<tree, 32> elts (nunits); + tree_vector_builder elts (vectype, nunits, 1); stmts = NULL; for (unsigned eltn = 0; eltn < nunits; ++eltn) { @@ -6708,7 +6706,7 @@ vectorizable_induction (gimple *phi, elt, step_expr); elts.quick_push (elt); } - vec_init = gimple_build_vector (&stmts, vectype, elts); + vec_init = gimple_build_vector (&stmts, &elts); if (stmts) { new_bb = gsi_insert_seq_on_edge_immediate (pe, stmts); @@ -6815,7 +6813,7 @@ vectorizable_induction (gimple *phi, stmts = NULL; new_name = gimple_convert (&stmts, TREE_TYPE (vectype), init_expr); - auto_vec<tree, 32> elts (nunits); + tree_vector_builder elts (vectype, nunits, 1); elts.quick_push (new_name); for (i = 1; i < nunits; i++) { @@ -6826,7 +6824,7 @@ vectorizable_induction (gimple *phi, } /* Create a vector from [new_name_0, new_name_1, ..., new_name_nunits-1] */ - vec_init = gimple_build_vector (&stmts, vectype, elts); + vec_init = gimple_build_vector (&stmts, &elts); if (stmts) { new_bb = gsi_insert_seq_on_edge_immediate (pe, stmts);