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

Reply via email to