From: Richard Sandiford Date: Wed, 3 Jan 2018 08:59:18 +0000 (+0000) Subject: poly_int: vec_perm_indices element type X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=6b0630fbe8c34255f2739f63a8d3e5b636020bf4;p=gcc.git poly_int: vec_perm_indices element type This patch changes the vec_perm_indices element type from HOST_WIDE_INT to poly_int64, so that it can represent indices into a variable-length vector. 2018-01-03 Richard Sandiford gcc/ * vec-perm-indices.h (vec_perm_builder): Change element type from HOST_WIDE_INT to poly_int64. (vec_perm_indices::element_type): Update accordingly. (vec_perm_indices::clamp): Handle polynomial element_types. * vec-perm-indices.c (vec_perm_indices::series_p): Likewise. (vec_perm_indices::all_in_range_p): Likewise. (tree_to_vec_perm_builder): Check for poly_int64 trees rather than shwi trees. * vector-builder.h (vector_builder::stepped_sequence_p): Handle polynomial vec_perm_indices element types. * int-vector-builder.h (int_vector_builder::equal_p): Likewise. * fold-const.c (fold_vec_perm): Likewise. * optabs.c (shift_amt_for_vec_perm_mask): Likewise. * tree-vect-generic.c (lower_vec_perm): Likewise. * tree-vect-slp.c (vect_transform_slp_perm_load): Likewise. * config/aarch64/aarch64.c (aarch64_evpc_tbl): Cast d->perm element type to HOST_WIDE_INT. From-SVN: r256164 --- diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 31092fbf2ae..bc93660d1af 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,23 @@ +2018-01-03 Richard Sandiford + + * vec-perm-indices.h (vec_perm_builder): Change element type + from HOST_WIDE_INT to poly_int64. + (vec_perm_indices::element_type): Update accordingly. + (vec_perm_indices::clamp): Handle polynomial element_types. + * vec-perm-indices.c (vec_perm_indices::series_p): Likewise. + (vec_perm_indices::all_in_range_p): Likewise. + (tree_to_vec_perm_builder): Check for poly_int64 trees rather + than shwi trees. + * vector-builder.h (vector_builder::stepped_sequence_p): Handle + polynomial vec_perm_indices element types. + * int-vector-builder.h (int_vector_builder::equal_p): Likewise. + * fold-const.c (fold_vec_perm): Likewise. + * optabs.c (shift_amt_for_vec_perm_mask): Likewise. + * tree-vect-generic.c (lower_vec_perm): Likewise. + * tree-vect-slp.c (vect_transform_slp_perm_load): Likewise. + * config/aarch64/aarch64.c (aarch64_evpc_tbl): Cast d->perm + element type to HOST_WIDE_INT. + 2018-01-03 Richard Sandiford Alan Hayward David Sherwood diff --git a/gcc/config/aarch64/aarch64.c b/gcc/config/aarch64/aarch64.c index 21f049a4974..1fc57a218b7 100644 --- a/gcc/config/aarch64/aarch64.c +++ b/gcc/config/aarch64/aarch64.c @@ -13625,7 +13625,7 @@ aarch64_evpc_tbl (struct expand_vec_perm_d *d) mode on NEON. Reverse the index within each word but not the word itself. */ rperm[i] = GEN_INT (BYTES_BIG_ENDIAN ? d->perm[i] ^ (nunits - 1) - : d->perm[i]); + : (HOST_WIDE_INT) d->perm[i]); } sel = gen_rtx_CONST_VECTOR (vmode, gen_rtvec_v (nelt, rperm)); sel = force_reg (vmode, sel); diff --git a/gcc/fold-const.c b/gcc/fold-const.c index e2e46005f8c..6c13d6d3403 100644 --- a/gcc/fold-const.c +++ b/gcc/fold-const.c @@ -8945,9 +8945,12 @@ fold_vec_perm (tree type, tree arg0, tree arg1, const vec_perm_indices &sel) tree_vector_builder out_elts (type, nelts, 1); for (i = 0; i < nelts; i++) { - if (!CONSTANT_CLASS_P (in_elts[sel[i]])) + HOST_WIDE_INT index; + if (!sel[i].is_constant (&index)) + return NULL_TREE; + if (!CONSTANT_CLASS_P (in_elts[index])) need_ctor = true; - out_elts.quick_push (unshare_expr (in_elts[sel[i]])); + out_elts.quick_push (unshare_expr (in_elts[index])); } if (need_ctor) diff --git a/gcc/int-vector-builder.h b/gcc/int-vector-builder.h index c416ee05bbf..30a8ae18321 100644 --- a/gcc/int-vector-builder.h +++ b/gcc/int-vector-builder.h @@ -66,7 +66,7 @@ template inline bool int_vector_builder::equal_p (T elt1, T elt2) const { - return elt1 == elt2; + return known_eq (elt1, elt2); } /* Return the value of element ELT2 minus the value of element ELT1. */ diff --git a/gcc/optabs.c b/gcc/optabs.c index c3ee454f726..5706205069e 100644 --- a/gcc/optabs.c +++ b/gcc/optabs.c @@ -5398,16 +5398,18 @@ shift_amt_for_vec_perm_mask (machine_mode mode, const vec_perm_indices &sel) { unsigned int nelt = GET_MODE_NUNITS (mode); unsigned int bitsize = GET_MODE_UNIT_BITSIZE (mode); - unsigned int first = sel[0]; - if (first >= nelt) + poly_int64 first = sel[0]; + if (maybe_ge (sel[0], nelt)) return NULL_RTX; if (!sel.series_p (0, 1, first, 1)) for (unsigned int i = 1; i < nelt; i++) { - unsigned int expected = i + first; + poly_int64 expected = i + first; /* Indices into the second vector are all equivalent. */ - if (MIN (nelt, sel[i]) != MIN (nelt, expected)) + if (maybe_lt (sel[i], nelt) + ? maybe_ne (sel[i], expected) + : maybe_lt (expected, nelt)) return NULL_RTX; } diff --git a/gcc/tree-vect-generic.c b/gcc/tree-vect-generic.c index 27d03a7262f..a9a6640687b 100644 --- a/gcc/tree-vect-generic.c +++ b/gcc/tree-vect-generic.c @@ -1337,18 +1337,19 @@ lower_vec_perm (gimple_stmt_iterator *gsi) != CODE_FOR_nothing && TREE_CODE (vec1) == VECTOR_CST && initializer_zerop (vec1) - && indices[0] - && indices[0] < elements) + && maybe_ne (indices[0], 0) + && known_lt (indices[0], elements)) { bool ok_p = indices.series_p (0, 1, indices[0], 1); if (!ok_p) { for (i = 1; i < elements; ++i) { - unsigned int expected = i + indices[0]; + poly_int64 expected = i + indices[0]; /* Indices into the second vector are all equivalent. */ - if (MIN (elements, (unsigned) indices[i]) - != MIN (elements, expected)) + if (maybe_lt (indices[i], elements) + ? maybe_ne (indices[i], expected) + : maybe_lt (expected, elements)) break; } ok_p = i == elements; diff --git a/gcc/tree-vect-slp.c b/gcc/tree-vect-slp.c index 391b3ea1d88..5da3e156d5d 100644 --- a/gcc/tree-vect-slp.c +++ b/gcc/tree-vect-slp.c @@ -3727,8 +3727,10 @@ vect_transform_slp_perm_load (slp_tree node, vec dr_chain, vect_location, "unsupported vect permute { "); for (i = 0; i < nunits; ++i) - dump_printf (MSG_MISSED_OPTIMIZATION, - HOST_WIDE_INT_PRINT_DEC " ", mask[i]); + { + dump_dec (MSG_MISSED_OPTIMIZATION, mask[i]); + dump_printf (MSG_MISSED_OPTIMIZATION, " "); + } dump_printf (MSG_MISSED_OPTIMIZATION, "}\n"); } gcc_assert (analyze_only); diff --git a/gcc/vec-perm-indices.c b/gcc/vec-perm-indices.c index 8b6f412ba5f..2bcac72e5a8 100644 --- a/gcc/vec-perm-indices.c +++ b/gcc/vec-perm-indices.c @@ -95,7 +95,7 @@ vec_perm_indices::series_p (unsigned int out_base, unsigned int out_step, element_type in_base, element_type in_step) const { /* Check the base value. */ - if (clamp (m_encoding.elt (out_base)) != clamp (in_base)) + if (maybe_ne (clamp (m_encoding.elt (out_base)), clamp (in_base))) return false; unsigned int full_nelts = m_encoding.full_nelts (); @@ -127,7 +127,7 @@ vec_perm_indices::series_p (unsigned int out_base, unsigned int out_step, element_type v0 = m_encoding.elt (out_base - out_step); element_type v1 = m_encoding.elt (out_base); - if (clamp (v1 - v0) != in_step) + if (maybe_ne (clamp (v1 - v0), in_step)) return false; out_base += out_step; @@ -146,7 +146,7 @@ vec_perm_indices::all_in_range_p (element_type start, element_type size) const unsigned int nelts_per_pattern = m_encoding.nelts_per_pattern (); unsigned int base_nelts = npatterns * MIN (nelts_per_pattern, 2); for (unsigned int i = 0; i < base_nelts; ++i) - if (m_encoding[i] < start || (m_encoding[i] - start) >= size) + if (!known_in_range_p (m_encoding[i], start, size)) return false; /* For stepped encodings, check the full range of the series. */ @@ -174,8 +174,11 @@ vec_perm_indices::all_in_range_p (element_type start, element_type size) const wide enough for overflow not to be a problem. */ element_type headroom_down = base1 - start; element_type headroom_up = size - headroom_down - 1; - if (headroom_up < step * step_nelts - && headroom_down < (limit - step) * step_nelts) + HOST_WIDE_INT diff; + if ((!step.is_constant (&diff) + || maybe_lt (headroom_up, diff * step_nelts)) + && (!(limit - step).is_constant (&diff) + || maybe_lt (headroom_down, diff * step_nelts))) return false; } } @@ -191,14 +194,14 @@ tree_to_vec_perm_builder (vec_perm_builder *builder, tree cst) { unsigned int encoded_nelts = vector_cst_encoded_nelts (cst); for (unsigned int i = 0; i < encoded_nelts; ++i) - if (!tree_fits_shwi_p (VECTOR_CST_ENCODED_ELT (cst, i))) + if (!tree_fits_poly_int64_p (VECTOR_CST_ENCODED_ELT (cst, i))) return false; builder->new_vector (TYPE_VECTOR_SUBPARTS (TREE_TYPE (cst)), VECTOR_CST_NPATTERNS (cst), VECTOR_CST_NELTS_PER_PATTERN (cst)); for (unsigned int i = 0; i < encoded_nelts; ++i) - builder->quick_push (tree_to_shwi (VECTOR_CST_ENCODED_ELT (cst, i))); + builder->quick_push (tree_to_poly_int64 (VECTOR_CST_ENCODED_ELT (cst, i))); return true; } diff --git a/gcc/vec-perm-indices.h b/gcc/vec-perm-indices.h index 52b65a51e4b..0b547820711 100644 --- a/gcc/vec-perm-indices.h +++ b/gcc/vec-perm-indices.h @@ -25,7 +25,7 @@ along with GCC; see the file COPYING3. If not see /* A vector_builder for building constant permutation vectors. The elements do not need to be clamped to a particular range of input elements. */ -typedef int_vector_builder vec_perm_builder; +typedef int_vector_builder vec_perm_builder; /* This class represents a constant permutation vector, such as that used as the final operand to a VEC_PERM_EXPR. @@ -49,7 +49,7 @@ typedef int_vector_builder vec_perm_builder; different numbers of elements. */ class vec_perm_indices { - typedef HOST_WIDE_INT element_type; + typedef poly_int64 element_type; public: vec_perm_indices (); @@ -118,13 +118,17 @@ vec_perm_indices::vec_perm_indices (const vec_perm_builder &elements, inline vec_perm_indices::element_type vec_perm_indices::clamp (element_type elt) const { - element_type limit = input_nelts (); - elt %= limit; + element_type limit = input_nelts (), elem_within_input; + int input; + if (!can_div_trunc_p (elt, limit, &input, &elem_within_input)) + return elt; + /* Treat negative elements as counting from the end. This only matters if the vector size is not a power of 2. */ - if (elt < 0) - elt += limit; - return elt; + if (known_lt (elem_within_input, 0)) + return elem_within_input + limit; + + return elem_within_input; } /* Return the value of vector element I, which might or might not be diff --git a/gcc/vector-builder.h b/gcc/vector-builder.h index 74e0b7655ad..939709ca582 100644 --- a/gcc/vector-builder.h +++ b/gcc/vector-builder.h @@ -284,7 +284,8 @@ vector_builder::stepped_sequence_p (unsigned int start, || !derived ()->integral_p (elt3)) return false; - if (derived ()->step (elt1, elt2) != derived ()->step (elt2, elt3)) + if (maybe_ne (derived ()->step (elt1, elt2), + derived ()->step (elt2, elt3))) return false; if (!derived ()->can_elide_p (elt3))