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.
>
> 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
>>
>>