https://gcc.gnu.org/g:47f2a222ceda5f9834e0840a14cc6155f7d15190

commit r17-401-g47f2a222ceda5f9834e0840a14cc6155f7d15190
Author: Bohan Lei <[email protected]>
Date:   Wed Apr 15 15:42:20 2026 +0800

    RISC-V: Implement even-odd shuffles with vnsrl
    
    This patch tries to implement some even-odd shuffles with vnsrl instead
    of vcompress, which is inspired by the current behavior of LLVM.  Since
    vcompress is slower than vnsrl on many implementations, and that
    vcompress needs a mask load, using vnsrl seems to be more desirable.
    
    gcc/ChangeLog:
    
            * config/riscv/riscv-v.cc (shuffle_even_odd_patterns): Use vnsrl
            when possible.
    
    gcc/testsuite/ChangeLog:
    
            * gcc.target/riscv/rvv/autovec/vls-vlmax/shuffle-evenodd.c:
            Match vnsrl patterns.

Diff:
---
 gcc/config/riscv/riscv-v.cc                        | 40 ++++++++++++++++++++--
 .../riscv/rvv/autovec/vls-vlmax/shuffle-evenodd.c  |  3 +-
 2 files changed, 40 insertions(+), 3 deletions(-)

diff --git a/gcc/config/riscv/riscv-v.cc b/gcc/config/riscv/riscv-v.cc
index eabc792f8b7d..3b9f685e7708 100644
--- a/gcc/config/riscv/riscv-v.cc
+++ b/gcc/config/riscv/riscv-v.cc
@@ -4052,8 +4052,9 @@ shuffle_interleave_patterns (struct expand_vec_perm_d *d)
 }
 
 
-/* Recognize even/odd patterns like [0 2 4 6].  We use two compress
-   and one slideup.  */
+/* Recognize even/odd patterns like [0 2 4 6].  We try to use two narrow shifts
+   and one slideup when possible.  Otherwise, we use two compress and one
+   slideup.  */
 
 static bool
 shuffle_even_odd_patterns (struct expand_vec_perm_d *d)
@@ -4087,6 +4088,41 @@ shuffle_even_odd_patterns (struct expand_vec_perm_d *d)
   if (d->testing_p)
     return true;
 
+  /* When the element width is smaller than the greatest ELEN, we can use two
+     vnsrl instructions, each extracting the even/odd elements of one source,
+     and a vslideup instruction to merge them into one vector.
+
+     PR target/124996: VLS mode subregs larger than what
+     riscv_regmode_natural_size allows cause a memory roundtrip.  Therefore, 
for
+     now, we only do this when the mode size is no greater than the natural 
size
+     of the register.  Once this is fixed, the condition should be replaced by
+     the ELEN condition.  */
+  if (known_le (GET_MODE_SIZE (vmode), riscv_regmode_natural_size (vmode)))
+    {
+      unsigned int elen = GET_MODE_BITSIZE (GET_MODE_INNER (vmode));
+      unsigned int elen2x = elen * 2;
+      scalar_int_mode smode_elen2x = int_mode_for_size (elen2x, 0).require ();
+      scalar_int_mode smode = int_mode_for_size (elen, 0).require ();
+      machine_mode vmode_elen2x
+       = get_vector_mode (smode_elen2x, vlen / 2).require ();
+      machine_mode vmode_half = get_vector_mode (smode, vlen / 2).require ();
+      unsigned int shift_amt = even ? 0 : elen;
+      insn_code icode = code_for_pred_narrow_scalar (LSHIFTRT, vmode_elen2x);
+      rtx tmp = gen_reg_rtx (vmode);
+      rtx ops_shift1[]
+       = {gen_lowpart (vmode_half, d->target),
+          gen_lowpart (vmode_elen2x, d->op0), gen_int_mode (shift_amt, Pmode)};
+      rtx ops_shift2[]
+       = {gen_lowpart (vmode_half, tmp), gen_lowpart (vmode_elen2x, d->op1),
+          gen_int_mode (shift_amt, Pmode)};
+      emit_vlmax_insn (icode, BINARY_OP, ops_shift1);
+      emit_vlmax_insn (icode, BINARY_OP, ops_shift2);
+      rtx ops[] = {d->target, d->target, tmp, gen_int_mode (vlen / 2, Pmode)};
+      icode = code_for_pred_slide (UNSPEC_VSLIDEUP, vmode);
+      emit_vlmax_insn (icode, SLIDEUP_OP_MERGE, ops);
+      return true;
+    }
+
   machine_mode mask_mode = get_mask_mode (vmode);
   rvv_builder builder (mask_mode, vlen, 1);
   int bit = even ? 0 : 1;
diff --git 
a/gcc/testsuite/gcc.target/riscv/rvv/autovec/vls-vlmax/shuffle-evenodd.c 
b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vls-vlmax/shuffle-evenodd.c
index 6db4c5ab3862..ba1131b1f166 100644
--- a/gcc/testsuite/gcc.target/riscv/rvv/autovec/vls-vlmax/shuffle-evenodd.c
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vls-vlmax/shuffle-evenodd.c
@@ -65,4 +65,5 @@ TEST_ALL (PERMUTE1)
 TEST_ALL (PERMUTE2)
 
 /* { dg-final { scan-assembler-times "vslideup" 48 } } */
-/* { dg-final { scan-assembler-times "vcompress" 96 } } */
+/* { dg-final { scan-assembler-times "vcompress" 84 } } */
+/* { dg-final { scan-assembler-times "vnsrl" 12 } } */

Reply via email to