Hi,
like the middle-end change, this is the split-out version for the riscv
changes. I went ahead and streamlined regmode_natural_size slightly.
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.
Regtested on rv64gcbv_zvl512b
Regards
Robin
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/config/riscv/riscv-v.cc | 14 +++++++------
gcc/config/riscv/riscv.cc | 21 +++++--------------
.../riscv/rvv/autovec/subreg-extract.c | 6 +++++-
.../rvv/autovec/vls-vlmax/full-vec-move1.c | 7 ++++++-
.../rvv/autovec/vls-vlmax/shuffle-evenodd.c | 4 ++--
5 files changed, 26 insertions(+), 26 deletions(-)
diff --git a/gcc/config/riscv/riscv-v.cc b/gcc/config/riscv/riscv-v.cc
index bec1c9ebaec..d98f0a94023 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 f24fe070521..a784c54b37c 100644
--- a/gcc/config/riscv/riscv.cc
+++ b/gcc/config/riscv/riscv.cc
@@ -13171,7 +13171,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;
@@ -13591,9 +13593,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);
@@ -13603,20 +13602,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/subreg-extract.c
b/gcc/testsuite/gcc.target/riscv/rvv/autovec/subreg-extract.c
index a2b568a0ee7..af78f912900 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 fae2ae91572..1a6e8320b8e 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 ba1131b1f16..ecc01b9a3e0 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 } } */
--
2.55.0