]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
[RISC-V][V2][PR target/123839] Improve subset of constant permutes for RISC-V
authorRaphael Zinsly <rzinsly@qti.qualcomm.com>
Fri, 24 Apr 2026 13:12:32 +0000 (07:12 -0600)
committerJeff Law <jeffrey.law@oss.qualcomm.com>
Fri, 24 Apr 2026 13:15:40 +0000 (07:15 -0600)
There's a set of constant permutes that are currently implemented
via vslideup+vcompress which requires a mask (and setup of the
mask), but which can be implemented via vslideup+vslidedown.

This has been tested on riscv{32,64}-elf as well as in a BPI-F3 which
is configured to use V by default.

PR target/123839
gcc/
* config/riscv/riscv-v.cc (shuffle_slide_patterns): Use a
vslideup+vslidedown pair rather than a vcompressed based
sequence.

gcc/testsuite
* gcc.target/riscv/rvv/autovec/binop/vcompress-avlprop-1.c: Adjust
expected output.
* gcc.target/riscv/rvv/autovec/pr123839.c: New test.

gcc/config/riscv/riscv-v.cc
gcc/testsuite/gcc.target/riscv/rvv/autovec/binop/vcompress-avlprop-1.c
gcc/testsuite/gcc.target/riscv/rvv/autovec/pr123839.c [new file with mode: 0644]

index 82313356a800628c51f87f219d8bf60abe6671c5..bc0a45f0ada2bf84516556c9574a33d587877a07 100644 (file)
@@ -3863,6 +3863,7 @@ shuffle_slide_patterns (struct expand_vec_perm_d *d)
      is the first element of OP0.  */
   bool slideup = false;
   bool slidedown = false;
+  bool need_slideup_p = false;
 
   /* For a slideup the permutation must start at OP0's first element.  */
   if (known_eq (d->perm[0], 0))
@@ -3872,8 +3873,21 @@ shuffle_slide_patterns (struct expand_vec_perm_d *d)
   if (known_eq (d->perm[vlen - 1], 2 * vlen - 1))
     slidedown = true;
 
+  int slideup_cnt = 0;
   if (!slideup && !slidedown)
-    return false;
+    {
+      /* Check if the permutation starts with the end of OP0 followed by the
+        beginning of OP1.  In this case we can do a slideup followed by a
+        slidedown. */
+      slideup_cnt = vlen - (d->perm[vlen - 1].to_constant () % vlen) - 1;
+      if (known_eq (d->perm[slideup_cnt], vlen) && known_eq (d->perm[slideup_cnt - 1], vlen - 1))
+       {
+         slidedown = true;
+         need_slideup_p = true;
+       }
+      else
+       return false;
+    }
 
   /* Check for a monotonic sequence with one or two pivots.  */
   int pivot = -1;
@@ -3939,8 +3953,17 @@ shuffle_slide_patterns (struct expand_vec_perm_d *d)
     }
   else
     {
+      rtx op1 = d->op1;
+      if (need_slideup_p)
+       {
+         op1 = gen_reg_rtx (vmode);
+         rtx ops[] = {op1, d->op1, gen_int_mode (slideup_cnt, Pmode)};
+         insn_code icode = code_for_pred_slide (UNSPEC_VSLIDEUP, vmode);
+         emit_vlmax_insn (icode, BINARY_OP, ops);
+       }
+
       len = pivot;
-      rtx ops[] = {d->target, d->op1, d->op0,
+      rtx ops[] = {d->target, op1, d->op0,
                   gen_int_mode (slide_cnt, Pmode)};
       icode = code_for_pred_slide (UNSPEC_VSLIDEDOWN, vmode);
       emit_nonvlmax_insn (icode, BINARY_OP_TUMA, ops,
index 98e53b38f094a326b3d96ed08a3f91b0f3c98b57..de86e904f9332240fc65b607351891c51989a490 100644 (file)
@@ -11,12 +11,11 @@ struct s sss[MAX];
 /*
 ** build_linked_list:
 **   ...
-**   vsetivli\s+zero,\s*8,\s*e64,\s*m1,\s*tu,\s*ma
+**   vslideup\.vi\s+v[0-9]+,\s*v[0-9]+,\s*1
 **   ...
-**   vcompress\.vm\s+v[0-9]+,\s*v[0-9]+,\s*v0
+**   vslidedown\.vi\s+v[0-9]+,\s*v[0-9]+,\s*7
 **   ...
-**   vcompress\.vm\s+v[0-9]+,\s*v[0-9]+,\s*v0
-**   vsetivli\s+zero,\s*2,\s*e64,\s*m1,\s*ta,\s*ma
+**   vslidedown\.vi\s+v[0-9]+,\s*v[0-9]+,\s*7
 **   ...
 */
 void
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/pr123839.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/pr123839.c
new file mode 100644 (file)
index 0000000..9abb4e3
--- /dev/null
@@ -0,0 +1,15 @@
+/* { dg-do compile { target { ! riscv_abi_e } } } */
+/* { dg-options "-O3 -march=rv64gcv -mrvv-max-lmul=m8 -Wno-overflow -mabi=lp64d" { target { rv64 } } } */
+/* { dg-options "-O3 -march=rv32gcv -mrvv-max-lmul=m8 -Wno-overflow -mabi=ilp32" { target { rv32 } } } */
+
+typedef int vnx4i __attribute__ ((vector_size (16)));
+
+vnx4i
+test (vnx4i x, vnx4i y)
+{
+  return __builtin_shufflevector (x, y, 2, 3, 4, 5);
+}
+
+/* { dg-final { scan-assembler-times "vslideup" 1 } } */
+/* { dg-final { scan-assembler-times "vslidedown" 1 } } */
+/* { dg-final { scan-assembler-not "vcompress" } } */