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.
"&& 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
--- /dev/null
+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;
+}