On Sun, Oct 11, 2026 at 1:29 PM Uros Bizjak <[email protected]> wrote:
> On Fri, Oct 9, 2026 at 5:09 PM Shreesh Adiga > <[email protected]> wrote: > > > > > > > > On Thu, Oct 8, 2026 at 10:25 PM Uros Bizjak <[email protected]> wrote: > >> > >> On Wed, Oct 7, 2026 at 5:28 PM Shreesh Adiga > >> <[email protected]> wrote: > >> > > >> > 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]> > >> > >> Mariam's signoff is needed here. > >> > >> >>> --- > >> >>> 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)); > >> > >> This will move the constant through GPR and will result in movabs (a > >> costly insn) and inter-unit movq. It is probably cheaper to have a > >> DImode constant in the constant pool and movq it from there. I assume > >> the compiler will move the memory load out of the loop by itself. > >> > >> >>> + /* 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))); > >> > >> const0_rtx > >> > >> >>> + > >> >>> + 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)); > >> > >> Here you should use movd from memory (sse2_loadld + some subreg magic). > >> > > > > Sure I have been looking into the review suggestions and have made the > changes locally. > > I just wanted to confirm if doing movq (quotient) + clmul + movd > (polynomial) + clmul is better than doing > > movdqa (quotient, polynomial) + clmul + clmul with different selector > argument instead of 0. > > Could you share your views on whether clubbing the two constants into a > single XMM register load and > > performing clmul with different lanes would be better or not? > > I don’t have performance data for this, and as the proposer it’s your > job to benchmark the alternatives. My expectation is that a single > 16-byte load with different clmul selectors is no worse than movq + > movd (fewer uops, no GPR→XMM move), but please verify. Agner Fog’s > tables [1] are a good start, and uiCA/llvm-mca can help with > estimates. Please post measured numbers from at least Intel and AMD > with the next revision. > > Sorry I've already submitted v2 yesterday with the changes. My reasoning was around reduced instruction count and register usage. I briefly looked at the instruction table and for nehalem and zen 4. I don't see movdqa being costlier than movq + movd with mem operand and they all look the same cost wise. Plus the constants reg is also preserved which should get hoisted in case of inside a loop. Therefore I think the v2 submission should be good enough. Thanks, Shreesh > [1] https://www.agner.org/optimize/ > > Uros. > > > > > Thanks, > > Shreesh > > > >> >>> + > >> >>> + /* 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) > >> > >> The same comments as above apply to this function, too. > >> > >> >>> +{ > >> >>> + /* 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") > >> > >> Please remove constraints, they are ignored in expanders. Also, please > >> place comments after operands, see e.g. atomic_compare_and_swap<mode>. > >> > >> >>> + ;; polynomial without leading 1 > >> >>> + (match_operand:SWI124 3 "const_int_operand")] > >> >>> + "TARGET_PCLMUL && TARGET_64BIT && <SWI124:MODE>mode >= > <SWI1248x:MODE>mode" > >> > >> Please write: > >> > >> TARGET_64BIT && TARGET_PCLMUL > >> && <SWI124... > >> > >> Please mind the line length limit. > >> > >> >>> +{ > >> >>> + 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")] > >> > >> Same here. > >> > >> >>> + "<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 > >> > >> Please put a newline here, also in other test files. > >> > >> Uros. > >> > >> >>> 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 > >> >>> >
