https://gcc.gnu.org/g:036f356caf6e7228c128cfb3c89b2027bcc5cf5e

commit 036f356caf6e7228c128cfb3c89b2027bcc5cf5e
Author: Jeff Law <[email protected]>
Date:   Sat Oct 4 08:33:19 2025 -0600

    [RISC-V][PR target/122147] Avoid creating (subreg (mem)) in RISC-V port
    
    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.
    
            PR target/122147
    gcc/
            * config/riscv/predicates.md (move_operand): Only allow a REG as the
            operand of a SUBREG.
    
    gcc/testsuite/
    
            * gcc.target/riscv/pr122147.c: New test.
    
    (cherry picked from commit e037693f66823c168ed7d37ae70b3cd5aa757b1e)

Diff:
---
 gcc/config/riscv/predicates.md            |  7 +++++++
 gcc/testsuite/gcc.target/riscv/pr122147.c | 14 ++++++++++++++
 2 files changed, 21 insertions(+)

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 @@
              && 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;
+}

Reply via email to