aboutsummaryrefslogtreecommitdiff
path: root/gcc/fold-const.c
diff options
context:
space:
mode:
authorRichard Sandiford <richard.sandiford@linaro.org>2017-09-14 15:46:08 +0000
committerRichard Sandiford <rsandifo@gcc.gnu.org>2017-09-14 15:46:08 +0000
commit794e31808f1554d51f0f0357c3a74a6365f0a274 (patch)
treed491aa520d3a8de4b35dbdde63439716c15b6f8d /gcc/fold-const.c
parent9e822269364f5268b2bdc82530fd6c871f47b1bc (diff)
downloadgcc-794e31808f1554d51f0f0357c3a74a6365f0a274.zip
gcc-794e31808f1554d51f0f0357c3a74a6365f0a274.tar.gz
gcc-794e31808f1554d51f0f0357c3a74a6365f0a274.tar.bz2
Use vec<> in build_vector
This patch makes build_vector take the elements as a vec<> rather than a tree *. This is useful for SVE because it bundles the number of elements with the elements themselves, and enforces the fact that the number is constant. Also, I think things like the folds can be used with any generic GNU vector, not just those that match machine vectors, so the arguments to XALLOCAVEC had no clear limit. 2017-09-14 Richard Sandiford <richard.sandiford@linaro.org> Alan Hayward <alan.hayward@arm.com> David Sherwood <david.sherwood@arm.com> gcc/ * tree.h (build_vector): Take a vec<tree> instead of a tree *. * tree.c (build_vector): Likewise. (build_vector_from_ctor): Update accordingly. (build_vector_from_val): Likewise. * gimple-fold.c (gimple_fold_stmt_to_constant_1): Likewise. * tree-ssa-forwprop.c (simplify_vector_constructor): Likewise. * tree-vect-generic.c (add_rshift): Likewise. (expand_vector_divmod): Likewise. (optimize_vector_constructor): Likewise. * tree-vect-slp.c (vect_get_constant_vectors): Likewise. (vect_transform_slp_perm_load): Likewise. (vect_schedule_slp_instance): Likewise. * tree-vect-stmts.c (vectorizable_bswap): Likewise. (vectorizable_call): Likewise. (vect_gen_perm_mask_any): Likewise. Add elements in order. * expmed.c (make_tree): Likewise. * fold-const.c (fold_negate_expr_1): Use auto_vec<tree> when building a vector passed to build_vector. (fold_convert_const): Likewise. (exact_inverse): Likewise. (fold_ternary_loc): Likewise. (fold_relational_const): Likewise. (const_binop): Likewise. Use VECTOR_CST_ELT directly when operating on VECTOR_CSTs, rather than going through vec_cst_ctor_to_array. (const_unop): Likewise. Store the reduction accumulator in a variable rather than an array. (vec_cst_ctor_to_array): Take the number of elements as a parameter. (fold_vec_perm): Update calls accordingly. Use auto_vec<tree> for the new vector, rather than constructing it after the input arrays. (native_interpret_vector): Use auto_vec<tree> when building a vector passed to build_vector. Add elements in order. * tree-vect-loop.c (get_initial_defs_for_reduction): Use auto_vec<tree> when building a vector passed to build_vector. (vect_create_epilog_for_reduction): Likewise. (vectorizable_induction): Likewise. (get_initial_def_for_reduction): Likewise. Fix indentation of case statements. * config/sparc/sparc.c (sparc_handle_vis_mul8x16): Change n_elts to a vec<tree> *. (sparc_fold_builtin): Use auto_vec<tree> when building a vector passed to build_vector. Co-Authored-By: Alan Hayward <alan.hayward@arm.com> Co-Authored-By: David Sherwood <david.sherwood@arm.com> From-SVN: r252760
Diffstat (limited to 'gcc/fold-const.c')
-rw-r--r--gcc/fold-const.c177
1 files changed, 86 insertions, 91 deletions
diff --git a/gcc/fold-const.c b/gcc/fold-const.c
index 66e7cc7..013081d 100644
--- a/gcc/fold-const.c
+++ b/gcc/fold-const.c
@@ -136,7 +136,6 @@ static tree fold_not_const (const_tree, tree);
static tree fold_relational_const (enum tree_code, tree, tree, tree);
static tree fold_convert_const (enum tree_code, tree, tree);
static tree fold_view_convert_expr (tree, tree);
-static bool vec_cst_ctor_to_array (tree, tree *);
static tree fold_negate_expr (location_t, tree);
@@ -565,13 +564,14 @@ fold_negate_expr_1 (location_t loc, tree t)
case VECTOR_CST:
{
int count = VECTOR_CST_NELTS (t), i;
- tree *elts = XALLOCAVEC (tree, count);
+ auto_vec<tree, 32> elts (count);
for (i = 0; i < count; i++)
{
- elts[i] = fold_negate_expr (loc, VECTOR_CST_ELT (t, i));
- if (elts[i] == NULL_TREE)
+ tree elt = fold_negate_expr (loc, VECTOR_CST_ELT (t, i));
+ if (elt == NULL_TREE)
return NULL_TREE;
+ elts.quick_push (elt);
}
return build_vector (type, elts);
@@ -1414,19 +1414,20 @@ const_binop (enum tree_code code, tree arg1, tree arg2)
{
tree type = TREE_TYPE (arg1);
int count = VECTOR_CST_NELTS (arg1), i;
- tree *elts = XALLOCAVEC (tree, count);
+ auto_vec<tree, 32> elts (count);
for (i = 0; i < count; i++)
{
tree elem1 = VECTOR_CST_ELT (arg1, i);
tree elem2 = VECTOR_CST_ELT (arg2, i);
- elts[i] = const_binop (code, elem1, elem2);
+ tree elt = const_binop (code, elem1, elem2);
/* It is possible that const_binop cannot handle the given
code and return NULL_TREE */
- if (elts[i] == NULL_TREE)
+ if (elt == NULL_TREE)
return NULL_TREE;
+ elts.quick_push (elt);
}
return build_vector (type, elts);
@@ -1438,18 +1439,19 @@ const_binop (enum tree_code code, tree arg1, tree arg2)
{
tree type = TREE_TYPE (arg1);
int count = VECTOR_CST_NELTS (arg1), i;
- tree *elts = XALLOCAVEC (tree, count);
+ auto_vec<tree, 32> elts (count);
for (i = 0; i < count; i++)
{
tree elem1 = VECTOR_CST_ELT (arg1, i);
- elts[i] = const_binop (code, elem1, arg2);
+ tree elt = const_binop (code, elem1, arg2);
/* It is possible that const_binop cannot handle the given
code and return NULL_TREE. */
- if (elts[i] == NULL_TREE)
+ if (elt == NULL_TREE)
return NULL_TREE;
+ elts.quick_push (elt);
}
return build_vector (type, elts);
@@ -1481,7 +1483,6 @@ const_binop (enum tree_code code, tree type, tree arg1, tree arg2)
case VEC_PACK_TRUNC_EXPR:
case VEC_PACK_FIX_TRUNC_EXPR:
{
- tree *elts;
unsigned int out_nelts, in_nelts, i;
if (TREE_CODE (arg1) != VECTOR_CST
@@ -1493,18 +1494,18 @@ const_binop (enum tree_code code, tree type, tree arg1, tree arg2)
gcc_assert (in_nelts == VECTOR_CST_NELTS (arg2)
&& out_nelts == TYPE_VECTOR_SUBPARTS (type));
- elts = XALLOCAVEC (tree, out_nelts);
- if (!vec_cst_ctor_to_array (arg1, elts)
- || !vec_cst_ctor_to_array (arg2, elts + in_nelts))
- return NULL_TREE;
-
+ auto_vec<tree, 32> elts (out_nelts);
for (i = 0; i < out_nelts; i++)
{
- elts[i] = fold_convert_const (code == VEC_PACK_TRUNC_EXPR
- ? NOP_EXPR : FIX_TRUNC_EXPR,
- TREE_TYPE (type), elts[i]);
- if (elts[i] == NULL_TREE || !CONSTANT_CLASS_P (elts[i]))
+ tree elt = (i < in_nelts
+ ? VECTOR_CST_ELT (arg1, i)
+ : VECTOR_CST_ELT (arg2, i - in_nelts));
+ elt = fold_convert_const (code == VEC_PACK_TRUNC_EXPR
+ ? NOP_EXPR : FIX_TRUNC_EXPR,
+ TREE_TYPE (type), elt);
+ if (elt == NULL_TREE || !CONSTANT_CLASS_P (elt))
return NULL_TREE;
+ elts.quick_push (elt);
}
return build_vector (type, elts);
@@ -1516,7 +1517,6 @@ const_binop (enum tree_code code, tree type, tree arg1, tree arg2)
case VEC_WIDEN_MULT_ODD_EXPR:
{
unsigned int out_nelts, in_nelts, out, ofs, scale;
- tree *elts;
if (TREE_CODE (arg1) != VECTOR_CST || TREE_CODE (arg2) != VECTOR_CST)
return NULL_TREE;
@@ -1526,11 +1526,6 @@ const_binop (enum tree_code code, tree type, tree arg1, tree arg2)
gcc_assert (in_nelts == VECTOR_CST_NELTS (arg2)
&& out_nelts == TYPE_VECTOR_SUBPARTS (type));
- elts = XALLOCAVEC (tree, in_nelts * 2);
- if (!vec_cst_ctor_to_array (arg1, elts)
- || !vec_cst_ctor_to_array (arg2, elts + in_nelts))
- return NULL_TREE;
-
if (code == VEC_WIDEN_MULT_LO_EXPR)
scale = 0, ofs = BYTES_BIG_ENDIAN ? out_nelts : 0;
else if (code == VEC_WIDEN_MULT_HI_EXPR)
@@ -1540,20 +1535,21 @@ const_binop (enum tree_code code, tree type, tree arg1, tree arg2)
else /* if (code == VEC_WIDEN_MULT_ODD_EXPR) */
scale = 1, ofs = 1;
+ auto_vec<tree, 32> elts (out_nelts);
for (out = 0; out < out_nelts; out++)
{
- unsigned int in1 = (out << scale) + ofs;
- unsigned int in2 = in1 + in_nelts;
- tree t1, t2;
-
- t1 = fold_convert_const (NOP_EXPR, TREE_TYPE (type), elts[in1]);
- t2 = fold_convert_const (NOP_EXPR, TREE_TYPE (type), elts[in2]);
+ unsigned int in = (out << scale) + ofs;
+ tree t1 = fold_convert_const (NOP_EXPR, TREE_TYPE (type),
+ VECTOR_CST_ELT (arg1, in));
+ tree t2 = fold_convert_const (NOP_EXPR, TREE_TYPE (type),
+ VECTOR_CST_ELT (arg2, in));
if (t1 == NULL_TREE || t2 == NULL_TREE)
return NULL_TREE;
- elts[out] = const_binop (MULT_EXPR, t1, t2);
- if (elts[out] == NULL_TREE || !CONSTANT_CLASS_P (elts[out]))
+ tree elt = const_binop (MULT_EXPR, t1, t2);
+ if (elt == NULL_TREE || !CONSTANT_CLASS_P (elt))
return NULL_TREE;
+ elts.quick_push (elt);
}
return build_vector (type, elts);
@@ -1638,18 +1634,17 @@ const_unop (enum tree_code code, tree type, tree arg0)
/* Perform BIT_NOT_EXPR on each element individually. */
else if (TREE_CODE (arg0) == VECTOR_CST)
{
- tree *elements;
tree elem;
unsigned count = VECTOR_CST_NELTS (arg0), i;
- elements = XALLOCAVEC (tree, count);
+ auto_vec<tree, 32> elements (count);
for (i = 0; i < count; i++)
{
elem = VECTOR_CST_ELT (arg0, i);
elem = const_unop (BIT_NOT_EXPR, TREE_TYPE (type), elem);
if (elem == NULL_TREE)
break;
- elements[i] = elem;
+ elements.quick_push (elem);
}
if (i == count)
return build_vector (type, elements);
@@ -1677,7 +1672,6 @@ const_unop (enum tree_code code, tree type, tree arg0)
case VEC_UNPACK_FLOAT_HI_EXPR:
{
unsigned int out_nelts, in_nelts, i;
- tree *elts;
enum tree_code subcode;
if (TREE_CODE (arg0) != VECTOR_CST)
@@ -1687,24 +1681,24 @@ const_unop (enum tree_code code, tree type, tree arg0)
out_nelts = in_nelts / 2;
gcc_assert (out_nelts == TYPE_VECTOR_SUBPARTS (type));
- elts = XALLOCAVEC (tree, in_nelts);
- if (!vec_cst_ctor_to_array (arg0, elts))
- return NULL_TREE;
-
+ unsigned int offset = 0;
if ((!BYTES_BIG_ENDIAN) ^ (code == VEC_UNPACK_LO_EXPR
|| code == VEC_UNPACK_FLOAT_LO_EXPR))
- elts += out_nelts;
+ offset = out_nelts;
if (code == VEC_UNPACK_LO_EXPR || code == VEC_UNPACK_HI_EXPR)
subcode = NOP_EXPR;
else
subcode = FLOAT_EXPR;
+ auto_vec<tree, 32> elts (out_nelts);
for (i = 0; i < out_nelts; i++)
{
- elts[i] = fold_convert_const (subcode, TREE_TYPE (type), elts[i]);
- if (elts[i] == NULL_TREE || !CONSTANT_CLASS_P (elts[i]))
+ tree elt = fold_convert_const (subcode, TREE_TYPE (type),
+ VECTOR_CST_ELT (arg0, i + offset));
+ if (elt == NULL_TREE || !CONSTANT_CLASS_P (elt))
return NULL_TREE;
+ elts.quick_push (elt);
}
return build_vector (type, elts);
@@ -1715,17 +1709,12 @@ const_unop (enum tree_code code, tree type, tree arg0)
case REDUC_PLUS_EXPR:
{
unsigned int nelts, i;
- tree *elts;
enum tree_code subcode;
if (TREE_CODE (arg0) != VECTOR_CST)
return NULL_TREE;
nelts = VECTOR_CST_NELTS (arg0);
- elts = XALLOCAVEC (tree, nelts);
- if (!vec_cst_ctor_to_array (arg0, elts))
- return NULL_TREE;
-
switch (code)
{
case REDUC_MIN_EXPR: subcode = MIN_EXPR; break;
@@ -1734,14 +1723,15 @@ const_unop (enum tree_code code, tree type, tree arg0)
default: gcc_unreachable ();
}
+ tree res = VECTOR_CST_ELT (arg0, 0);
for (i = 1; i < nelts; i++)
{
- elts[0] = const_binop (subcode, elts[0], elts[i]);
- if (elts[0] == NULL_TREE || !CONSTANT_CLASS_P (elts[0]))
+ res = const_binop (subcode, res, VECTOR_CST_ELT (arg0, i));
+ if (res == NULL_TREE || !CONSTANT_CLASS_P (res))
return NULL_TREE;
}
- return elts[0];
+ return res;
}
default:
@@ -2163,14 +2153,14 @@ fold_convert_const (enum tree_code code, tree type, tree arg1)
{
int len = VECTOR_CST_NELTS (arg1);
tree elttype = TREE_TYPE (type);
- tree *v = XALLOCAVEC (tree, len);
+ auto_vec<tree, 32> v (len);
for (int i = 0; i < len; ++i)
{
tree elt = VECTOR_CST_ELT (arg1, i);
tree cvt = fold_convert_const (code, elttype, elt);
if (cvt == NULL_TREE)
return NULL_TREE;
- v[i] = cvt;
+ v.quick_push (cvt);
}
return build_vector (type, v);
}
@@ -7392,7 +7382,6 @@ native_interpret_vector (tree type, const unsigned char *ptr, int len)
{
tree etype, elem;
int i, size, count;
- tree *elements;
etype = TREE_TYPE (type);
size = GET_MODE_SIZE (SCALAR_TYPE_MODE (etype));
@@ -7400,13 +7389,13 @@ native_interpret_vector (tree type, const unsigned char *ptr, int len)
if (size * count > len)
return NULL_TREE;
- elements = XALLOCAVEC (tree, count);
- for (i = count - 1; i >= 0; i--)
+ auto_vec<tree, 32> elements (count);
+ for (i = 0; i < count; ++i)
{
elem = native_interpret_expr (etype, ptr+(i*size), size);
if (!elem)
return NULL_TREE;
- elements[i] = elem;
+ elements.quick_push (elem);
}
return build_vector (type, elements);
}
@@ -8761,12 +8750,13 @@ fold_mult_zconjz (location_t loc, tree type, tree expr)
/* Helper function for fold_vec_perm. Store elements of VECTOR_CST or
- CONSTRUCTOR ARG into array ELTS and return true if successful. */
+ CONSTRUCTOR ARG into array ELTS, which has NELTS elements, and return
+ true if successful. */
static bool
-vec_cst_ctor_to_array (tree arg, tree *elts)
+vec_cst_ctor_to_array (tree arg, unsigned int nelts, tree *elts)
{
- unsigned int nelts = TYPE_VECTOR_SUBPARTS (TREE_TYPE (arg)), i;
+ unsigned int i;
if (TREE_CODE (arg) == VECTOR_CST)
{
@@ -8799,7 +8789,6 @@ static tree
fold_vec_perm (tree type, tree arg0, tree arg1, const unsigned char *sel)
{
unsigned int nelts = TYPE_VECTOR_SUBPARTS (type), i;
- tree *elts;
bool need_ctor = false;
gcc_assert (TYPE_VECTOR_SUBPARTS (TREE_TYPE (arg0)) == nelts
@@ -8808,16 +8797,17 @@ fold_vec_perm (tree type, tree arg0, tree arg1, const unsigned char *sel)
|| TREE_TYPE (TREE_TYPE (arg1)) != TREE_TYPE (type))
return NULL_TREE;
- elts = XALLOCAVEC (tree, nelts * 3);
- if (!vec_cst_ctor_to_array (arg0, elts)
- || !vec_cst_ctor_to_array (arg1, elts + nelts))
+ tree *in_elts = XALLOCAVEC (tree, nelts * 2);
+ if (!vec_cst_ctor_to_array (arg0, nelts, in_elts)
+ || !vec_cst_ctor_to_array (arg1, nelts, in_elts + nelts))
return NULL_TREE;
+ auto_vec<tree, 32> out_elts (nelts);
for (i = 0; i < nelts; i++)
{
- if (!CONSTANT_CLASS_P (elts[sel[i]]))
+ if (!CONSTANT_CLASS_P (in_elts[sel[i]]))
need_ctor = true;
- elts[i + 2 * nelts] = unshare_expr (elts[sel[i]]);
+ out_elts.quick_push (unshare_expr (in_elts[sel[i]]));
}
if (need_ctor)
@@ -8825,11 +8815,11 @@ fold_vec_perm (tree type, tree arg0, tree arg1, const unsigned char *sel)
vec<constructor_elt, va_gc> *v;
vec_alloc (v, nelts);
for (i = 0; i < nelts; i++)
- CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, elts[2 * nelts + i]);
+ CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, out_elts[i]);
return build_constructor (type, v);
}
else
- return build_vector (type, &elts[2 * nelts]);
+ return build_vector (type, out_elts);
}
/* Try to fold a pointer difference of type TYPE two address expressions of
@@ -8879,7 +8869,7 @@ tree
exact_inverse (tree type, tree cst)
{
REAL_VALUE_TYPE r;
- tree unit_type, *elts;
+ tree unit_type;
machine_mode mode;
unsigned vec_nelts, i;
@@ -8894,20 +8884,22 @@ exact_inverse (tree type, tree cst)
return NULL_TREE;
case VECTOR_CST:
- vec_nelts = VECTOR_CST_NELTS (cst);
- elts = XALLOCAVEC (tree, vec_nelts);
- unit_type = TREE_TYPE (type);
- mode = TYPE_MODE (unit_type);
+ {
+ vec_nelts = VECTOR_CST_NELTS (cst);
+ unit_type = TREE_TYPE (type);
+ mode = TYPE_MODE (unit_type);
- for (i = 0; i < vec_nelts; i++)
- {
- r = TREE_REAL_CST (VECTOR_CST_ELT (cst, i));
- if (!exact_real_inverse (mode, &r))
- return NULL_TREE;
- elts[i] = build_real (unit_type, r);
- }
+ auto_vec<tree, 32> elts (vec_nelts);
+ for (i = 0; i < vec_nelts; i++)
+ {
+ r = TREE_REAL_CST (VECTOR_CST_ELT (cst, i));
+ if (!exact_real_inverse (mode, &r))
+ return NULL_TREE;
+ elts.quick_push (build_real (unit_type, r));
+ }
- return build_vector (type, elts);
+ return build_vector (type, elts);
+ }
default:
return NULL_TREE;
@@ -11596,9 +11588,9 @@ fold_ternary_loc (location_t loc, enum tree_code code, tree type,
if (n == 1)
return VECTOR_CST_ELT (arg0, idx);
- tree *vals = XALLOCAVEC (tree, n);
+ auto_vec<tree, 32> vals (n);
for (unsigned i = 0; i < n; ++i)
- vals[i] = VECTOR_CST_ELT (arg0, idx + i);
+ vals.quick_push (VECTOR_CST_ELT (arg0, idx + i));
return build_vector (type, vals);
}
}
@@ -11731,10 +11723,10 @@ fold_ternary_loc (location_t loc, enum tree_code code, tree type,
if (need_mask_canon && arg2 == op2)
{
- tree *tsel = XALLOCAVEC (tree, nelts);
tree eltype = TREE_TYPE (TREE_TYPE (arg2));
+ auto_vec<tree, 32> tsel (nelts);
for (i = 0; i < nelts; i++)
- tsel[i] = build_int_cst (eltype, sel[i]);
+ tsel.quick_push (build_int_cst (eltype, sel[i]));
op2 = build_vector (TREE_TYPE (arg2), tsel);
changed = true;
}
@@ -11775,8 +11767,10 @@ fold_ternary_loc (location_t loc, enum tree_code code, tree type,
else
{
unsigned int nelts = VECTOR_CST_NELTS (arg0);
- tree *elts = XALLOCAVEC (tree, nelts);
- memcpy (elts, VECTOR_CST_ELTS (arg0), sizeof (tree) * nelts);
+ auto_vec<tree, 32> elts (nelts);
+ elts.quick_grow (nelts);
+ memcpy (&elts[0], VECTOR_CST_ELTS (arg0),
+ sizeof (tree) * nelts);
elts[k] = arg1;
return build_vector (type, elts);
}
@@ -13894,10 +13888,10 @@ fold_relational_const (enum tree_code code, tree type, tree op0, tree op1)
return constant_boolean_node (true, type);
}
unsigned count = VECTOR_CST_NELTS (op0);
- tree *elts = XALLOCAVEC (tree, count);
gcc_assert (VECTOR_CST_NELTS (op1) == count
&& TYPE_VECTOR_SUBPARTS (type) == count);
+ auto_vec<tree, 32> elts (count);
for (unsigned i = 0; i < count; i++)
{
tree elem_type = TREE_TYPE (type);
@@ -13910,7 +13904,8 @@ fold_relational_const (enum tree_code code, tree type, tree op0, tree op1)
if (tem == NULL_TREE)
return NULL_TREE;
- elts[i] = build_int_cst (elem_type, integer_zerop (tem) ? 0 : -1);
+ elts.quick_push (build_int_cst (elem_type,
+ integer_zerop (tem) ? 0 : -1));
}
return build_vector (type, elts);