On 8/27/24 8:02 AM, Robin Dapp wrote:
Hi,
this is a hopefully better way to solve the "subreg problem" by first,
in the generic case, have the RA go via memory and second, providing a
vector-vector extract that deals with it in an optimized way.
When the source mode is potentially larger than one vector (e.g. an
LMUL2 mode for VLEN=128) we don't know which vector the subreg actually
refers to. For zvl128b and LMUL=2 the subreg in (subreg:V2DI (reg:V4DI))
could actually be the a full (high) vector register of a two-register
group (at VLEN=128) or the higher part of a single register (at VLEN>128).
As the subreg is statically ambiguous we prevent such situations in
can_change_mode_class.
The culprit in PR116086 is
_12 = BIT_FIELD_REF <vect_cst__42, 128, 128>;
which can be expanded with a vector-vector extract (from V4DI to V2DI).
This patch adds a VLS-mode vector-vector extract that handles "halving"
cases like this one by sliding down the source vector, thus making sure
the correct part is used.
Regtested on rv64gcv_zvfh_zvbb.
Regards
Robin
PR target/116086
gcc/ChangeLog:
* config/riscv/autovec.md (vec_extract<mode><v_half>): Add
vector-vector extract for VLS modes.
* config/riscv/riscv.cc (riscv_can_change_mode_class): Forbid
VLS modes larger than one vector.
* config/riscv/vector-iterators.md: Add vector-vector extract
iterators.
gcc/testsuite/ChangeLog:
* lib/target-supports.exp: Add effective target checks for
zvl256b and zvl512b.
* gcc.target/riscv/rvv/autovec/pr116086-2-run.c: New test.
* gcc.target/riscv/rvv/autovec/pr116086-2.c: New test.
* gcc.target/riscv/rvv/autovec/pr116086.c: New test.
---
diff --git a/gcc/config/riscv/riscv.cc b/gcc/config/riscv/riscv.cc
index 8538d405f50..4b9f3081ac5 100644
--- a/gcc/config/riscv/riscv.cc
+++ b/gcc/config/riscv/riscv.cc
@@ -10630,6 +10630,17 @@ riscv_can_change_mode_class (machine_mode from,
machine_mode to,
if (reg_classes_intersect_p (V_REGS, rclass)
&& !ordered_p (GET_MODE_PRECISION (from), GET_MODE_PRECISION (to)))
return false;
+
+ /* Subregs of modes larger than one vector are ambiguous.
+ A V4DImode with rv64gcv_zvl128b could, for example, span two registers/one
+ register group of two at VLEN = 128 or one register at VLEN >= 256 and
+ we cannot, statically, determine which part of it to extract.
+ Therefore prevent that. */
+ if (reg_classes_intersect_p (V_REGS, rclass)
+ && riscv_v_ext_vls_mode_p (from)
+ && !ordered_p (BITS_PER_RISCV_VECTOR, GET_MODE_PRECISION (from)))
+ return false;
+
return !reg_classes_intersect_p (FP_REGS, rclass);
}
Yea, this looks much more likely to avoid problems in the middle-end by
indicating it's not safe to use a SUBREG to change the view of certain
vector modes.
I think this is good to go once Juzhe's comments are addressed.
jeff