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