Commit abe73c3d by Richard Sandiford Committed by Richard Sandiford

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  <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.

From-SVN: r255478
parent b3def403
2017-12-07 Richard Sandiford <richard.sandiford@linaro.org> 2017-12-07 Richard Sandiford <richard.sandiford@linaro.org>
* 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 <richard.sandiford@linaro.org>
* tree-vector-builder.h * tree-vector-builder.h
(tree_vector_builder::new_binary_operation): Declare. (tree_vector_builder::new_binary_operation): Declare.
* tree-vector-builder.c * tree-vector-builder.c
...@@ -7178,23 +7178,30 @@ gimple_build_vector_from_val (gimple_seq *seq, location_t loc, tree type, ...@@ -7178,23 +7178,30 @@ gimple_build_vector_from_val (gimple_seq *seq, location_t loc, tree type,
return res; return res;
} }
/* Build a vector of type TYPE in which the elements have the values /* Build a vector from BUILDER, handling the case in which some elements
given by ELTS. Return a gimple value for the result, appending any are non-constant. Return a gimple value for the result, appending any
new instructions to SEQ. */ 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 tree
gimple_build_vector (gimple_seq *seq, location_t loc, tree type, gimple_build_vector (gimple_seq *seq, location_t loc,
vec<tree> elts) tree_vector_builder *builder)
{ {
unsigned int nelts = elts.length (); gcc_assert (builder->nelts_per_pattern () <= 2);
gcc_assert (nelts == TYPE_VECTOR_SUBPARTS (type)); unsigned int encoded_nelts = builder->encoded_nelts ();
for (unsigned int i = 0; i < nelts; ++i) for (unsigned int i = 0; i < encoded_nelts; ++i)
if (!TREE_CONSTANT (elts[i])) if (!TREE_CONSTANT ((*builder)[i]))
{ {
tree type = builder->type ();
unsigned int nelts = TYPE_VECTOR_SUBPARTS (type);
vec<constructor_elt, va_gc> *v; vec<constructor_elt, va_gc> *v;
vec_alloc (v, nelts); vec_alloc (v, nelts);
for (i = 0; i < nelts; ++i) 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; tree res;
if (gimple_in_ssa_p (cfun)) if (gimple_in_ssa_p (cfun))
...@@ -7206,7 +7213,7 @@ gimple_build_vector (gimple_seq *seq, location_t loc, tree type, ...@@ -7206,7 +7213,7 @@ gimple_build_vector (gimple_seq *seq, location_t loc, tree type,
gimple_seq_add_stmt_without_update (seq, stmt); gimple_seq_add_stmt_without_update (seq, stmt);
return res; return res;
} }
return build_vector (type, elts); return builder->build ();
} }
/* Return true if the result of assignment STMT is known to be non-negative. /* Return true if the result of assignment STMT is known to be non-negative.
......
...@@ -135,11 +135,13 @@ gimple_build_vector_from_val (gimple_seq *seq, tree type, tree op) ...@@ -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); 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 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); extern bool gimple_stmt_nonnegative_warnv_p (gimple *, bool *, int = 0);
......
...@@ -3978,11 +3978,9 @@ get_initial_def_for_reduction (gimple *stmt, tree init_val, ...@@ -3978,11 +3978,9 @@ get_initial_def_for_reduction (gimple *stmt, tree init_val,
struct loop *loop = LOOP_VINFO_LOOP (loop_vinfo); struct loop *loop = LOOP_VINFO_LOOP (loop_vinfo);
tree scalar_type = TREE_TYPE (init_val); tree scalar_type = TREE_TYPE (init_val);
tree vectype = get_vectype_for_scalar_type (scalar_type); tree vectype = get_vectype_for_scalar_type (scalar_type);
int nunits;
enum tree_code code = gimple_assign_rhs_code (stmt); enum tree_code code = gimple_assign_rhs_code (stmt);
tree def_for_init; tree def_for_init;
tree init_def; tree init_def;
int i;
bool nested_in_vect_loop = false; bool nested_in_vect_loop = false;
REAL_VALUE_TYPE real_init_val = dconst0; REAL_VALUE_TYPE real_init_val = dconst0;
int int_init_val = 0; int int_init_val = 0;
...@@ -3990,7 +3988,6 @@ get_initial_def_for_reduction (gimple *stmt, tree init_val, ...@@ -3990,7 +3988,6 @@ get_initial_def_for_reduction (gimple *stmt, tree init_val,
gimple_seq stmts = NULL; gimple_seq stmts = NULL;
gcc_assert (vectype); gcc_assert (vectype);
nunits = TYPE_VECTOR_SUBPARTS (vectype);
gcc_assert (POINTER_TYPE_P (scalar_type) || INTEGRAL_TYPE_P (scalar_type) gcc_assert (POINTER_TYPE_P (scalar_type) || INTEGRAL_TYPE_P (scalar_type)
|| SCALAR_FLOAT_TYPE_P (scalar_type)); || SCALAR_FLOAT_TYPE_P (scalar_type));
...@@ -4063,11 +4060,10 @@ get_initial_def_for_reduction (gimple *stmt, tree init_val, ...@@ -4063,11 +4060,10 @@ get_initial_def_for_reduction (gimple *stmt, tree init_val,
else else
{ {
/* Option2: the first element is INIT_VAL. */ /* 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); elts.quick_push (init_val);
for (i = 1; i < nunits; ++i) elts.quick_push (def_for_init);
elts.quick_push (def_for_init); init_def = gimple_build_vector (&stmts, &elts);
init_def = gimple_build_vector (&stmts, vectype, elts);
} }
} }
break; break;
...@@ -4192,7 +4188,7 @@ get_initial_defs_for_reduction (slp_tree slp_node, ...@@ -4192,7 +4188,7 @@ get_initial_defs_for_reduction (slp_tree slp_node,
number_of_copies = nunits * number_of_vectors / group_size; number_of_copies = nunits * number_of_vectors / group_size;
number_of_places_left_in_vector = nunits; 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); elts.quick_grow (nunits);
for (j = 0; j < number_of_copies; j++) for (j = 0; j < number_of_copies; j++)
{ {
...@@ -4215,12 +4211,14 @@ get_initial_defs_for_reduction (slp_tree slp_node, ...@@ -4215,12 +4211,14 @@ get_initial_defs_for_reduction (slp_tree slp_node,
if (number_of_places_left_in_vector == 0) if (number_of_places_left_in_vector == 0)
{ {
gimple_seq ctor_seq = NULL; 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) if (ctor_seq != NULL)
gsi_insert_seq_on_edge_immediate (pe, ctor_seq); gsi_insert_seq_on_edge_immediate (pe, ctor_seq);
voprnds.quick_push (init); voprnds.quick_push (init);
number_of_places_left_in_vector = nunits; 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, ...@@ -6708,7 +6706,7 @@ vectorizable_induction (gimple *phi,
unsigned ivn; unsigned ivn;
for (ivn = 0; ivn < nivs; ++ivn) for (ivn = 0; ivn < nivs; ++ivn)
{ {
auto_vec<tree, 32> elts (nunits); tree_vector_builder elts (vectype, nunits, 1);
stmts = NULL; stmts = NULL;
for (unsigned eltn = 0; eltn < nunits; ++eltn) for (unsigned eltn = 0; eltn < nunits; ++eltn)
{ {
...@@ -6718,7 +6716,7 @@ vectorizable_induction (gimple *phi, ...@@ -6718,7 +6716,7 @@ vectorizable_induction (gimple *phi,
elt, step_expr); elt, step_expr);
elts.quick_push (elt); elts.quick_push (elt);
} }
vec_init = gimple_build_vector (&stmts, vectype, elts); vec_init = gimple_build_vector (&stmts, &elts);
if (stmts) if (stmts)
{ {
new_bb = gsi_insert_seq_on_edge_immediate (pe, stmts); new_bb = gsi_insert_seq_on_edge_immediate (pe, stmts);
...@@ -6825,7 +6823,7 @@ vectorizable_induction (gimple *phi, ...@@ -6825,7 +6823,7 @@ vectorizable_induction (gimple *phi,
stmts = NULL; stmts = NULL;
new_name = gimple_convert (&stmts, TREE_TYPE (vectype), init_expr); 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); elts.quick_push (new_name);
for (i = 1; i < nunits; i++) for (i = 1; i < nunits; i++)
{ {
...@@ -6836,7 +6834,7 @@ vectorizable_induction (gimple *phi, ...@@ -6836,7 +6834,7 @@ vectorizable_induction (gimple *phi,
} }
/* Create a vector from [new_name_0, new_name_1, ..., /* Create a vector from [new_name_0, new_name_1, ...,
new_name_nunits-1] */ new_name_nunits-1] */
vec_init = gimple_build_vector (&stmts, vectype, elts); vec_init = gimple_build_vector (&stmts, &elts);
if (stmts) if (stmts)
{ {
new_bb = gsi_insert_seq_on_edge_immediate (pe, stmts); new_bb = gsi_insert_seq_on_edge_immediate (pe, stmts);
......
...@@ -96,6 +96,16 @@ tree_vector_builder::new_binary_operation (tree type, tree t1, tree t2, ...@@ -96,6 +96,16 @@ tree_vector_builder::new_binary_operation (tree type, tree t1, tree t2,
return true; 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. */ /* Return a VECTOR_CST for the current constant. */
tree tree
......
...@@ -45,6 +45,7 @@ private: ...@@ -45,6 +45,7 @@ private:
bool allow_steps_p () const; bool allow_steps_p () const;
bool integral_p (const_tree) const; bool integral_p (const_tree) const;
wide_int step (const_tree, 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; bool can_elide_p (const_tree) const;
void note_representative (tree *, tree); void note_representative (tree *, tree);
......
...@@ -68,6 +68,10 @@ along with GCC; see the file COPYING3. If not see ...@@ -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 given integral_p (ELT1) && integral_p (ELT2). There is no fixed
choice of StepType. 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; bool can_elide_p (T elt) const;
Return true if we can drop element ELT, even if the retained Return true if we can drop element ELT, even if the retained
...@@ -91,6 +95,7 @@ public: ...@@ -91,6 +95,7 @@ public:
unsigned int nelts_per_pattern () const { return m_nelts_per_pattern; } unsigned int nelts_per_pattern () const { return m_nelts_per_pattern; }
unsigned int encoded_nelts () const; unsigned int encoded_nelts () const;
bool encoded_full_vector_p () const; bool encoded_full_vector_p () const;
T elt (unsigned int) const;
void finalize (); void finalize ();
...@@ -163,6 +168,38 @@ vector_builder<T, Derived>::new_vector (unsigned int full_nelts, ...@@ -163,6 +168,38 @@ vector_builder<T, Derived>::new_vector (unsigned int full_nelts,
this->truncate (0); 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, /* Change the encoding to NPATTERNS patterns of NELTS_PER_PATTERN each,
but without changing the underlying vector. */ but without changing the underlying vector. */
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment