On May 11, 2020 6:35:58 PM GMT+02:00, Richard Sandiford <richard.sandif...@arm.com> wrote: >A lot of code that wants to know the number of bits in a vector >element gets that information from the element's TYPE_SIZE, >which is always equal to TYPE_SIZE_UNIT * BITS_PER_UNIT. >This doesn't work for SVE and AVX512-style packed boolean vectors, >where several elements can occupy a single byte. > >This patch introduces a new pair of helpers for getting the true >(possibly sub-byte) size. I made a token attempt to convert obvious >element size calculations, but I'm sure I missed some. > >Tested individually on aarch64-linux-gnu and as a series on >x86_64-linux-gnu. OK to install?
OK. Richard. >Richard > > >2020-05-11 Richard Sandiford <richard.sandif...@arm.com> > >gcc/ > PR tree-optimization/94980 > * tree.h (vector_element_bits, vector_element_bits_tree): Declare. > * tree.c (vector_element_bits, vector_element_bits_tree): New. > * match.pd: Use the new functions instead of determining the > vector element size directly from TYPE_SIZE(_UNIT). > * tree-vect-data-refs.c (vect_gather_scatter_fn_p): Likewise. > * tree-vect-patterns.c (vect_recog_mask_conversion_pattern): Likewise. > * tree-vect-stmts.c (vect_is_simple_cond): Likewise. > * tree-vect-generic.c (expand_vector_piecewise): Likewise. > (expand_vector_conversion): Likewise. > (expand_vector_addition): Likewise for a TYPE_SIZE_UNIT used as > a divisor. Convert the dividend to bits to compensate. > * tree-vect-loop.c (vectorizable_live_operation): Call > vector_element_bits instead of open-coding it. >--- > gcc/match.pd | 2 +- > gcc/tree-vect-data-refs.c | 2 +- > gcc/tree-vect-generic.c | 19 +++++++------------ > gcc/tree-vect-loop.c | 4 +--- > gcc/tree-vect-patterns.c | 3 +-- > gcc/tree-vect-stmts.c | 3 +-- > gcc/tree.c | 24 ++++++++++++++++++++++++ > gcc/tree.h | 2 ++ > 8 files changed, 38 insertions(+), 21 deletions(-) > >diff --git a/gcc/tree.h b/gcc/tree.h >index 4644d6616d9..11c109fffcd 100644 >--- a/gcc/tree.h >+++ b/gcc/tree.h >@@ -1996,6 +1996,8 @@ class auto_suppress_location_wrappers > > extern machine_mode element_mode (const_tree); > extern machine_mode vector_type_mode (const_tree); >+extern unsigned int vector_element_bits (const_tree); >+extern tree vector_element_bits_tree (const_tree); > >/* The "canonical" type for this type node, which is used by frontends >to > compare the type for equality with another type. If two types are >diff --git a/gcc/tree.c b/gcc/tree.c >index 5b7d3fddbcb..1aabffeea43 100644 >--- a/gcc/tree.c >+++ b/gcc/tree.c >@@ -13806,6 +13806,30 @@ vector_type_mode (const_tree t) > return mode; > } > >+/* Return the size in bits of each element of vector type TYPE. */ >+ >+unsigned int >+vector_element_bits (const_tree type) >+{ >+ gcc_checking_assert (VECTOR_TYPE_P (type)); >+ if (VECTOR_BOOLEAN_TYPE_P (type)) >+ return vector_element_size (tree_to_poly_uint64 (TYPE_SIZE >(type)), >+ TYPE_VECTOR_SUBPARTS (type)); >+ return tree_to_uhwi (TYPE_SIZE (TREE_TYPE (type))); >+} >+ >+/* Calculate the size in bits of each element of vector type TYPE >+ and return the result as a tree of type bitsizetype. */ >+ >+tree >+vector_element_bits_tree (const_tree type) >+{ >+ gcc_checking_assert (VECTOR_TYPE_P (type)); >+ if (VECTOR_BOOLEAN_TYPE_P (type)) >+ return bitsize_int (vector_element_bits (type)); >+ return TYPE_SIZE (TREE_TYPE (type)); >+} >+ >/* Verify that basic properties of T match TV and thus T can be a >variant of >TV. TV should be the more specified variant (i.e. the main variant). >*/ > >diff --git a/gcc/match.pd b/gcc/match.pd >index 58a4ac66414..33ee1a920bf 100644 >--- a/gcc/match.pd >+++ b/gcc/match.pd >@@ -6306,7 +6306,7 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT) > } > (if (ins) > (bit_insert { op0; } { ins; } >- { bitsize_int (at * tree_to_uhwi (TYPE_SIZE (TREE_TYPE >(type)))); }) >+ { bitsize_int (at * vector_element_bits (type)); }) > (if (changed) > (vec_perm { op0; } { op1; } { op2; })))))))))) > >diff --git a/gcc/tree-vect-data-refs.c b/gcc/tree-vect-data-refs.c >index d41ba49fabf..b950aa9e50d 100644 >--- a/gcc/tree-vect-data-refs.c >+++ b/gcc/tree-vect-data-refs.c >@@ -3693,7 +3693,7 @@ vect_gather_scatter_fn_p (vec_info *vinfo, bool >read_p, bool masked_p, > tree *offset_vectype_out) > { > unsigned int memory_bits = tree_to_uhwi (TYPE_SIZE (memory_type)); >- unsigned int element_bits = tree_to_uhwi (TYPE_SIZE (TREE_TYPE >(vectype))); >+ unsigned int element_bits = vector_element_bits (vectype); > if (element_bits != memory_bits) > /* For now the vector elements must be the same width as the > memory elements. */ >diff --git a/gcc/tree-vect-generic.c b/gcc/tree-vect-generic.c >index 8b00f325054..126e906e0a9 100644 >--- a/gcc/tree-vect-generic.c >+++ b/gcc/tree-vect-generic.c >@@ -276,8 +276,7 @@ expand_vector_piecewise (gimple_stmt_iterator *gsi, >elem_op_func f, > tree part_width = TYPE_SIZE (inner_type); > tree index = bitsize_int (0); > int nunits = nunits_for_known_piecewise_op (type); >- int delta = tree_to_uhwi (part_width) >- / tree_to_uhwi (TYPE_SIZE (TREE_TYPE (type))); >+ int delta = tree_to_uhwi (part_width) / vector_element_bits (type); > int i; > location_t loc = gimple_location (gsi_stmt (*gsi)); > >@@ -357,8 +356,7 @@ expand_vector_addition (gimple_stmt_iterator *gsi, > elem_op_func f, elem_op_func f_parallel, > tree type, tree a, tree b, enum tree_code code) > { >- int parts_per_word = UNITS_PER_WORD >- / tree_to_uhwi (TYPE_SIZE_UNIT (TREE_TYPE (type))); >+ int parts_per_word = BITS_PER_WORD / vector_element_bits (type); > > if (INTEGRAL_TYPE_P (TREE_TYPE (type)) > && parts_per_word >= 4 >@@ -1727,19 +1725,17 @@ expand_vector_conversion (gimple_stmt_iterator >*gsi) > optab optab1 = unknown_optab; > >gcc_checking_assert (VECTOR_TYPE_P (ret_type) && VECTOR_TYPE_P >(arg_type)); >- gcc_checking_assert (tree_fits_uhwi_p (TYPE_SIZE (TREE_TYPE >(ret_type)))); >- gcc_checking_assert (tree_fits_uhwi_p (TYPE_SIZE (TREE_TYPE >(arg_type)))); > if (INTEGRAL_TYPE_P (TREE_TYPE (ret_type)) > && SCALAR_FLOAT_TYPE_P (TREE_TYPE (arg_type))) > code = FIX_TRUNC_EXPR; > else if (INTEGRAL_TYPE_P (TREE_TYPE (arg_type)) > && SCALAR_FLOAT_TYPE_P (TREE_TYPE (ret_type))) > code = FLOAT_EXPR; >- if (tree_to_uhwi (TYPE_SIZE (TREE_TYPE (ret_type))) >- < tree_to_uhwi (TYPE_SIZE (TREE_TYPE (arg_type)))) >+ unsigned int ret_elt_bits = vector_element_bits (ret_type); >+ unsigned int arg_elt_bits = vector_element_bits (arg_type); >+ if (ret_elt_bits < arg_elt_bits) > modifier = NARROW; >- else if (tree_to_uhwi (TYPE_SIZE (TREE_TYPE (ret_type))) >- > tree_to_uhwi (TYPE_SIZE (TREE_TYPE (arg_type)))) >+ else if (ret_elt_bits > arg_elt_bits) > modifier = WIDEN; > >if (modifier == NONE && (code == FIX_TRUNC_EXPR || code == FLOAT_EXPR)) >@@ -1902,8 +1898,7 @@ expand_vector_conversion (gimple_stmt_iterator >*gsi) > tree part_width = TYPE_SIZE (compute_type); > tree index = bitsize_int (0); > int nunits = nunits_for_known_piecewise_op (arg_type); >- int delta = tree_to_uhwi (part_width) >- / tree_to_uhwi (TYPE_SIZE (TREE_TYPE (arg_type))); >+ int delta = tree_to_uhwi (part_width) / arg_elt_bits; > int i; > location_t loc = gimple_location (gsi_stmt (*gsi)); > >diff --git a/gcc/tree-vect-loop.c b/gcc/tree-vect-loop.c >index 64463b874c7..180790abf42 100644 >--- a/gcc/tree-vect-loop.c >+++ b/gcc/tree-vect-loop.c >@@ -8017,9 +8017,7 @@ vectorizable_live_operation (loop_vec_info >loop_vinfo, > : gimple_get_lhs (stmt); > lhs_type = TREE_TYPE (lhs); > >- bitsize = (VECTOR_BOOLEAN_TYPE_P (vectype) >- ? bitsize_int (TYPE_PRECISION (TREE_TYPE (vectype))) >- : TYPE_SIZE (TREE_TYPE (vectype))); >+ bitsize = vector_element_bits_tree (vectype); > vec_bitsize = TYPE_SIZE (vectype); > >/* Get the vectorized lhs of STMT and the lane to use (counted in >bits). */ >diff --git a/gcc/tree-vect-patterns.c b/gcc/tree-vect-patterns.c >index 1f148a0e620..a1fd67341d7 100644 >--- a/gcc/tree-vect-patterns.c >+++ b/gcc/tree-vect-patterns.c >@@ -4381,8 +4381,7 @@ vect_recog_mask_conversion_pattern (vec_info >*vinfo, > || dt == vect_constant_def)) > { > tree wide_scalar_type = build_nonstandard_integer_type >- (tree_to_uhwi (TYPE_SIZE (TREE_TYPE (vectype1))), >- TYPE_UNSIGNED (rhs1_type)); >+ (vector_element_bits (vectype1), TYPE_UNSIGNED (rhs1_type)); > tree vectype3 = get_vectype_for_scalar_type (vinfo, > wide_scalar_type); > if (expand_vec_cond_expr_p (vectype1, vectype3, TREE_CODE >(rhs1))) >diff --git a/gcc/tree-vect-stmts.c b/gcc/tree-vect-stmts.c >index f7f19fee1bb..9a715b82f1a 100644 >--- a/gcc/tree-vect-stmts.c >+++ b/gcc/tree-vect-stmts.c >@@ -10041,8 +10041,7 @@ vect_is_simple_cond (tree cond, vec_info >*vinfo, slp_tree slp_node, > && tree_int_cst_lt (TYPE_SIZE (scalar_type), > TYPE_SIZE (TREE_TYPE (vectype)))) > scalar_type = build_nonstandard_integer_type >- (tree_to_uhwi (TYPE_SIZE (TREE_TYPE (vectype))), >- TYPE_UNSIGNED (scalar_type)); >+ (vector_element_bits (vectype), TYPE_UNSIGNED (scalar_type)); > *comp_vectype = get_vectype_for_scalar_type (vinfo, scalar_type, > slp_node); > }