https://gcc.gnu.org/g:0b67b93cfe0a67fe431a22b163ac0319fd6ec5da

commit r17-3908-g0b67b93cfe0a67fe431a22b163ac0319fd6ec5da
Author: Robin Dapp <[email protected]>
Date:   Mon Aug 31 14:42:10 2026 +0200

    RISC-V: Set REGMODE_NATURAL_SIZE for VLS vectors.
    
    Following the middle-end changes, this patch makes REGMODE_NATURAL_SIZE
    return the size of one vector.  This implies that subregs of VLS vectors
    smaller than the vector itself are invalid.
    
    Note that this is going to cause a few code-quality regression.  Before
    this change, we could rely on "subregging" our way into vectors but
    that's not possible anymore.  My plan is to fix this by a few
    adjustments to vec-vec extracts and vec-vec sets during expand,
    defining a vec-vec vec_init for riscv, as well maybe adding
    vec_extract and vec_set rtx codes to help with all of that.
    
            PR middle-end/125390
    
    gcc/ChangeLog:
    
            * config/riscv/riscv-v.cc (shuffle_even_odd_patterns): Adjust
            check and clarify comment.
            * config/riscv/riscv.cc (riscv_can_change_mode_class): Allow
            same-sized vectors.
            (riscv_regmode_natural_size): Set to "one vector" for VLS modes.
    
    gcc/testsuite/ChangeLog:
    
            * gcc.target/riscv/rvv/autovec/subreg-extract.c: Adjust test
            expectation.
            * gcc.target/riscv/rvv/autovec/vls-vlmax/full-vec-move1.c:
            Likewise.
            * gcc.target/riscv/rvv/autovec/vls-vlmax/shuffle-evenodd.c:
            Likewise.
            * gcc.target/riscv/rvv/autovec/pr125390.c: New test.

Diff:
---
 gcc/config/riscv/riscv-v.cc                        | 14 +++++----
 gcc/config/riscv/riscv.cc                          | 21 ++++---------
 .../gcc.target/riscv/rvv/autovec/pr125390.c        | 34 ++++++++++++++++++++++
 .../gcc.target/riscv/rvv/autovec/subreg-extract.c  |  6 +++-
 .../riscv/rvv/autovec/vls-vlmax/full-vec-move1.c   |  7 ++++-
 .../riscv/rvv/autovec/vls-vlmax/shuffle-evenodd.c  |  4 +--
 6 files changed, 60 insertions(+), 26 deletions(-)

diff --git a/gcc/config/riscv/riscv-v.cc b/gcc/config/riscv/riscv-v.cc
index bec1c9ebaec1..d98f0a940230 100644
--- a/gcc/config/riscv/riscv-v.cc
+++ b/gcc/config/riscv/riscv-v.cc
@@ -4059,12 +4059,12 @@ shuffle_even_odd_patterns (struct expand_vec_perm_d *d)
      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)))
+     Until we have a "widening" vector concat pattern (just like slideup here
+     but with the proper modes) we still need the natural-size check for
+     LMUL > 1 cases.  */
+  unsigned int max_elen = TARGET_VECTOR_ELEN_64 ? 64 : 32;
+  if (GET_MODE_BITSIZE (GET_MODE_INNER (vmode)) * 2 <= max_elen
+      && 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;
@@ -4075,6 +4075,8 @@ shuffle_even_odd_patterns (struct expand_vec_perm_d *d)
       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);
