https://gcc.gnu.org/g:113ed3adc03f79f09ffe00d429d18f89f335b188

commit r16-1998-g113ed3adc03f79f09ffe00d429d18f89f335b188
Author: Xi Ruoyao <xry...@xry111.site>
Date:   Wed Jul 2 15:28:33 2025 +0800

    LoongArch: Prevent subreg of subreg in CRC
    
    The register_operand predicate can match subreg, then we'd have a subreg
    of subreg and it's invalid.  Use lowpart_subreg to avoid the nested
     subreg.
    
    gcc/ChangeLog:
    
            * config/loongarch/loongarch.md (crc_combine): Avoid nested
            subreg.
    
    gcc/testsuite/ChangeLog:
    
            * gcc.c-torture/compile/pr120708.c: New test.

Diff:
---
 gcc/config/loongarch/loongarch.md              |  3 ++-
 gcc/testsuite/gcc.c-torture/compile/pr120708.c | 20 ++++++++++++++++++++
 2 files changed, 22 insertions(+), 1 deletion(-)

diff --git a/gcc/config/loongarch/loongarch.md 
b/gcc/config/loongarch/loongarch.md
index f7005dee5b61..32ef9809b108 100644
--- a/gcc/config/loongarch/loongarch.md
+++ b/gcc/config/loongarch/loongarch.md
@@ -4573,9 +4573,10 @@
   "&& true"
   [(set (match_dup 3) (match_dup 2))
    (set (match_dup 0)
-       (unspec:SI [(match_dup 3) (subreg:SI (match_dup 1) 0)] CRC))]
+       (unspec:SI [(match_dup 3) (match_dup 1)] CRC))]
   {
     operands[3] = gen_reg_rtx (<MODE>mode);
+    operands[1] = lowpart_subreg (SImode, operands[1], DImode);
   })
 
 ;; With normal or medium code models, if the only use of a pc-relative
diff --git a/gcc/testsuite/gcc.c-torture/compile/pr120708.c 
b/gcc/testsuite/gcc.c-torture/compile/pr120708.c
new file mode 100644
index 000000000000..9b37e608d7f5
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/compile/pr120708.c
@@ -0,0 +1,20 @@
+typedef __UINT8_TYPE__ uint8_t;
+typedef __UINT32_TYPE__ uint32_t;
+
+typedef struct
+{
+  uint32_t dword[2];
+  uint8_t byte[8];
+} reg64_t;
+reg64_t TestF20F_opgd, TestF20F_oped;
+
+void
+TestF20F ()
+{
+  TestF20F_opgd.dword[0] ^= TestF20F_oped.byte[0];
+  for (int i = 0; i < 8; i++)
+    if (TestF20F_opgd.dword[0] & 1)
+      TestF20F_opgd.dword[0] = TestF20F_opgd.dword[0] >> 1 ^ 
(uint32_t)2197175160UL;
+    else
+      TestF20F_opgd.dword[0] = TestF20F_opgd.dword[0] >> 1;
+}

Reply via email to