Commit 708cc613 by Richard Sandiford Committed by Richard Sandiford

Generalise VEC_DUPLICATE folding for variable-length vectors

This patch uses the constant vector encoding scheme to handle
more cases of a VEC_DUPLICATE of another vector.  Duplicating
any fixed-length vector is fine, and duplicating a variable-length
vector is OK as long as that vector is also a duplicate of a
fixed-length sequence.

Other cases fell through to:

  if (VECTOR_MODE_P (mode) && GET_CODE (op) == CONST_VECTOR)

which was only expecting to deal with elementwise operations.

2019-07-29  Richard Sandiford  <richard.sandiford@arm.com>

gcc/
	* simplify-rtx.c (simplify_const_unary_operation): Fold a
	VEC_DUPLICATE of a fixed-length vector even if the result
	is variable-length.  Likewise fold a duplicate of a
	variable-length vector if the variable-length vector is
	itself a duplicate of a fixed-length sequence.
	(test_vector_ops_duplicate): Test more cases.

From-SVN: r273868
parent 4ce6ab68
2019-07-29 Richard Sandiford <richard.sandiford@arm.com> 2019-07-29 Richard Sandiford <richard.sandiford@arm.com>
* simplify-rtx.c (simplify_const_unary_operation): Fold a
VEC_DUPLICATE of a fixed-length vector even if the result
is variable-length. Likewise fold a duplicate of a
variable-length vector if the variable-length vector is
itself a duplicate of a fixed-length sequence.
(test_vector_ops_duplicate): Test more cases.
2019-07-29 Richard Sandiford <richard.sandiford@arm.com>
* vector-builder.h (vector_builder): Add a shape template parameter. * vector-builder.h (vector_builder): Add a shape template parameter.
(vector_builder::new_unary_operation): New function, generalizing (vector_builder::new_unary_operation): New function, generalizing
the old tree_vector_builder function. the old tree_vector_builder function.
......
...@@ -1736,23 +1736,24 @@ simplify_const_unary_operation (enum rtx_code code, machine_mode mode, ...@@ -1736,23 +1736,24 @@ simplify_const_unary_operation (enum rtx_code code, machine_mode mode,
} }
if (CONST_SCALAR_INT_P (op) || CONST_DOUBLE_AS_FLOAT_P (op)) if (CONST_SCALAR_INT_P (op) || CONST_DOUBLE_AS_FLOAT_P (op))
return gen_const_vec_duplicate (mode, op); return gen_const_vec_duplicate (mode, op);
unsigned int n_elts;
if (GET_CODE (op) == CONST_VECTOR if (GET_CODE (op) == CONST_VECTOR
&& GET_MODE_NUNITS (mode).is_constant (&n_elts)) && (CONST_VECTOR_DUPLICATE_P (op)
{ || CONST_VECTOR_NUNITS (op).is_constant ()))
/* This must be constant if we're duplicating it to a constant {
number of elements. */ unsigned int npatterns = (CONST_VECTOR_DUPLICATE_P (op)
unsigned int in_n_elts = CONST_VECTOR_NUNITS (op).to_constant (); ? CONST_VECTOR_NPATTERNS (op)
gcc_assert (in_n_elts < n_elts); : CONST_VECTOR_NUNITS (op).to_constant ());
gcc_assert ((n_elts % in_n_elts) == 0); gcc_assert (multiple_p (GET_MODE_NUNITS (mode), npatterns));
rtvec v = rtvec_alloc (n_elts); rtx_vector_builder builder (mode, npatterns, 1);
for (unsigned i = 0; i < n_elts; i++) for (unsigned i = 0; i < npatterns; i++)
RTVEC_ELT (v, i) = CONST_VECTOR_ELT (op, i % in_n_elts); builder.quick_push (CONST_VECTOR_ELT (op, i));
return gen_rtx_CONST_VECTOR (mode, v); return builder.build ();
} }
} }
if (VECTOR_MODE_P (mode) && GET_CODE (op) == CONST_VECTOR) if (VECTOR_MODE_P (mode)
&& GET_CODE (op) == CONST_VECTOR
&& known_eq (GET_MODE_NUNITS (mode), CONST_VECTOR_NUNITS (op)))
{ {
gcc_assert (GET_MODE (op) == op_mode); gcc_assert (GET_MODE (op) == op_mode);
...@@ -6977,6 +6978,18 @@ test_vector_ops_duplicate (machine_mode mode, rtx scalar_reg) ...@@ -6977,6 +6978,18 @@ test_vector_ops_duplicate (machine_mode mode, rtx scalar_reg)
&& mode_for_vector (inner_mode, 2).exists (&narrower_mode) && mode_for_vector (inner_mode, 2).exists (&narrower_mode)
&& VECTOR_MODE_P (narrower_mode)) && VECTOR_MODE_P (narrower_mode))
{ {
/* Test VEC_DUPLICATE of a vector. */
rtx_vector_builder nbuilder (narrower_mode, 2, 1);
nbuilder.quick_push (const0_rtx);
nbuilder.quick_push (const1_rtx);
rtx_vector_builder builder (mode, 2, 1);
builder.quick_push (const0_rtx);
builder.quick_push (const1_rtx);
ASSERT_RTX_EQ (builder.build (),
simplify_unary_operation (VEC_DUPLICATE, mode,
nbuilder.build (),
narrower_mode));
/* Test VEC_SELECT of a vector. */ /* Test VEC_SELECT of a vector. */
rtx vec_par rtx vec_par
= gen_rtx_PARALLEL (VOIDmode, gen_rtvec (2, const1_rtx, const0_rtx)); = gen_rtx_PARALLEL (VOIDmode, gen_rtvec (2, const1_rtx, const0_rtx));
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment