So another fun bug. Utterly amazed we didn't trip over this in some
form or another until now.
We're generating a (subreg (mem)) expression during combine because
"move_operand" accepts it as a valid operand. We've discouraged those
kinds of expressions for a long time, even though they're generally
expected to act like registers due to reloading.
In this case reloading just goes into an infinite loop :( Rather than
try to fix this in LRA, let's just avoiding creating the problematical
subreg to begin with. That's accomplished by being a bit more selective
in what move_operand allows. I'm not particularly happy with what I saw
in move_operand, but I'm inclined to let it be right now.
Tested on rv32 and rv64. Bootstraps on the Pioneer and BPI will run
later today. I'll push once the pre-commit CI system has done its thing.
Jeff
PR target/122147
gcc/
* config/riscv/predicates (move_operand): Only allow a REG as the
operand of a SUBREG.
gcc/testsuite/
* gcc.target/riscv/pr122147.c: New test.
diff --git a/gcc/config/riscv/predicates.md b/gcc/config/riscv/predicates.md
index 056f9e219092..f811a4e40ca7 100644
--- a/gcc/config/riscv/predicates.md
+++ b/gcc/config/riscv/predicates.md
@@ -334,6 +334,13 @@ (define_predicate "move_operand"
&& riscv_split_symbol_type (symbol_type)
&& symbol_type != SYMBOL_PCREL;
+ /* Be tight about the SUBREGs we accept. In particular,
+ (subreg (mem)) has been discouraged for decades. Just
+ allow (subreg (reg)) until such time as we see a strong
+ need to be more permissive. */
+ case SUBREG:
+ return REG_P (SUBREG_REG (op));
+
default:
return true;
}
diff --git a/gcc/testsuite/gcc.target/riscv/pr122147.c
b/gcc/testsuite/gcc.target/riscv/pr122147.c
new file mode 100644
index 000000000000..14da321bc85f
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/pr122147.c
@@ -0,0 +1,14 @@
+/* { dg-do compile } */
+/* { dg-additional-options "-w -march=rv64gcv -mabi=lp64d" { target rv64 } } */
+/* { dg-additional-options "-w -march=rv32gcv -mabi=ilp32" { target rv32 } } */
+
+typedef __attribute__((__vector_size__ (4))) _Float16 F;
+_Complex char cc;
+F f;
+
+void
+foo ()
+{
+ __builtin_memmove (&f, &cc, 2);
+ f *= f;
+}