]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
RISC-V: Make tuple vector not tieable to some modes.
authorwangzicong <wangzicong@masscore.cn>
Thu, 30 Apr 2026 13:23:07 +0000 (21:23 +0800)
committerRobin Dapp <robin.dapp@oss.qualcomm.com>
Tue, 5 May 2026 13:58:33 +0000 (15:58 +0200)
This patch makes riscv tuple modes not tieable to non-tuple modes. Without
this patch some unnecessary type conversions may occur, especially when zvl
is specified.
E.g. RVVMF2x4HI and RVVM2DI are tieable in gcc trunk, and when extracting
an inner vector mode RVVMF2HI from RVVMF2x4HI and zvl is specified, it will
be converted to DI, which is not expected. But with same inner modes, e.g.
RVVM1x4QI and RVVM1QI, they should be tieable.

        PR target/124448

gcc/ChangeLog:

* config/riscv/riscv.cc (riscv_modes_tieable_p): Make tuple modes
not tieable to some modes.

gcc/testsuite/ChangeLog:

* gcc.target/riscv/rvv/autovec/pr124448.c: New test.

Signed-off-by: wangzicong <wangzicong@masscore.cn>
gcc/config/riscv/riscv.cc
gcc/testsuite/gcc.target/riscv/rvv/autovec/pr124448.c [new file with mode: 0644]

index 3fae7b5b9f06cfc7b35649ab51a889115a8bb159..108f1c4b3cfdc19720bf1d9350bae00c48d9f251 100644 (file)
@@ -10992,6 +10992,33 @@ riscv_modes_tieable_p (machine_mode mode1, machine_mode mode2)
      E.g. V2SI and DI are not tieable.  */
   if (riscv_vector_mode_p (mode1) != riscv_vector_mode_p (mode2))
     return false;
+
+  /* We don't allow tuple vector modes to be tied to any vector mode
+     that has different inner mode.  It may cause unnecessary type
+     conversions.
+     E.g.  RVVMF2x4HI and RVVM2DI are not tieable, but
+     RVVM1x4QI and RVVM1QI are tieable.  */
+  if (riscv_tuple_mode_p (mode1) || riscv_tuple_mode_p (mode2))
+  {
+    machine_mode subpart_mode1, subpart_mode2;
+    if (riscv_tuple_mode_p (mode1))
+    {
+      subpart_mode1 = riscv_vector::get_subpart_mode (mode1);
+      subpart_mode1 = GET_MODE_INNER (subpart_mode1);
+    }
+    else
+      subpart_mode1 = GET_MODE_INNER (mode1);
+    if (riscv_tuple_mode_p (mode2))
+    {
+      subpart_mode2 = riscv_vector::get_subpart_mode (mode2);
+      subpart_mode2 = GET_MODE_INNER (subpart_mode2);
+    }
+    else
+      subpart_mode2 = GET_MODE_INNER (mode2);
+    if (subpart_mode1 != subpart_mode2)
+      return false;
+  }
+
   return (mode1 == mode2
          || !(GET_MODE_CLASS (mode1) == MODE_FLOAT
               && GET_MODE_CLASS (mode2) == MODE_FLOAT));
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/pr124448.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/pr124448.c
new file mode 100644 (file)
index 0000000..c907433
--- /dev/null
@@ -0,0 +1,36 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv64gcv_zvl128b -mabi=lp64d -O3 -mrvv-vector-bits=zvl  -fdump-rtl-vregs" } */
+
+typedef short int16_t;
+
+void dct( int16_t d[16], int16_t dct[16] )
+{
+    int16_t tmp[16];
+    for( int i = 0; i < 4; i++ )
+    {
+        int s03 = d[i*4+0] + d[i*4+3];
+        int s12 = d[i*4+1] + d[i*4+2];
+        int d03 = d[i*4+0] - d[i*4+3];
+        int d12 = d[i*4+1] - d[i*4+2];
+        tmp[0*4+i] =   s03 +   s12;
+        tmp[1*4+i] = 2*d03 +   d12;
+        tmp[2*4+i] =   s03 -   s12;
+        tmp[3*4+i] =   d03 - 2*d12;
+    }
+    for( int i = 0; i < 4; i++ )
+    {
+        int s03 = tmp[i*4+0] + tmp[i*4+3];
+        int s12 = tmp[i*4+1] + tmp[i*4+2];
+        int d03 = tmp[i*4+0] - tmp[i*4+3];
+        int d12 = tmp[i*4+1] - tmp[i*4+2];
+
+        dct[i*4+0] =   s03 +   s12;
+        dct[i*4+1] = 2*d03 +   d12;
+        dct[i*4+2] =   s03 -   s12;
+        dct[i*4+3] =   d03 - 2*d12;
+    }
+}
+
+/* { dg-final { scan-assembler-times {vsetivli} 1 } } */
+/* { dg-final { scan-assembler-not {vslidedown\.vi} } } */
+/* { dg-final { scan-rtl-dump-not "\(subreg:RVVM2DI \(reg:RVVMF2x4HI.*\).*\)" "vregs" } } */