[PATCH] RISC-V: Fix sub-Pmode index in vec_set/vec_extract [PR126873]

Jin Ma <[email protected]>
Newsgroups gmane.comp.gcc.patches
Message-ID <[email protected]>
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.

Signed-off-by: Jin Ma <[email protected]>
---
 gcc/config/riscv/autovec.md               |  4 +--
 gcc/testsuite/gcc.target/riscv/pr126873.c | 37 +++++++++++++++++++++++
 2 files changed, 39 insertions(+), 2 deletions(-)
 create mode 100644 gcc/testsuite/gcc.target/riscv/pr126873.c

diff --git a/gcc/config/riscv/autovec.md b/gcc/config/riscv/autovec.md
index 964eed927c8..16d08cae30b 100644
--- a/gcc/config/riscv/autovec.md
+++ b/gcc/config/riscv/autovec.md
@@ -1396,7 +1396,7 @@ (define_expand "vec_set<mode>"
 
       /* 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 @@ (define_expand "vec_extract<mode><vel>"
 
     /* 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 00000000000..eab525d0cf2
--- /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;
+}
-- 
2.52.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.