RISC-V: Load VLS perm indices directly from memory.

Instead of loading the permutation indices and using vmslt in order to
determine which elements belong to which source vector we can compute
the proper mask at compile time.  That way we can emit vlm instead of
vle + vmslt.

gcc/ChangeLog:

	* config/riscv/riscv-v.cc (shuffle_merge_patterns): Load VLS
	indices directly.

gcc/testsuite/ChangeLog:

	* gcc.target/riscv/rvv/autovec/vls/merge-1.c: Check for vlm and
	no vmsleu etc.
	* gcc.target/riscv/rvv/autovec/vls/merge-2.c: Ditto.
	* gcc.target/riscv/rvv/autovec/vls/merge-3.c: Ditto.
	* gcc.target/riscv/rvv/autovec/vls/merge-4.c: Ditto.
	* gcc.target/riscv/rvv/autovec/vls/merge-5.c: Ditto.
	* gcc.target/riscv/rvv/autovec/vls/merge-6.c: Ditto.
This commit is contained in:
Robin Dapp 2024-09-26 11:56:08 +02:00
parent 387dba05e4
commit a18592e1c3
7 changed files with 32 additions and 2 deletions

View File

@ -3101,9 +3101,27 @@ shuffle_merge_patterns (struct expand_vec_perm_d *d)
machine_mode mask_mode = get_mask_mode (vmode);
rtx mask = gen_reg_rtx (mask_mode);
if (indices_fit_selector_p)
if (indices_fit_selector_p && vec_len.is_constant ())
{
/* MASK = SELECTOR < NUNITS ? 1 : 0. */
/* For a constant vector length we can generate the needed mask at
compile time and load it as mask at runtime.
This saves a compare at runtime. */
rtx_vector_builder sel (mask_mode, d->perm.encoding ().npatterns (),
d->perm.encoding ().nelts_per_pattern ());
unsigned int encoded_nelts = sel.encoded_nelts ();
for (unsigned int i = 0; i < encoded_nelts; i++)
sel.quick_push (gen_int_mode (d->perm[i].to_constant ()
< vec_len.to_constant (),
GET_MODE_INNER (mask_mode)));
mask = sel.build ();
}
else if (indices_fit_selector_p)
{
/* For a dynamic vector length < 256 we keep the permutation
indices in the literal pool, load it at runtime and create the
mask by selecting either OP0 or OP1 by
INDICES < NUNITS ? 1 : 0. */
rtx sel = vec_perm_indices_to_rtx (sel_mode, d->perm);
rtx x = gen_int_mode (vec_len, GET_MODE_INNER (sel_mode));
insn_code icode = code_for_pred_cmp_scalar (sel_mode);

View File

@ -4,3 +4,5 @@
#include "../vls-vlmax/merge-1.c"
/* { dg-final { scan-assembler-times {\tvmerge.vvm} 11 } } */
/* { dg-final { scan-assembler-not {\tvms} } } */
/* { dg-final { scan-assembler-times {\tvlm.v} 11 } } */

View File

@ -4,3 +4,5 @@
#include "../vls-vlmax/merge-2.c"
/* { dg-final { scan-assembler-times {\tvmerge.vvm} 11 } } */
/* { dg-final { scan-assembler-not {\tvms} } } */
/* { dg-final { scan-assembler-times {\tvlm.v} 11 } } */

View File

@ -4,3 +4,5 @@
#include "../vls-vlmax/merge-3.c"
/* { dg-final { scan-assembler-times {\tvmerge.vvm} 11 } } */
/* { dg-final { scan-assembler-not {\tvms} } } */
/* { dg-final { scan-assembler-times {\tvlm.v} 11 } } */

View File

@ -4,3 +4,5 @@
#include "../vls-vlmax/merge-4.c"
/* dg-final scan-assembler-times {\tvmerge.vvm} 11 */
/* { dg-final { scan-assembler-not {\tvms} } } */
/* { dg-final { scan-assembler-times {\tvlm.v} 11 } } */

View File

@ -4,3 +4,5 @@
#include "../vls-vlmax/merge-5.c"
/* { dg-final { scan-assembler-times {\tvmerge.vvm} 8 } } */
/* { dg-final { scan-assembler-not {\tvms} } } */
/* { dg-final { scan-assembler-times {\tvlm.v} 8 } } */

View File

@ -4,3 +4,5 @@
#include "../vls-vlmax/merge-6.c"
/* { dg-final { scan-assembler-times {\tvmerge.vvm} 5 } } */
/* { dg-final { scan-assembler-not {\tvms} } } */
/* { dg-final { scan-assembler-times {\tvlm.v} 5 } } */