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