Add gimple_build_vector* helpers
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. 2017-09-14 Richard Sandiford <richard.sandiford@linaro.org> Alan Hayward <alan.hayward@arm.com> David Sherwood <david.sherwood@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. Co-Authored-By: Alan Hayward <alan.hayward@arm.com> Co-Authored-By: David Sherwood <david.sherwood@arm.com> From-SVN: r252762
This commit is contained in:
parent
908a1a166d
commit
e7c45b6600
@ -1,3 +1,21 @@
|
||||
2017-09-14 Richard Sandiford <richard.sandiford@linaro.org>
|
||||
Alan Hayward <alan.hayward@arm.com>
|
||||
David Sherwood <david.sherwood@arm.com>
|
||||
|
||||
* 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.
|
||||
|
||||
2017-09-14 Richard Sandiford <richard.sandiford@linaro.org>
|
||||
Alan Hayward <alan.hayward@arm.com>
|
||||
David Sherwood <david.sherwood@arm.com>
|
||||
|
@ -7058,6 +7058,58 @@ gimple_convert_to_ptrofftype (gimple_seq *seq, location_t loc, tree op)
|
||||
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
|
||||
|
@ -127,6 +127,21 @@ gimple_convert_to_ptrofftype (gimple_seq *seq, tree op)
|
||||
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);
|
||||
|
||||
|
@ -4044,33 +4044,18 @@ get_initial_def_for_reduction (gimple *stmt, tree init_val,
|
||||
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 *stmt, tree init_val,
|
||||
}
|
||||
}
|
||||
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 *stmt, tree init_val,
|
||||
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 slp_node,
|
||||
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 slp_node,
|
||||
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 slp_node,
|
||||
|
||||
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 slp_node,
|
||||
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 slp_node,
|
||||
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 slp_node,
|
||||
&& 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 slp_node,
|
||||
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<tree> vect_defs, gimple *stmt,
|
||||
/* 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_finalize_reduction:
|
||||
{
|
||||
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_finalize_reduction:
|
||||
/* 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);
|
||||
}
|
||||
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user