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 } } */
