On Tue, Oct 13, 2026 at 11:05 AM Hongtao Liu <[email protected]> wrote:
> On Mon Oct 12, 2026 at 10:16 PM PDT, Hongtao Liu wrote: > > On Mon Oct 12, 2026 at 9:26 AM PDT, Shreesh Adiga wrote: > >> On Mon, Oct 12, 2026 at 12:45 PM Hongtao Liu <[email protected]> > wrote: > >> > >>> On Sat Oct 10, 2026 at 9:52 AM PDT, Shreesh Adiga 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. > >>> > > >>> > 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: Mariam Arutunian <[email protected]> > >>> > Signed-off-by: Shreesh Adiga <[email protected]> > >>> > --- > >>> > Changes in v2: > >>> > Replaced movabs + movq of quotient and polynomial with a single > >>> > 16 byte load and operate on different lanes of it with pclmul > >>> > selector argument. > >>> > Formatted i386.md changes to remove constraint and comments > >>> > after operand as per suggestion. > >>> > Added missing newline in the tests. > >>> > > >>> > gcc/config/i386/i386-expand.cc | 131 > ++++++++++++++++++ > >>> > gcc/config/i386/i386-protos.h | 3 + > >>> > gcc/config/i386/i386.md | 46 ++++-- > >>> > 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, 483 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..f483a04dfe1 100644 > >>> > --- a/gcc/config/i386/i386-expand.cc > >>> > +++ b/gcc/config/i386/i386-expand.cc > >>> > @@ -29917,4 +29917,135 @@ 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 and polynomial in V2DImode. */ > >>> > + rtvec q_poly_constants = gen_rtvec (2, gen_int_mode (q, DImode), > >>> > + gen_int_mode (UINTVAL > (polynomial), > >>> > + DImode)); > >>> > + rtx constants_v2di = gen_rtx_CONST_VECTOR (V2DImode, > >>> q_poly_constants); > >>> > + rtx constants_mem = validize_mem (force_const_mem (V2DImode, > >>> constants_v2di)); > >>> > + rtx constants_reg = gen_reg_rtx (V2DImode); > >>> > + emit_move_insn (constants_reg, constants_mem); > >>> > + > >>> > + /* 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 with quotient. */ > >>> > + emit_insn (gen_pclmulqdq (res, res, constants_reg, const0_rtx)); > >>> > + > >>> > + res = expand_shift (RSHIFT_EXPR, V2DImode, res, crc_size, > NULL_RTX, > >>> 1); > >>> > + > >>> > + /* Perform carry-less multiplication with polynomial and get low > >>> part. */ > >>> > + emit_insn (gen_pclmulqdq (res, res, constants_reg, > >>> > + gen_int_mode (0x10, 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); > >>> > + > >>> > + unsigned HOST_WIDE_INT reflected_op3 = reflect_hwi (UINTVAL > >>> (polynomial), > >>> > + crc_size); > >>> > + /* Keep the quotient and reflected polynomial in V2DImode. */ > >>> > + rtvec q_poly_constants = gen_rtvec (2, gen_int_mode (q, DImode), > >>> > + gen_int_mode (reflected_op3 << 1, > >>> > + DImode)); > >>> > + rtx constants_v2di = gen_rtx_CONST_VECTOR (V2DImode, > >>> q_poly_constants); > >>> > + rtx constants_mem = validize_mem (force_const_mem (V2DImode, > >>> constants_v2di)); > >>> > + rtx constants_reg = gen_reg_rtx (V2DImode); > >>> > + emit_move_insn (constants_reg, constants_mem); > >>> > + > >>> > + /* 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 with quotient. */ > >>> > + rtx res = gen_reg_rtx (V2DImode); > >>> > + emit_insn (gen_vec_concatv2di (res, cd_xor, const0_rtx)); > >>> > + emit_insn (gen_pclmulqdq (res, res, constants_reg, const0_rtx)); > >>> > + > >>> > + res = expand_shift (LSHIFT_EXPR, V2DImode, res, 64 - data_size, > >>> NULL_RTX, 0); > >>> > + > >>> > + /* Perform carry-less multiplication with polynomial and get high > >>> part. */ > >>> > + emit_insn (gen_pclmulqdq (res, res, constants_reg, > >>> > + gen_int_mode (0x10, 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..d032c2269f4 100644 > >>> > --- a/gcc/config/i386/i386.md > >>> > +++ b/gcc/config/i386/i386.md > >>> > @@ -30504,19 +30504,39 @@ (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" > >>> > + [(match_operand:SWI124 0 "register_operand") ;; return value > >>> (CRC) > >>> > + (match_operand:SWI124 1 "register_operand") ;; initial CRC > >>> > + (match_operand:SWI1248x 2 "register_operand") ;; data > >>> > + (match_operand:SWI124 3 "const_int_operand")] ;; polynomial > >>> > + "TARGET_64BIT && TARGET_PCLMUL > >>> > + && <SWI124:MODE>mode >= <SWI1248x:MODE>mode" > >>> I think pclmul benifts 16/32/64-bit but not 8-bit data? > >>> > >>> > >> It does save on the lookup table though. 32 bit CRC would use 2kB > storage. > >> Do you suggest this should be skipped for 8-bit data? > > Yes. > > > >> > >> > >>> > +{ > >>> > + ix86_expand_crc_using_pclmul (<SWI124:MODE>mode, > <SWI1248x:MODE>mode, > >>> > + operands); > >>> > + DONE; > >>> > +}) > >>> > + > >>> > +;; Reversed CRC > >>> > +(define_expand "crc_rev<SWI1248x:mode><SWI124:mode>4" > >>> > + [(match_operand:SWI124 0 "register_operand") ;; return > value > >>> (CRC) > >>> > + (match_operand:SWI124 1 "register_operand") ;; initial CRC > >>> > + (match_operand:SWI1248x 2 "register_operand") ;; data > >>> > + (match_operand:SWI124 3 "const_int_operand")] ;; polynomial > >>> > + "<SWI124:MODE>mode >= <SWI1248x:MODE>mode" > >>> Should it be > >>> "<SWI124:MODE>mode >= <SWI1248x:MODE>mode > >>> && ((TARGET_64BIT && TARGET_PCLMUL) > >>> || (TARGET_CRC32 && <SWI124:MODE>mode == SImode))" ? > >>> > >>> Without an ISA test, crc_rev is now available on every x86 target. > >>> I think the purpose of the patch is to extend it with PCLMUL but not > >>> change other behaviors? > >>> > >>> > >> The else part is generic right? Is it necessary to have all the ISA > tests > >> here? > >> I'm planning to remove the 64 bit check as this seems to also work for > 32 > >> bit as well. > > Yes else part is generic, but the existenece of the optab impacts the > > middle-end optimization decisions(it replaces bit loop with optab when > it's > > available, but the body then emits the table which has bigger codesize > than > > bit loop), I think that's why we have TARGET_CRC32 in the original > crc_rev > > optab, so I think we probably should also keep TARGET_64BIT check > instead of > > falling back to table solution. > Looks like the patch can generate pclmul solution for ia32 too, so removing > TARGET_64BIT won't fall back to table solution, and should be ok. > >> > >> Thanks, > >> Shreesh > >> > >> > >>> > + { > >>> > + /* 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_64BIT && TARGET_PCLMUL) > >>> > + 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..f423c08cf07 > >>> > --- /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"} } */ > >>> > 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..4b487fefd95 > >>> > --- /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"} } */ > >>> > 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..614423039d4 > >>> > --- /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"} } */ > >>> > 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..1676eb5265b > >>> > --- /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"} } */ > >>> > 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..241181f89e2 > >>> > --- /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"} } */ > >>> > 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..c64d17e30fd > >>> > --- /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"} } */ > >>> > 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 > >>> > >>> > > Thanks for the various suggestions and explanations! I've incorporated most of the suggestions and submitted v3 follow-up. This will only cover 16-bit and 32-bit CRCs with 16/32 bit data. 64-bit will be separately taken up once this is merged. One last thing that I was wondering to change for 32-bit target is + /* 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)); I'd like to use movd to move the reg value to XMM but here it seems to be generating movq which is okay on 64-bit but slightly inefficient on 32-bit. If someone could provide details on how to achieve this then I'd be happy to make the changes. Thanks, Shreesh