+      /* TODO these lowpart subreg workarounds should go, this is actually a
+        simple concatenation of two "half"-sized vectors.  */
       rtx tmp = gen_reg_rtx (vmode);
       rtx ops_shift1[]
        = {gen_lowpart (vmode_half, d->target),
diff --git a/gcc/config/riscv/riscv.cc b/gcc/config/riscv/riscv.cc
index a1474b05ad8a..f8b54fc4ae68 100644
--- a/gcc/config/riscv/riscv.cc
+++ b/gcc/config/riscv/riscv.cc
@@ -13175,7 +13175,9 @@ riscv_can_change_mode_class (machine_mode from, 
machine_mode to,
      we cannot, statically, determine which part of it to extract.
      Therefore prevent that.  */
   if (reg_classes_intersect_p (V_REGS, rclass)
-      && riscv_vls_mode_p (from)
+      && VECTOR_MODE_P (from)
+      && GET_MODE_NUNITS (from).is_constant ()
+      && maybe_ne (GET_MODE_PRECISION (from), GET_MODE_PRECISION (to))
       && !ordered_p (BITS_PER_RISCV_VECTOR, GET_MODE_PRECISION (from)))
       return false;
 
@@ -13595,9 +13597,6 @@ riscv_regmode_natural_size (machine_mode mode)
   /* The natural size for RVV data modes is one RVV data vector,
      and similarly for predicates.  We can't independently modify
      anything smaller than that.  */
-  /* ??? For now, only do this for variable-width RVV registers.
-     Doing it for constant-sized registers breaks lower-subreg.c.  */
-
   if (riscv_vector_mode_p (mode))
     {
       poly_uint64 size = GET_MODE_SIZE (mode);
@@ -13607,20 +13606,10 @@ riscv_regmode_natural_size (machine_mode mode)
          if (known_lt (size, BYTES_PER_RISCV_VECTOR))
            return size;
        }
-      else if (riscv_vla_mode_p (mode))
-       {
-         /* RVV mask modes always consume a single register.  */
-         if (GET_MODE_CLASS (mode) == MODE_VECTOR_BOOL)
-           return BYTES_PER_RISCV_VECTOR;
-       }
       if (!size.is_constant ())
        return BYTES_PER_RISCV_VECTOR;
-      else if (!riscv_vls_mode_p (mode))
-       /* For -march=rv64gc_zve32f, the natural vector register size
-          is 32 bits which is smaller than scalar register size, so we
-          return minimum size between vector register size and scalar
-          register size.  */
-       return MIN (size.to_constant (), UNITS_PER_WORD);
+      else
+       return TARGET_MIN_VLEN / BITS_PER_UNIT;
     }
   return UNITS_PER_WORD;
 }
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/pr125390.c 
b/gcc/testsuite/gcc.target/riscv/rvv/autovec/pr125390.c
new file mode 100644
index 000000000000..6ea9e509ba83
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/pr125390.c
@@ -0,0 +1,34 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv64gcv_zvl256b -mabi=lp64d -mrvv-vector-bits=zvl -O2 
--param=riscv-autovec-mode=RVVMF8QI -fno-vect-cost-model" } */
+
+int a, b[64], c[64];
+
+void
+foo (void)
+{
+  for (unsigned e = 0; e < 8; e += 2)
+    {
+      a = c[e] ^ c[e + 1];
+      b[e] = 0;
+    }
+}
+
+void
+bar (void)
+{
+  for (unsigned e = 0; e < 16; e += 2)
+    {
+      a = c[e] ^ c[e + 1];
+      b[e] = 0;
+    }
+}
+
+void
+baz (void)
+{
+  for (unsigned e = 0; e < 32; e += 4)
+    {
+      a = c[e] ^ c[e + 1] ^ c[e + 2] ^ c[e + 3];
+      b[e] = 0;
+    }
+}
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/subreg-extract.c 
b/gcc/testsuite/gcc.target/riscv/rvv/autovec/subreg-extract.c
index a2b568a0ee74..af78f912900b 100644
--- a/gcc/testsuite/gcc.target/riscv/rvv/autovec/subreg-extract.c
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/subreg-extract.c
@@ -16,4 +16,8 @@ foo ()
     }
 }
 
-/* { dg-final { scan-assembler-times "vslidedown" 2 } } */
+/* Since the regmode-natural-size changes we cannot build half-vector subregs
+   of regs.  Xfail this until we have a better way of describing and especially
+   querying vec_extract support.  */
+
+/* { dg-final { scan-assembler-times "vslidedown" 2 { xfail *-*-* } } } */
diff --git 
a/gcc/testsuite/gcc.target/riscv/rvv/autovec/vls-vlmax/full-vec-move1.c 
b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vls-vlmax/full-vec-move1.c
index fae2ae91572f..1a6e8320b8ea 100644
--- a/gcc/testsuite/gcc.target/riscv/rvv/autovec/vls-vlmax/full-vec-move1.c
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vls-vlmax/full-vec-move1.c
@@ -21,5 +21,10 @@ int main ()
     test_element (res[i]);
 }
 
+/* This fails because we don't have a proper way of
+   inserting vectors into vectors yet and regmode_natural_size
+   prevents us from subregging into them.  Xfail until this
+   is fixed.  */
+
 /* { dg-final { scan-assembler-not {vl[1248]r.v} } }  */
-/* { dg-final { scan-assembler-times {vl[1248]re16.v} 1 } }  */
+/* { dg-final { scan-assembler-times {vl[1248]re16.v} 1 { xfail *-*-* } } }  */
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 ba1131b1f166..ecc01b9a3e07 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,5 +65,5 @@ TEST_ALL (PERMUTE1)
 TEST_ALL (PERMUTE2)
 
 /* { dg-final { scan-assembler-times "vslideup" 48 } } */
-/* { dg-final { scan-assembler-times "vcompress" 84 } } */
-/* { dg-final { scan-assembler-times "vnsrl" 12 } } */
+/* { dg-final { scan-assembler-times "vcompress" 68 } } */
+/* { dg-final { scan-assembler-times "vnsrl" 28 } } */

Reply via email to