[gcc r17-3520] RISC-V: Fix sub-Pmode index in vec_set/vec_extract [PR126873]
Ma Jin via Gcc-cvs <[email protected]>
| Newsgroups | gmane.comp.gcc.cvs |
|---|---|
| Message-ID | <[email protected]> |
https://gcc.gnu.org/g:1a29fdbdcb6775cd93bfc23426bf4e8b6b0475d2 commit r17-3520-g1a29fdbdcb6775cd93bfc23426bf4e8b6b0475d2 Author: Jin Ma <[email protected]> Date: Tue Aug 18 23:31:24 2026 +0800 RISC-V: Fix sub-Pmode index in vec_set/vec_extract [PR126873] When gimple-isel lowers a variable-index element access on a fixed-length vector into .VEC_SET or .VEC_EXTRACT, the index may be narrower than Pmode. The vec_set and vec_extract expanders used gen_lowpart to convert it to Pmode, which only reinterprets the register and drops the source-level truncation. The full 64-bit value is then used as the slide amount of vslideup/vslidedown and wrong code is generated. Fix this by zero-extending a sub-Pmode index with convert_to_mode instead. PR target/126873 gcc/ChangeLog: * config/riscv/autovec.md (vec_set<mode>): Zero-extend a sub-Pmode index to Pmode. (vec_extract<mode><vel>): Likewise. gcc/testsuite/ChangeLog: * gcc.target/riscv/pr126873.c: New test. Reported-by: XChy <[email protected]> Signed-off-by: Jin Ma <[email protected]> Diff: --- gcc/config/riscv/autovec.md | 4 ++-- gcc/testsuite/gcc.target/riscv/pr126873.c | 37 +++++++++++++++++++++++++++++++ 2 files changed, 39 insertions(+), 2 deletions(-) diff --git a/gcc/config/riscv/autovec.md b/gcc/config/riscv/autovec.md index 964eed927c82..16d08cae30be 100644 --- a/gcc/config/riscv/autovec.md +++ b/gcc/config/riscv/autovec.md @@ -1396,7 +1396,7 @@ /* Here we set VL = offset + 1. */ rtx length = gen_reg_rtx (Pmode); - operands[2] = gen_lowpart (Pmode, operands[2]); + operands[2] = convert_to_mode (Pmode, operands[2], true); if (CONST_INT_P (operands[2])) emit_move_insn (length, GEN_INT (INTVAL (operands[2]) + 1)); else @@ -1452,7 +1452,7 @@ /* Emit the slide down to index 0 in a new vector. */ tmp = gen_reg_rtx (<MODE>mode); - operands[2] = gen_lowpart (Pmode, operands[2]); + operands[2] = convert_to_mode (Pmode, operands[2], true); rtx ops[] = {tmp, operands[1], operands[2]}; riscv_vector::emit_vlmax_insn (code_for_pred_slide (UNSPEC_VSLIDEDOWN, <MODE>mode), diff --git a/gcc/testsuite/gcc.target/riscv/pr126873.c b/gcc/testsuite/gcc.target/riscv/pr126873.c new file mode 100644 index 000000000000..eab525d0cf20 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/pr126873.c @@ -0,0 +1,37 @@ +/* { dg-do run { target rv64 } } */ +/* { dg-require-effective-target riscv_v } */ +/* { dg-require-effective-target rvv_zvl128b_ok } */ +/* { dg-options "-march=rv64gcv -mabi=lp64d -O1" } */ + +typedef unsigned short u16 __attribute__ ((vector_size (4))); + +unsigned long long g; + +void __attribute__ ((noinline)) +f1 (unsigned long long a3) +{ + unsigned long long v15 + = __builtin_bswap64 ((long long) 10398105857157080808ull + / (long long) a3); + u16 bc13 = (u16) { 29637 }; + if (0 >= bc13[(unsigned int) v15]) + __builtin_abort (); +} + +u16 __attribute__ ((noinline)) +f2 (u16 in) +{ + in[(unsigned int) g] = 123; + return in; +} + +int +main (void) +{ + f1 (17752357569705450221ull); + g = 0x0b00000000000000ull; + u16 r = f2 ((u16) { 1, 2 }); + if (r[0] != 123 || r[1] != 2) + __builtin_abort (); + return 0; +}