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
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;
}
}
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;
gcc_unreachable ();
}
+ if (stmts)
+ gsi_insert_seq_on_edge_immediate (loop_preheader_edge (loop), stmts);
return init_def;
}
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;
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);
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)
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:
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++)
&& 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;
}
}
}
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
/* 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)
{
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;
/* 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,
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_");
}
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);
}