[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;
+}
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.