diff options
author | Xi Ruoyao <xry111@xry111.site> | 2024-12-16 20:43:03 +0800 |
---|---|---|
committer | Xi Ruoyao <xry111@xry111.site> | 2024-12-18 16:43:37 +0800 |
commit | 5b5b517e819837e1950cd4d809cdc6efb8e80302 (patch) | |
tree | 1a327cffc0355c0fe2885123f10a4df0dc5becab /gcc | |
parent | 13ea50fdac104b674eb484936023e20dec0b62cf (diff) | |
download | gcc-5b5b517e819837e1950cd4d809cdc6efb8e80302.zip gcc-5b5b517e819837e1950cd4d809cdc6efb8e80302.tar.gz gcc-5b5b517e819837e1950cd4d809cdc6efb8e80302.tar.bz2 |
LoongArch: Add CRC expander to generate faster CRC
64-bit LoongArch has native CRC instructions for two specific
polynomials. For other polynomials or 32-bit, use the generic
table-based approach but optimize bit reversing.
gcc/ChangeLog:
* config/loongarch/loongarch.md (crc_rev<mode:SUBDI>si4): New
define_expand.
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/config/loongarch/loongarch.md | 57 |
1 files changed, 57 insertions, 0 deletions
diff --git a/gcc/config/loongarch/loongarch.md b/gcc/config/loongarch/loongarch.md index fe1678c..806b0ec 100644 --- a/gcc/config/loongarch/loongarch.md +++ b/gcc/config/loongarch/loongarch.md @@ -4420,6 +4420,63 @@ [(set_attr "type" "unknown") (set_attr "mode" "<MODE>")]) +(define_expand "crc_rev<mode>si4" + [(match_operand:SI 0 "register_operand") ; new_chksum + (match_operand:SI 1 "register_operand") ; old_chksum + (match_operand:SUBDI 2 "reg_or_0_operand") ; msg + (match_operand 3 "const_int_operand")] ; poly + "" + { + unsigned HOST_WIDE_INT poly = UINTVAL (operands[3]); + rtx msg = operands[2]; + rtx (*crc_insn)(rtx, rtx, rtx) = nullptr; + + /* TODO: Review this when adding LA32 support. If we're going to + support CRC instructions on LA32 we'll need a "-mcrc" switch as + they are optional on LA32. */ + + if (TARGET_64BIT) + { + if (poly == reflect_hwi (0xedb88320u, 32)) + crc_insn = gen_loongarch_crc_w_<size>_w; + else if (poly == reflect_hwi (0x82f63b78u, 32)) + crc_insn = gen_loongarch_crcc_w_<size>_w; + } + + if (crc_insn) + { + /* We cannot make crc_insn to accept const0_rtx easily: + it's not possible to figure out the mode of const0_rtx so we'd + have to separate both UNSPEC_CRC and UNSPEC_CRCC to 4 different + UNSPECs. Instead just hack it around here. */ + if (msg == const0_rtx) + msg = gen_rtx_REG (<MODE>mode, 0); + + emit_insn (crc_insn (operands[0], msg, operands[1])); + } + else + { + /* No CRC instruction is suitable, use the generic table-based + implementation but optimize bit reversion. */ + auto rbit = [](rtx *r) + { + /* Well, this is ugly. The problem is + expand_reversed_crc_table_based only accepts one helper + for reversing data elements and CRC states. */ + auto mode = GET_MODE (*r); + auto rbit = (mode == <MODE>mode ? gen_rbit<mode> : gen_rbitsi); + rtx out = gen_reg_rtx (mode); + + emit_insn (rbit (out, *r)); + *r = out; + }; + expand_reversed_crc_table_based (operands[0], operands[1], + msg, operands[3], <MODE>mode, + rbit); + } + DONE; + }) + ;; With normal or medium code models, if the only use of a pc-relative ;; address is for loading or storing a value, then relying on linker ;; relaxation is not better than emitting the machine instruction directly. |