summaryrefslogtreecommitdiff
path: root/gcc/fold-const.c
diff options
context:
space:
mode:
authorrsandifo <rsandifo@138bc75d-0d04-0410-961f-82ee72b054a4>2018-01-03 21:42:12 +0000
committerrsandifo <rsandifo@138bc75d-0d04-0410-961f-82ee72b054a4>2018-01-03 21:42:12 +0000
commitf08ee65f2a9a4e115b710b90cb3c390acd40b607 (patch)
tree88cbf9a40cb8344238ea471bb4c046691b5a1e40 /gcc/fold-const.c
parent8b22192765da1da9bb05609218c55c7f03d1a3d3 (diff)
downloadgcc-f08ee65f2a9a4e115b710b90cb3c390acd40b607.tar.gz
poly_int: TYPE_VECTOR_SUBPARTS
This patch changes TYPE_VECTOR_SUBPARTS to a poly_uint64. The value is encoded in the 10-bit precision field and was previously always stored as a simple log2 value. The challenge was to use this 10 bits to encode the number of elements in variable-length vectors, so that we didn't need to increase the size of the tree. In practice the number of vector elements should always have the form N + N * X (where X is the runtime value), and as for constant-length vectors, N must be a power of 2 (even though X itself might not be). The patch therefore uses the low 8 bits to encode log2(N) and bit 8 to select between constant-length and variable-length vectors. Targets without variable-length vectors continue to use the old scheme. A new valid_vector_subparts_p function tests whether a given number of elements can be encoded. This is false for the vector modes that represent an LD3 or ST3 vector triple (which we want to treat as arrays of vectors rather than single vectors). Most of the patch is mechanical; previous patches handled the changes that weren't entirely straightforward. 2018-01-03 Richard Sandiford <richard.sandiford@linaro.org> Alan Hayward <alan.hayward@arm.com> David Sherwood <david.sherwood@arm.com> gcc/ * tree.h (TYPE_VECTOR_SUBPARTS): Turn into a function and handle polynomial numbers of units. (SET_TYPE_VECTOR_SUBPARTS): Likewise. (valid_vector_subparts_p): New function. (build_vector_type): Remove temporary shim and take the number of units as a poly_uint64 rather than an int. (build_opaque_vector_type): Take the number of units as a poly_uint64 rather than an int. * tree.c (build_vector_from_ctor): Handle polynomial TYPE_VECTOR_SUBPARTS. (type_hash_canon_hash, type_cache_hasher::equal): Likewise. (uniform_vector_p, vector_type_mode, build_vector): Likewise. (build_vector_from_val): If the number of units is variable, use build_vec_duplicate_cst for constant operands and VEC_DUPLICATE_EXPR otherwise. (make_vector_type): Remove temporary is_constant (). (build_vector_type, build_opaque_vector_type): Take the number of units as a poly_uint64 rather than an int. (check_vector_cst): Handle polynomial TYPE_VECTOR_SUBPARTS and VECTOR_CST_NELTS. * cfgexpand.c (expand_debug_expr): Likewise. * expr.c (count_type_elements, categorize_ctor_elements_1): Likewise. (store_constructor, expand_expr_real_1): Likewise. (const_scalar_mask_from_tree): Likewise. * fold-const-call.c (fold_const_reduction): Likewise. * fold-const.c (const_binop, const_unop, fold_convert_const): Likewise. (operand_equal_p, fold_vec_perm, fold_ternary_loc): Likewise. (native_encode_vector, vec_cst_ctor_to_array): Likewise. (fold_relational_const): Likewise. (native_interpret_vector): Likewise. Change the size from an int to an unsigned int. * gimple-fold.c (gimple_fold_stmt_to_constant_1): Handle polynomial TYPE_VECTOR_SUBPARTS. (gimple_fold_indirect_ref, gimple_build_vector): Likewise. (gimple_build_vector_from_val): Use VEC_DUPLICATE_EXPR when duplicating a non-constant operand into a variable-length vector. * hsa-brig.c (hsa_op_immed::emit_to_buffer): Handle polynomial TYPE_VECTOR_SUBPARTS and VECTOR_CST_NELTS. * ipa-icf.c (sem_variable::equals): Likewise. * match.pd: Likewise. * omp-simd-clone.c (simd_clone_subparts): Likewise. * print-tree.c (print_node): Likewise. * stor-layout.c (layout_type): Likewise. * targhooks.c (default_builtin_vectorization_cost): Likewise. * tree-cfg.c (verify_gimple_comparison): Likewise. (verify_gimple_assign_binary): Likewise. (verify_gimple_assign_ternary): Likewise. (verify_gimple_assign_single): Likewise. * tree-pretty-print.c (dump_generic_node): Likewise. * tree-ssa-forwprop.c (simplify_vector_constructor): Likewise. (simplify_bitfield_ref, is_combined_permutation_identity): Likewise. * tree-vect-data-refs.c (vect_permute_store_chain): Likewise. (vect_grouped_load_supported, vect_permute_load_chain): Likewise. (vect_shift_permute_load_chain): Likewise. * tree-vect-generic.c (nunits_for_known_piecewise_op): Likewise. (expand_vector_condition, optimize_vector_constructor): Likewise. (lower_vec_perm, get_compute_type): Likewise. * tree-vect-loop.c (vect_determine_vectorization_factor): Likewise. (get_initial_defs_for_reduction, vect_transform_loop): Likewise. * tree-vect-patterns.c (vect_recog_bool_pattern): Likewise. (vect_recog_mask_conversion_pattern): Likewise. * tree-vect-slp.c (vect_supported_load_permutation_p): Likewise. (vect_get_constant_vectors, vect_transform_slp_perm_load): Likewise. * tree-vect-stmts.c (perm_mask_for_reverse): Likewise. (get_group_load_store_type, vectorizable_mask_load_store): Likewise. (vectorizable_bswap, simd_clone_subparts, vectorizable_assignment) (vectorizable_shift, vectorizable_operation, vectorizable_store) (vectorizable_load, vect_is_simple_cond, vectorizable_comparison) (supportable_widening_operation): Likewise. (supportable_narrowing_operation): Likewise. * tree-vector-builder.c (tree_vector_builder::binary_encoded_nelts): Likewise. * varasm.c (output_constant): Likewise. gcc/ada/ * gcc-interface/utils.c (gnat_types_compatible_p): Handle polynomial TYPE_VECTOR_SUBPARTS. gcc/brig/ * brigfrontend/brig-to-generic.cc (get_unsigned_int_type): Handle polynomial TYPE_VECTOR_SUBPARTS. * brigfrontend/brig-util.h (gccbrig_type_vector_subparts): Likewise. gcc/c-family/ * c-common.c (vector_types_convertible_p, c_build_vec_perm_expr) (convert_vector_to_array_for_subscript): Handle polynomial TYPE_VECTOR_SUBPARTS. (c_common_type_for_mode): Check valid_vector_subparts_p. * c-pretty-print.c (pp_c_initializer_list): Handle polynomial VECTOR_CST_NELTS. gcc/c/ * c-typeck.c (comptypes_internal, build_binary_op): Handle polynomial TYPE_VECTOR_SUBPARTS. gcc/cp/ * constexpr.c (cxx_eval_array_reference): Handle polynomial VECTOR_CST_NELTS. (cxx_fold_indirect_ref): Handle polynomial TYPE_VECTOR_SUBPARTS. * call.c (build_conditional_expr_1): Likewise. * decl.c (cp_finish_decomp): Likewise. * mangle.c (write_type): Likewise. * typeck.c (structural_comptypes): Likewise. (cp_build_binary_op): Likewise. * typeck2.c (process_init_constructor_array): Likewise. gcc/fortran/ * trans-types.c (gfc_type_for_mode): Check valid_vector_subparts_p. gcc/lto/ * lto-lang.c (lto_type_for_mode): Check valid_vector_subparts_p. * lto.c (hash_canonical_type): Handle polynomial TYPE_VECTOR_SUBPARTS. gcc/go/ * go-lang.c (go_langhook_type_for_mode): Check valid_vector_subparts_p. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@256197 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/fold-const.c')
-rw-r--r--gcc/fold-const.c90
1 files changed, 51 insertions, 39 deletions
diff --git a/gcc/fold-const.c b/gcc/fold-const.c
index 9f558e26c80..eabaa4a08a8 100644
--- a/gcc/fold-const.c
+++ b/gcc/fold-const.c
@@ -1500,8 +1500,8 @@ const_binop (enum tree_code code, tree arg1, tree arg2)
if (TREE_CODE (arg1) == VECTOR_CST
&& TREE_CODE (arg2) == VECTOR_CST
- && (TYPE_VECTOR_SUBPARTS (TREE_TYPE (arg1))
- == TYPE_VECTOR_SUBPARTS (TREE_TYPE (arg2))))
+ && known_eq (TYPE_VECTOR_SUBPARTS (TREE_TYPE (arg1)),
+ TYPE_VECTOR_SUBPARTS (TREE_TYPE (arg2))))
{
tree type = TREE_TYPE (arg1);
bool step_ok_p;
@@ -1617,16 +1617,18 @@ const_binop (enum tree_code code, tree type, tree arg1, tree arg2)
case VEC_PACK_TRUNC_EXPR:
case VEC_PACK_FIX_TRUNC_EXPR:
{
- unsigned int out_nelts, in_nelts, i;
+ unsigned int HOST_WIDE_INT out_nelts, in_nelts, i;
if (TREE_CODE (arg1) != VECTOR_CST
|| TREE_CODE (arg2) != VECTOR_CST)
return NULL_TREE;
- in_nelts = VECTOR_CST_NELTS (arg1);
+ if (!VECTOR_CST_NELTS (arg1).is_constant (&in_nelts))
+ return NULL_TREE;
+
out_nelts = in_nelts * 2;
- gcc_assert (in_nelts == VECTOR_CST_NELTS (arg2)
- && out_nelts == TYPE_VECTOR_SUBPARTS (type));
+ gcc_assert (known_eq (in_nelts, VECTOR_CST_NELTS (arg2))
+ && known_eq (out_nelts, TYPE_VECTOR_SUBPARTS (type)));
tree_vector_builder elts (type, out_nelts, 1);
for (i = 0; i < out_nelts; i++)
@@ -1650,15 +1652,16 @@ const_binop (enum tree_code code, tree type, tree arg1, tree arg2)
case VEC_WIDEN_MULT_EVEN_EXPR:
case VEC_WIDEN_MULT_ODD_EXPR:
{
- unsigned int out_nelts, in_nelts, out, ofs, scale;
+ unsigned HOST_WIDE_INT out_nelts, in_nelts, out, ofs, scale;
if (TREE_CODE (arg1) != VECTOR_CST || TREE_CODE (arg2) != VECTOR_CST)
return NULL_TREE;
- in_nelts = VECTOR_CST_NELTS (arg1);
+ if (!VECTOR_CST_NELTS (arg1).is_constant (&in_nelts))
+ return NULL_TREE;
out_nelts = in_nelts / 2;
- gcc_assert (in_nelts == VECTOR_CST_NELTS (arg2)
- && out_nelts == TYPE_VECTOR_SUBPARTS (type));
+ gcc_assert (known_eq (in_nelts, VECTOR_CST_NELTS (arg2))
+ && known_eq (out_nelts, TYPE_VECTOR_SUBPARTS (type)));
if (code == VEC_WIDEN_MULT_LO_EXPR)
scale = 0, ofs = BYTES_BIG_ENDIAN ? out_nelts : 0;
@@ -1809,15 +1812,16 @@ const_unop (enum tree_code code, tree type, tree arg0)
case VEC_UNPACK_FLOAT_LO_EXPR:
case VEC_UNPACK_FLOAT_HI_EXPR:
{
- unsigned int out_nelts, in_nelts, i;
+ unsigned HOST_WIDE_INT out_nelts, in_nelts, i;
enum tree_code subcode;
if (TREE_CODE (arg0) != VECTOR_CST)
return NULL_TREE;
- in_nelts = VECTOR_CST_NELTS (arg0);
+ if (!VECTOR_CST_NELTS (arg0).is_constant (&in_nelts))
+ return NULL_TREE;
out_nelts = in_nelts / 2;
- gcc_assert (out_nelts == TYPE_VECTOR_SUBPARTS (type));
+ gcc_assert (known_eq (out_nelts, TYPE_VECTOR_SUBPARTS (type)));
unsigned int offset = 0;
if ((!BYTES_BIG_ENDIAN) ^ (code == VEC_UNPACK_LO_EXPR
@@ -2275,7 +2279,7 @@ fold_convert_const (enum tree_code code, tree type, tree arg1)
else if (TREE_CODE (type) == VECTOR_TYPE)
{
if (TREE_CODE (arg1) == VECTOR_CST
- && TYPE_VECTOR_SUBPARTS (type) == VECTOR_CST_NELTS (arg1))
+ && known_eq (TYPE_VECTOR_SUBPARTS (type), VECTOR_CST_NELTS (arg1)))
{
tree elttype = TREE_TYPE (type);
tree arg1_elttype = TREE_TYPE (TREE_TYPE (arg1));
@@ -3429,8 +3433,8 @@ operand_equal_p (const_tree arg0, const_tree arg1, unsigned int flags)
We only tested element precision and modes to match.
Vectors may be BLKmode and thus also check that the number of
parts match. */
- if (TYPE_VECTOR_SUBPARTS (TREE_TYPE (arg0))
- != TYPE_VECTOR_SUBPARTS (TREE_TYPE (arg1)))
+ if (maybe_ne (TYPE_VECTOR_SUBPARTS (TREE_TYPE (arg0)),
+ TYPE_VECTOR_SUBPARTS (TREE_TYPE (arg1))))
return 0;
vec<constructor_elt, va_gc> *v0 = CONSTRUCTOR_ELTS (arg0);
@@ -7290,12 +7294,13 @@ native_encode_complex (const_tree expr, unsigned char *ptr, int len, int off)
static int
native_encode_vector (const_tree expr, unsigned char *ptr, int len, int off)
{
- unsigned i, count;
+ unsigned HOST_WIDE_INT i, count;
int size, offset;
tree itype, elem;
offset = 0;
- count = VECTOR_CST_NELTS (expr);
+ if (!VECTOR_CST_NELTS (expr).is_constant (&count))
+ return 0;
itype = TREE_TYPE (TREE_TYPE (expr));
size = GET_MODE_SIZE (SCALAR_TYPE_MODE (itype));
for (i = 0; i < count; i++)
@@ -7532,15 +7537,16 @@ native_interpret_complex (tree type, const unsigned char *ptr, int len)
If the buffer cannot be interpreted, return NULL_TREE. */
static tree
-native_interpret_vector (tree type, const unsigned char *ptr, int len)
+native_interpret_vector (tree type, const unsigned char *ptr, unsigned int len)
{
tree etype, elem;
- int i, size, count;
+ unsigned int i, size;
+ unsigned HOST_WIDE_INT count;
etype = TREE_TYPE (type);
size = GET_MODE_SIZE (SCALAR_TYPE_MODE (etype));
- count = TYPE_VECTOR_SUBPARTS (type);
- if (size * count > len)
+ if (!TYPE_VECTOR_SUBPARTS (type).is_constant (&count)
+ || size * count > len)
return NULL_TREE;
tree_vector_builder elements (type, count, 1);
@@ -8894,11 +8900,12 @@ fold_mult_zconjz (location_t loc, tree type, tree expr)
static bool
vec_cst_ctor_to_array (tree arg, unsigned int nelts, tree *elts)
{
- unsigned int i;
+ unsigned HOST_WIDE_INT i, nunits;
- if (TREE_CODE (arg) == VECTOR_CST)
+ if (TREE_CODE (arg) == VECTOR_CST
+ && VECTOR_CST_NELTS (arg).is_constant (&nunits))
{
- for (i = 0; i < VECTOR_CST_NELTS (arg); ++i)
+ for (i = 0; i < nunits; ++i)
elts[i] = VECTOR_CST_ELT (arg, i);
}
else if (TREE_CODE (arg) == CONSTRUCTOR)
@@ -8932,9 +8939,9 @@ fold_vec_perm (tree type, tree arg0, tree arg1, const vec_perm_indices &sel)
if (!sel.length ().is_constant (&nelts))
return NULL_TREE;
- gcc_assert (TYPE_VECTOR_SUBPARTS (type) == nelts
- && TYPE_VECTOR_SUBPARTS (TREE_TYPE (arg0)) == nelts
- && TYPE_VECTOR_SUBPARTS (TREE_TYPE (arg1)) == nelts);
+ gcc_assert (known_eq (TYPE_VECTOR_SUBPARTS (type), nelts)
+ && known_eq (TYPE_VECTOR_SUBPARTS (TREE_TYPE (arg0)), nelts)
+ && known_eq (TYPE_VECTOR_SUBPARTS (TREE_TYPE (arg1)), nelts));
if (TREE_TYPE (TREE_TYPE (arg0)) != TREE_TYPE (type)
|| TREE_TYPE (TREE_TYPE (arg1)) != TREE_TYPE (type))
return NULL_TREE;
@@ -11371,15 +11378,15 @@ fold_ternary_loc (location_t loc, enum tree_code code, tree type,
}
else if (TREE_CODE (arg0) == VECTOR_CST)
{
+ unsigned HOST_WIDE_INT nelts;
if ((TREE_CODE (arg1) == VECTOR_CST
|| TREE_CODE (arg1) == CONSTRUCTOR)
&& (TREE_CODE (arg2) == VECTOR_CST
- || TREE_CODE (arg2) == CONSTRUCTOR))
+ || TREE_CODE (arg2) == CONSTRUCTOR)
+ && TYPE_VECTOR_SUBPARTS (type).is_constant (&nelts))
{
- unsigned int nelts = VECTOR_CST_NELTS (arg0), i;
- gcc_assert (nelts == TYPE_VECTOR_SUBPARTS (type));
vec_perm_builder sel (nelts, nelts, 1);
- for (i = 0; i < nelts; i++)
+ for (unsigned int i = 0; i < nelts; i++)
{
tree val = VECTOR_CST_ELT (arg0, i);
if (integer_all_onesp (val))
@@ -11644,7 +11651,8 @@ fold_ternary_loc (location_t loc, enum tree_code code, tree type,
if (n != 0
&& (idx % width) == 0
&& (n % width) == 0
- && ((idx + n) / width) <= TYPE_VECTOR_SUBPARTS (TREE_TYPE (arg0)))
+ && known_le ((idx + n) / width,
+ TYPE_VECTOR_SUBPARTS (TREE_TYPE (arg0))))
{
idx = idx / width;
n = n / width;
@@ -11716,7 +11724,7 @@ fold_ternary_loc (location_t loc, enum tree_code code, tree type,
return NULL_TREE;
/* Create a vec_perm_indices for the integer vector. */
- unsigned int nelts = TYPE_VECTOR_SUBPARTS (type);
+ poly_uint64 nelts = TYPE_VECTOR_SUBPARTS (type);
bool single_arg = (op0 == op1);
vec_perm_indices sel (builder, single_arg ? 1 : 2, nelts);
@@ -11803,14 +11811,14 @@ fold_ternary_loc (location_t loc, enum tree_code code, tree type,
if (bitpos % elsize == 0)
{
unsigned k = bitpos / elsize;
+ unsigned HOST_WIDE_INT nelts;
if (operand_equal_p (VECTOR_CST_ELT (arg0, k), arg1, 0))
return arg0;
- else
+ else if (VECTOR_CST_NELTS (arg0).is_constant (&nelts))
{
- unsigned int nelts = VECTOR_CST_NELTS (arg0);
tree_vector_builder elts (type, nelts, 1);
elts.quick_grow (nelts);
- for (unsigned int i = 0; i < nelts; ++i)
+ for (unsigned HOST_WIDE_INT i = 0; i < nelts; ++i)
elts[i] = (i == k ? arg1 : VECTOR_CST_ELT (arg0, i));
return elts.build ();
}
@@ -13937,8 +13945,12 @@ fold_relational_const (enum tree_code code, tree type, tree op0, tree op1)
{
/* Have vector comparison with scalar boolean result. */
gcc_assert ((code == EQ_EXPR || code == NE_EXPR)
- && VECTOR_CST_NELTS (op0) == VECTOR_CST_NELTS (op1));
- for (unsigned i = 0; i < VECTOR_CST_NELTS (op0); i++)
+ && known_eq (VECTOR_CST_NELTS (op0),
+ VECTOR_CST_NELTS (op1)));
+ unsigned HOST_WIDE_INT nunits;
+ if (!VECTOR_CST_NELTS (op0).is_constant (&nunits))
+ return NULL_TREE;
+ for (unsigned i = 0; i < nunits; i++)
{
tree elem0 = VECTOR_CST_ELT (op0, i);
tree elem1 = VECTOR_CST_ELT (op1, i);