Change vect_maybe_permute_loop_masks so that it can check if the
permutation is possible without code generation.
Additionally, allow overriding of what controls to use for source and
target.
gcc/ChangeLog:
* tree-vect-loop-manip.cc (vect_maybe_permute_loop_masks):
Make the function optional and retargetable.
---
gcc/tree-vect-loop-manip.cc | 32 ++++++++++++++++++++++++--------
1 file changed, 24 insertions(+), 8 deletions(-)
diff --git a/gcc/tree-vect-loop-manip.cc b/gcc/tree-vect-loop-manip.cc
index 99e8af8135b..c42e101824d 100644
--- a/gcc/tree-vect-loop-manip.cc
+++ b/gcc/tree-vect-loop-manip.cc
@@ -324,18 +324,30 @@ interleave_supported_p (vec_perm_indices *indices, tree
vectype,
*indices);
}
-/* Try to use permutes to define the masks in DEST_RGM using the masks
- in SRC_RGM, given that the former has twice as many masks as the
- latter. Return true on success, adding any new statements to SEQ. */
+/* Check if its possible to use permutes to define the masks in DEST_RGM using
+ the masks in SRC_RGM, given that the former has twice as many masks as the
+ latter. Return true on success.
+
+ Optionally, if SEQ is non-null add new statements for the permutation to
SEQ.
+ Additionally, if SRC_MASKS and DST_MASKS are defined, use these instead
+ of the masks from SRC_RGM and DST_RGM. */
static bool
vect_maybe_permute_loop_masks (gimple_seq *seq, rgroup_controls *dest_rgm,
- rgroup_controls *src_rgm)
+ rgroup_controls *src_rgm,
+ vec<tree> *dst_masks = NULL,
+ vec<tree> *src_masks = NULL)
{
tree src_masktype = src_rgm->type;
tree dest_masktype = dest_rgm->type;
+ if (!src_masktype && !seq)
+ return true;
machine_mode src_mode = TYPE_MODE (src_masktype);
insn_code icode1, icode2;
+
+ vec<tree> src_controls = src_masks ? *src_masks : src_rgm->controls;
+ vec<tree> dst_controls = dst_masks ? *dst_masks : dest_rgm->controls;
+
if (dest_rgm->max_nscalars_per_iter <= src_rgm->max_nscalars_per_iter
&& (icode1 = optab_handler (vec_unpacku_hi_optab,
src_mode)) != CODE_FOR_nothing
@@ -347,10 +359,12 @@ vect_maybe_permute_loop_masks (gimple_seq *seq,
rgroup_controls *dest_rgm,
machine_mode dest_mode = insn_data[icode1].operand[0].mode;
gcc_assert (dest_mode == insn_data[icode2].operand[0].mode);
tree unpack_masktype = vect_halve_mask_nunits (src_masktype, dest_mode);
+ if (!seq)
+ return true;
for (unsigned int i = 0; i < dest_rgm->controls.length (); ++i)
{
- tree src = src_rgm->controls[i / 2];
- tree dest = dest_rgm->controls[i];
+ tree src = src_controls[i / 2];
+ tree dest = dst_controls[i];
tree_code code = ((i & 1) == (BYTES_BIG_ENDIAN ? 0 : 1)
? VEC_UNPACK_HI_EXPR
: VEC_UNPACK_LO_EXPR);
@@ -375,6 +389,8 @@ vect_maybe_permute_loop_masks (gimple_seq *seq,
rgroup_controls *dest_rgm,
&& interleave_supported_p (&indices[0], src_masktype, 0)
&& interleave_supported_p (&indices[1], src_masktype, 1))
{
+ if (!seq)
+ return true;
/* The destination requires twice as many mask bits as the source, so
we can use interleaving permutes to double up the number of bits. */
tree masks[2];
@@ -382,8 +398,8 @@ vect_maybe_permute_loop_masks (gimple_seq *seq,
rgroup_controls *dest_rgm,
masks[i] = vect_gen_perm_mask_checked (src_masktype, indices[i]);
for (unsigned int i = 0; i < dest_rgm->controls.length (); ++i)
{
- tree src = src_rgm->controls[i / 2];
- tree dest = dest_rgm->controls[i];
+ tree src = src_controls[i / 2];
+ tree dest = dst_controls[i];
gimple *stmt = gimple_build_assign (dest, VEC_PERM_EXPR,
src, src, masks[i & 1]);
gimple_seq_add_stmt (seq, stmt);
--
2.34.1