On Wed, Oct 21, 2026 at 12:21 PM Shreesh Adiga <[email protected]> wrote: > > This patch extends pclmul expanders for the i386 backend to > generate optimized code for CRC64 computations. > > This is an extension to the 16-bit and 32-bit data CRC computation added > earlier. The algorithm is slightly different which is described in the > paper "Fast CRC Computation for Generic Polynomials Using PCLMULQDQ > Instruction" described in the section > "Barrett Reduction Algorithm for a degree-64 polynomial modulus > (polynomials defined over GF(2))" Page 17 and 18. > > Bit-reverse CRC also is based on the above, except that the bit 65 after > performing bit-reflect of polynomial maybe 0 and thus the xor operation > needs to be conditionally performed only when LSB=1. > > The quotient computation which needs 65 bits now returns the lower 64 > bits and the 65th bit is assumed to be 1 since the polynomials are > expected to have the leading bit to be 1. Thus the assert is modified to > allow the 64 bit cases as well. > > Added tests for covering 8-bit, 16-bit, 32-bit and 64-bit for both > forward and reverse CRC64, along with reverse CRC64 testing for > polynomials with LSB=0 and LSB=1 as well that gets passed into the CRC > expander. > > gcc/ChangeLog: > > * config/i386/i386-expand.cc (ix86_expand_crc_using_pclmul): > Modified to allow 64-bit CRC. > (ix86_expand_reversed_crc_using_pclmul): Likewise. > * config/i386/i386.md (crc<SWI248x:mode><SWI24:mode>4): Renamed > the second iterator to allow 64-bit CRC. > (crc<SWI1248x:mode><SWI248x:mode>4): Likewise. > (crc_rev<SWI1248x:mode><SWI24:mode>4): Likewise. > (crc_rev<SWI1248x:mode><SWI248x:mode>4): Likewise. > * expr.cc (gf2n_poly_long_div_quotient): Relaxed assert to allow > computing lower 64-bit of quotient for 64-bit CRC. > > gcc/testsuite/ChangeLog: > > * gcc.dg/torture/crc-34.c: New test. > * gcc.dg/torture/crc-35.c: New test. > * gcc.dg/torture/crc-36.c: New test. > * gcc.dg/torture/crc-37.c: New test. > * gcc.dg/torture/crc-38.c: New test. > * gcc.dg/torture/crc-39.c: New test. > * gcc.dg/torture/crc-40.c: New test. > * gcc.dg/torture/crc-41.c: New test. > * gcc.target/i386/crc-34-pclmul.c: New test. > * gcc.target/i386/crc-35-pclmul.c: New test. > * gcc.target/i386/crc-36-pclmul.c: New test. > * gcc.target/i386/crc-37-pclmul.c: New test. > * gcc.target/i386/crc-38-pclmul.c: New test. > * gcc.target/i386/crc-39-pclmul.c: New test. > * gcc.target/i386/crc-40-pclmul.c: New test. > * gcc.target/i386/crc-41-pclmul.c: New test.
OK. Reviewed-by: Uros Bizjak <[email protected]> expr.cc change was approved by Jeff in [1]. Pushed. [1] https://gcc.gnu.org/pipermail/gcc-patches/2026-October/735613.html Thanks, Uros. > > Signed-off-by: Shreesh Adiga <[email protected]> > --- > Changes in v4: > Removed extra braces for single line statements. > Removed extra gen_lowpart for V2DImode. > Updated CRC64_POLY2 in test to be consistent. > Renamed temp variable to crc_temp as per review request. > > Changes in v3: > Incorporated review suggestions around untangling the clmul expander > to have less duplications. > Made the tests run for 256 iterations and renamed expand8 as well. > Clarified commit message comment around LSB for bit-reverse. > > Changes in v2: > extended the existing routines instead of adding new expanders. > changed the iterators in md file to be able to support 64-bit CRC. > > gcc/config/i386/i386-expand.cc | 119 +++++++++++++----- > gcc/config/i386/i386.md | 38 +++--- > gcc/expr.cc | 6 +- > gcc/testsuite/gcc.dg/torture/crc-34.c | 56 +++++++++ > gcc/testsuite/gcc.dg/torture/crc-35.c | 56 +++++++++ > gcc/testsuite/gcc.dg/torture/crc-36.c | 65 ++++++++++ > gcc/testsuite/gcc.dg/torture/crc-37.c | 65 ++++++++++ > gcc/testsuite/gcc.dg/torture/crc-38.c | 89 +++++++++++++ > gcc/testsuite/gcc.dg/torture/crc-39.c | 89 +++++++++++++ > gcc/testsuite/gcc.dg/torture/crc-40.c | 98 +++++++++++++++ > gcc/testsuite/gcc.dg/torture/crc-41.c | 98 +++++++++++++++ > gcc/testsuite/gcc.target/i386/crc-34-pclmul.c | 9 ++ > gcc/testsuite/gcc.target/i386/crc-35-pclmul.c | 8 ++ > gcc/testsuite/gcc.target/i386/crc-36-pclmul.c | 8 ++ > gcc/testsuite/gcc.target/i386/crc-37-pclmul.c | 8 ++ > gcc/testsuite/gcc.target/i386/crc-38-pclmul.c | 9 ++ > gcc/testsuite/gcc.target/i386/crc-39-pclmul.c | 8 ++ > gcc/testsuite/gcc.target/i386/crc-40-pclmul.c | 8 ++ > gcc/testsuite/gcc.target/i386/crc-41-pclmul.c | 8 ++ > 19 files changed, 792 insertions(+), 53 deletions(-) > create mode 100644 gcc/testsuite/gcc.dg/torture/crc-34.c > create mode 100644 gcc/testsuite/gcc.dg/torture/crc-35.c > create mode 100644 gcc/testsuite/gcc.dg/torture/crc-36.c > create mode 100644 gcc/testsuite/gcc.dg/torture/crc-37.c > create mode 100644 gcc/testsuite/gcc.dg/torture/crc-38.c > create mode 100644 gcc/testsuite/gcc.dg/torture/crc-39.c > create mode 100644 gcc/testsuite/gcc.dg/torture/crc-40.c > create mode 100644 gcc/testsuite/gcc.dg/torture/crc-41.c > create mode 100644 gcc/testsuite/gcc.target/i386/crc-34-pclmul.c > create mode 100644 gcc/testsuite/gcc.target/i386/crc-35-pclmul.c > create mode 100644 gcc/testsuite/gcc.target/i386/crc-36-pclmul.c > create mode 100644 gcc/testsuite/gcc.target/i386/crc-37-pclmul.c > create mode 100644 gcc/testsuite/gcc.target/i386/crc-38-pclmul.c > create mode 100644 gcc/testsuite/gcc.target/i386/crc-39-pclmul.c > create mode 100644 gcc/testsuite/gcc.target/i386/crc-40-pclmul.c > create mode 100644 gcc/testsuite/gcc.target/i386/crc-41-pclmul.c > > diff --git a/gcc/config/i386/i386-expand.cc b/gcc/config/i386/i386-expand.cc > index c0869abcf49..2b709a9262f 100644 > --- a/gcc/config/i386/i386-expand.cc > +++ b/gcc/config/i386/i386-expand.cc > @@ -29936,15 +29936,17 @@ ix86_expand_crc_using_pclmul (scalar_mode crc_mode, > > 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 (crc_size <= 64); > gcc_assert (data_size <= crc_size); > > + machine_mode op_mode = crc_size == 64 ? DImode : SImode; > + > /* 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, SImode, crc, crc_size - data_size, > + crc = expand_shift (RSHIFT_EXPR, op_mode, crc, crc_size - data_size, > NULL_RTX, 1); > > /* Keep the quotient and polynomial in V2DImode. */ > @@ -29956,29 +29958,53 @@ ix86_expand_crc_using_pclmul (scalar_mode crc_mode, > emit_move_insn (constants_reg, constants_v2di); > > /* crc ^ data and keep in V2DImode. */ > - rtx cd_xor = expand_binop (SImode, xor_optab, crc, data, NULL_RTX, 1, > + rtx cd_xor = expand_binop (op_mode, xor_optab, crc, data, NULL_RTX, 1, > OPTAB_WIDEN); > - rtx res = gen_reg_rtx (V4SImode); > - emit_insn (gen_vec_setv4si_0 (res, CONST0_RTX (V4SImode), cd_xor)); > - res = gen_lowpart (V2DImode, res); > + rtx crc_temp; > + if (op_mode == DImode) > + { > + crc_temp = gen_reg_rtx (V2DImode); > + emit_insn (gen_vec_concatv2di (crc_temp, cd_xor, cd_xor)); > + } > + else > + { > + crc_temp = gen_reg_rtx (V4SImode); > + emit_insn (gen_vec_setv4si_0 (crc_temp, CONST0_RTX (V4SImode), > cd_xor)); > + crc_temp = gen_lowpart (V2DImode, crc_temp); > + } > + > /* Perform carry-less multiplication with quotient. */ > - emit_insn (gen_pclmulqdq (res, res, constants_reg, const0_rtx)); > + rtx res = gen_reg_rtx (V2DImode); > + emit_insn (gen_pclmulqdq (res, crc_temp, constants_reg, const0_rtx)); > > - res = expand_shift (RSHIFT_EXPR, V2DImode, res, crc_size, NULL_RTX, 1); > + if (op_mode == DImode) > + { > + /* Perform res ^ crc to handle 65th bit of quotient. */ > + res = expand_binop (V2DImode, xor_optab, res, crc_temp, NULL_RTX, 1, > + OPTAB_WIDEN); > + } > + else > + 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 (SImode); > - res = gen_lowpart (V4SImode, res); > - emit_insn (gen_vec_extractv4sisi (crc_part, res, const0_rtx)); > + GEN_INT (op_mode == DImode ? 0x11 : 0x10))); > + > + rtx crc_part = gen_reg_rtx (op_mode); > + if (op_mode == DImode) > + emit_insn (gen_vec_extractv2didi (crc_part, res, const0_rtx)); > + else > + { > + res = gen_lowpart (V4SImode, res); > + emit_insn (gen_vec_extractv4sisi (crc_part, res, const0_rtx)); > + } > > if (crc_size > data_size) > { > - rtx shift = expand_shift (LSHIFT_EXPR, SImode, operands[1], data_size, > + rtx shift = expand_shift (LSHIFT_EXPR, op_mode, operands[1], data_size, > NULL_RTX, 1); > - crc_part = expand_binop (SImode, xor_optab, crc_part, shift, NULL_RTX, > 1, > - OPTAB_DIRECT); > + crc_part = expand_binop (op_mode, xor_optab, crc_part, shift, > + NULL_RTX, 1, OPTAB_DIRECT); > } > emit_move_insn (operands[0], gen_lowpart (crc_mode, crc_part)); > } > @@ -30002,14 +30028,16 @@ ix86_expand_reversed_crc_using_pclmul (scalar_mode > crc_mode, > > 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 (crc_size <= 64); > gcc_assert (data_size <= crc_size); > > + machine_mode op_mode = crc_size == 64 ? DImode : SImode; > + > /* 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); > + q = (reflect_hwi (q, crc_size) << 1) + 1; > > unsigned HOST_WIDE_INT reflected_op3 = reflect_hwi (UINTVAL (polynomial), > crc_size); > @@ -30022,30 +30050,55 @@ ix86_expand_reversed_crc_using_pclmul (scalar_mode > crc_mode, > emit_move_insn (constants_reg, constants_v2di); > > /* crc ^ data and keep in V2DImode. */ > - rtx cd_xor = expand_binop (SImode, xor_optab, crc, data, NULL_RTX, 1, > + rtx cd_xor = expand_binop (op_mode, xor_optab, crc, data, NULL_RTX, 1, > OPTAB_WIDEN); > > - /* Perform carry-less multiplication with quotient. */ > - rtx res = gen_reg_rtx (V4SImode); > - emit_insn (gen_vec_setv4si_0 (res, CONST0_RTX (V4SImode), cd_xor)); > - res = gen_lowpart (V2DImode, res); > - emit_insn (gen_pclmulqdq (res, res, constants_reg, const0_rtx)); > + rtx crc_temp; > + if (op_mode == DImode) > + { > + crc_temp = gen_reg_rtx (V2DImode); > + emit_insn (gen_vec_concatv2di (crc_temp, cd_xor, const0_rtx)); > + } > + else > + { > + crc_temp = gen_reg_rtx (V4SImode); > + emit_insn (gen_vec_setv4si_0 (crc_temp, CONST0_RTX (V4SImode), > cd_xor)); > + crc_temp = gen_lowpart (V2DImode, crc_temp); > + } > > - res = expand_shift (LSHIFT_EXPR, V2DImode, res, 64 - data_size, NULL_RTX, > 0); > + /* Perform carry-less multiplication with quotient. */ > + emit_insn (gen_pclmulqdq (crc_temp, crc_temp, constants_reg, const0_rtx)); > + if (data_size < 64) > + crc_temp = expand_shift (LSHIFT_EXPR, V2DImode, crc_temp, 64 - data_size, > + NULL_RTX, 0); > + > + rtx res = gen_reg_rtx (V2DImode); > + /* Perform carry-less multiplication with polynomial. */ > + emit_insn (gen_pclmulqdq (res, crc_temp, constants_reg, GEN_INT (0x10))); > + if (op_mode == DImode && (UINTVAL (polynomial) & 1)) > + { > + /* Perform xor of res[127:64] with temp[63:0]. > + This is needed when the 65th bit of reflected polynomial is 1. */ > + emit_insn (gen_vec_interleave_lowv2di (crc_temp, crc_temp, crc_temp)); > + res = expand_binop (V2DImode, xor_optab, res, crc_temp, NULL_RTX, 1, > + OPTAB_WIDEN); > + } > > - /* 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 (SImode); > - res = gen_lowpart (V4SImode, res); > - emit_insn (gen_vec_extractv4sisi (res_high, res, const2_rtx)); > + rtx res_high = gen_reg_rtx (op_mode); > + if (op_mode == DImode) > + emit_insn (gen_vec_extractv2didi (res_high, res, const1_rtx)); > + else > + { > + res = gen_lowpart (V4SImode, res); > + emit_insn (gen_vec_extractv4sisi (res_high, res, const2_rtx)); > + } > > if (crc_size > data_size) > { > - rtx shift = expand_shift (RSHIFT_EXPR, SImode, crc, data_size, > + rtx shift = expand_shift (RSHIFT_EXPR, op_mode, crc, data_size, > NULL_RTX, 1); > - res_high = expand_binop (SImode, xor_optab, res_high, shift, NULL_RTX, > 1, > - OPTAB_DIRECT); > + res_high = expand_binop (op_mode, xor_optab, res_high, shift, > + NULL_RTX, 1, OPTAB_DIRECT); > } > emit_move_insn (operands[0], gen_lowpart (crc_mode, res_high)); > } > diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md > index fbd227ac40a..89745e9a810 100644 > --- a/gcc/config/i386/i386.md > +++ b/gcc/config/i386/i386.md > @@ -30505,37 +30505,39 @@ (define_insn "sse4_2_crc32di" > (set_attr "mode" "DI")]) > > ;; Bit-forward CRC > -(define_expand "crc<SWI248x:mode><SWI24:mode>4" > - [(match_operand:SWI24 0 "register_operand") ;; return value (CRC) > - (match_operand:SWI24 1 "register_operand") ;; initial CRC > - (match_operand:SWI248x 2 "nonimmediate_operand") ;; data > - (match_operand:SWI24 3 "const_int_operand")] ;; polynomial > - "TARGET_PCLMUL && <SWI24:MODE>mode >= <SWI248x:MODE>mode" > -{ > - ix86_expand_crc_using_pclmul (<SWI24:MODE>mode, <SWI248x:MODE>mode, > +(define_expand "crc<SWI1248x:mode><SWI248x:mode>4" > + [(match_operand:SWI248x 0 "register_operand") ;; return value (CRC) > + (match_operand:SWI248x 1 "register_operand") ;; initial CRC > + (match_operand:SWI1248x 2 "nonimmediate_operand") ;; data > + (match_operand:SWI248x 3 "const_int_operand")] ;; polynomial > + "TARGET_PCLMUL && <SWI248x:MODE>mode >= <SWI1248x:MODE>mode > + && <SWI1248x:MODE>mode != QImode" > +{ > + /* Generate pclmul expansion for 16-bit, 32-bit and 64-bit data. */ > + ix86_expand_crc_using_pclmul (<SWI248x:MODE>mode, <SWI1248x:MODE>mode, > operands); > DONE; > }) > > ;; Reversed CRC > -(define_expand "crc_rev<SWI1248x:mode><SWI24:mode>4" > - [(match_operand:SWI24 0 "register_operand") ;; return value (CRC) > - (match_operand:SWI24 1 "register_operand") ;; initial CRC > +(define_expand "crc_rev<SWI1248x:mode><SWI248x:mode>4" > + [(match_operand:SWI248x 0 "register_operand") ;; return value (CRC) > + (match_operand:SWI248x 1 "register_operand") ;; initial CRC > (match_operand:SWI1248x 2 "nonimmediate_operand") ;; data > - (match_operand:SWI24 3 "const_int_operand")] ;; polynomial > - "(TARGET_PCLMUL && <SWI24:MODE>mode >= <SWI1248x:MODE>mode > + (match_operand:SWI248x 3 "const_int_operand")] ;; polynomial > + "(TARGET_PCLMUL && <SWI248x:MODE>mode >= <SWI1248x:MODE>mode > && <SWI1248x:MODE>mode != QImode) > - || (TARGET_CRC32 && <SWI24:MODE>mode == SImode)" > + || (TARGET_CRC32 && <SWI248x:MODE>mode == SImode)" > { > /* If it is iSCSI polynomial (0x1EDC6F41), generate crc32 instruction. > */ > if (TARGET_CRC32 && INTVAL (operands[3]) == 0x1EDC6F41 > - && <SWI24:MODE>mode == SImode) > + && <SWI248x:MODE>mode == SImode) > emit_insn (gen_sse4_2_crc32<SWI1248x:mode> (operands[0], operands[1], > operands[2])); > - /* Generate pclmul expansion for 16-bit and 32-bit data. */ > - else if (TARGET_PCLMUL && <SWI24:MODE>mode >= <SWI1248x:MODE>mode > + /* Generate pclmul expansion for 16-bit, 32-bit and 64-bit data. */ > + else if (TARGET_PCLMUL && <SWI248x:MODE>mode >= <SWI1248x:MODE>mode > && <SWI1248x:MODE>mode != QImode) > - ix86_expand_reversed_crc_using_pclmul (<SWI24:MODE>mode, > + ix86_expand_reversed_crc_using_pclmul (<SWI248x:MODE>mode, > <SWI1248x:MODE>mode, operands); > else > expand_reversed_crc_table_based (operands[0], operands[1], operands[2], > diff --git a/gcc/expr.cc b/gcc/expr.cc > index 3d99be8472f..6c98277aaaa 100644 > --- a/gcc/expr.cc > +++ b/gcc/expr.cc > @@ -14562,8 +14562,10 @@ unsigned HOST_WIDE_INT > gf2n_poly_long_div_quotient (unsigned HOST_WIDE_INT polynomial, > unsigned short n) > { > - /* The result has degree N, so needs N + 1 bits. */ > - gcc_assert (n < 64); > + /* The result has degree N, so needs N + 1 bits. > + For 64-bit CRC, compute the lower 64 bits of the division. > + The 65th bit is 1 since the leading bit of polynomial is 1. */ > + gcc_assert (n <= 64); > > /* Perform a division step for the x^2N coefficient. At this point the > quotient and remainder have N implicit trailing zeros. */ > diff --git a/gcc/testsuite/gcc.dg/torture/crc-34.c > b/gcc/testsuite/gcc.dg/torture/crc-34.c > new file mode 100644 > index 00000000000..d25fcc51620 > --- /dev/null > +++ b/gcc/testsuite/gcc.dg/torture/crc-34.c > @@ -0,0 +1,56 @@ > +/* { dg-do run { target lp64 } } */ > +/* { dg-options "-fdump-tree-crc-details -w" } */ > +/* { dg-skip-if "" { *-*-* } { "-O0" "-O1" "-g" "-Os" "-flto" } } */ > + > +#include <stdint.h> > +#include <stdlib.h> > + > +// CRC64_ECMA_182 > +#define CRC64_POLY 0x42F0E1EBA9EA3693 > + > +// Test bit-forward CRC64 8-bit data > +__attribute__ ((noinline,optimize(0))) > +uint64_t _crc64_O0 (uint8_t data, uint64_t crc) { > + int i; > + for (i = 0; i < 8; i++) { > + if (((crc & 0x8000000000000000) >> 56 ^ (data & 0x80))) > + crc = (crc << 1) ^ CRC64_POLY; > + else > + crc = (crc << 1); > + data <<= 1; > + } > + return crc; > +} > + > +uint64_t _crc64 (uint8_t data, uint64_t crc) { > + int i; > + for (i = 0; i < 8; i++) { > + if (((crc & 0x8000000000000000) >> 56 ^ (data & 0x80))) > + crc = (crc << 1) ^ CRC64_POLY; > + else > + crc = (crc << 1); > + data <<= 1; > + } > + return crc; > +} > + > +int main () > +{ > + uint64_t crc = 0; > + > + for (uint16_t i = 0; i <= 0xff; i++) > + { > + uint8_t data = (uint8_t)i; > + uint64_t res1 = _crc64_O0 (data, crc); > + uint64_t res2 = _crc64 (data, crc); > + crc = res2; > + if (res1 != res2) > + abort (); > + } > +} > + > +/* { dg-final { scan-tree-dump "function maybe contains CRC calculation." > "crc" } } */ > +/* { dg-final { scan-tree-dump "Loop iteration number is 7" "crc" } } */ > +/* { dg-final { scan-tree-dump "Bit forward" "crc" } } */ > +/* { dg-final { scan-tree-dump "calculates CRC!" "crc" } } */ > +/* { dg-final { scan-tree-dump-times "Couldn't generate faster CRC code." 0 > "crc" } } */ > diff --git a/gcc/testsuite/gcc.dg/torture/crc-35.c > b/gcc/testsuite/gcc.dg/torture/crc-35.c > new file mode 100644 > index 00000000000..40e7d447395 > --- /dev/null > +++ b/gcc/testsuite/gcc.dg/torture/crc-35.c > @@ -0,0 +1,56 @@ > +/* { dg-do run { target lp64 } } */ > +/* { dg-options "-fdump-tree-crc-details -w" } */ > +/* { dg-skip-if "" { *-*-* } { "-O0" "-O1" "-g" "-Os" "-flto" } } */ > + > +#include <stdint.h> > +#include <stdlib.h> > + > +// CRC64_ECMA_182 > +#define CRC64_POLY 0x42F0E1EBA9EA3693 > + > +// Test bit-forward CRC64 16-bit data > +__attribute__ ((noinline,optimize(0))) > +uint64_t _crc64_O0 (uint16_t data, uint64_t crc) { > + int i; > + for (i = 0; i < 16; i++) { > + if (((crc & 0x8000000000000000) >> 48 ^ (data & 0x8000))) > + crc = (crc << 1) ^ CRC64_POLY; > + else > + crc = (crc << 1); > + data <<= 1; > + } > + return crc; > +} > + > +uint64_t _crc64 (uint16_t data, uint64_t crc) { > + int i; > + for (i = 0; i < 16; i++) { > + if (((crc & 0x8000000000000000) >> 48 ^ (data & 0x8000))) > + crc = (crc << 1) ^ CRC64_POLY; > + else > + crc = (crc << 1); > + data <<= 1; > + } > + return crc; > +} > + > +int main () > +{ > + uint64_t crc = 0; > + > + for (uint16_t i = 0; i <= 0xff; i++) > + { > + uint16_t data = (i << 8) | (~i); // cover 2-byte range > + uint64_t res1 = _crc64_O0 (data, crc); > + uint64_t res2 = _crc64 (data, crc); > + crc = res2; > + if (res1 != res2) > + abort (); > + } > +} > + > +/* { dg-final { scan-tree-dump "function maybe contains CRC calculation." > "crc" } } */ > +/* { dg-final { scan-tree-dump "Loop iteration number is 15" "crc" } } */ > +/* { dg-final { scan-tree-dump "Bit forward" "crc" } } */ > +/* { dg-final { scan-tree-dump "calculates CRC!" "crc" } } */ > +/* { dg-final { scan-tree-dump-times "Couldn't generate faster CRC code." 0 > "crc" } } */ > diff --git a/gcc/testsuite/gcc.dg/torture/crc-36.c > b/gcc/testsuite/gcc.dg/torture/crc-36.c > new file mode 100644 > index 00000000000..b9b0c3fc7bd > --- /dev/null > +++ b/gcc/testsuite/gcc.dg/torture/crc-36.c > @@ -0,0 +1,65 @@ > +/* { dg-do run { target lp64 } } */ > +/* { dg-options "-fdump-tree-crc-details -w" } */ > +/* { dg-skip-if "" { *-*-* } { "-O0" "-O1" "-g" "-Os" "-flto" } } */ > + > +#include <stdint.h> > +#include <stdlib.h> > + > +// CRC64_ECMA_182 > +#define CRC64_POLY 0x42F0E1EBA9EA3693 > + > +uint32_t expand8to32 (uint32_t x) { > + x ^= x >> 16; > + x *= 0x7feb352dU; > + x ^= x >> 15; > + x *= 0x846ca68bU; > + x ^= x >> 16; > + return x; > +} > + > +// Test bit-forward CRC64 32-bit data > +__attribute__ ((noinline,optimize(0))) > +uint64_t _crc64_O0 (uint32_t data, uint64_t crc) { > + int i; > + for (i = 0; i < 32; i++) { > + if (((crc & 0x8000000000000000) >> 32 ^ (data & 0x80000000))) > + crc = (crc << 1) ^ CRC64_POLY; > + else > + crc = (crc << 1); > + data <<= 1; > + } > + return crc; > +} > + > +uint64_t _crc64 (uint32_t data, uint64_t crc) { > + int i; > + for (i = 0; i < 32; i++) { > + if (((crc & 0x8000000000000000) >> 32 ^ (data & 0x80000000))) > + crc = (crc << 1) ^ CRC64_POLY; > + else > + crc = (crc << 1); > + data <<= 1; > + } > + return crc; > +} > + > +int main () > +{ > + uint64_t crc = 0; > + > + for (uint32_t i = 0; i <= 0xff; i++) > + { > + uint32_t data = expand8to32 (i); > + uint64_t res1 = _crc64_O0 (data, crc); > + uint64_t res2 = _crc64 (data, crc); > + crc = res2; > + if (res1 != res2) > + abort (); > + } > +} > + > +/* { dg-final { scan-tree-dump "function maybe contains CRC calculation." > "crc" } } */ > +/* { dg-final { scan-tree-dump "Loop iteration number is 31" "crc" } } */ > +/* { dg-final { scan-tree-dump "Bit forward" "crc" } } */ > +/* { dg-final { scan-tree-dump "calculates CRC!" "crc" } } */ > +/* { dg-final { scan-tree-dump-times "Couldn't generate faster CRC code." 0 > "crc" } } */ > diff --git a/gcc/testsuite/gcc.dg/torture/crc-37.c > b/gcc/testsuite/gcc.dg/torture/crc-37.c > new file mode 100644 > index 00000000000..2445730d449 > --- /dev/null > +++ b/gcc/testsuite/gcc.dg/torture/crc-37.c > @@ -0,0 +1,65 @@ > +/* { dg-do run { target lp64 } } */ > +/* { dg-options "-fdump-tree-crc-details -w" } */ > +/* { dg-skip-if "" { *-*-* } { "-O0" "-O1" "-g" "-Os" "-flto" } } */ > + > +#include <stdint.h> > +#include <stdlib.h> > + > +// CRC64_ECMA_182 > +#define CRC64_POLY 0x42F0E1EBA9EA3693 > + > +uint64_t expand8to64 (uint64_t x) { > + x ^= x >> 30; > + x *= UINT64_C(0xbf58476d1ce4e5b9); > + x ^= x >> 27; > + x *= UINT64_C(0x94d049bb133111eb); > + x ^= x >> 31; > + return x; > +} > + > +// Test bit-forward CRC64 64-bit data > +__attribute__ ((noinline,optimize(0))) > +uint64_t _crc64_O0 (uint64_t data, uint64_t crc) { > + int i; > + for (i = 0; i < 64; i++) { > + if (((crc & 0x8000000000000000) ^ (data & 0x8000000000000000))) > + crc = (crc << 1) ^ CRC64_POLY; > + else > + crc = (crc << 1); > + data <<= 1; > + } > + return crc; > +} > + > +uint64_t _crc64 (uint64_t data, uint64_t crc) { > + int i; > + for (i = 0; i < 64; i++) { > + if (((crc & 0x8000000000000000) ^ (data & 0x8000000000000000))) > + crc = (crc << 1) ^ CRC64_POLY; > + else > + crc = (crc << 1); > + data <<= 1; > + } > + return crc; > +} > + > +int main () > +{ > + uint64_t crc = 0; > + > + for (uint64_t i = 0; i <= 0xff; i++) > + { > + uint64_t data = expand8to64 (i); > + uint64_t res1 = _crc64_O0 (data, crc); > + uint64_t res2 = _crc64 (data, crc); > + crc = res2; > + if (res1 != res2) > + abort (); > + } > +} > + > +/* { dg-final { scan-tree-dump "function maybe contains CRC calculation." > "crc" } } */ > +/* { dg-final { scan-tree-dump "Loop iteration number is 63" "crc" } } */ > +/* { dg-final { scan-tree-dump "Bit forward" "crc" } } */ > +/* { dg-final { scan-tree-dump "calculates CRC!" "crc" } } */ > +/* { dg-final { scan-tree-dump-times "Couldn't generate faster CRC code." 0 > "crc" } } */ > diff --git a/gcc/testsuite/gcc.dg/torture/crc-38.c > b/gcc/testsuite/gcc.dg/torture/crc-38.c > new file mode 100644 > index 00000000000..a37aa492a17 > --- /dev/null > +++ b/gcc/testsuite/gcc.dg/torture/crc-38.c > @@ -0,0 +1,89 @@ > +/* { dg-do run { target lp64 } } */ > +/* { dg-options "-fdump-tree-crc-details -w" } */ > +/* { dg-skip-if "" { *-*-* } { "-O0" "-O1" "-g" "-Os" "-flto" } } */ > + > +#include <stdint.h> > +#include <stdlib.h> > + > +#define CRC64_POLY1 0x9A6C9329AC4BC9B5 > +#define CRC64_POLY2 0x1A6C9329AC4BC9B4 > + > +// Test bit-reverse CRC64 8-bit data with Poly having LSB=1 > +__attribute__ ((noinline,optimize(0))) > +uint64_t _crc64_poly1_O0 (uint8_t data, uint64_t crc) { > + int i; > + for (i = 0; i < 8; i++) { > + if (((crc & 0x1) ^ (data & 0x1))) > + crc = (crc >> 1) ^ CRC64_POLY1; > + else > + crc = (crc >> 1); > + data >>= 1; > + } > + return crc; > +} > + > +uint64_t _crc64_poly1 (uint8_t data, uint64_t crc) { > + int i; > + for (i = 0; i < 8; i++) { > + if (((crc & 0x1) ^ (data & 0x1))) > + crc = (crc >> 1) ^ CRC64_POLY1; > + else > + crc = (crc >> 1); > + data >>= 1; > + } > + return crc; > +} > + > +// Test bit-reverse CRC64 8-bit data with Poly having LSB=0 > +__attribute__ ((noinline,optimize(0))) > +uint64_t _crc64_poly2_O0 (uint8_t data, uint64_t crc) { > + int i; > + for (i = 0; i < 8; i++) { > + if (((crc & 0x1) ^ (data & 0x1))) > + crc = (crc >> 1) ^ CRC64_POLY2; > + else > + crc = (crc >> 1); > + data >>= 1; > + } > + return crc; > +} > + > +uint64_t _crc64_poly2 (uint8_t data, uint64_t crc) { > + int i; > + for (i = 0; i < 8; i++) { > + if (((crc & 0x1) ^ (data & 0x1))) > + crc = (crc >> 1) ^ CRC64_POLY2; > + else > + crc = (crc >> 1); > + data >>= 1; > + } > + return crc; > +} > + > +int main () > +{ > + uint64_t crc1 = 0; > + uint64_t crc2 = 0; > + > + for (uint16_t i = 0; i <= 0xff; i++) > + { > + uint8_t data = (uint8_t)i; > + uint64_t res1 = _crc64_poly1_O0 (data, crc1); > + uint64_t res2 = _crc64_poly1 (data, crc1); > + crc1 = res2; > + if (res1 != res2) > + abort (); > + > + uint64_t res3 = _crc64_poly2_O0 (data, crc2); > + uint64_t res4 = _crc64_poly2 (data, crc2); > + crc2 = res4; > + if (res3 != res4) > + abort (); > + } > +} > + > +/* { dg-final { scan-tree-dump "function maybe contains CRC calculation." > "crc" } } */ > +/* { dg-final { scan-tree-dump "Loop iteration number is 7" "crc" } } */ > +/* { dg-final { scan-tree-dump "Bit reverse" "crc" } } */ > +/* { dg-final { scan-tree-dump "calculates CRC!" "crc" } } */ > +/* { dg-final { scan-tree-dump-times "Couldn't generate faster CRC code." 0 > "crc" } } */ > diff --git a/gcc/testsuite/gcc.dg/torture/crc-39.c > b/gcc/testsuite/gcc.dg/torture/crc-39.c > new file mode 100644 > index 00000000000..2bc5894009f > --- /dev/null > +++ b/gcc/testsuite/gcc.dg/torture/crc-39.c > @@ -0,0 +1,89 @@ > +/* { dg-do run { target lp64 } } */ > +/* { dg-options "-fdump-tree-crc-details -w" } */ > +/* { dg-skip-if "" { *-*-* } { "-O0" "-O1" "-g" "-Os" "-flto" } } */ > + > +#include <stdint.h> > +#include <stdlib.h> > + > +#define CRC64_POLY1 0x9A6C9329AC4BC9B5 > +#define CRC64_POLY2 0x1A6C9329AC4BC9B4 > + > +// Test bit-reverse CRC64 16-bit data with Poly having LSB=1 > +__attribute__ ((noinline,optimize(0))) > +uint64_t _crc64_poly1_O0 (uint16_t data, uint64_t crc) { > + int i; > + for (i = 0; i < 16; i++) { > + if (((crc & 0x1) ^ (data & 0x1))) > + crc = (crc >> 1) ^ CRC64_POLY1; > + else > + crc = (crc >> 1); > + data >>= 1; > + } > + return crc; > +} > + > +uint64_t _crc64_poly1 (uint16_t data, uint64_t crc) { > + int i; > + for (i = 0; i < 16; i++) { > + if (((crc & 0x1) ^ (data & 0x1))) > + crc = (crc >> 1) ^ CRC64_POLY1; > + else > + crc = (crc >> 1); > + data >>= 1; > + } > + return crc; > +} > + > +// Test bit-reverse CRC64 16-bit data with Poly having LSB=0 > +__attribute__ ((noinline,optimize(0))) > +uint64_t _crc64_poly2_O0 (uint16_t data, uint64_t crc) { > + int i; > + for (i = 0; i < 16; i++) { > + if (((crc & 0x1) ^ (data & 0x1))) > + crc = (crc >> 1) ^ CRC64_POLY2; > + else > + crc = (crc >> 1); > + data >>= 1; > + } > + return crc; > +} > + > +uint64_t _crc64_poly2 (uint16_t data, uint64_t crc) { > + int i; > + for (i = 0; i < 16; i++) { > + if (((crc & 0x1) ^ (data & 0x1))) > + crc = (crc >> 1) ^ CRC64_POLY2; > + else > + crc = (crc >> 1); > + data >>= 1; > + } > + return crc; > +} > + > +int main () > +{ > + uint64_t crc1 = 0; > + uint64_t crc2 = 0; > + > + for (uint16_t i = 0; i <= 0xff; i++) > + { > + uint16_t data = (i << 8) | (~i); > + uint64_t res1 = _crc64_poly1_O0 (data, crc1); > + uint64_t res2 = _crc64_poly1 (data, crc1); > + crc1 = res2; > + if (res1 != res2) > + abort (); > + > + uint64_t res3 = _crc64_poly2_O0 (data, crc2); > + uint64_t res4 = _crc64_poly2 (data, crc2); > + crc2 = res4; > + if (res3 != res4) > + abort (); > + } > +} > + > +/* { dg-final { scan-tree-dump "function maybe contains CRC calculation." > "crc" } } */ > +/* { dg-final { scan-tree-dump "Loop iteration number is 15" "crc" } } */ > +/* { dg-final { scan-tree-dump "Bit reverse" "crc" } } */ > +/* { dg-final { scan-tree-dump "calculates CRC!" "crc" } } */ > +/* { dg-final { scan-tree-dump-times "Couldn't generate faster CRC code." 0 > "crc" } } */ > diff --git a/gcc/testsuite/gcc.dg/torture/crc-40.c > b/gcc/testsuite/gcc.dg/torture/crc-40.c > new file mode 100644 > index 00000000000..47556c91ab9 > --- /dev/null > +++ b/gcc/testsuite/gcc.dg/torture/crc-40.c > @@ -0,0 +1,98 @@ > +/* { dg-do run { target lp64 } } */ > +/* { dg-options "-fdump-tree-crc-details -w" } */ > +/* { dg-skip-if "" { *-*-* } { "-O0" "-O1" "-g" "-Os" "-flto" } } */ > + > +#include <stdint.h> > +#include <stdlib.h> > + > +#define CRC64_POLY1 0x9A6C9329AC4BC9B5 > +#define CRC64_POLY2 0x1A6C9329AC4BC9B4 > + > +uint32_t expand8to32 (uint32_t x) { > + x ^= x >> 16; > + x *= 0x7feb352dU; > + x ^= x >> 15; > + x *= 0x846ca68bU; > + x ^= x >> 16; > + return x; > +} > + > +// Test bit-reverse CRC64 32-bit data with Poly having LSB=1 > +__attribute__ ((noinline,optimize(0))) > +uint64_t _crc64_poly1_O0 (uint32_t data, uint64_t crc) { > + int i; > + for (i = 0; i < 32; i++) { > + if (((crc & 0x1) ^ (data & 0x1))) > + crc = (crc >> 1) ^ CRC64_POLY1; > + else > + crc = (crc >> 1); > + data >>= 1; > + } > + return crc; > +} > + > +uint64_t _crc64_poly1 (uint32_t data, uint64_t crc) { > + int i; > + for (i = 0; i < 32; i++) { > + if (((crc & 0x1) ^ (data & 0x1))) > + crc = (crc >> 1) ^ CRC64_POLY1; > + else > + crc = (crc >> 1); > + data >>= 1; > + } > + return crc; > +} > + > +// Test bit-reverse CRC64 32-bit data with Poly having LSB=0 > +__attribute__ ((noinline,optimize(0))) > +uint64_t _crc64_poly2_O0 (uint32_t data, uint64_t crc) { > + int i; > + for (i = 0; i < 32; i++) { > + if (((crc & 0x1) ^ (data & 0x1))) > + crc = (crc >> 1) ^ CRC64_POLY2; > + else > + crc = (crc >> 1); > + data >>= 1; > + } > + return crc; > +} > + > +uint64_t _crc64_poly2 (uint32_t data, uint64_t crc) { > + int i; > + for (i = 0; i < 32; i++) { > + if (((crc & 0x1) ^ (data & 0x1))) > + crc = (crc >> 1) ^ CRC64_POLY2; > + else > + crc = (crc >> 1); > + data >>= 1; > + } > + return crc; > +} > + > +int main () > +{ > + uint64_t crc1 = 0; > + uint64_t crc2 = 0; > + > + for (uint32_t i = 0; i <= 0xff; i++) > + { > + uint32_t data = expand8to32 (i); > + uint64_t res1 = _crc64_poly1_O0 (data, crc1); > + uint64_t res2 = _crc64_poly1 (data, crc1); > + crc1 = res2; > + if (res1 != res2) > + abort (); > + > + uint64_t res3 = _crc64_poly2_O0 (data, crc2); > + uint64_t res4 = _crc64_poly2 (data, crc2); > + crc2 = res4; > + if (res3 != res4) > + abort (); > + } > +} > + > +/* { dg-final { scan-tree-dump "function maybe contains CRC calculation." > "crc" } } */ > +/* { dg-final { scan-tree-dump "Loop iteration number is 31" "crc" } } */ > +/* { dg-final { scan-tree-dump "Bit reverse" "crc" } } */ > +/* { dg-final { scan-tree-dump "calculates CRC!" "crc" } } */ > +/* { dg-final { scan-tree-dump-times "Couldn't generate faster CRC code." 0 > "crc" } } */ > diff --git a/gcc/testsuite/gcc.dg/torture/crc-41.c > b/gcc/testsuite/gcc.dg/torture/crc-41.c > new file mode 100644 > index 00000000000..6aaa71c41e5 > --- /dev/null > +++ b/gcc/testsuite/gcc.dg/torture/crc-41.c > @@ -0,0 +1,98 @@ > +/* { dg-do run { target lp64 } } */ > +/* { dg-options "-fdump-tree-crc-details -w" } */ > +/* { dg-skip-if "" { *-*-* } { "-O0" "-O1" "-g" "-Os" "-flto" } } */ > + > +#include <stdint.h> > +#include <stdlib.h> > + > +#define CRC64_POLY1 0x9A6C9329AC4BC9B5 > +#define CRC64_POLY2 0x1A6C9329AC4BC9B4 > + > +uint64_t expand8to64 (uint64_t x) { > + x ^= x >> 30; > + x *= UINT64_C(0xbf58476d1ce4e5b9); > + x ^= x >> 27; > + x *= UINT64_C(0x94d049bb133111eb); > + x ^= x >> 31; > + return x; > +} > + > +// Test bit-reverse CRC64 64-bit data with Poly having LSB=1 > +__attribute__ ((noinline,optimize(0))) > +uint64_t _crc64_poly1_O0 (uint64_t data, uint64_t crc) { > + int i; > + for (i = 0; i < 64; i++) { > + if (((crc & 0x1) ^ (data & 0x1))) > + crc = (crc >> 1) ^ CRC64_POLY1; > + else > + crc = (crc >> 1); > + data >>= 1; > + } > + return crc; > +} > + > +uint64_t _crc64_poly1 (uint64_t data, uint64_t crc) { > + int i; > + for (i = 0; i < 64; i++) { > + if (((crc & 0x1) ^ (data & 0x1))) > + crc = (crc >> 1) ^ CRC64_POLY1; > + else > + crc = (crc >> 1); > + data >>= 1; > + } > + return crc; > +} > + > +// Test bit-reverse CRC64 64-bit data with Poly having LSB=0 > +__attribute__ ((noinline,optimize(0))) > +uint64_t _crc64_poly2_O0 (uint64_t data, uint64_t crc) { > + int i; > + for (i = 0; i < 64; i++) { > + if (((crc & 0x1) ^ (data & 0x1))) > + crc = (crc >> 1) ^ CRC64_POLY2; > + else > + crc = (crc >> 1); > + data >>= 1; > + } > + return crc; > +} > + > +uint64_t _crc64_poly2 (uint64_t data, uint64_t crc) { > + int i; > + for (i = 0; i < 64; i++) { > + if (((crc & 0x1) ^ (data & 0x1))) > + crc = (crc >> 1) ^ CRC64_POLY2; > + else > + crc = (crc >> 1); > + data >>= 1; > + } > + return crc; > +} > + > +int main () > +{ > + uint64_t crc1 = 0; > + uint64_t crc2 = 0; > + > + for (uint64_t i = 0; i <= 0xff; i++) > + { > + uint64_t data = expand8to64 (i); > + uint64_t res1 = _crc64_poly1_O0 (data, crc1); > + uint64_t res2 = _crc64_poly1 (data, crc1); > + crc1 = res2; > + if (res1 != res2) > + abort (); > + > + uint64_t res3 = _crc64_poly2_O0 (data, crc2); > + uint64_t res4 = _crc64_poly2 (data, crc2); > + crc2 = res4; > + if (res3 != res4) > + abort (); > + } > +} > + > +/* { dg-final { scan-tree-dump "function maybe contains CRC calculation." > "crc" } } */ > +/* { dg-final { scan-tree-dump "Loop iteration number is 63" "crc" } } */ > +/* { dg-final { scan-tree-dump "Bit reverse" "crc" } } */ > +/* { dg-final { scan-tree-dump "calculates CRC!" "crc" } } */ > +/* { dg-final { scan-tree-dump-times "Couldn't generate faster CRC code." 0 > "crc" } } */ > diff --git a/gcc/testsuite/gcc.target/i386/crc-34-pclmul.c > b/gcc/testsuite/gcc.target/i386/crc-34-pclmul.c > new file mode 100644 > index 00000000000..51f747ed11c > --- /dev/null > +++ b/gcc/testsuite/gcc.target/i386/crc-34-pclmul.c > @@ -0,0 +1,9 @@ > +/* { dg-do run { target { pclmul_runtime } } } */ > +/* { dg-options "-mpclmul -O2 -fdump-rtl-dfinish -fdump-tree-crc" } */ > + > +#include "../../gcc.dg/torture/crc-34.c" > + > +/* { dg-final { scan-tree-dump "calculates CRC!" "crc"} } */ > +/* { dg-final { scan-tree-dump-times "Couldn't generate faster CRC code." 0 > "crc"} } */ > +/* Check 8-bit data CRC doesn't expand with pclmul */ > +/* { dg-final { scan-rtl-dump-not "pclmulqdq" "dfinish"} } */ > diff --git a/gcc/testsuite/gcc.target/i386/crc-35-pclmul.c > b/gcc/testsuite/gcc.target/i386/crc-35-pclmul.c > new file mode 100644 > index 00000000000..054928ccae4 > --- /dev/null > +++ b/gcc/testsuite/gcc.target/i386/crc-35-pclmul.c > @@ -0,0 +1,8 @@ > +/* { dg-do run { target { pclmul_runtime } } } */ > +/* { dg-options "-mpclmul -O2 -fdump-rtl-dfinish -fdump-tree-crc" } */ > + > +#include "../../gcc.dg/torture/crc-35.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-36-pclmul.c > b/gcc/testsuite/gcc.target/i386/crc-36-pclmul.c > new file mode 100644 > index 00000000000..8db16b4c09a > --- /dev/null > +++ b/gcc/testsuite/gcc.target/i386/crc-36-pclmul.c > @@ -0,0 +1,8 @@ > +/* { dg-do run { target { pclmul_runtime } } } */ > +/* { dg-options "-mpclmul -O2 -fdump-rtl-dfinish -fdump-tree-crc" } */ > + > +#include "../../gcc.dg/torture/crc-36.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-37-pclmul.c > b/gcc/testsuite/gcc.target/i386/crc-37-pclmul.c > new file mode 100644 > index 00000000000..8d8567732df > --- /dev/null > +++ b/gcc/testsuite/gcc.target/i386/crc-37-pclmul.c > @@ -0,0 +1,8 @@ > +/* { dg-do run { target { pclmul_runtime } } } */ > +/* { dg-options "-mpclmul -O2 -fdump-rtl-dfinish -fdump-tree-crc" } */ > + > +#include "../../gcc.dg/torture/crc-37.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-38-pclmul.c > b/gcc/testsuite/gcc.target/i386/crc-38-pclmul.c > new file mode 100644 > index 00000000000..55767ac1c71 > --- /dev/null > +++ b/gcc/testsuite/gcc.target/i386/crc-38-pclmul.c > @@ -0,0 +1,9 @@ > +/* { dg-do run { target { pclmul_runtime } } } */ > +/* { dg-options "-mpclmul -O2 -fdump-rtl-dfinish -fdump-tree-crc" } */ > + > +#include "../../gcc.dg/torture/crc-38.c" > + > +/* { dg-final { scan-tree-dump "calculates CRC!" "crc"} } */ > +/* { dg-final { scan-tree-dump-times "Couldn't generate faster CRC code." 0 > "crc"} } */ > +/* Check 8-bit data CRC doesn't expand with pclmul */ > +/* { dg-final { scan-rtl-dump-not "pclmulqdq" "dfinish"} } */ > diff --git a/gcc/testsuite/gcc.target/i386/crc-39-pclmul.c > b/gcc/testsuite/gcc.target/i386/crc-39-pclmul.c > new file mode 100644 > index 00000000000..b26b93139aa > --- /dev/null > +++ b/gcc/testsuite/gcc.target/i386/crc-39-pclmul.c > @@ -0,0 +1,8 @@ > +/* { dg-do run { target { pclmul_runtime } } } */ > +/* { dg-options "-mpclmul -O2 -fdump-rtl-dfinish -fdump-tree-crc" } */ > + > +#include "../../gcc.dg/torture/crc-39.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-40-pclmul.c > b/gcc/testsuite/gcc.target/i386/crc-40-pclmul.c > new file mode 100644 > index 00000000000..3f48f84a1cf > --- /dev/null > +++ b/gcc/testsuite/gcc.target/i386/crc-40-pclmul.c > @@ -0,0 +1,8 @@ > +/* { dg-do run { target { pclmul_runtime } } } */ > +/* { dg-options "-mpclmul -O2 -fdump-rtl-dfinish -fdump-tree-crc" } */ > + > +#include "../../gcc.dg/torture/crc-40.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-41-pclmul.c > b/gcc/testsuite/gcc.target/i386/crc-41-pclmul.c > new file mode 100644 > index 00000000000..734b81bb4bb > --- /dev/null > +++ b/gcc/testsuite/gcc.target/i386/crc-41-pclmul.c > @@ -0,0 +1,8 @@ > +/* { dg-do run { target { pclmul_runtime } } } */ > +/* { dg-options "-mpclmul -O2 -fdump-rtl-dfinish -fdump-tree-crc" } */ > + > +#include "../../gcc.dg/torture/crc-41.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"} } */ > -- > 2.55.0 >
