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.
}
}
+ /* 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;
}
--- /dev/null
+/* { 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;
+}
+