On Tue, Sep 8, 2026 at 3:46 PM Mariam Arutunian <[email protected]> wrote:
> Thanks for the patch! > > I've had a quick look, and everything looks okay so far. > Thanks Mariam for your review! GCC x86 maintainers: ping for review. Kindly assist with the next steps for this change. I'm interested in working on 64-bit CRC expansion as a follow up once this is merged. Thanks, Shreesh > On Mon, Sep 7, 2026 at 1:56 PM Shreesh Adiga <[email protected]> > wrote: > >> From: Mariam Arutunian <[email protected]> >> >> This patch introduces pclmul expanders for the i386 backend, >> dedicated to generating optimized code for CRC computations. >> >> Expander 1: Bit-Forward CRC (crc<SWI1248x:mode><SWI124:mode>4) >> For targets that support both pclmulqdq instruction (TARGET_PCLMUL) and >> are >> 64-bit (TARGET_64BIT), >> the expander will generate code that uses the pclmulqdq instruction for >> CRC >> computation. >> >> Expander 2: Bit-Reversed CRC (crc_rev<SWI1248x:mode><SWI124:mode>4) >> If the target does not support crc32 but supports pclmulqdq, it then uses >> the pclmulqdq instruction for bit-reversed CRC computation. >> >> This makes the x86 backend similar to aarch64 which uses pmull. >> This is based on earlier submitted patch which was not merged for x86: >> https://gcc.gnu.org/pipermail/gcc-patches/2024-November/668248.html >> >> gcc/ChangeLog: >> >> * config/i386/i386-expand.cc (ix86_expand_crc_using_pclmul): New >> function that implements pclmul expansion for Bit-Forward CRC >> computation. >> (ix86_expand_reversed_crc_using_pclmul): New function that >> implements pclmul expansion for Bit-Reversed CRC computation. >> * config/i386/i386-protos.h (ix86_expand_crc_using_pclmul): New >> extern function declaration. >> (ix86_expand_reversed_crc_using_pclmul): Likewise. >> * config/i386/i386.md (crc_rev<SWI124:mode>si4): Removed older >> expansion for Bit-Reversed CRC. >> (crc<SWI1248x:mode><SWI124:mode>4): Added new expander for >> Bit-Forward CRC. >> (crc_rev<SWI1248x:mode><SWI124:mode>4): Added new expander for >> Bit-Reversed CRC which extends previous CRC32 expansion. >> >> gcc/testsuite/ChangeLog: >> >> * gcc.target/i386/crc-1-pclmul.c: New test. >> * gcc.target/i386/crc-10-pclmul.c: New test. >> * gcc.target/i386/crc-12-pclmul.c: New test. >> * gcc.target/i386/crc-13-pclmul.c: New test. >> * gcc.target/i386/crc-14-pclmul.c: New test. >> * gcc.target/i386/crc-17-pclmul.c: New test. >> * gcc.target/i386/crc-18-pclmul.c: New test. >> * gcc.target/i386/crc-21-pclmul.c: New test. >> * gcc.target/i386/crc-22-pclmul.c: New test. >> * gcc.target/i386/crc-23-pclmul.c: New test. >> * gcc.target/i386/crc-4-pclmul.c: New test. >> * gcc.target/i386/crc-5-pclmul.c: New test. >> * gcc.target/i386/crc-6-pclmul.c: New test. >> * gcc.target/i386/crc-7-pclmul.c: New test. >> * gcc.target/i386/crc-8-pclmul.c: New test. >> * gcc.target/i386/crc-9-pclmul.c: New test. >> * gcc.target/i386/crc-CCIT-data16-pclmul.c: New test. >> * gcc.target/i386/crc-CCIT-data8-pclmul.c: New test. >> * gcc.target/i386/crc-coremark-16bitdata-pclmul.c: New test. >> * gcc.target/i386/crc-crc32-data16.c: New test. >> * gcc.target/i386/crc-crc32-data32.c: New test. >> * gcc.target/i386/crc-crc32-data8.c: New test. >> >> Co-authored-by: Shreesh Adiga <[email protected]> >> Signed-off-by: Shreesh Adiga <[email protected]> >> --- >> gcc/config/i386/i386-expand.cc | 133 ++++++++++++++++++ >> gcc/config/i386/i386-protos.h | 3 + >> gcc/config/i386/i386.md | 53 +++++-- >> gcc/testsuite/gcc.target/i386/crc-1-pclmul.c | 8 ++ >> gcc/testsuite/gcc.target/i386/crc-10-pclmul.c | 8 ++ >> gcc/testsuite/gcc.target/i386/crc-12-pclmul.c | 9 ++ >> gcc/testsuite/gcc.target/i386/crc-13-pclmul.c | 8 ++ >> gcc/testsuite/gcc.target/i386/crc-14-pclmul.c | 8 ++ >> gcc/testsuite/gcc.target/i386/crc-17-pclmul.c | 8 ++ >> gcc/testsuite/gcc.target/i386/crc-18-pclmul.c | 8 ++ >> gcc/testsuite/gcc.target/i386/crc-21-pclmul.c | 8 ++ >> gcc/testsuite/gcc.target/i386/crc-22-pclmul.c | 8 ++ >> gcc/testsuite/gcc.target/i386/crc-23-pclmul.c | 8 ++ >> gcc/testsuite/gcc.target/i386/crc-4-pclmul.c | 8 ++ >> gcc/testsuite/gcc.target/i386/crc-5-pclmul.c | 9 ++ >> gcc/testsuite/gcc.target/i386/crc-6-pclmul.c | 8 ++ >> gcc/testsuite/gcc.target/i386/crc-7-pclmul.c | 8 ++ >> gcc/testsuite/gcc.target/i386/crc-8-pclmul.c | 8 ++ >> gcc/testsuite/gcc.target/i386/crc-9-pclmul.c | 8 ++ >> .../gcc.target/i386/crc-CCIT-data16-pclmul.c | 9 ++ >> .../gcc.target/i386/crc-CCIT-data8-pclmul.c | 9 ++ >> .../i386/crc-coremark-16bitdata-pclmul.c | 9 ++ >> .../gcc.target/i386/crc-crc32-data16.c | 53 +++++++ >> .../gcc.target/i386/crc-crc32-data32.c | 53 +++++++ >> .../gcc.target/i386/crc-crc32-data8.c | 53 +++++++ >> 25 files changed, 492 insertions(+), 13 deletions(-) >> create mode 100644 gcc/testsuite/gcc.target/i386/crc-1-pclmul.c >> create mode 100644 gcc/testsuite/gcc.target/i386/crc-10-pclmul.c >> create mode 100644 gcc/testsuite/gcc.target/i386/crc-12-pclmul.c >> create mode 100644 gcc/testsuite/gcc.target/i386/crc-13-pclmul.c >> create mode 100644 gcc/testsuite/gcc.target/i386/crc-14-pclmul.c >> create mode 100644 gcc/testsuite/gcc.target/i386/crc-17-pclmul.c >> create mode 100644 gcc/testsuite/gcc.target/i386/crc-18-pclmul.c >> create mode 100644 gcc/testsuite/gcc.target/i386/crc-21-pclmul.c >> create mode 100644 gcc/testsuite/gcc.target/i386/crc-22-pclmul.c >> create mode 100644 gcc/testsuite/gcc.target/i386/crc-23-pclmul.c >> create mode 100644 gcc/testsuite/gcc.target/i386/crc-4-pclmul.c >> create mode 100644 gcc/testsuite/gcc.target/i386/crc-5-pclmul.c >> create mode 100644 gcc/testsuite/gcc.target/i386/crc-6-pclmul.c >> create mode 100644 gcc/testsuite/gcc.target/i386/crc-7-pclmul.c >> create mode 100644 gcc/testsuite/gcc.target/i386/crc-8-pclmul.c >> create mode 100644 gcc/testsuite/gcc.target/i386/crc-9-pclmul.c >> create mode 100644 gcc/testsuite/gcc.target/i386/crc-CCIT-data16-pclmul.c >> create mode 100644 gcc/testsuite/gcc.target/i386/crc-CCIT-data8-pclmul.c >> create mode 100644 >> gcc/testsuite/gcc.target/i386/crc-coremark-16bitdata-pclmul.c >> create mode 100644 gcc/testsuite/gcc.target/i386/crc-crc32-data16.c >> create mode 100644 gcc/testsuite/gcc.target/i386/crc-crc32-data32.c >> create mode 100644 gcc/testsuite/gcc.target/i386/crc-crc32-data8.c >> >> diff --git a/gcc/config/i386/i386-expand.cc >> b/gcc/config/i386/i386-expand.cc >> index fb4224af0da..6010892e3dc 100644 >> --- a/gcc/config/i386/i386-expand.cc >> +++ b/gcc/config/i386/i386-expand.cc >> @@ -29917,4 +29917,137 @@ ix86_expand_lcp_stall_peephole (rtx_insn *insn, >> rtx *operands, >> emit_insn (set); >> } >> >> +/* Generate assembly to calculate CRC using pclmulqdq instruction. >> + OPERANDS[1] is input CRC, >> + OPERANDS[2] is data (message), >> + OPERANDS[3] is the polynomial without the leading 1. */ >> + >> +void >> +ix86_expand_crc_using_pclmul (scalar_mode crc_mode, >> + scalar_mode data_mode, >> + rtx *operands) >> +{ >> + /* Check and keep arguments. */ >> + gcc_assert (!CONST_INT_P (operands[0])); >> + gcc_assert (CONST_INT_P (operands[3])); >> + rtx crc = operands[1]; >> + rtx data = operands[2]; >> + rtx polynomial = operands[3]; >> + >> + unsigned HOST_WIDE_INT crc_size = GET_MODE_BITSIZE (crc_mode); >> + unsigned HOST_WIDE_INT data_size = GET_MODE_BITSIZE (data_mode); >> + gcc_assert (crc_size <= 32); >> + gcc_assert (data_size <= crc_size); >> + >> + /* Calculate the quotient. */ >> + unsigned HOST_WIDE_INT >> + q = gf2n_poly_long_div_quotient (UINTVAL (polynomial), crc_size); >> + >> + if (crc_size > data_size) >> + crc = expand_shift (RSHIFT_EXPR, DImode, crc, crc_size - data_size, >> + NULL_RTX, 1); >> + >> + /* Keep the quotient in V2DImode. */ >> + rtx q_v2di = gen_reg_rtx (V2DImode); >> + rtx quotient = force_reg (DImode, gen_int_mode (q, DImode)); >> + emit_insn (gen_vec_concatv2di (q_v2di, quotient, const0_rtx)); >> + >> + /* crc ^ data and keep in V2DImode. */ >> + rtx cd_xor = expand_binop (DImode, xor_optab, crc, data, NULL_RTX, 1, >> + OPTAB_WIDEN); >> + rtx res = gen_reg_rtx (V2DImode); >> + emit_insn (gen_vec_concatv2di (res, cd_xor, const0_rtx)); >> + /* Perform carry-less multiplication. */ >> + emit_insn (gen_pclmulqdq (res, res, q_v2di, gen_int_mode (0, SImode))); >> + >> + res = expand_shift (RSHIFT_EXPR, V2DImode, res, crc_size, NULL_RTX, 1); >> + >> + /* Keep the polynomial in V2DImode. */ >> + polynomial = simplify_gen_unary (ZERO_EXTEND, DImode, polynomial, >> + GET_MODE (polynomial)); >> + rtx t1 = force_reg (DImode, polynomial); >> + rtx p_v2di = gen_reg_rtx (V2DImode); >> + emit_insn (gen_vec_concatv2di (p_v2di, t1, const0_rtx)); >> + >> + /* Perform carry-less multiplication and get low part. */ >> + emit_insn (gen_pclmulqdq (res, res, p_v2di, gen_int_mode (0, SImode))); >> + rtx crc_part = gen_reg_rtx (DImode); >> + emit_insn (gen_vec_extractv2didi (crc_part, res, const0_rtx)); >> + >> + if (crc_size > data_size) >> + { >> + rtx shift = expand_shift (LSHIFT_EXPR, DImode, operands[1], >> data_size, >> + NULL_RTX, 1); >> + crc_part = expand_binop (DImode, xor_optab, crc_part, shift, >> NULL_RTX, 1, >> + OPTAB_DIRECT); >> + } >> + emit_move_insn (operands[0], gen_lowpart (crc_mode, crc_part)); >> +} >> + >> +/* Generate assembly to calculate reversed CRC using pclmulqdq >> instruction. >> + OPERANDS[1] is input CRC, >> + OPERANDS[2] is data (message), >> + OPERANDS[3] is the polynomial without the leading 1. */ >> + >> +void >> +ix86_expand_reversed_crc_using_pclmul (scalar_mode crc_mode, >> + scalar_mode data_mode, >> + rtx *operands) >> +{ >> + /* Check and keep arguments. */ >> + gcc_assert (!CONST_INT_P (operands[0])); >> + gcc_assert (CONST_INT_P (operands[3])); >> + rtx crc = operands[1]; >> + rtx data = operands[2]; >> + rtx polynomial = operands[3]; >> + >> + unsigned HOST_WIDE_INT crc_size = GET_MODE_BITSIZE (crc_mode); >> + unsigned HOST_WIDE_INT data_size = GET_MODE_BITSIZE (data_mode); >> + gcc_assert (crc_size <= 32); >> + gcc_assert (data_size <= crc_size); >> + >> + /* Calculate the quotient. */ >> + unsigned HOST_WIDE_INT >> + q = gf2n_poly_long_div_quotient (UINTVAL (polynomial), crc_size); >> + /* Reflect the calculated quotient. */ >> + q = reflect_hwi (q, crc_size + 1); >> + >> + rtx q_v2di = gen_reg_rtx (V2DImode); >> + rtx quotient = force_reg (DImode, gen_int_mode (q, DImode)); >> + emit_insn (gen_vec_concatv2di (q_v2di, quotient, const0_rtx)); >> + >> + /* crc ^ data and keep in V2DImode. */ >> + rtx cd_xor = expand_binop (DImode, xor_optab, crc, data, NULL_RTX, 1, >> + OPTAB_WIDEN); >> + >> + /* Perform carry-less multiplication. */ >> + rtx res = gen_reg_rtx (V2DImode); >> + emit_insn (gen_vec_concatv2di (res, cd_xor, const0_rtx)); >> + emit_insn (gen_pclmulqdq (res, res, q_v2di, gen_int_mode (0, SImode))); >> + >> + res = expand_shift (LSHIFT_EXPR, V2DImode, res, 64 - data_size, >> NULL_RTX, 0); >> + >> + /* Reflect the polynomial and keep in V2DImode. */ >> + unsigned HOST_WIDE_INT reflected_op3 = reflect_hwi (UINTVAL >> (polynomial), >> + crc_size); >> + rtx ref_polynomial = force_reg (DImode, >> + gen_int_mode (reflected_op3 << 1, >> DImode)); >> + rtx p_v2di = gen_reg_rtx (V2DImode); >> + emit_insn (gen_vec_concatv2di (p_v2di, ref_polynomial, const0_rtx)); >> + >> + /* Perform carry-less multiplication and get high part. */ >> + emit_insn (gen_pclmulqdq (res, res, p_v2di, gen_int_mode (0, SImode))); >> + rtx res_high = gen_reg_rtx (DImode); >> + emit_insn (gen_vec_extractv2didi (res_high, res, const1_rtx)); >> + >> + if (crc_size > data_size) >> + { >> + rtx shift = expand_shift (RSHIFT_EXPR, DImode, crc, data_size, >> + NULL_RTX, 1); >> + res_high = expand_binop (DImode, xor_optab, res_high, shift, >> NULL_RTX, 1, >> + OPTAB_DIRECT); >> + } >> + emit_move_insn (operands[0], gen_lowpart (crc_mode, res_high)); >> +} >> + >> #include "gt-i386-expand.h" >> diff --git a/gcc/config/i386/i386-protos.h b/gcc/config/i386/i386-protos.h >> index 21994d3d498..d225a8fadc2 100644 >> --- a/gcc/config/i386/i386-protos.h >> +++ b/gcc/config/i386/i386-protos.h >> @@ -449,3 +449,6 @@ extern void ix86_set_handled_components (sbitmap); >> bool ix86_check_builtin_isa_match (unsigned int, HOST_WIDE_INT*, >> HOST_WIDE_INT*); >> rtx ix86_vgf2p8affine_shift_matrix (rtx, rtx, enum rtx_code); >> +extern void ix86_expand_crc_using_pclmul (scalar_mode, scalar_mode, rtx >> *); >> +extern void ix86_expand_reversed_crc_using_pclmul (scalar_mode, >> scalar_mode, >> + rtx *); >> diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md >> index 4e18797743f..7538b1f70f1 100644 >> --- a/gcc/config/i386/i386.md >> +++ b/gcc/config/i386/i386.md >> @@ -30504,19 +30504,46 @@ (define_insn "sse4_2_crc32di" >> (set_attr "prefix_extra" "1") >> (set_attr "mode" "DI")]) >> >> -(define_expand "crc_rev<SWI124:mode>si4" >> - [(match_operand:SI 0 "register_operand") >> - (match_operand:SI 1 "register_operand") >> - (match_operand:SWI124 2 "nonimmediate_operand") >> - (match_operand:SI 3 "const_int_operand")] >> - "TARGET_CRC32" >> -{ >> - /* crc32 uses iSCSI polynomial */ >> - if (INTVAL (operands[3]) == 0x1EDC6F41) >> - emit_insn (gen_sse4_2_crc32<mode> (operands[0], operands[1], >> operands[2])); >> - else >> - expand_reversed_crc_table_based (operands[0], operands[1], >> operands[2], >> - operands[3], <SWI124:MODE>mode); >> +;; Bit-forward CRC >> +(define_expand "crc<SWI1248x:mode><SWI124:mode>4" >> + [;; return value (calculated CRC) >> + (match_operand:SWI124 0 "register_operand" "=r") >> + ;; initial CRC >> + (match_operand:SWI124 1 "register_operand" "r") >> + ;; data >> + (match_operand:SWI1248x 2 "register_operand" "r") >> + ;; polynomial without leading 1 >> + (match_operand:SWI124 3 "const_int_operand")] >> + "TARGET_PCLMUL && TARGET_64BIT && <SWI124:MODE>mode >= >> <SWI1248x:MODE>mode" >> +{ >> + ix86_expand_crc_using_pclmul (<SWI124:MODE>mode, <SWI1248x:MODE>mode, >> + operands); >> + DONE; >> +}) >> + >> +;; Reversed CRC >> +(define_expand "crc_rev<SWI1248x:mode><SWI124:mode>4" >> + [;; return value (calculated CRC) >> + (match_operand:SWI124 0 "register_operand" "=r") >> + ;; initial CRC >> + (match_operand:SWI124 1 "register_operand" "r") >> + ;; data >> + (match_operand:SWI1248x 2 "register_operand" "r") >> + ;; polynomial without leading 1 >> + (match_operand:SWI124 3 "const_int_operand")] >> + "<SWI124:MODE>mode >= <SWI1248x:MODE>mode" >> + { >> + /* If it is iSCSI polynomial (0x1EDC6F41), generate crc32 >> instruction. */ >> + if (TARGET_CRC32 && INTVAL (operands[3]) == 0x1EDC6F41 >> + && <SWI124:MODE>mode == SImode) >> + emit_insn (gen_sse4_2_crc32<SWI1248x:mode> (operands[0], >> operands[1], >> + operands[2])); >> + else if (TARGET_PCLMUL && TARGET_64BIT) >> + ix86_expand_reversed_crc_using_pclmul (<SWI124:MODE>mode, >> + <SWI1248x:MODE>mode, >> operands); >> + else >> + expand_reversed_crc_table_based (operands[0], operands[1], >> operands[2], >> + operands[3], <SWI1248x:MODE>mode); >> DONE; >> }) >> >> diff --git a/gcc/testsuite/gcc.target/i386/crc-1-pclmul.c >> b/gcc/testsuite/gcc.target/i386/crc-1-pclmul.c >> new file mode 100644 >> index 00000000000..21edf417f0c >> --- /dev/null >> +++ b/gcc/testsuite/gcc.target/i386/crc-1-pclmul.c >> @@ -0,0 +1,8 @@ >> +/* { dg-do run } */ >> +/* { dg-options "-mpclmul -O2 -fdump-rtl-dfinish -fdump-tree-crc >> -fdisable-tree-phiopt2 -fdisable-tree-phiopt3" } */ >> + >> +#include "../../gcc.dg/torture/crc-1.c" >> + >> +/* { dg-final { scan-tree-dump "calculates CRC!" "crc"} } */ >> +/* { dg-final { scan-tree-dump-times "Couldn't generate faster CRC >> code." 0 "crc"} } */ >> +/* { dg-final { scan-rtl-dump "pclmulqdq" "dfinish"} } */ >> \ No newline at end of file >> diff --git a/gcc/testsuite/gcc.target/i386/crc-10-pclmul.c >> b/gcc/testsuite/gcc.target/i386/crc-10-pclmul.c >> new file mode 100644 >> index 00000000000..39bfd386d9c >> --- /dev/null >> +++ b/gcc/testsuite/gcc.target/i386/crc-10-pclmul.c >> @@ -0,0 +1,8 @@ >> +/* { dg-do run } */ >> +/* { dg-options "-mpclmul -O2 -fdump-rtl-dfinish -fdump-tree-crc" } */ >> + >> +#include "../../gcc.dg/torture/crc-10.c" >> + >> +/* { dg-final { scan-tree-dump "calculates CRC!" "crc"} } */ >> +/* { dg-final { scan-tree-dump-times "Couldn't generate faster CRC >> code." 0 "crc"} } */ >> +/* { dg-final { scan-rtl-dump "pclmulqdq" "dfinish"} } */ >> diff --git a/gcc/testsuite/gcc.target/i386/crc-12-pclmul.c >> b/gcc/testsuite/gcc.target/i386/crc-12-pclmul.c >> new file mode 100644 >> index 00000000000..1ac9a6bf56d >> --- /dev/null >> +++ b/gcc/testsuite/gcc.target/i386/crc-12-pclmul.c >> @@ -0,0 +1,9 @@ >> +/* { dg-do run } */ >> +/* { dg-options "-mpclmul -O2 -fdump-rtl-dfinish -fdump-tree-crc >> -fdisable-tree-phiopt2 -fdisable-tree-phiopt3" } */ >> +/* { dg-skip-if "" { *-*-* } { "-flto"} } */ >> + >> +#include "../../gcc.dg/torture/crc-12.c" >> + >> +/* { dg-final { scan-tree-dump "calculates CRC!" "crc"} } */ >> +/* { dg-final { scan-tree-dump-times "Couldn't generate faster CRC >> code." 0 "crc"} } */ >> +/* { dg-final { scan-rtl-dump "pclmulqdq" "dfinish"} } */ >> diff --git a/gcc/testsuite/gcc.target/i386/crc-13-pclmul.c >> b/gcc/testsuite/gcc.target/i386/crc-13-pclmul.c >> new file mode 100644 >> index 00000000000..c290539fad3 >> --- /dev/null >> +++ b/gcc/testsuite/gcc.target/i386/crc-13-pclmul.c >> @@ -0,0 +1,8 @@ >> +/* { dg-do run } */ >> +/* { dg-options "-mpclmul -O2 -fdump-rtl-dfinish -fdump-tree-crc" } */ >> + >> +#include "../../gcc.dg/torture/crc-13.c" >> + >> +/* { dg-final { scan-tree-dump "calculates CRC!" "crc"} } */ >> +/* { dg-final { scan-tree-dump-times "Couldn't generate faster CRC >> code." 0 "crc"} } */ >> +/* { dg-final { scan-rtl-dump "pclmulqdq" "dfinish"} } */ >> diff --git a/gcc/testsuite/gcc.target/i386/crc-14-pclmul.c >> b/gcc/testsuite/gcc.target/i386/crc-14-pclmul.c >> new file mode 100644 >> index 00000000000..cc62ee471c7 >> --- /dev/null >> +++ b/gcc/testsuite/gcc.target/i386/crc-14-pclmul.c >> @@ -0,0 +1,8 @@ >> +/* { dg-do run } */ >> +/* { dg-options "-mpclmul -O2 -fdump-rtl-dfinish -fdump-tree-crc" } */ >> + >> +#include "../../gcc.dg/torture/crc-14.c" >> + >> +/* { dg-final { scan-tree-dump "calculates CRC!" "crc"} } */ >> +/* { dg-final { scan-tree-dump-times "Couldn't generate faster CRC >> code." 0 "crc"} } */ >> +/* { dg-final { scan-rtl-dump "pclmulqdq" "dfinish"} } */ >> diff --git a/gcc/testsuite/gcc.target/i386/crc-17-pclmul.c >> b/gcc/testsuite/gcc.target/i386/crc-17-pclmul.c >> new file mode 100644 >> index 00000000000..660bff55e1b >> --- /dev/null >> +++ b/gcc/testsuite/gcc.target/i386/crc-17-pclmul.c >> @@ -0,0 +1,8 @@ >> +/* { dg-do run } */ >> +/* { dg-options "-mpclmul -O2 -fdump-rtl-dfinish -fdump-tree-crc" } */ >> + >> +#include "../../gcc.dg/torture/crc-17.c" >> + >> +/* { dg-final { scan-tree-dump "calculates CRC!" "crc"} } */ >> +/* { dg-final { scan-tree-dump-times "Couldn't generate faster CRC >> code." 0 "crc"} } */ >> +/* { dg-final { scan-rtl-dump "pclmulqdq" "dfinish"} } */ >> diff --git a/gcc/testsuite/gcc.target/i386/crc-18-pclmul.c >> b/gcc/testsuite/gcc.target/i386/crc-18-pclmul.c >> new file mode 100644 >> index 00000000000..e54392b32a9 >> --- /dev/null >> +++ b/gcc/testsuite/gcc.target/i386/crc-18-pclmul.c >> @@ -0,0 +1,8 @@ >> +/* { dg-do run } */ >> +/* { dg-options "-mpclmul -O2 -fdump-rtl-dfinish -fdump-tree-crc" } */ >> + >> +#include "../../gcc.dg/torture/crc-18.c" >> + >> +/* { dg-final { scan-tree-dump "calculates CRC!" "crc"} } */ >> +/* { dg-final { scan-tree-dump-times "Couldn't generate faster CRC >> code." 0 "crc"} } */ >> +/* { dg-final { scan-rtl-dump "pclmulqdq" "dfinish"} } */ >> diff --git a/gcc/testsuite/gcc.target/i386/crc-21-pclmul.c >> b/gcc/testsuite/gcc.target/i386/crc-21-pclmul.c >> new file mode 100644 >> index 00000000000..4db1504cd49 >> --- /dev/null >> +++ b/gcc/testsuite/gcc.target/i386/crc-21-pclmul.c >> @@ -0,0 +1,8 @@ >> +/* { dg-do run } */ >> +/* { dg-options "-mpclmul -O2 -fdump-rtl-dfinish -fdump-tree-crc" } */ >> + >> +#include "../../gcc.dg/torture/crc-21.c" >> + >> +/* { dg-final { scan-tree-dump "calculates CRC!" "crc"} } */ >> +/* { dg-final { scan-tree-dump-times "Couldn't generate faster CRC >> code." 0 "crc"} } */ >> +/* { dg-final { scan-rtl-dump "pclmulqdq" "dfinish"} } */ >> diff --git a/gcc/testsuite/gcc.target/i386/crc-22-pclmul.c >> b/gcc/testsuite/gcc.target/i386/crc-22-pclmul.c >> new file mode 100644 >> index 00000000000..d0f27d96069 >> --- /dev/null >> +++ b/gcc/testsuite/gcc.target/i386/crc-22-pclmul.c >> @@ -0,0 +1,8 @@ >> +/* { dg-do run } */ >> +/* { dg-options "-mpclmul -O2 -fdump-rtl-dfinish -fdump-tree-crc" } */ >> + >> +#include "../../gcc.dg/torture/crc-22.c" >> + >> +/* { dg-final { scan-tree-dump "calculates CRC!" "crc"} } */ >> +/* { dg-final { scan-tree-dump-times "Couldn't generate faster CRC >> code." 0 "crc"} } */ >> +/* { dg-final { scan-rtl-dump "pclmulqdq" "dfinish"} } */ >> diff --git a/gcc/testsuite/gcc.target/i386/crc-23-pclmul.c >> b/gcc/testsuite/gcc.target/i386/crc-23-pclmul.c >> new file mode 100644 >> index 00000000000..666f3620597 >> --- /dev/null >> +++ b/gcc/testsuite/gcc.target/i386/crc-23-pclmul.c >> @@ -0,0 +1,8 @@ >> +/* { dg-do run } */ >> +/* { dg-options "-mpclmul -O2 -fdump-rtl-dfinish -fdump-tree-crc" } */ >> + >> +#include "../../gcc.dg/torture/crc-23.c" >> + >> +/* { dg-final { scan-tree-dump "calculates CRC!" "crc"} } */ >> +/* { dg-final { scan-tree-dump-times "Couldn't generate faster CRC >> code." 0 "crc"} } */ >> +/* { dg-final { scan-rtl-dump "pclmulqdq" "dfinish"} } */ >> diff --git a/gcc/testsuite/gcc.target/i386/crc-4-pclmul.c >> b/gcc/testsuite/gcc.target/i386/crc-4-pclmul.c >> new file mode 100644 >> index 00000000000..398ecaa4aba >> --- /dev/null >> +++ b/gcc/testsuite/gcc.target/i386/crc-4-pclmul.c >> @@ -0,0 +1,8 @@ >> +/* { dg-do run } */ >> +/* { dg-options "-mpclmul -O2 -fdump-rtl-dfinish -fdump-tree-crc" } */ >> + >> +#include "../../gcc.dg/torture/crc-4.c" >> + >> +/* { dg-final { scan-tree-dump "calculates CRC!" "crc"} } */ >> +/* { dg-final { scan-tree-dump-times "Couldn't generate faster CRC >> code." 0 "crc"} } */ >> +/* { dg-final { scan-rtl-dump "pclmulqdq" "dfinish"} } */ >> diff --git a/gcc/testsuite/gcc.target/i386/crc-5-pclmul.c >> b/gcc/testsuite/gcc.target/i386/crc-5-pclmul.c >> new file mode 100644 >> index 00000000000..b80368e81bc >> --- /dev/null >> +++ b/gcc/testsuite/gcc.target/i386/crc-5-pclmul.c >> @@ -0,0 +1,9 @@ >> +/* { dg-do run } */ >> +/* { dg-options "-mpclmul -O2 -w -fdump-rtl-dfinish -fdump-tree-crc" } */ >> +/* { dg-skip-if "" { *-*-* } { "-flto"} } */ >> + >> +#include "../../gcc.dg/torture/crc-5.c" >> + >> +/* { dg-final { scan-tree-dump "calculates CRC!" "crc"} } */ >> +/* { dg-final { scan-tree-dump-times "Couldn't generate faster CRC >> code." 0 "crc"} } */ >> +/* { dg-final { scan-rtl-dump "pclmulqdq" "dfinish"} } */ >> \ No newline at end of file >> diff --git a/gcc/testsuite/gcc.target/i386/crc-6-pclmul.c >> b/gcc/testsuite/gcc.target/i386/crc-6-pclmul.c >> new file mode 100644 >> index 00000000000..20b851e3596 >> --- /dev/null >> +++ b/gcc/testsuite/gcc.target/i386/crc-6-pclmul.c >> @@ -0,0 +1,8 @@ >> +/* { dg-do run } */ >> +/* { dg-options "-mpclmul -O2 -fdump-rtl-dfinish -fdump-tree-crc" } */ >> + >> +#include "../../gcc.dg/torture/crc-6.c" >> + >> +/* { dg-final { scan-tree-dump "calculates CRC!" "crc"} } */ >> +/* { dg-final { scan-tree-dump-times "Couldn't generate faster CRC >> code." 0 "crc"} } */ >> +/* { dg-final { scan-rtl-dump "pclmulqdq" "dfinish"} } */ >> \ No newline at end of file >> diff --git a/gcc/testsuite/gcc.target/i386/crc-7-pclmul.c >> b/gcc/testsuite/gcc.target/i386/crc-7-pclmul.c >> new file mode 100644 >> index 00000000000..3e5cc75338e >> --- /dev/null >> +++ b/gcc/testsuite/gcc.target/i386/crc-7-pclmul.c >> @@ -0,0 +1,8 @@ >> +/* { dg-do run } */ >> +/* { dg-options "-mpclmul -O2 -fdump-rtl-dfinish -fdump-tree-crc" } */ >> + >> +#include "../../gcc.dg/torture/crc-7.c" >> + >> +/* { dg-final { scan-tree-dump "calculates CRC!" "crc"} } */ >> +/* { dg-final { scan-tree-dump-times "Couldn't generate faster CRC >> code." 0 "crc"} } */ >> +/* { dg-final { scan-rtl-dump "pclmulqdq" "dfinish"} } */ >> diff --git a/gcc/testsuite/gcc.target/i386/crc-8-pclmul.c >> b/gcc/testsuite/gcc.target/i386/crc-8-pclmul.c >> new file mode 100644 >> index 00000000000..4b1145553fc >> --- /dev/null >> +++ b/gcc/testsuite/gcc.target/i386/crc-8-pclmul.c >> @@ -0,0 +1,8 @@ >> +/* { dg-do run } */ >> +/* { dg-options "-mpclmul -O2 -fdump-rtl-dfinish -fdump-tree-crc" } */ >> + >> +#include "../../gcc.dg/torture/crc-8.c" >> + >> +/* { dg-final { scan-tree-dump "calculates CRC!" "crc"} } */ >> +/* { dg-final { scan-tree-dump-times "Couldn't generate faster CRC >> code." 0 "crc"} } */ >> +/* { dg-final { scan-rtl-dump "pclmulqdq" "dfinish"} } */ >> diff --git a/gcc/testsuite/gcc.target/i386/crc-9-pclmul.c >> b/gcc/testsuite/gcc.target/i386/crc-9-pclmul.c >> new file mode 100644 >> index 00000000000..204d6c84d47 >> --- /dev/null >> +++ b/gcc/testsuite/gcc.target/i386/crc-9-pclmul.c >> @@ -0,0 +1,8 @@ >> +/* { dg-do run } */ >> +/* { dg-options "-mpclmul -O2 -fdump-rtl-dfinish -fdump-tree-crc" } */ >> + >> +#include "../../gcc.dg/torture/crc-9.c" >> + >> +/* { dg-final { scan-tree-dump "calculates CRC!" "crc"} } */ >> +/* { dg-final { scan-tree-dump-times "Couldn't generate faster CRC >> code." 0 "crc"} } */ >> +/* { dg-final { scan-rtl-dump "pclmulqdq" "dfinish"} } */ >> diff --git a/gcc/testsuite/gcc.target/i386/crc-CCIT-data16-pclmul.c >> b/gcc/testsuite/gcc.target/i386/crc-CCIT-data16-pclmul.c >> new file mode 100644 >> index 00000000000..ca728120858 >> --- /dev/null >> +++ b/gcc/testsuite/gcc.target/i386/crc-CCIT-data16-pclmul.c >> @@ -0,0 +1,9 @@ >> +/* { dg-do run } */ >> +/* { dg-options "-w -mpclmul -O2 -fdump-rtl-dfinish -fdump-tree-crc" } */ >> +/* { dg-skip-if "" { *-*-* } { "-flto"} } */ >> + >> +#include "../../gcc.dg/torture/crc-CCIT-data16.c" >> + >> +/* { dg-final { scan-tree-dump "calculates CRC!" "crc"} } */ >> +/* { dg-final { scan-tree-dump-times "Couldn't generate faster CRC >> code." 0 "crc"} } */ >> +/* { dg-final { scan-rtl-dump "pclmulqdq" "dfinish"} } */ >> \ No newline at end of file >> diff --git a/gcc/testsuite/gcc.target/i386/crc-CCIT-data8-pclmul.c >> b/gcc/testsuite/gcc.target/i386/crc-CCIT-data8-pclmul.c >> new file mode 100644 >> index 00000000000..816e0561d8f >> --- /dev/null >> +++ b/gcc/testsuite/gcc.target/i386/crc-CCIT-data8-pclmul.c >> @@ -0,0 +1,9 @@ >> +/* { dg-do run } */ >> +/* { dg-options "-w -mpclmul -O2 -fdump-rtl-dfinish -fdump-tree-crc" } */ >> +/* { dg-skip-if "" { *-*-* } { "-flto" } } */ >> + >> +#include "../../gcc.dg/torture/crc-CCIT-data8.c" >> + >> +/* { dg-final { scan-tree-dump "calculates CRC!" "crc"} } */ >> +/* { dg-final { scan-tree-dump-times "Couldn't generate faster CRC >> code." 0 "crc"} } */ >> +/* { dg-final { scan-rtl-dump "pclmulqdq" "dfinish"} } */ >> \ No newline at end of file >> diff --git >> a/gcc/testsuite/gcc.target/i386/crc-coremark-16bitdata-pclmul.c >> b/gcc/testsuite/gcc.target/i386/crc-coremark-16bitdata-pclmul.c >> new file mode 100644 >> index 00000000000..817d960b0aa >> --- /dev/null >> +++ b/gcc/testsuite/gcc.target/i386/crc-coremark-16bitdata-pclmul.c >> @@ -0,0 +1,9 @@ >> +/* { dg-do run } */ >> +/* { dg-options "-w -mpclmul -O2 -fdump-rtl-dfinish -fdump-tree-crc" } */ >> +/* { dg-skip-if "" { *-*-* } { "-flto"} } */ >> + >> +#include "../../gcc.dg/torture/crc-coremark16-data16.c" >> + >> +/* { dg-final { scan-tree-dump "calculates CRC!" "crc"} } */ >> +/* { dg-final { scan-tree-dump-times "Couldn't generate faster CRC >> code." 0 "crc"} } */ >> +/* { dg-final { scan-rtl-dump "pclmulqdq" "dfinish"} } */ >> \ No newline at end of file >> diff --git a/gcc/testsuite/gcc.target/i386/crc-crc32-data16.c >> b/gcc/testsuite/gcc.target/i386/crc-crc32-data16.c >> new file mode 100644 >> index 00000000000..49ab5f31ef0 >> --- /dev/null >> +++ b/gcc/testsuite/gcc.target/i386/crc-crc32-data16.c >> @@ -0,0 +1,53 @@ >> +/* { dg-do run } */ >> +/* { dg-options "-mcrc32 -O2 -fdump-rtl-dfinish -fdump-tree-crc" } */ >> +/* { dg-skip-if "" { *-*-* } { "-flto"} } */ >> + >> +#include <stdint.h> >> +#include <stdlib.h> >> + >> +__attribute__ ((noinline,optimize(0))) >> +uint32_t _crc32_O0 (uint32_t crc, uint16_t data) { >> + int i; >> + crc = crc ^ data; >> + >> + for (i = 0; i < 8; i++) { >> + if (crc & 1) >> + crc = (crc >> 1) ^ 0x82F63B78; >> + else >> + crc = (crc >> 1); >> + } >> + >> + return crc; >> +} >> + >> +uint32_t _crc32 (uint32_t crc, uint16_t data) { >> + int i; >> + crc = crc ^ data; >> + >> + for (i = 0; i < 8; i++) { >> + if (crc & 1) >> + crc = (crc >> 1) ^ 0x82F63B78; >> + else >> + crc = (crc >> 1); >> + } >> + >> + return crc; >> +} >> + >> +int main () >> +{ >> + uint32_t crc = 0x0D800D80; >> + for (uint16_t i = 0; i < 0xffff; i++) >> + { >> + uint32_t res1 = _crc32_O0 (crc, i); >> + uint32_t res2 = _crc32 (crc, i); >> + if (res1 != res2) >> + abort (); >> + crc = res1; >> + } >> +} >> + >> +/* { dg-final { scan-tree-dump "calculates CRC!" "crc"} } */ >> +/* { dg-final { scan-tree-dump-times "Couldn't generate faster CRC >> code." 0 "crc"} } */ >> +/* { dg-final { scan-rtl-dump "UNSPEC_CRC32" "dfinish"} } */ >> +/* { dg-final { scan-rtl-dump-times "pclmulqdq" 0 "dfinish"} } */ >> diff --git a/gcc/testsuite/gcc.target/i386/crc-crc32-data32.c >> b/gcc/testsuite/gcc.target/i386/crc-crc32-data32.c >> new file mode 100644 >> index 00000000000..08d6c193a77 >> --- /dev/null >> +++ b/gcc/testsuite/gcc.target/i386/crc-crc32-data32.c >> @@ -0,0 +1,53 @@ >> +/* { dg-do run } */ >> +/* { dg-options "-mcrc32 -O2 -fdump-rtl-dfinish -fdump-tree-crc" } */ >> +/* { dg-skip-if "" { *-*-* } { "-flto"} } */ >> + >> +#include <stdint.h> >> +#include <stdlib.h> >> + >> +__attribute__ ((noinline,optimize(0))) >> +uint32_t _crc32_O0 (uint32_t crc, uint32_t data) { >> + int i; >> + crc = crc ^ data; >> + >> + for (i = 0; i < 32; i++) { >> + if (crc & 1) >> + crc = (crc >> 1) ^ 0x82F63B78; >> + else >> + crc = (crc >> 1); >> + } >> + >> + return crc; >> +} >> + >> +uint32_t _crc32 (uint32_t crc, uint32_t data) { >> + int i; >> + crc = crc ^ data; >> + >> + for (i = 0; i < 32; i++) { >> + if (crc & 1) >> + crc = (crc >> 1) ^ 0x82F63B78; >> + else >> + crc = (crc >> 1); >> + } >> + >> + return crc; >> +} >> + >> +int main () >> +{ >> + uint32_t crc = 0x0D800D80; >> + for (uint8_t i = 0; i < 0xff; i++) >> + { >> + uint32_t res1 = _crc32_O0 (crc, i); >> + uint32_t res2 = _crc32 (crc, i); >> + if (res1 != res2) >> + abort (); >> + crc = res1; >> + } >> +} >> + >> +/* { dg-final { scan-tree-dump "calculates CRC!" "crc"} } */ >> +/* { dg-final { scan-tree-dump-times "Couldn't generate faster CRC >> code." 0 "crc"} } */ >> +/* { dg-final { scan-rtl-dump "UNSPEC_CRC32" "dfinish"} } */ >> +/* { dg-final { scan-rtl-dump-times "pclmulqdq" 0 "dfinish"} } */ >> diff --git a/gcc/testsuite/gcc.target/i386/crc-crc32-data8.c >> b/gcc/testsuite/gcc.target/i386/crc-crc32-data8.c >> new file mode 100644 >> index 00000000000..7a76b27fd28 >> --- /dev/null >> +++ b/gcc/testsuite/gcc.target/i386/crc-crc32-data8.c >> @@ -0,0 +1,53 @@ >> +/* { dg-do run } */ >> +/* { dg-options "-mcrc32 -O2 -fdump-rtl-dfinish -fdump-tree-crc" } */ >> +/* { dg-skip-if "" { *-*-* } { "-flto"} } */ >> + >> +#include <stdint.h> >> +#include <stdlib.h> >> + >> +__attribute__ ((noinline,optimize(0))) >> +uint32_t _crc32_O0 (uint32_t crc, uint8_t data) { >> + int i; >> + crc = crc ^ data; >> + >> + for (i = 0; i < 8; i++) { >> + if (crc & 1) >> + crc = (crc >> 1) ^ 0x82F63B78; >> + else >> + crc = (crc >> 1); >> + } >> + >> + return crc; >> +} >> + >> +uint32_t _crc32 (uint32_t crc, uint8_t data) { >> + int i; >> + crc = crc ^ data; >> + >> + for (i = 0; i < 8; i++) { >> + if (crc & 1) >> + crc = (crc >> 1) ^ 0x82F63B78; >> + else >> + crc = (crc >> 1); >> + } >> + >> + return crc; >> +} >> + >> +int main () >> +{ >> + uint32_t crc = 0x0D800D80; >> + for (uint8_t i = 0; i < 0xff; i++) >> + { >> + uint32_t res1 = _crc32_O0 (crc, i); >> + uint32_t res2 = _crc32 (crc, i); >> + if (res1 != res2) >> + abort (); >> + crc = res1; >> + } >> +} >> + >> +/* { dg-final { scan-tree-dump "calculates CRC!" "crc"} } */ >> +/* { dg-final { scan-tree-dump-times "Couldn't generate faster CRC >> code." 0 "crc"} } */ >> +/* { dg-final { scan-rtl-dump "UNSPEC_CRC32" "dfinish"} } */ >> +/* { dg-final { scan-rtl-dump-times "pclmulqdq" 0 "dfinish"} } */ >> -- >> 2.55.0 >> >>
