On 9/22/26 3:04 AM, Robin Dapp wrote:
Hi,

In the PRs we hit the same problem as before, just this time with a
(subreg:TF (reg:V4SF)) pun on a 32-bit target and a complex int128.
These are different quadword splits than before but they can be
handled similarly.  This patch extends riscv_subpart so it
can deal with sub-parts of arbitrary modes.  The new functionality
is then used to move a spilled TFmode value in word-sized chunks.

Regtested on rv64gcv_zvl512b.

Regards
  Robin

        PR target/127484
        PR target/127547

gcc/ChangeLog:

        * config/riscv/riscv.cc (riscv_subpart): Add parameters and
        handle more part sizes.
        (spill_subreg_move): Allow subreg bytes != 0.
        (riscv_split_quadword_move):  Use riscv_subpart for TFmode.
        * config/riscv/riscv.md (movtf): Add.

gcc/testsuite/ChangeLog:

        * gcc.target/riscv/rvv/autovec/pr127484.c: New test.
        * gcc.target/riscv/rvv/autovec/pr127547.c: New test.
---
  gcc/config/riscv/riscv.cc                     | 78 ++++++++++++-------
  gcc/config/riscv/riscv.md                     | 13 ++++
  .../gcc.target/riscv/rvv/autovec/pr127484.c   | 19 +++++
  .../gcc.target/riscv/rvv/autovec/pr127547.c   | 13 ++++
  4 files changed, 93 insertions(+), 30 deletions(-)
  create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/autovec/pr127484.c
  create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/autovec/pr127547.c

diff --git a/gcc/config/riscv/riscv.cc b/gcc/config/riscv/riscv.cc
index 49e7476b832..2840a8b3133 100644
--- a/gcc/config/riscv/riscv.cc
+++ b/gcc/config/riscv/riscv.cc
@@ -5324,23 +5324,20 @@ riscv_subword (rtx op, bool high_p)
    return simplify_gen_subreg (word_mode, op, mode, byte);
  }
-/* Same as riscv_subword, just only for OImode. */
+/* Similar to riscv_subword, but gets sub-part PART_IDX of mode PART_MODE
+   from OP (of mode MODE).  */
static rtx
-riscv_subpart (rtx op, bool high_p)
+riscv_subpart (rtx op, machine_mode mode, scalar_mode part_mode,
+              poly_uint64 part_idx)
  {
-  unsigned int byte = (high_p != BYTES_BIG_ENDIAN) ? 16 : 0;
-  machine_mode mode = GET_MODE (op);
-
-  if (mode == VOIDmode)
-    mode = OImode;
-
-  gcc_assert (mode == OImode);
+  gcc_assert (multiple_p (GET_MODE_SIZE (mode), GET_MODE_SIZE (part_mode)));
+ poly_uint64 byte = part_idx * GET_MODE_SIZE (part_mode);
    if (MEM_P (op))
-    return adjust_address (op, TImode, byte);
+    return adjust_address (op, part_mode, byte);
- return simplify_gen_subreg (TImode, op, mode, byte);
+  return simplify_gen_subreg (part_mode, op, mode, byte);
  }
/* Return true if OP is a subreg that we cannot split into words or false
@@ -5375,11 +5372,10 @@ spill_subreg_move (rtx dest, rtx src)
         "view" in outer mode.  We can only get here when handling
         subreg-punned registers for which the subreg byte is 0.  */
        rtx inner = SUBREG_REG (src);
-      gcc_assert (known_eq (SUBREG_BYTE (src), 0));
Might need to adjust the comment as it suggests we're only supporting subreg byte of 0, but you're dropping the assert.

Looks good to me.

Jeff

Reply via email to