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"
+{
+ 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"
+ {
+ /* 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