From: Richard Earnshaw <[email protected]>
If a vec_perm selects the same element from the source for every
element in the destination, eg with
__builtin_shuffle (v1, v2, { N, N,... N });
then this can be simplified to
vec_duplicate (v[N'])
where v and N' are picked from the first vector or the second depending
on the value of N.
gcc/ChangeLog:
* match.pd: Simplify vec_perm to vec_duplicate when all outputs
come from the same input lane.
---
gcc/match.pd | 24 +++++++++++++++++++++++-
1 file changed, 23 insertions(+), 1 deletion(-)
diff --git a/gcc/match.pd b/gcc/match.pd
index 3912f9f7d5438..52ebf642677e8 100644
--- a/gcc/match.pd
+++ b/gcc/match.pd
@@ -12910,6 +12910,28 @@ and,
(view_convert @0)
(if (known_eq (nelts, nelts_in) && sel.series_p (0, 1, nelts_in, 1))
(view_convert @1)
+ (if (canonicalize_math_after_vectorization_p ()
+ && known_eq (nelts, nelts_in) && sel.series_p (0, 1, sel[0], 0)
+ && (known_lt ((poly_uint64) sel[0], nelts)
+ || known_ge ((poly_uint64) sel[0], nelts)))
+ (with
+ {
+ poly_uint64 index = sel[0];
+ tree vec = op0;
+ poly_uint64 lane = index;
+ if (known_ge (index, nelts))
+ {
+ vec = op1;
+ lane -= nelts;
+ }
+ tree elem_type = TREE_TYPE (TREE_TYPE (vec));
+ unsigned HOST_WIDE_INT bits = tree_to_uhwi (TYPE_SIZE (elem_type));
+ }
+ (
+ vec_duplicate
+ (BIT_FIELD_REF:elem_type { vec; }
+ { bitsize_int (bits); }
+ { bitsize_int (lane * bits); })))
(with
{
if (!single_arg)
@@ -13022,7 +13044,7 @@ and,
(bit_insert { op0; } { ins; }
{ bitsize_int (at * vector_element_bits (type)); })
(if (changed)
- (vec_perm { op0; } { op1; } { op2; }))))))))))))
+ (vec_perm { op0; } { op1; } { op2; })))))))))))))
/* VEC_PERM_EXPR (v, v, mask) -> v where v contains same element. */
--
2.56.0