]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
[PR target/123911][RISC-V] Fix infinite recursion in riscv_legitimize_move
authorJeff Law <jeffrey.law@oss.qualcomm.com>
Sun, 8 Feb 2026 15:23:07 +0000 (08:23 -0700)
committerJeff Law <jeffrey.law@oss.qualcomm.com>
Mon, 9 Feb 2026 02:35:53 +0000 (19:35 -0700)
I kept hoping I'd see a better solution, perhaps one where chunks of this
routine just go away, but that hasn't materialized.  So...

This patch avoids infinite recursion through riscv_legitimize_move.
Essentially we end up calling it recursively with arguments that are a nop-move
and those particular arguments trigger infinite recursion.

So this patch just recognizes and elides the nop move.   Bootstrapped on
riscv64-linux-gnu and regression tested on riscv{32,64}-elf with no
regressions.  Pushing to the trunk.

PR target/123911
gcc/
* config/riscv/riscv.cc (riscv_legitimize_move): Elide nop moves to
avoid infinite recursion.

gcc/testsuite/
* gcc.target/riscv/pr123911.c: New test.

gcc/config/riscv/riscv.cc
gcc/testsuite/gcc.target/riscv/pr123911.c [new file with mode: 0644]

index 25749af14366b993aaa7ab079b366534caf5d81a..3baf0a936b5857c621eb471449971cc2e7f9ce4b 100644 (file)
@@ -3912,9 +3912,16 @@ riscv_legitimize_move (machine_mode mode, rtx dest, rtx src)
                }
            }
 
+         /* If we are extracting a single element out of a vector and do
+            not need an intermediate register, then the extraction will
+            occur directly into RESULT.  RESULT is the same as DEST and
+            INT_REG.  So we end up with a nop move.  That is not a major
+            problem, except in this case it'll send us right back into
+            this code and we recurse.  Given we put the value in RESULT
+            already we can just elide the nop move here and be done.  */
          if (need_int_reg_p)
            emit_move_insn (dest, gen_lowpart (GET_MODE (dest), int_reg));
-         else
+         else if (!rtx_equal_p (dest, int_reg)) 
            emit_move_insn (dest, int_reg);
          return true;
        }
diff --git a/gcc/testsuite/gcc.target/riscv/pr123911.c b/gcc/testsuite/gcc.target/riscv/pr123911.c
new file mode 100644 (file)
index 0000000..30abe7a
--- /dev/null
@@ -0,0 +1,15 @@
+/* { dg-do compile */
+/* { dg-options "-march=rv64gv -mabi=lp64d" { target { rv64 } } } */
+/* { dg-options "-march=rv32gv -mabi=ilp32" { target { rv32 } } } */
+
+typedef __attribute__((__vector_size__(8))) char W;
+typedef __attribute__((__vector_size__(64))) short V;
+
+V
+foo(V v, W w)
+{
+  __builtin_memmove(30 + (char *)&v, &w, 1);
+  __builtin_memmove(&v, &w, 8);
+  return v;
+}
+