@@ -1117,5 +1117,8 @@ extern void mingw_pe_encode_section_info (tree, rtx, int);
bool aarch64_optimize_mode_switching (aarch64_mode_entity);
void aarch64_restore_za (rtx);
+void aarch64_expand_crc_using_pmul (scalar_mode, scalar_mode, rtx *);
+void aarch64_expand_reversed_crc_using_pmul (scalar_mode, scalar_mode, rtx *);
+
#endif /* GCC_AARCH64_PROTOS_H */
@@ -30265,6 +30265,131 @@ aarch64_retrieve_sysreg (const char *regname, bool write_p, bool is128op)
return sysreg->encoding;
}
+/* Generate assembly to calculate CRC
+ using carry-less multiplication instruction.
+ OPERANDS[1] is input CRC,
+ OPERANDS[2] is data (message),
+ OPERANDS[3] is the polynomial without the leading 1. */
+
+void
+aarch64_expand_crc_using_pmul (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 + 1);
+
+ /* CRC calculation's main part. */
+ if (crc_size > data_size)
+ crc = expand_shift (RSHIFT_EXPR, DImode, crc, crc_size - data_size,
+ NULL_RTX, 1);
+
+ rtx t0 = force_reg (DImode, gen_int_mode (q, DImode));
+ polynomial = simplify_gen_unary (ZERO_EXTEND, DImode, polynomial,
+ GET_MODE (polynomial));
+ rtx t1 = force_reg (DImode, polynomial);
+
+ rtx a0 = expand_binop (DImode, xor_optab, crc, data, NULL_RTX, 1,
+ OPTAB_WIDEN);
+
+ rtx clmul_res = gen_reg_rtx (TImode);
+ emit_insn (gen_aarch64_crypto_pmulldi (clmul_res, a0, t0));
+ a0 = gen_lowpart (DImode, clmul_res);
+
+ a0 = expand_shift (RSHIFT_EXPR, DImode, a0, crc_size, NULL_RTX, 1);
+
+ emit_insn (gen_aarch64_crypto_pmulldi (clmul_res, a0, t1));
+ a0 = gen_lowpart (DImode, clmul_res);
+
+ if (crc_size > data_size)
+ {
+ rtx crc_part = expand_shift (LSHIFT_EXPR, DImode, operands[1], data_size,
+ NULL_RTX, 0);
+ a0 = expand_binop (DImode, xor_optab, a0, crc_part, NULL_RTX, 1,
+ OPTAB_DIRECT);
+ }
+ /* Zero upper bits beyond crc_size. */
+ rtx mask = gen_int_mode (GET_MODE_MASK (crc_mode), DImode);
+ a0 = expand_binop (DImode, and_optab, a0, mask, NULL_RTX, 1, OPTAB_DIRECT);
+
+ rtx tgt = simplify_gen_subreg (DImode, operands[0], crc_mode, 0);
+ aarch64_emit_move (tgt, a0);
+}
+
+/* Generate assembly to calculate reversed CRC
+ using carry-less multiplication instruction.
+ OPERANDS[1] is input CRC,
+ OPERANDS[2] is data,
+ OPERANDS[3] is the polynomial without the leading 1. */
+
+void
+aarch64_expand_reversed_crc_using_pmul (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 + 1);
+ /* Reflect the calculated quotient. */
+ q = reflect (q);
+ rtx t0 = force_reg (DImode, gen_int_mode (q >> (data_size - 4), DImode));
+
+ /* Reflect the polynomial. */
+ unsigned HOST_WIDE_INT ref_polynomial = reflect (UINTVAL (polynomial));
+ rtx t1 = force_reg (DImode, gen_int_mode (ref_polynomial << 1, DImode));
+
+ /* CRC calculation's main part. */
+ rtx a0 = expand_binop (DImode, xor_optab, crc, data, NULL_RTX, 1,
+ OPTAB_WIDEN);
+
+ /* Perform carry-less multiplication and get low part. */
+ rtx clmul_res = gen_reg_rtx (TImode);
+ emit_insn (gen_aarch64_crypto_pmulldi (clmul_res, a0, t0));
+ a0 = gen_lowpart (DImode, clmul_res);
+
+ a0 = expand_shift (LSHIFT_EXPR, DImode, a0, 64 - crc_size - 3, NULL_RTX, 0);
+
+ /* Perform carry-less multiplication and get high part. */
+ emit_insn (gen_aarch64_crypto_pmulldi (clmul_res, a0, t1));
+ a0 = gen_highpart (DImode, clmul_res);
+
+ if (crc_size > data_size)
+ {
+ rtx crc_part = expand_shift (RSHIFT_EXPR, DImode, crc, data_size,
+ NULL_RTX, 1);
+ a0 = expand_binop (DImode, xor_optab, a0, crc_part, NULL_RTX, 1,
+ OPTAB_DIRECT);
+ }
+
+ rtx tgt = simplify_gen_subreg (DImode, operands[0], crc_mode, 0);
+ aarch64_emit_move (tgt, a0);
+}
+
/* Target-specific selftests. */
#if CHECKING_P
@@ -4543,6 +4543,62 @@
[(set_attr "type" "crc")]
)
+;; Reversed CRC
+(define_expand "crc_rev<ALLI:mode><ALLX:mode>4"
+ [;; return value (calculated CRC)
+ (match_operand:ALLX 0 "register_operand" "=r")
+ ;; initial CRC
+ (match_operand:ALLX 1 "register_operand" "r")
+ ;; data
+ (match_operand:ALLI 2 "register_operand" "r")
+ ;; polynomial without leading 1
+ (match_operand:ALLX 3)]
+ ""
+ {
+ /* If the polynomial is the same as the polynomial of crc32c* instruction,
+ put that instruction. crc32c uses iSCSI polynomial. */
+ if (TARGET_CRC32 && INTVAL (operands[3]) == 0x1EDC6F41
+ && <ALLX:MODE>mode == SImode)
+ emit_insn (gen_aarch64_crc32c<ALLI:crc_data_type> (operands[0],
+ operands[1],
+ operands[2]));
+ /* If the polynomial is the same as the polynomial of crc32* instruction,
+ put that instruction. crc32 uses HDLC etc. polynomial. */
+ else if (TARGET_CRC32 && INTVAL (operands[3]) == 0x04C11DB7
+ && <ALLX:MODE>mode == SImode)
+ emit_insn (gen_aarch64_crc32<ALLI:crc_data_type> (operands[0],
+ operands[1],
+ operands[2]));
+ else if (TARGET_AES && <ALLI:sizen> <= <ALLX:sizen>)
+ aarch64_expand_reversed_crc_using_pmul (<ALLX:MODE>mode, <ALLI:MODE>mode,
+ operands);
+ else
+ /* Otherwise, generate table-based CRC. */
+ expand_reversed_crc_table_based (operands[0], operands[1], operands[2],
+ operands[3], <ALLI:MODE>mode,
+ generate_reflecting_code_standard);
+ DONE;
+ }
+)
+
+;; Bit-forward CRC
+(define_expand "crc<ALLI:mode><ALLX:mode>4"
+ [;; return value (calculated CRC)
+ (match_operand:ALLX 0 "register_operand" "=r")
+ ;; initial CRC
+ (match_operand:ALLX 1 "register_operand" "r")
+ ;; data
+ (match_operand:ALLI 2 "register_operand" "r")
+ ;; polynomial without leading 1
+ (match_operand:ALLX 3)]
+ "TARGET_AES && <ALLI:sizen> <= <ALLX:sizen>"
+ {
+ aarch64_expand_crc_using_pmul (<ALLX:MODE>mode, <ALLI:MODE>mode,
+ operands);
+ DONE;
+ }
+)
+
(define_insn "*csinc2<mode>_insn"
[(set (match_operand:GPI 0 "register_operand" "=r")
(plus:GPI (match_operand 2 "aarch64_comparison_operation" "")
@@ -1276,6 +1276,10 @@
;; Map a mode to a specific constraint character.
(define_mode_attr cmode [(QI "q") (HI "h") (SI "s") (DI "d")])
+;; Map a mode to a specific constraint character for calling
+;; appropriate version of crc.
+(define_mode_attr crc_data_type [(QI "b") (HI "h") (SI "w") (DI "x")])
+
;; Map modes to Usg and Usj constraints for SISD right shifts
(define_mode_attr cmode_simd [(SI "g") (DI "j")])
new file mode 100644
@@ -0,0 +1,8 @@
+/* { dg-do run } */
+/* { dg-options "-march=armv8-a+crypto -O2 -fdump-rtl-dfinish -fdump-tree-crc -fdisable-tree-phiopt2 -fdisable-tree-phiopt3" } */
+
+#include "../../gcc.c-torture/execute/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 "pmull" "dfinish"} } */
\ No newline at end of file
new file mode 100644
@@ -0,0 +1,9 @@
+/* { dg-do run } */
+/* { dg-options "-march=armv8-a+crypto -O2 -fdump-rtl-dfinish -fdump-tree-crc" } */
+/* { dg-skip-if "" { *-*-* } { "-flto"} } */
+
+#include "../../gcc.c-torture/execute/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 "pmull" "dfinish"} } */
new file mode 100644
@@ -0,0 +1,9 @@
+/* { dg-do run } */
+/* { dg-options "-march=armv8-a+crypto -O2 -fdump-rtl-dfinish -fdump-tree-crc -fdisable-tree-phiopt2 -fdisable-tree-phiopt3" } */
+/* { dg-skip-if "" { *-*-* } { "-flto"} } */
+
+#include "../../gcc.c-torture/execute/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 "pmull" "dfinish"} } */
new file mode 100644
@@ -0,0 +1,9 @@
+/* { dg-do run } */
+/* { dg-options "-march=armv8-a+crypto -O2 -fdump-rtl-dfinish -fdump-tree-crc" } */
+/* { dg-skip-if "" { *-*-* } { "-flto"} } */
+
+#include "../../gcc.c-torture/execute/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 "pmull" "dfinish"} } */
new file mode 100644
@@ -0,0 +1,9 @@
+/* { dg-do run } */
+/* { dg-options "-march=armv8-a+crypto -O2 -fdump-rtl-dfinish -fdump-tree-crc" } */
+/* { dg-skip-if "" { *-*-* } { "-flto"} } */
+
+#include "../../gcc.c-torture/execute/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 "pmull" "dfinish"} } */
new file mode 100644
@@ -0,0 +1,9 @@
+/* { dg-do run } */
+/* { dg-options "-march=armv8-a+crypto -O2 -fdump-rtl-dfinish -fdump-tree-crc" } */
+/* { dg-skip-if "" { *-*-* } { "-flto"} } */
+
+#include "../../gcc.c-torture/execute/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 "pmull" "dfinish"} } */
new file mode 100644
@@ -0,0 +1,9 @@
+/* { dg-do run } */
+/* { dg-options "-march=armv8-a+crypto -O2 -fdump-rtl-dfinish -fdump-tree-crc" } */
+/* { dg-skip-if "" { *-*-* } { "-flto"} } */
+
+#include "../../gcc.c-torture/execute/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 "pmull" "dfinish"} } */
new file mode 100644
@@ -0,0 +1,9 @@
+/* { dg-do run } */
+/* { dg-options "-march=armv8-a+crypto -O2 -fdump-rtl-dfinish -fdump-tree-crc" } */
+/* { dg-skip-if "" { *-*-* } { "-flto"} } */
+
+#include "../../gcc.c-torture/execute/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 "pmull" "dfinish"} } */
new file mode 100644
@@ -0,0 +1,9 @@
+/* { dg-do run } */
+/* { dg-options "-march=armv8-a+crypto -O2 -fdump-rtl-dfinish -fdump-tree-crc" } */
+/* { dg-skip-if "" { *-*-* } { "-flto"} } */
+
+#include "../../gcc.c-torture/execute/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 "pmull" "dfinish"} } */
new file mode 100644
@@ -0,0 +1,9 @@
+/* { dg-do run } */
+/* { dg-options "-march=armv8-a+crypto -O2 -fdump-rtl-dfinish -fdump-tree-crc" } */
+/* { dg-skip-if "" { *-*-* } { "-flto"} } */
+
+#include "../../gcc.c-torture/execute/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 "pmull" "dfinish"} } */
new file mode 100644
@@ -0,0 +1,9 @@
+/* { dg-do run } */
+/* { dg-options "-march=armv8-a+crypto -O2 -fdump-rtl-dfinish -fdump-tree-crc" } */
+/* { dg-skip-if "" { *-*-* } { "-flto"} } */
+
+#include "../../gcc.c-torture/execute/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 "pmull" "dfinish"} } */
new file mode 100644
@@ -0,0 +1,9 @@
+/* { dg-do run } */
+/* { dg-options "-march=armv8-a+crypto -O2 -w -fdump-rtl-dfinish -fdump-tree-crc" } */
+/* { dg-skip-if "" { *-*-* } { "-flto"} } */
+
+#include "../../gcc.c-torture/execute/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 "pmull" "dfinish"} } */
\ No newline at end of file
new file mode 100644
@@ -0,0 +1,9 @@
+/* { dg-do run } */
+/* { dg-options "-march=armv8-a+crypto -O2 -fdump-rtl-dfinish -fdump-tree-crc" } */
+/* { dg-skip-if "" { *-*-* } { "-flto"} } */
+
+#include "../../gcc.c-torture/execute/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 "pmull" "dfinish"} } */
\ No newline at end of file
new file mode 100644
@@ -0,0 +1,9 @@
+/* { dg-do run } */
+/* { dg-options "-march=armv8-a+crypto -O2 -fdump-rtl-dfinish -fdump-tree-crc" } */
+/* { dg-skip-if "" { *-*-* } { "-flto"} } */
+
+#include "../../gcc.c-torture/execute/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 "pmull" "dfinish"} } */
new file mode 100644
@@ -0,0 +1,9 @@
+/* { dg-do run } */
+/* { dg-options "-march=armv8-a+crypto -O2 -fdump-rtl-dfinish -fdump-tree-crc" } */
+/* { dg-skip-if "" { *-*-* } { "-flto"} } */
+
+#include "../../gcc.c-torture/execute/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 "pmull" "dfinish"} } */
new file mode 100644
@@ -0,0 +1,9 @@
+/* { dg-do run } */
+/* { dg-options "-march=armv8-a+crypto -O2 -fdump-rtl-dfinish -fdump-tree-crc" } */
+/* { dg-skip-if "" { *-*-* } { "-flto"} } */
+
+#include "../../gcc.c-torture/execute/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 "pmull" "dfinish"} } */
new file mode 100644
@@ -0,0 +1,9 @@
+/* { dg-do run } */
+/* { dg-options "-w -march=armv8-a+crypto -O2 -fdump-rtl-dfinish -fdump-tree-crc" } */
+/* { dg-skip-if "" { *-*-* } { "-flto"} } */
+
+#include "../../gcc.c-torture/execute/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 "pmull" "dfinish"} } */
\ No newline at end of file
new file mode 100644
@@ -0,0 +1,9 @@
+/* { dg-do run } */
+/* { dg-options "-w -march=armv8-a+crypto -O2 -fdump-rtl-dfinish -fdump-tree-crc" } */
+/* { dg-skip-if "" { *-*-* } { "-flto" } } */
+
+#include "../../gcc.c-torture/execute/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 "pmull" "dfinish"} } */
\ No newline at end of file
new file mode 100644
@@ -0,0 +1,9 @@
+/* { dg-do run } */
+/* { dg-options "-w -march=armv8-a+crypto -O2 -fdump-rtl-dfinish -fdump-tree-crc" } */
+/* { dg-skip-if "" { *-*-* } { "-flto"} } */
+
+#include "../../gcc.c-torture/execute/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 "pmull" "dfinish"} } */
\ No newline at end of file
new file mode 100644
@@ -0,0 +1,53 @@
+/* { dg-do run } */
+/* { dg-options "-march=armv8-a+crc -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) ^ 0xEDB88320;
+ 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) ^ 0xEDB88320;
+ 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 "pmull" 0 "dfinish"} } */
new file mode 100644
@@ -0,0 +1,52 @@
+/* { dg-do run } */
+/* { dg-options "-march=armv8-a+crc -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) ^ 0xEDB88320;
+ 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) ^ 0xEDB88320;
+ 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 "pmull" 0 "dfinish"} } */
new file mode 100644
@@ -0,0 +1,53 @@
+/* { dg-do run } */
+/* { dg-options "-march=armv8-a+crc -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) ^ 0xEDB88320;
+ 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) ^ 0xEDB88320;
+ 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 "pmull" 0 "dfinish"} } */
new file mode 100644
@@ -0,0 +1,53 @@
+/* { dg-do run } */
+/* { dg-options "-march=armv8-a+crc -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_CRC32C" "dfinish"} } */
+/* { dg-final { scan-rtl-dump-times "pmull" 0 "dfinish"} } */
new file mode 100644
@@ -0,0 +1,52 @@
+/* { dg-do run } */
+/* { dg-options "-march=armv8-a+crc -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_CRC32C" "dfinish"} } */
+/* { dg-final { scan-rtl-dump-times "pmull" 0 "dfinish"} } */
new file mode 100644
@@ -0,0 +1,53 @@
+/* { dg-do run } */
+/* { dg-options "-march=armv8-a+crc -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_CRC32C" "dfinish"} } */
+/* { dg-final { scan-rtl-dump-times "pmull" 0 "dfinish"} } */
--
2.25.1