]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
LoongArch: Prevent subreg of subreg in CRC
authorXi Ruoyao <xry111@xry111.site>
Wed, 2 Jul 2025 07:28:33 +0000 (15:28 +0800)
committerXi Ruoyao <xry111@xry111.site>
Fri, 4 Jul 2025 03:19:33 +0000 (11:19 +0800)
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.

gcc/config/loongarch/loongarch.md
gcc/testsuite/gcc.c-torture/compile/pr120708.c [new file with mode: 0644]

index f7005dee5b61dd7a2e48c802b49749aa42228ac3..32ef9809b1082e4027f6b9286f1d6db70a797925 100644 (file)
   "&& 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 (file)
index 0000000..9b37e60
--- /dev/null
@@ -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;
+}