From: Richard Sandiford Date: Thu, 7 Dec 2017 18:41:59 +0000 (+0000) Subject: Make gimple_build_vector take a tree_vector_builder X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=abe73c3d32b68809628eaa3266bf98cb7352851c;p=gcc.git Make gimple_build_vector take a tree_vector_builder This patch changes gimple_build_vector so that it takes a tree_vector_builder instead of a size and a vector of trees. 2017-12-07 Richard Sandiford 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. From-SVN: r255478 --- diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 6fb51605354..d7954ff8fc6 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,20 @@ +2017-12-07 Richard Sandiford + + * 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. + 2017-12-07 Richard Sandiford * tree-vector-builder.h diff --git a/gcc/gimple-fold.c b/gcc/gimple-fold.c index 6044092412c..24f7e76228b 100644 --- a/gcc/gimple-fold.c +++ b/gcc/gimple-fold.c @@ -7178,23 +7178,30 @@ gimple_build_vector_from_val (gimple_seq *seq, location_t loc, tree type, 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 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 *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, location_t loc, tree type, 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. diff --git a/gcc/gimple-fold.h b/gcc/gimple-fold.h index ddbc4f0a7c5..83babfa4fd5 100644 --- a/gcc/gimple-fold.h +++ b/gcc/gimple-fold.h @@ -135,11 +135,13 @@ 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); +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 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); diff --git a/gcc/tree-vect-loop.c b/gcc/tree-vect-loop.c index 566e2a6c3e7..1759655fd07 100644 --- a/gcc/tree-vect-loop.c +++ b/gcc/tree-vect-loop.c @@ -3978,11 +3978,9 @@ get_initial_def_for_reduction (gimple *stmt, tree init_val, 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; @@ -3990,7 +3988,6 @@ get_initial_def_for_reduction (gimple *stmt, tree init_val, 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)); @@ -4063,11 +4060,10 @@ get_initial_def_for_reduction (gimple *stmt, tree init_val, else { /* Option2: the first element is INIT_VAL. */ - auto_vec 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; @@ -4192,7 +4188,7 @@ get_initial_defs_for_reduction (slp_tree slp_node, number_of_copies = nunits * number_of_vectors / group_size; number_of_places_left_in_vector = nunits; - auto_vec elts (nunits); + tree_vector_builder elts (vector_type, nunits, 1); elts.quick_grow (nunits); for (j = 0; j < number_of_copies; j++) { @@ -4215,12 +4211,14 @@ get_initial_defs_for_reduction (slp_tree slp_node, 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); } } } @@ -6708,7 +6706,7 @@ vectorizable_induction (gimple *phi, unsigned ivn; for (ivn = 0; ivn < nivs; ++ivn) { - auto_vec elts (nunits); + tree_vector_builder elts (vectype, nunits, 1); stmts = NULL; for (unsigned eltn = 0; eltn < nunits; ++eltn) { @@ -6718,7 +6716,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); @@ -6825,7 +6823,7 @@ vectorizable_induction (gimple *phi, stmts = NULL; new_name = gimple_convert (&stmts, TREE_TYPE (vectype), init_expr); - auto_vec elts (nunits); + tree_vector_builder elts (vectype, nunits, 1); elts.quick_push (new_name); for (i = 1; i < nunits; i++) { @@ -6836,7 +6834,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); diff --git a/gcc/tree-vector-builder.c b/gcc/tree-vector-builder.c index a8a98970f37..954dbcd7215 100644 --- a/gcc/tree-vector-builder.c +++ b/gcc/tree-vector-builder.c @@ -96,6 +96,16 @@ tree_vector_builder::new_binary_operation (tree type, tree t1, tree t2, 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 diff --git a/gcc/tree-vector-builder.h b/gcc/tree-vector-builder.h index b89d3ab3af6..1038be77c15 100644 --- a/gcc/tree-vector-builder.h +++ b/gcc/tree-vector-builder.h @@ -45,6 +45,7 @@ private: 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); diff --git a/gcc/vector-builder.h b/gcc/vector-builder.h index ae30b3bba2f..0edd6f5c092 100644 --- a/gcc/vector-builder.h +++ b/gcc/vector-builder.h @@ -68,6 +68,10 @@ along with GCC; see the file COPYING3. If not see 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 @@ public: 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::new_vector (unsigned int full_nelts, this->truncate (0); } +/* Return the value of vector element I, which might or might not be + encoded explicitly. */ + +template +T +vector_builder::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. */