diff mbox series

[RFC/RFA,v2,03/12] RISC-V: Add CRC expander to generate faster CRC.

Message ID CAE65F3NHstQNxuT3bq=R_Yf0UbwynVSem1JfCiH8rNeh3fv+Vg@mail.gmail.com
State New
Headers show
Series [RFC/RFA,v2,01/12] Implement internal functions for efficient CRC computation | expand

Commit Message

Mariam Arutunian July 26, 2024, 6:06 p.m. UTC
If the target is ZBC or ZBKC, it uses clmul instruction for the CRC
calculation.
  Otherwise, if the target is ZBKB, generates table-based CRC, but for
reversing inputs and the output uses bswap and brev8 instructions.
  Add new tests to check CRC generation for ZBC, ZBKC and ZBKB targets.

     gcc/

        * expr.cc (reflect): New function.
        (gf2n_poly_long_div_quotient): Likewise.
        * expr.h (reflect): New function declaration.
        (gf2n_poly_long_div_quotient): Likewise.

     gcc/config/riscv/

        * bitmanip.md (crc_rev<ANYI1:mode><ANYI:mode>4): New expander for
reversed CRC.
        (crc<SUBX1:mode><SUBX:mode>4): New expander for bit-forward CRC.
        (SUBX1, ANYI1): New iterators.
        * riscv-protos.h (generate_reflecting_code_using_brev): New
function declaration.
        (expand_crc_using_clmul): Likewise.
        (expand_reversed_crc_using_clmul): Likewise.
        * riscv.cc (generate_reflecting_code_using_brev): New function.
        (expand_crc_using_clmul): Likewise.
        (expand_reversed_crc_using_clmul): Likewise.
        * riscv.md (UNSPEC_CRC, UNSPEC_CRC_REV):  New unspecs.

     gcc/testsuite/gcc.target/riscv/

           * crc-1-zbc.c: New test.
           * crc-1-zbc.c: Likewise.
           * crc-10-zbc.c: Likewise.
           * crc-10-zbkc.c: Likewise.
           * crc-12-zbc.c: Likewise.
           * crc-12-zbkc.c: Likewise.
           * crc-13-zbc.c: Likewise.
           * crc-13-zbkc.c: Likewise.
           * crc-14-zbc.c: Likewise.
           * crc-14-zbkc.c: Likewise.
           * crc-17-zbc.c: Likewise.
           * crc-17-zbkc.c: Likewise.
           * crc-18-zbc.c: Likewise.
           * crc-18-zbkc.c: Likewise.
           * crc-21-zbc.c: Likewise.
           * crc-21-zbkc.c: Likewise.
           * crc-22-rv64-zbc.c: Likewise.
           * crc-22-rv64-zbkb.c: Likewise.
           * crc-22-rv64-zbkc.c: Likewise.
           * crc-23-zbc.c: Likewise.
           * crc-23-zbkc.c: Likewise.
           * crc-4-zbc.c: Likewise.
           * crc-4-zbkb.c: Likewise.
           * crc-4-zbkc.c: Likewise.
           * crc-5-zbc.c: Likewise.
           * crc-5-zbkb.c: Likewise.
           * crc-5-zbkc.c: Likewise.
           * crc-6-zbc.c: Likewise.
           * crc-6-zbkc.c: Likewise.
           * crc-7-zbc.c: Likewise.
           * crc-7-zbkc.c: Likewise.
           * crc-8-zbc.c: Likewise.
           * crc-8-zbkb.c: Likewise.
           * crc-8-zbkc.c: Likewise.
           * crc-9-zbc.c: Likewise.
           * crc-9-zbkc.c: Likewise.
           * crc-CCIT-data16-zbc.c: Likewise.
           * crc-CCIT-data16-zbkc.c: Likewise.
           * crc-CCIT-data8-zbc.c: Likewise.
           * crc-CCIT-data8-zbkc.c: Likewise.
           * crc-coremark-16bitdata-zbc.c: Likewise.
           * crc-coremark-16bitdata-zbkc.c: Likewise.

   Signed-off-by: Mariam Arutunian <mariamarutunian@gmail.com>

Comments

Jeff Law Aug. 25, 2024, 5:41 p.m. UTC | #1
On 7/26/24 12:06 PM, Mariam Arutunian wrote:
>    If the target is ZBC or ZBKC, it uses clmul instruction for the CRC 
> calculation.
> Otherwise, if the target is ZBKB, generates table-based CRC, but for 
> reversing inputs and the output uses bswap and brev8 instructions.
>    Add new tests to check CRC generation for ZBC, ZBKC and ZBKB targets.
> 
>       gcc/
> 
>          * expr.cc (reflect): New function.
>          (gf2n_poly_long_div_quotient): Likewise.
>          * expr.h (reflect): New function declaration.
>          (gf2n_poly_long_div_quotient): Likewise.
> 
>       gcc/config/riscv/
> 
>          * bitmanip.md (crc_rev<ANYI1:mode><ANYI:mode>4): New expander 
> for reversed CRC.
>          (crc<SUBX1:mode><SUBX:mode>4): New expander for bit-forward CRC.
>          (SUBX1, ANYI1): New iterators.
>          * riscv-protos.h (generate_reflecting_code_using_brev): New 
> function declaration.
>          (expand_crc_using_clmul): Likewise.
>          (expand_reversed_crc_using_clmul): Likewise.
>          * riscv.cc (generate_reflecting_code_using_brev): New function.
>          (expand_crc_using_clmul): Likewise.
>          (expand_reversed_crc_using_clmul): Likewise.
>          * riscv.md (UNSPEC_CRC, UNSPEC_CRC_REV):  New unspecs.
> 
>       gcc/testsuite/gcc.target/riscv/
> 
>             * crc-1-zbc.c: New test.
>             * crc-1-zbc.c: Likewise.
>             * crc-10-zbc.c: Likewise.
>             * crc-10-zbkc.c: Likewise.
>             * crc-12-zbc.c: Likewise.
>             * crc-12-zbkc.c: Likewise.
>             * crc-13-zbc.c: Likewise.
>             * crc-13-zbkc.c: Likewise.
>             * crc-14-zbc.c: Likewise.
>             * crc-14-zbkc.c: Likewise.
>             * crc-17-zbc.c: Likewise.
>             * crc-17-zbkc.c: Likewise.
>             * crc-18-zbc.c: Likewise.
>             * crc-18-zbkc.c: Likewise.
>             * crc-21-zbc.c: Likewise.
>             * crc-21-zbkc.c: Likewise.
>             * crc-22-rv64-zbc.c: Likewise.
>             * crc-22-rv64-zbkb.c: Likewise.
>             * crc-22-rv64-zbkc.c: Likewise.
>             * crc-23-zbc.c: Likewise.
>             * crc-23-zbkc.c: Likewise.
>             * crc-4-zbc.c: Likewise.
>             * crc-4-zbkb.c: Likewise.
>             * crc-4-zbkc.c: Likewise.
>             * crc-5-zbc.c: Likewise.
>             * crc-5-zbkb.c: Likewise.
>             * crc-5-zbkc.c: Likewise.
>             * crc-6-zbc.c: Likewise.
>             * crc-6-zbkc.c: Likewise.
>             * crc-7-zbc.c: Likewise.
>             * crc-7-zbkc.c: Likewise.
>             * crc-8-zbc.c: Likewise.
>             * crc-8-zbkb.c: Likewise.
>             * crc-8-zbkc.c: Likewise.
>             * crc-9-zbc.c: Likewise.
>             * crc-9-zbkc.c: Likewise.
>             * crc-CCIT-data16-zbc.c: Likewise.
>             * crc-CCIT-data16-zbkc.c: Likewise.
>             * crc-CCIT-data8-zbc.c: Likewise.
>             * crc-CCIT-data8-zbkc.c: Likewise.
>             * crc-coremark-16bitdata-zbc.c: Likewise.
>             * crc-coremark-16bitdata-zbkc.c: Likewise.
> 
>     Signed-off-by: Mariam Arutunian <mariamarutunian@gmail.com 
> <mailto:mariamarutunian@gmail.com>>
> 
> 
> 0003-RISC-V-Add-CRC-expander-to-generate-faster-CRC.patch
> 
> diff --git a/gcc/config/riscv/bitmanip.md b/gcc/config/riscv/bitmanip.md
> index 8769a6b818b..9683ac48ef6 100644
> --- a/gcc/config/riscv/bitmanip.md
> +++ b/gcc/config/riscv/bitmanip.md
> @@ -973,3 +973,67 @@
>     "TARGET_ZBC"
>     "clmulr\t%0,%1,%2"
>     [(set_attr "type" "clmul")])
> +
> +
> +;; Iterator for hardware integer modes narrower than XLEN, same as SUBX
> +(define_mode_iterator SUBX1 [QI HI (SI "TARGET_64BIT")])
> +
> +;; Iterator for hardware integer modes narrower than XLEN, same as ANYI
> +(define_mode_iterator ANYI1 [QI HI SI (DI "TARGET_64BIT")])
Might as well go ahead and put these into iterators.md.


> +
> +;; Reversed CRC 8, 16, 32 for TARGET_64
> +(define_expand "crc_rev<ANYI1:mode><ANYI:mode>4"
> +	;; return value (calculated CRC)
> +  [(set (match_operand:ANYI 0 "register_operand" "=r")
> +		      ;; initial CRC
> +	(unspec:ANYI [(match_operand:ANYI 1 "register_operand" "r")
> +		      ;; data
> +		      (match_operand:ANYI1 2 "register_operand" "r")
> +		      ;; polynomial without leading 1
> +		      (match_operand:ANYI 3)]
> +		      UNSPEC_CRC_REV))]
> +  /* We don't support the case when data's size is bigger than CRC's size.  */
> +  "(((TARGET_ZBKC || TARGET_ZBC) && <ANYI:MODE>mode < word_mode)
> +    || TARGET_ZBKB) && <ANYI:MODE>mode >= <ANYI1:MODE>mode"
This condition should get reformatted.   Ideally the condition should be 
fairly obvious, but it's fairly obfuscated here.

I would expect that the TARGET_ZBKB likely belongs inside the 
conditional with the other TARGET tests.  Perhaps something like this:

> "(TARGET_ZBKB || TARGET_ZBKC || TARGET_ZBC)
>  && <ANYI:MODE>mode < word_mode
>  && <ANYI:MODE>mode >= <ANYI1:MODE>mode"

Or did you mean to allow ZBKB even if the quotient needs 65 bits?  If so 
the condition still needs adjustment, just a different adjustment.


Otherwise this looks fine to me.  Were there any adjustments you were 
considering after working through the aarch64 expansion with Richard S?

jeff
Mariam Arutunian Aug. 28, 2024, 8:14 a.m. UTC | #2
On Sun, Aug 25, 2024 at 9:41 PM Jeff Law <jeffreyalaw@gmail.com> wrote:

>
>
> On 7/26/24 12:06 PM, Mariam Arutunian wrote:
> >    If the target is ZBC or ZBKC, it uses clmul instruction for the CRC
> > calculation.
> > Otherwise, if the target is ZBKB, generates table-based CRC, but for
> > reversing inputs and the output uses bswap and brev8 instructions.
> >    Add new tests to check CRC generation for ZBC, ZBKC and ZBKB targets.
> >
> >       gcc/
> >
> >          * expr.cc (reflect): New function.
> >          (gf2n_poly_long_div_quotient): Likewise.
> >          * expr.h (reflect): New function declaration.
> >          (gf2n_poly_long_div_quotient): Likewise.
> >
> >       gcc/config/riscv/
> >
> >          * bitmanip.md (crc_rev<ANYI1:mode><ANYI:mode>4): New expander
> > for reversed CRC.
> >          (crc<SUBX1:mode><SUBX:mode>4): New expander for bit-forward CRC.
> >          (SUBX1, ANYI1): New iterators.
> >          * riscv-protos.h (generate_reflecting_code_using_brev): New
> > function declaration.
> >          (expand_crc_using_clmul): Likewise.
> >          (expand_reversed_crc_using_clmul): Likewise.
> >          * riscv.cc (generate_reflecting_code_using_brev): New function.
> >          (expand_crc_using_clmul): Likewise.
> >          (expand_reversed_crc_using_clmul): Likewise.
> >          * riscv.md (UNSPEC_CRC, UNSPEC_CRC_REV):  New unspecs.
> >
> >       gcc/testsuite/gcc.target/riscv/
> >
> >             * crc-1-zbc.c: New test.
> >             * crc-1-zbc.c: Likewise.
> >             * crc-10-zbc.c: Likewise.
> >             * crc-10-zbkc.c: Likewise.
> >             * crc-12-zbc.c: Likewise.
> >             * crc-12-zbkc.c: Likewise.
> >             * crc-13-zbc.c: Likewise.
> >             * crc-13-zbkc.c: Likewise.
> >             * crc-14-zbc.c: Likewise.
> >             * crc-14-zbkc.c: Likewise.
> >             * crc-17-zbc.c: Likewise.
> >             * crc-17-zbkc.c: Likewise.
> >             * crc-18-zbc.c: Likewise.
> >             * crc-18-zbkc.c: Likewise.
> >             * crc-21-zbc.c: Likewise.
> >             * crc-21-zbkc.c: Likewise.
> >             * crc-22-rv64-zbc.c: Likewise.
> >             * crc-22-rv64-zbkb.c: Likewise.
> >             * crc-22-rv64-zbkc.c: Likewise.
> >             * crc-23-zbc.c: Likewise.
> >             * crc-23-zbkc.c: Likewise.
> >             * crc-4-zbc.c: Likewise.
> >             * crc-4-zbkb.c: Likewise.
> >             * crc-4-zbkc.c: Likewise.
> >             * crc-5-zbc.c: Likewise.
> >             * crc-5-zbkb.c: Likewise.
> >             * crc-5-zbkc.c: Likewise.
> >             * crc-6-zbc.c: Likewise.
> >             * crc-6-zbkc.c: Likewise.
> >             * crc-7-zbc.c: Likewise.
> >             * crc-7-zbkc.c: Likewise.
> >             * crc-8-zbc.c: Likewise.
> >             * crc-8-zbkb.c: Likewise.
> >             * crc-8-zbkc.c: Likewise.
> >             * crc-9-zbc.c: Likewise.
> >             * crc-9-zbkc.c: Likewise.
> >             * crc-CCIT-data16-zbc.c: Likewise.
> >             * crc-CCIT-data16-zbkc.c: Likewise.
> >             * crc-CCIT-data8-zbc.c: Likewise.
> >             * crc-CCIT-data8-zbkc.c: Likewise.
> >             * crc-coremark-16bitdata-zbc.c: Likewise.
> >             * crc-coremark-16bitdata-zbkc.c: Likewise.
> >
> >     Signed-off-by: Mariam Arutunian <mariamarutunian@gmail.com
> > <mailto:mariamarutunian@gmail.com>>
> >
> >
> > 0003-RISC-V-Add-CRC-expander-to-generate-faster-CRC.patch
> >
> > diff --git a/gcc/config/riscv/bitmanip.md b/gcc/config/riscv/bitmanip.md
> > index 8769a6b818b..9683ac48ef6 100644
> > --- a/gcc/config/riscv/bitmanip.md
> > +++ b/gcc/config/riscv/bitmanip.md
> > @@ -973,3 +973,67 @@
> >     "TARGET_ZBC"
> >     "clmulr\t%0,%1,%2"
> >     [(set_attr "type" "clmul")])
> > +
> > +
> > +;; Iterator for hardware integer modes narrower than XLEN, same as SUBX
> > +(define_mode_iterator SUBX1 [QI HI (SI "TARGET_64BIT")])
> > +
> > +;; Iterator for hardware integer modes narrower than XLEN, same as ANYI
> > +(define_mode_iterator ANYI1 [QI HI SI (DI "TARGET_64BIT")])
> Might as well go ahead and put these into iterators.md.


Ok.


>
>

> > +
> > +;; Reversed CRC 8, 16, 32 for TARGET_64
> > +(define_expand "crc_rev<ANYI1:mode><ANYI:mode>4"
> > +     ;; return value (calculated CRC)
> > +  [(set (match_operand:ANYI 0 "register_operand" "=r")
> > +                   ;; initial CRC
> > +     (unspec:ANYI [(match_operand:ANYI 1 "register_operand" "r")
> > +                   ;; data
> > +                   (match_operand:ANYI1 2 "register_operand" "r")
> > +                   ;; polynomial without leading 1
> > +                   (match_operand:ANYI 3)]
> > +                   UNSPEC_CRC_REV))]
> > +  /* We don't support the case when data's size is bigger than CRC's
> size.  */
> > +  "(((TARGET_ZBKC || TARGET_ZBC) && <ANYI:MODE>mode < word_mode)
> > +    || TARGET_ZBKB) && <ANYI:MODE>mode >= <ANYI1:MODE>mode"
> This condition should get reformatted.   Ideally the condition should be
> fairly obvious, but it's fairly obfuscated here.
>
> I would expect that the TARGET_ZBKB likely belongs inside the
> conditional with the other TARGET tests.  Perhaps something like this:
>
> > "(TARGET_ZBKB || TARGET_ZBKC || TARGET_ZBC)
> >  && <ANYI:MODE>mode < word_mode
> >  && <ANYI:MODE>mode >= <ANYI1:MODE>mode"
>
> Or did you mean to allow ZBKB even if the quotient needs 65 bits?  If so
> the condition still needs adjustment, just a different adjustment.


Yes, in the case of ZBKB I generate table-based CRC, just use specific
instructions to reverse values.
Would it be okay if I just leave "<ANYI:MODE>mode >= <ANYI1:MODE>",
and then generate a standard table-based implementation in the body if none
of the conditions are met?

Or just write this way:
"(TARGET_ZBKB
  || ((TARGET_ZBKC || TARGET_ZBC) && <ANYI:MODE>mode < word_mode))
  && <ANYI:MODE>mode >= <ANYI1:MODE>mode"


>

> Otherwise this looks fine to me.  Were there any adjustments you were
> considering after working through the aarch64 expansion with Richard S?
>

Yes, I applied some of the changes I made in AArch64 here as well, where
possible and worked.
Also, in AArch64, I used force_reg in some cases, but here, I didn't
change, as you had told me to use riscv_expand_* instead of force_reg.

Thanks,
Mariam


> jeff
>
>
>
diff mbox series

Patch

diff --git a/gcc/config/riscv/bitmanip.md b/gcc/config/riscv/bitmanip.md
index 8769a6b818b..9683ac48ef6 100644
--- a/gcc/config/riscv/bitmanip.md
+++ b/gcc/config/riscv/bitmanip.md
@@ -973,3 +973,67 @@ 
   "TARGET_ZBC"
   "clmulr\t%0,%1,%2"
   [(set_attr "type" "clmul")])
+
+
+;; Iterator for hardware integer modes narrower than XLEN, same as SUBX
+(define_mode_iterator SUBX1 [QI HI (SI "TARGET_64BIT")])
+
+;; Iterator for hardware integer modes narrower than XLEN, same as ANYI
+(define_mode_iterator ANYI1 [QI HI SI (DI "TARGET_64BIT")])
+
+;; Reversed CRC 8, 16, 32 for TARGET_64
+(define_expand "crc_rev<ANYI1:mode><ANYI:mode>4"
+	;; return value (calculated CRC)
+  [(set (match_operand:ANYI 0 "register_operand" "=r")
+		      ;; initial CRC
+	(unspec:ANYI [(match_operand:ANYI 1 "register_operand" "r")
+		      ;; data
+		      (match_operand:ANYI1 2 "register_operand" "r")
+		      ;; polynomial without leading 1
+		      (match_operand:ANYI 3)]
+		      UNSPEC_CRC_REV))]
+  /* We don't support the case when data's size is bigger than CRC's size.  */
+  "(((TARGET_ZBKC || TARGET_ZBC) && <ANYI:MODE>mode < word_mode)
+    || TARGET_ZBKB) && <ANYI:MODE>mode >= <ANYI1:MODE>mode"
+{
+  /* If we have the ZBC or ZBKC extension (ie, clmul) and
+     it is possible to store the quotient within a single variable
+     (E.g.  CRC64's quotient may need 65 bits,
+     we can't keep it in 64 bit variable.)
+     then use clmul instruction to implement the CRC,
+     otherwise (TARGET_ZBKB) generate table based using brev.  */
+  if ((TARGET_ZBKC || TARGET_ZBC) && <ANYI:MODE>mode < word_mode)
+    expand_reversed_crc_using_clmul (<ANYI:MODE>mode, <ANYI1:MODE>mode,
+				     operands);
+  else
+    /* Generate table-based CRC.
+       To reflect values use brev and bswap instructions.  */
+    expand_reversed_crc_table_based (operands[0], operands[1],
+				     operands[2], operands[3],
+				     GET_MODE (operands[2]),
+				     generate_reflecting_code_using_brev);
+  DONE;
+})
+
+;; CRC 8, 16, (32 for TARGET_64)
+(define_expand "crc<SUBX1:mode><SUBX:mode>4"
+	;; return value (calculated CRC)
+  [(set (match_operand:SUBX 0 "register_operand" "=r")
+		      ;; initial CRC
+	(unspec:SUBX [(match_operand:SUBX 1 "register_operand" "r")
+		      ;; data
+		      (match_operand:SUBX1 2 "register_operand" "r")
+		      ;; polynomial without leading 1
+		      (match_operand:SUBX 3)]
+		      UNSPEC_CRC))]
+  /* We don't support the case when data's size is bigger than CRC's size.  */
+  "(TARGET_ZBKC || TARGET_ZBC) && <SUBX:MODE>mode >= <SUBX1:MODE>mode"
+{
+  /* If we have the ZBC or ZBKC extension (ie, clmul) and
+     it is possible to store the quotient within a single variable
+     (E.g.  CRC64's quotient may need 65 bits,
+     we can't keep it in 64 bit variable.)
+     then use clmul instruction to implement the CRC.  */
+  expand_crc_using_clmul (<SUBX:MODE>mode, <SUBX1:MODE>mode, operands);
+  DONE;
+})
diff --git a/gcc/config/riscv/riscv-protos.h b/gcc/config/riscv/riscv-protos.h
index 0704968561b..9cac9b9ae7f 100644
--- a/gcc/config/riscv/riscv-protos.h
+++ b/gcc/config/riscv/riscv-protos.h
@@ -169,6 +169,9 @@  extern enum memmodel riscv_union_memmodels (enum memmodel, enum memmodel);
 extern bool riscv_reg_frame_related (rtx);
 extern void riscv_split_sum_of_two_s12 (HOST_WIDE_INT, HOST_WIDE_INT *,
 					HOST_WIDE_INT *);
+extern void generate_reflecting_code_using_brev (rtx *, int);
+extern void expand_crc_using_clmul (scalar_mode, scalar_mode, rtx *);
+extern void expand_reversed_crc_using_clmul (scalar_mode, scalar_mode, rtx *);
 
 /* Routines implemented in riscv-c.cc.  */
 void riscv_cpu_cpp_builtins (cpp_reader *);
diff --git a/gcc/config/riscv/riscv.cc b/gcc/config/riscv/riscv.cc
index 85df5b7ab49..ccfd57c1da4 100644
--- a/gcc/config/riscv/riscv.cc
+++ b/gcc/config/riscv/riscv.cc
@@ -11415,6 +11415,158 @@  riscv_expand_usadd (rtx dest, rtx x, rtx y)
   emit_move_insn (dest, gen_lowpart (mode, xmode_dest));
 }
 
+/* Generate instruction sequence
+   which reflects the value of the OP using bswap and brev8 instructions.
+   OP's mode may be less than word_mode, to get the correct number,
+   after reflecting we shift right the value by SHIFT_VAL.
+   E.g. we have 1111 0001, after reflection (target 32-bit) we will get
+   1000 1111 0000 0000, if we shift-out 16 bits,
+   we will get the desired one: 1000 1111.  */
+
+void
+generate_reflecting_code_using_brev (rtx *op, int shift_val)
+{
+
+  riscv_expand_op (BSWAP, word_mode, *op, *op, *op);
+  riscv_expand_op (LSHIFTRT, word_mode, *op, *op,
+		   gen_int_mode (shift_val, word_mode));
+  if (TARGET_64BIT)
+    emit_insn (gen_riscv_brev8_di (*op, *op));
+  else
+    emit_insn (gen_riscv_brev8_si (*op, *op));
+}
+
+
+/* Generate assembly to calculate CRC using clmul instruction.
+   The following code will be generated when the CRC and data sizes are equal:
+     li      a4,quotient
+     li      a5,polynomial
+     xor     a0,a1,a0
+     clmul   a0,a0,a4
+     srli    a0,a0,crc_size
+     clmul   a0,a0,a5
+     slli    a0,a0,word_mode_size - crc_size
+     srli    a0,a0,word_mode_size - crc_size
+     ret
+   crc_size may be 8, 16, 32.
+   Some instructions will be added for the cases when CRC's size is larger than
+   data's size.
+   OPERANDS[1] is input CRC,
+   OPERANDS[2] is data (message),
+   OPERANDS[3] is the polynomial without the leading 1.  */
+
+void
+expand_crc_using_clmul (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]));
+  unsigned short crc_size = GET_MODE_BITSIZE (crc_mode);
+  gcc_assert (crc_size <= 32);
+  unsigned short data_size = GET_MODE_BITSIZE (data_mode);
+
+  /* Calculate the quotient.  */
+  unsigned HOST_WIDE_INT
+      q = gf2n_poly_long_div_quotient (UINTVAL (operands[3]), crc_size);
+
+  rtx crc_extended = gen_rtx_ZERO_EXTEND (word_mode, operands[1]);
+  rtx crc = gen_reg_rtx (word_mode);
+  if (crc_size > data_size)
+    riscv_expand_op (LSHIFTRT, word_mode, crc, crc_extended,
+		     gen_int_mode (crc_size - data_size, word_mode));
+  else
+    crc = gen_rtx_ZERO_EXTEND (word_mode, operands[1]);
+  rtx t0 = gen_reg_rtx (word_mode);
+  riscv_emit_move (t0, gen_int_mode (q, word_mode));
+  rtx t1 = gen_reg_rtx (word_mode);
+  riscv_emit_move (t1, operands[3]);
+
+  rtx a0 = gen_reg_rtx (word_mode);
+  rtx data = gen_rtx_ZERO_EXTEND (word_mode, operands[2]);
+  riscv_expand_op (XOR, word_mode, a0, crc, data);
+
+  if (TARGET_64BIT)
+    emit_insn (gen_riscv_clmul_di (a0, a0, t0));
+  else
+    emit_insn (gen_riscv_clmul_si (a0, a0, t0));
+
+  riscv_expand_op (LSHIFTRT, word_mode, a0, a0,
+		   gen_int_mode (crc_size, word_mode));
+  if (TARGET_64BIT)
+    emit_insn (gen_riscv_clmul_di (a0, a0, t1));
+  else
+    emit_insn (gen_riscv_clmul_si (a0, a0, t1));
+
+  if (crc_size > data_size)
+    {
+      rtx crc_part = gen_reg_rtx (word_mode);
+      riscv_expand_op (ASHIFT, word_mode, crc_part, operands[1],
+		       gen_int_mode (data_size, word_mode));
+      riscv_expand_op (XOR, word_mode, a0, a0, crc_part);
+    }
+  riscv_emit_move (operands[0], gen_lowpart (crc_mode, a0));
+}
+
+/* Generate assembly to calculate reversed CRC using clmul instruction.
+   OPERANDS[1] is input CRC,
+   OPERANDS[2] is data (message),
+   OPERANDS[3] is the polynomial without the leading 1.  */
+
+void
+expand_reversed_crc_using_clmul (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]));
+  unsigned short crc_size = GET_MODE_BITSIZE (crc_mode);
+  gcc_assert (crc_size <= 32);
+  unsigned short data_size = GET_MODE_BITSIZE (data_mode);
+
+  /* Calculate the quotient.  */
+  unsigned HOST_WIDE_INT
+      q = gf2n_poly_long_div_quotient (UINTVAL (operands[3]), crc_size);
+  /* Reflect the calculated quotient.  */
+  q = reflect (q);
+  rtx t0 = gen_reg_rtx (word_mode);
+  riscv_emit_move (t0, gen_int_mode (q >> (data_size - 4), word_mode));
+
+  /* Reflect the polynomial.  */
+  unsigned HOST_WIDE_INT polynomial = reflect (UINTVAL (operands[3]));
+  rtx t1 = gen_reg_rtx (word_mode);
+  riscv_emit_move (t1, gen_int_mode (polynomial << 1, word_mode));
+
+  rtx crc = gen_rtx_ZERO_EXTEND (word_mode, operands[1]);
+  rtx data = gen_rtx_ZERO_EXTEND (word_mode, operands[2]);
+  rtx a0 = gen_reg_rtx (word_mode);
+  riscv_expand_op (XOR, word_mode, a0, crc, data);
+
+  if (TARGET_64BIT)
+    emit_insn (gen_riscv_clmul_di (a0, a0, t0));
+  else
+    emit_insn (gen_riscv_clmul_si (a0, a0, t0));
+  rtx num_shift = gen_int_mode (GET_MODE_BITSIZE (word_mode) - crc_size - 3,
+				word_mode);
+  riscv_expand_op (ASHIFT, word_mode, a0, a0, num_shift);
+
+  if (TARGET_64BIT)
+    emit_insn (gen_riscv_clmulh_di (a0, a0, t1));
+  else
+    emit_insn (gen_riscv_clmulh_si (a0, a0, t1));
+
+  if (crc_size > data_size)
+    {
+      rtx data_size_shift = gen_int_mode (data_size, word_mode);
+      rtx crc_part = gen_reg_rtx (word_mode);
+      riscv_expand_op (LSHIFTRT, word_mode, crc_part, crc, data_size_shift);
+      riscv_expand_op (XOR, word_mode, a0, a0, crc_part);
+    }
+
+  riscv_emit_move (operands[0], gen_lowpart (crc_mode, a0));
+
+}
+
 /* Initialize the GCC target structure.  */
 #undef TARGET_ASM_ALIGNED_HI_OP
 #define TARGET_ASM_ALIGNED_HI_OP "\t.half\t"
diff --git a/gcc/config/riscv/riscv.md b/gcc/config/riscv/riscv.md
index 78c16adee98..1b216b01766 100644
--- a/gcc/config/riscv/riscv.md
+++ b/gcc/config/riscv/riscv.md
@@ -92,6 +92,10 @@ 
   ;; XTheadFmv moves
   UNSPEC_XTHEADFMV
   UNSPEC_XTHEADFMV_HW
+
+  ;; CRC unspecs
+  UNSPEC_CRC
+  UNSPEC_CRC_REV
 ])
 
 (define_c_enum "unspecv" [
diff --git a/gcc/expr.cc b/gcc/expr.cc
index c9a049aeecc..57b12784895 100644
--- a/gcc/expr.cc
+++ b/gcc/expr.cc
@@ -14092,6 +14092,52 @@  int_expr_size (const_tree exp)
   return tree_to_shwi (size);
 }
 
+/* Reflect the VALUE.
+   If we have 0000 0000 0101 0111, we will get 1110 1010.  */
+
+unsigned HOST_WIDE_INT
+reflect (unsigned HOST_WIDE_INT value)
+{
+  unsigned HOST_WIDE_INT reflectedValue = 0;
+  /* Looping through each bit in the byte.  */
+  for (size_t i = 0; value || !(i == 8 || i == 16 || i == 32 || i == 64); i++)
+	{
+	  reflectedValue <<= 1;
+	  /* Add the least significant bit of the original value to the
+	     reflected value.  */
+	  reflectedValue |= (value & 1);
+	  value >>= 1;
+	}
+  return reflectedValue;
+}
+
+/* Return the quotient of polynomial long division of x^2N by POLYNOMIAL
+   in GF (2^N).
+   Author: Richard Sandiford <richard.sandiford@arm.com>  */
+
+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);
+
+  /* Perform a division step for the x^2N coefficient.  At this point the
+     quotient and remainder have N implicit trailing zeros.  */
+  unsigned HOST_WIDE_INT quotient = 1;
+  unsigned HOST_WIDE_INT remainder = polynomial;
+
+  /* Process the coefficients for x^(2N-1) down to x^N, with each step
+     reducing the number of implicit trailing zeros by one.  */
+  for (unsigned int i = 0; i < n; ++i)
+    {
+      bool coeff = remainder & (HOST_WIDE_INT_1U << (n - 1));
+      quotient = (quotient << 1) | coeff;
+      remainder = (remainder << 1) ^ (coeff ? polynomial : 0);
+    }
+  return quotient;
+}
+
 /* Calculate CRC for the initial CRC and given POLYNOMIAL.
    CRC_BITS is CRC size.  */
 
diff --git a/gcc/expr.h b/gcc/expr.h
index 74634d22777..114f1e2fb7a 100644
--- a/gcc/expr.h
+++ b/gcc/expr.h
@@ -374,6 +374,15 @@  extern rtx expr_size (tree);
 extern bool mem_ref_refers_to_non_mem_p (tree);
 extern bool non_mem_decl_p (tree);
 
+/* Reflect the VALUE.
+   If we have 0000 0000 0101 0111, we will get 1110 1010.  */
+extern unsigned HOST_WIDE_INT reflect (unsigned HOST_WIDE_INT);
+
+/* Return the quotient of the polynomial long division of x^2N by POLYNOMIAL
+   in GF (2^N).  */
+extern unsigned HOST_WIDE_INT
+gf2n_poly_long_div_quotient (unsigned HOST_WIDE_INT, unsigned short);
+
 /* Generate table-based CRC.  */
 extern void generate_reflecting_code_standard (rtx *, int);
 extern void expand_crc_table_based (rtx, rtx, rtx, rtx, machine_mode);
diff --git a/gcc/testsuite/gcc.target/riscv/crc-1-zbc.c b/gcc/testsuite/gcc.target/riscv/crc-1-zbc.c
new file mode 100644
index 00000000000..a554ff97bb9
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/crc-1-zbc.c
@@ -0,0 +1,11 @@ 
+/* { dg-do run } */
+/* { dg-options "-fdump-tree-crc -fdump-rtl-dfinish  -fdisable-tree-phiopt2 -fdisable-tree-phiopt3" } */
+/* { dg-additional-options "-march=rv64gc_zbc" { target { rv64 } } } */
+/* { dg-additional-options "-march=rv32gc_zbc" { target { rv32 } } } */
+/* { dg-skip-if "" { *-*-* } { "-O0" "-O1" "-Os" "-Oz" "-Og" "-flto"} } */
+
+#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 "clmul" "dfinish"} } */
\ No newline at end of file
diff --git a/gcc/testsuite/gcc.target/riscv/crc-1-zbkc.c b/gcc/testsuite/gcc.target/riscv/crc-1-zbkc.c
new file mode 100644
index 00000000000..861dd982e9e
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/crc-1-zbkc.c
@@ -0,0 +1,11 @@ 
+/* { dg-do run } */
+/* { dg-options "-fdump-tree-crc -fdump-rtl-dfinish  -fdisable-tree-phiopt2 -fdisable-tree-phiopt3" } */
+/* { dg-additional-options "-march=rv64gc_zbkc" { target { rv64 } } } */
+/* { dg-additional-options "-march=rv32gc_zbkc" { target { rv32 } } } */
+/* { dg-skip-if "" { *-*-* } { "-O0" "-O1" "-Os" "-Oz" "-Og" "-flto"} } */
+
+#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 "clmul" "dfinish"} } */
\ No newline at end of file
diff --git a/gcc/testsuite/gcc.target/riscv/crc-10-zbc.c b/gcc/testsuite/gcc.target/riscv/crc-10-zbc.c
new file mode 100644
index 00000000000..1778315efb9
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/crc-10-zbc.c
@@ -0,0 +1,11 @@ 
+/* { dg-do run } */
+/* { dg-options "-fdump-tree-crc -fdump-rtl-dfinish " } */
+/* { dg-additional-options "-march=rv64gc_zbc" { target { rv64 } } } */
+/* { dg-additional-options "-march=rv32gc_zbc" { target { rv32 } } } */
+/* { dg-skip-if "" { *-*-* } { "-O0" "-O1" "-Os" "-Oz" "-Og" "-flto"} } */
+
+#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 "clmul" "dfinish"} } */
diff --git a/gcc/testsuite/gcc.target/riscv/crc-10-zbkc.c b/gcc/testsuite/gcc.target/riscv/crc-10-zbkc.c
new file mode 100644
index 00000000000..587a8d8bb80
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/crc-10-zbkc.c
@@ -0,0 +1,11 @@ 
+/* { dg-do run } */
+/* { dg-options "-fdump-tree-crc -fdump-rtl-dfinish " } */
+/* { dg-additional-options "-march=rv64gc_zbkc" { target { rv64 } } } */
+/* { dg-additional-options "-march=rv32gc_zbkc" { target { rv32 } } } */
+/* { dg-skip-if "" { *-*-* } { "-O0" "-O1" "-Os" "-Oz" "-Og" "-flto"} } */
+
+#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 "clmul" "dfinish"} } */
diff --git a/gcc/testsuite/gcc.target/riscv/crc-12-zbc.c b/gcc/testsuite/gcc.target/riscv/crc-12-zbc.c
new file mode 100644
index 00000000000..a096e529019
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/crc-12-zbc.c
@@ -0,0 +1,11 @@ 
+/* { dg-do run } */
+/* { dg-options "-fdump-tree-crc -fdump-rtl-dfinish  -fdisable-tree-phiopt2 -fdisable-tree-phiopt3" } */
+/* { dg-additional-options "-march=rv64gc_zbc" { target { rv64 } } } */
+/* { dg-additional-options "-march=rv32gc_zbc" { target { rv32 } } } */
+/* { dg-skip-if "" { *-*-* } { "-O0" "-O1" "-Os" "-Oz" "-Og" "-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 "clmul" "dfinish"} } */
diff --git a/gcc/testsuite/gcc.target/riscv/crc-12-zbkc.c b/gcc/testsuite/gcc.target/riscv/crc-12-zbkc.c
new file mode 100644
index 00000000000..4ea76d2b923
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/crc-12-zbkc.c
@@ -0,0 +1,11 @@ 
+/* { dg-do run } */
+/* { dg-options "-fdump-tree-crc -fdump-rtl-dfinish  -fdisable-tree-phiopt2 -fdisable-tree-phiopt3" } */
+/* { dg-additional-options "-march=rv64gc_zbkc" { target { rv64 } } } */
+/* { dg-additional-options "-march=rv32gc_zbkc" { target { rv32 } } } */
+/* { dg-skip-if "" { *-*-* } { "-O0" "-O1" "-Os" "-Oz" "-Og" "-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 "clmul" "dfinish"} } */
diff --git a/gcc/testsuite/gcc.target/riscv/crc-13-zbc.c b/gcc/testsuite/gcc.target/riscv/crc-13-zbc.c
new file mode 100644
index 00000000000..dbcb66a8379
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/crc-13-zbc.c
@@ -0,0 +1,11 @@ 
+/* { dg-do run } */
+/* { dg-options "-fdump-tree-crc -fdump-rtl-dfinish " } */
+/* { dg-additional-options "-march=rv64gc_zbc" { target { rv64 } } } */
+/* { dg-additional-options "-march=rv32gc_zbc" { target { rv32 } } } */
+/* { dg-skip-if "" { *-*-* } { "-O0" "-O1" "-Os" "-Oz" "-Og" "-flto"} } */
+
+#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 "clmul" "dfinish"} } */
diff --git a/gcc/testsuite/gcc.target/riscv/crc-13-zbkc.c b/gcc/testsuite/gcc.target/riscv/crc-13-zbkc.c
new file mode 100644
index 00000000000..f545f3303ee
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/crc-13-zbkc.c
@@ -0,0 +1,11 @@ 
+/* { dg-do run } */
+/* { dg-options "-fdump-tree-crc -fdump-rtl-dfinish " } */
+/* { dg-additional-options "-march=rv64gc_zbkc" { target { rv64 } } } */
+/* { dg-additional-options "-march=rv32gc_zbkc" { target { rv32 } } } */
+/* { dg-skip-if "" { *-*-* } { "-O0" "-O1" "-Os" "-Oz" "-Og" "-flto"} } */
+
+#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 "clmul" "dfinish"} } */
diff --git a/gcc/testsuite/gcc.target/riscv/crc-14-zbc.c b/gcc/testsuite/gcc.target/riscv/crc-14-zbc.c
new file mode 100644
index 00000000000..6bdf04406c2
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/crc-14-zbc.c
@@ -0,0 +1,11 @@ 
+/* { dg-do run } */
+/* { dg-options "-fdump-tree-crc -fdump-rtl-dfinish " } */
+/* { dg-additional-options "-march=rv64gc_zbc" { target { rv64 } } } */
+/* { dg-additional-options "-march=rv32gc_zbc" { target { rv32 } } } */
+/* { dg-skip-if "" { *-*-* } { "-O0" "-O1" "-Os" "-Oz" "-Og" "-flto"} } */
+
+#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 "clmul" "dfinish"} } */
diff --git a/gcc/testsuite/gcc.target/riscv/crc-14-zbkc.c b/gcc/testsuite/gcc.target/riscv/crc-14-zbkc.c
new file mode 100644
index 00000000000..2a0211ff0b0
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/crc-14-zbkc.c
@@ -0,0 +1,11 @@ 
+/* { dg-do run } */
+/* { dg-options "-fdump-tree-crc -fdump-rtl-dfinish " } */
+/* { dg-additional-options "-march=rv64gc_zbkc" { target { rv64 } } } */
+/* { dg-additional-options "-march=rv32gc_zbkc" { target { rv32 } } } */
+/* { dg-skip-if "" { *-*-* } { "-O0" "-O1" "-Os" "-Oz" "-Og" "-flto"} } */
+
+#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 "clmul" "dfinish"} } */
diff --git a/gcc/testsuite/gcc.target/riscv/crc-17-zbc.c b/gcc/testsuite/gcc.target/riscv/crc-17-zbc.c
new file mode 100644
index 00000000000..8dc16a87ce1
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/crc-17-zbc.c
@@ -0,0 +1,11 @@ 
+/* { dg-do run } */
+/* { dg-options "-fdump-tree-crc -fdump-rtl-dfinish " } */
+/* { dg-additional-options "-march=rv64gc_zbc" { target { rv64 } } } */
+/* { dg-additional-options "-march=rv32gc_zbc" { target { rv32 } } } */
+/* { dg-skip-if "" { *-*-* } { "-O0" "-O1" "-Os" "-Oz" "-Og" "-flto"} } */
+
+#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 "clmul" "dfinish"} } */
diff --git a/gcc/testsuite/gcc.target/riscv/crc-17-zbkc.c b/gcc/testsuite/gcc.target/riscv/crc-17-zbkc.c
new file mode 100644
index 00000000000..3099385924d
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/crc-17-zbkc.c
@@ -0,0 +1,11 @@ 
+/* { dg-do run } */
+/* { dg-options "-fdump-tree-crc -fdump-rtl-dfinish " } */
+/* { dg-additional-options "-march=rv64gc_zbkc" { target { rv64 } } } */
+/* { dg-additional-options "-march=rv32gc_zbkc" { target { rv32 } } } */
+/* { dg-skip-if "" { *-*-* } { "-O0" "-O1" "-Os" "-Oz" "-Og" "-flto"} } */
+
+#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 "clmul" "dfinish"} } */
diff --git a/gcc/testsuite/gcc.target/riscv/crc-18-zbc.c b/gcc/testsuite/gcc.target/riscv/crc-18-zbc.c
new file mode 100644
index 00000000000..bd239926d8e
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/crc-18-zbc.c
@@ -0,0 +1,11 @@ 
+/* { dg-do run } */
+/* { dg-options "-fdump-tree-crc -fdump-rtl-dfinish " } */
+/* { dg-additional-options "-march=rv64gc_zbc" { target { rv64 } } } */
+/* { dg-additional-options "-march=rv32gc_zbc" { target { rv32 } } } */
+/* { dg-skip-if "" { *-*-* } { "-O0" "-O1" "-Os" "-Oz" "-Og" "-flto"} } */
+
+#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 "clmul" "dfinish"} } */
diff --git a/gcc/testsuite/gcc.target/riscv/crc-18-zbkc.c b/gcc/testsuite/gcc.target/riscv/crc-18-zbkc.c
new file mode 100644
index 00000000000..856d0b59441
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/crc-18-zbkc.c
@@ -0,0 +1,11 @@ 
+/* { dg-do run } */
+/* { dg-options "-fdump-tree-crc -fdump-rtl-dfinish " } */
+/* { dg-additional-options "-march=rv64gc_zbkc" { target { rv64 } } } */
+/* { dg-additional-options "-march=rv32gc_zbkc" { target { rv32 } } } */
+/* { dg-skip-if "" { *-*-* } { "-O0" "-O1" "-Os" "-Oz" "-Og" "-flto"} } */
+
+#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 "clmul" "dfinish"} } */
diff --git a/gcc/testsuite/gcc.target/riscv/crc-21-rv64-zbc.c b/gcc/testsuite/gcc.target/riscv/crc-21-rv64-zbc.c
new file mode 100644
index 00000000000..f4adcde2f7f
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/crc-21-rv64-zbc.c
@@ -0,0 +1,9 @@ 
+/* { dg-do run { target { riscv64*-*-* } } } */
+/* { dg-options "-fdump-tree-crc -fdump-rtl-dfinish  -march=rv64gc_zbc" } */
+/* { dg-skip-if "" { *-*-* } { "-O0" "-O1" "-Os" "-Oz" "-Og" "-flto"} } */
+
+#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 "clmul" "dfinish"} } */
diff --git a/gcc/testsuite/gcc.target/riscv/crc-21-rv64-zbkc.c b/gcc/testsuite/gcc.target/riscv/crc-21-rv64-zbkc.c
new file mode 100644
index 00000000000..4f0b44e9624
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/crc-21-rv64-zbkc.c
@@ -0,0 +1,9 @@ 
+/* { dg-do run { target { riscv64*-*-* } } } */
+/* { dg-options "-fdump-tree-crc -fdump-rtl-dfinish  -march=rv64gc_zbkc" } */
+/* { dg-skip-if "" { *-*-* } { "-O0" "-O1" "-Os" "-Oz" "-Og" "-flto"} } */
+
+#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 "clmul" "dfinish"} } */
diff --git a/gcc/testsuite/gcc.target/riscv/crc-22-zbc.c b/gcc/testsuite/gcc.target/riscv/crc-22-zbc.c
new file mode 100644
index 00000000000..295834e0ebf
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/crc-22-zbc.c
@@ -0,0 +1,11 @@ 
+/* { dg-do run } */
+/* { dg-options "-fdump-tree-crc -fdump-rtl-dfinish " } */
+/* { dg-additional-options "-march=rv64gc_zbc" { target { rv64 } } } */
+/* { dg-additional-options "-march=rv32gc_zbc" { target { rv32 } } } */
+/* { dg-skip-if "" { *-*-* } { "-O0" "-O1" "-Os" "-Oz" "-Og" "-flto"} } */
+
+#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 "clmul" "dfinish"} } */
diff --git a/gcc/testsuite/gcc.target/riscv/crc-22-zbkb.c b/gcc/testsuite/gcc.target/riscv/crc-22-zbkb.c
new file mode 100644
index 00000000000..9c89219e169
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/crc-22-zbkb.c
@@ -0,0 +1,11 @@ 
+/* { dg-do run } */
+/* { dg-options "-fdump-tree-crc-details" } */
+/* { dg-additional-options "-march=rv64gc_zbkb" { target { rv64 } } } */
+/* { dg-additional-options "-march=rv32gc_zbkb" { target { rv32 } } } */
+/* { dg-skip-if "" { *-*-* } { "-O0" "-O1" "-Os" "-Oz" "-Og" "-flto"} } */
+
+#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 "clmul" "dfinish"} } */
diff --git a/gcc/testsuite/gcc.target/riscv/crc-22-zbkc.c b/gcc/testsuite/gcc.target/riscv/crc-22-zbkc.c
new file mode 100644
index 00000000000..506af22169f
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/crc-22-zbkc.c
@@ -0,0 +1,11 @@ 
+/* { dg-do run } */
+/* { dg-options "-fdump-tree-crc -fdump-rtl-dfinish " } */
+/* { dg-additional-options "-march=rv64gc_zbkc" { target { rv64 } } } */
+/* { dg-additional-options "-march=rv32gc_zbkc" { target { rv32 } } } */
+/* { dg-skip-if "" { *-*-* } { "-O0" "-O1" "-Os" "-Oz" "-Og" "-flto"} } */
+
+#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 "clmul" "dfinish"} } */
diff --git a/gcc/testsuite/gcc.target/riscv/crc-23-zbc.c b/gcc/testsuite/gcc.target/riscv/crc-23-zbc.c
new file mode 100644
index 00000000000..5f3d53910f4
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/crc-23-zbc.c
@@ -0,0 +1,11 @@ 
+/* { dg-do run } */
+/* { dg-options "-fdump-tree-crc -fdump-rtl-dfinish " } */
+/* { dg-additional-options "-march=rv64gc_zbc" { target { rv64 } } } */
+/* { dg-additional-options "-march=rv32gc_zbc" { target { rv32 } } } */
+/* { dg-skip-if "" { *-*-* } { "-O0" "-O1" "-Os" "-Oz" "-Og" "-flto"} } */
+
+#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 "clmul" "dfinish"} } */
diff --git a/gcc/testsuite/gcc.target/riscv/crc-23-zbkc.c b/gcc/testsuite/gcc.target/riscv/crc-23-zbkc.c
new file mode 100644
index 00000000000..87a5dc0790f
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/crc-23-zbkc.c
@@ -0,0 +1,11 @@ 
+/* { dg-do run } */
+/* { dg-options "-fdump-tree-crc -fdump-rtl-dfinish " } */
+/* { dg-additional-options "-march=rv64gc_zbkc" { target { rv64 } } } */
+/* { dg-additional-options "-march=rv32gc_zbkc" { target { rv32 } } } */
+/* { dg-skip-if "" { *-*-* } { "-O0" "-O1" "-Os" "-Oz" "-Og" "-flto"} } */
+
+#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 "clmul" "dfinish"} } */
diff --git a/gcc/testsuite/gcc.target/riscv/crc-4-zbc.c b/gcc/testsuite/gcc.target/riscv/crc-4-zbc.c
new file mode 100644
index 00000000000..94af839aa79
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/crc-4-zbc.c
@@ -0,0 +1,11 @@ 
+/* { dg-do run } */
+/* { dg-options "-fdump-tree-crc -fdump-rtl-dfinish " } */
+/* { dg-additional-options "-march=rv64gc_zbc" { target { rv64 } } } */
+/* { dg-additional-options "-march=rv32gc_zbc" { target { rv32 } } } */
+/* { dg-skip-if "" { *-*-* } { "-O0" "-O1" "-Os" "-Oz" "-Og" "-flto"} } */
+
+#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 "clmul" "dfinish"} } */
diff --git a/gcc/testsuite/gcc.target/riscv/crc-4-zbkb.c b/gcc/testsuite/gcc.target/riscv/crc-4-zbkb.c
new file mode 100644
index 00000000000..7017de9bec9
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/crc-4-zbkb.c
@@ -0,0 +1,10 @@ 
+/* { dg-do run } */
+/* { dg-options "-fdump-tree-crc-details" } */
+/* { dg-additional-options "-march=rv64gc_zbkb" { target { rv64 } } } */
+/* { dg-additional-options "-march=rv32gc_zbkb" { target { rv32 } } } */
+/* { dg-skip-if "" { *-*-* } { "-O0" "-O1" "-Os" "-Oz" "-Og" "-flto"} } */
+
+#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"} } */
diff --git a/gcc/testsuite/gcc.target/riscv/crc-4-zbkc.c b/gcc/testsuite/gcc.target/riscv/crc-4-zbkc.c
new file mode 100644
index 00000000000..40c033c4b80
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/crc-4-zbkc.c
@@ -0,0 +1,11 @@ 
+/* { dg-do run } */
+/* { dg-options "-fdump-tree-crc -fdump-rtl-dfinish " } */
+/* { dg-additional-options "-march=rv64gc_zbkc" { target { rv64 } } } */
+/* { dg-additional-options "-march=rv32gc_zbkc" { target { rv32 } } } */
+/* { dg-skip-if "" { *-*-* } { "-O0" "-O1" "-Os" "-Oz" "-Og" "-flto"} } */
+
+#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 "clmul" "dfinish"} } */
diff --git a/gcc/testsuite/gcc.target/riscv/crc-5-zbc.c b/gcc/testsuite/gcc.target/riscv/crc-5-zbc.c
new file mode 100644
index 00000000000..24633539d1d
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/crc-5-zbc.c
@@ -0,0 +1,11 @@ 
+/* { dg-do run } */
+/* { dg-options "-w -fdump-tree-crc -fdump-rtl-dfinish " } */
+/* { dg-additional-options "-march=rv64gc_zbc" { target { rv64 } } } */
+/* { dg-additional-options "-march=rv32gc_zbc" { target { rv32 } } } */
+/* { dg-skip-if "" { *-*-* } { "-O0" "-O1" "-Os" "-Oz" "-Og" "-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 "clmul" "dfinish"} } */
\ No newline at end of file
diff --git a/gcc/testsuite/gcc.target/riscv/crc-5-zbkb.c b/gcc/testsuite/gcc.target/riscv/crc-5-zbkb.c
new file mode 100644
index 00000000000..ee327064dce
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/crc-5-zbkb.c
@@ -0,0 +1,10 @@ 
+/* { dg-do run } */
+/* { dg-options "-w -fdump-tree-crc-details" } */
+/* { dg-additional-options "-march=rv64gc_zbkb" { target { rv64 } } } */
+/* { dg-additional-options "-march=rv32gc_zbkb" { target { rv32 } } } */
+/* { dg-skip-if "" { *-*-* } { "-O0" "-O1" "-Os" "-Oz" "-Og" "-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"} } */
\ No newline at end of file
diff --git a/gcc/testsuite/gcc.target/riscv/crc-5-zbkc.c b/gcc/testsuite/gcc.target/riscv/crc-5-zbkc.c
new file mode 100644
index 00000000000..fe2cada70a6
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/crc-5-zbkc.c
@@ -0,0 +1,11 @@ 
+/* { dg-do run } */
+/* { dg-options "-w -fdump-tree-crc -fdump-rtl-dfinish " } */
+/* { dg-additional-options "-march=rv64gc_zbkc" { target { rv64 } } } */
+/* { dg-additional-options "-march=rv32gc_zbkc" { target { rv32 } } } */
+/* { dg-skip-if "" { *-*-* } { "-O0" "-O1" "-Os" "-Oz" "-Og" "-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 "clmul" "dfinish"} } */
\ No newline at end of file
diff --git a/gcc/testsuite/gcc.target/riscv/crc-6-zbc.c b/gcc/testsuite/gcc.target/riscv/crc-6-zbc.c
new file mode 100644
index 00000000000..c771326991b
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/crc-6-zbc.c
@@ -0,0 +1,11 @@ 
+/* { dg-do run } */
+/* { dg-options "-fdump-tree-crc -fdump-rtl-dfinish " } */
+/* { dg-additional-options "-march=rv64gc_zbc" { target { rv64 } } } */
+/* { dg-additional-options "-march=rv32gc_zbc" { target { rv32 } } } */
+/* { dg-skip-if "" { *-*-* } { "-O0" "-O1" "-O3" "-Os" "-Oz" "-Og" "-flto"} } */
+
+#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 "clmul" "dfinish"} } */
\ No newline at end of file
diff --git a/gcc/testsuite/gcc.target/riscv/crc-6-zbkc.c b/gcc/testsuite/gcc.target/riscv/crc-6-zbkc.c
new file mode 100644
index 00000000000..b4d03f67d98
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/crc-6-zbkc.c
@@ -0,0 +1,11 @@ 
+/* { dg-do run } */
+/* { dg-options "-fdump-tree-crc -fdump-rtl-dfinish " } */
+/* { dg-additional-options "-march=rv64gc_zbkc" { target { rv64 } } } */
+/* { dg-additional-options "-march=rv32gc_zbkc" { target { rv32 } } } */
+/* { dg-skip-if "" { *-*-* } { "-O0" "-O1" "-O3" "-Os" "-Oz" "-Og" "-flto"} } */
+
+#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 "clmul" "dfinish"} } */
\ No newline at end of file
diff --git a/gcc/testsuite/gcc.target/riscv/crc-7-zbc.c b/gcc/testsuite/gcc.target/riscv/crc-7-zbc.c
new file mode 100644
index 00000000000..574caf1286f
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/crc-7-zbc.c
@@ -0,0 +1,11 @@ 
+/* { dg-do run } */
+/* { dg-options "-fdump-tree-crc -fdump-rtl-dfinish " } */
+/* { dg-additional-options "-march=rv64gc_zbc" { target { rv64 } } } */
+/* { dg-additional-options "-march=rv32gc_zbc" { target { rv32 } } } */
+/* { dg-skip-if "" { *-*-* } { "-O0" "-O1" "-Os" "-Oz" "-Og" "-flto"} } */
+
+#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 "clmul" "dfinish"} } */
diff --git a/gcc/testsuite/gcc.target/riscv/crc-7-zbkc.c b/gcc/testsuite/gcc.target/riscv/crc-7-zbkc.c
new file mode 100644
index 00000000000..15f2232e58e
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/crc-7-zbkc.c
@@ -0,0 +1,11 @@ 
+/* { dg-do run } */
+/* { dg-options "-fdump-tree-crc -fdump-rtl-dfinish " } */
+/* { dg-additional-options "-march=rv64gc_zbkc" { target { rv64 } } } */
+/* { dg-additional-options "-march=rv32gc_zbkc" { target { rv32 } } } */
+/* { dg-skip-if "" { *-*-* } { "-O0" "-O1" "-Os" "-Oz" "-Og" "-flto"} } */
+
+#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 "clmul" "dfinish"} } */
diff --git a/gcc/testsuite/gcc.target/riscv/crc-8-zbc.c b/gcc/testsuite/gcc.target/riscv/crc-8-zbc.c
new file mode 100644
index 00000000000..a4b719045fe
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/crc-8-zbc.c
@@ -0,0 +1,11 @@ 
+/* { dg-do run } */
+/* { dg-options "-fdump-tree-crc -fdump-rtl-dfinish " } */
+/* { dg-additional-options "-march=rv64gc_zbc" { target { rv64 } } } */
+/* { dg-additional-options "-march=rv32gc_zbc" { target { rv32 } } } */
+/* { dg-skip-if "" { *-*-* } { "-O0" "-O1" "-Os" "-Oz" "-Og" "-flto"} } */
+
+#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 "clmul" "dfinish"} } */
diff --git a/gcc/testsuite/gcc.target/riscv/crc-8-zbkb.c b/gcc/testsuite/gcc.target/riscv/crc-8-zbkb.c
new file mode 100644
index 00000000000..f9bd4945fbf
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/crc-8-zbkb.c
@@ -0,0 +1,10 @@ 
+/* { dg-do run } */
+/* { dg-options "-fdump-tree-crc-details" } */
+/* { dg-additional-options "-march=rv64gc_zbkb" { target { rv64 } } } */
+/* { dg-additional-options "-march=rv32gc_zbkb" { target { rv32 } } } */
+/* { dg-skip-if "" { *-*-* } { "-O0" "-O1" "-Os" "-Oz" "-Og" "-flto"} } */
+
+#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"} } */
diff --git a/gcc/testsuite/gcc.target/riscv/crc-8-zbkc.c b/gcc/testsuite/gcc.target/riscv/crc-8-zbkc.c
new file mode 100644
index 00000000000..55189b0c8c9
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/crc-8-zbkc.c
@@ -0,0 +1,11 @@ 
+/* { dg-do run } */
+/* { dg-options "-fdump-tree-crc -fdump-rtl-dfinish " } */
+/* { dg-additional-options "-march=rv64gc_zbkc" { target { rv64 } } } */
+/* { dg-additional-options "-march=rv32gc_zbkc" { target { rv32 } } } */
+/* { dg-skip-if "" { *-*-* } { "-O0" "-O1" "-Os" "-Oz" "-Og" "-flto"} } */
+
+#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 "clmul" "dfinish"} } */
diff --git a/gcc/testsuite/gcc.target/riscv/crc-9-zbc.c b/gcc/testsuite/gcc.target/riscv/crc-9-zbc.c
new file mode 100644
index 00000000000..88b5aaba3aa
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/crc-9-zbc.c
@@ -0,0 +1,11 @@ 
+/* { dg-do run } */
+/* { dg-options "-fdump-tree-crc -fdump-rtl-dfinish " } */
+/* { dg-additional-options "-march=rv64gc_zbc" { target { rv64 } } } */
+/* { dg-additional-options "-march=rv32gc_zbc" { target { rv32 } } } */
+/* { dg-skip-if "" { *-*-* } { "-O0" "-O1" "-O3" "-Os" "-Oz" "-Og" "-flto"} } */
+
+#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 "clmul" "dfinish"} } */
diff --git a/gcc/testsuite/gcc.target/riscv/crc-9-zbkc.c b/gcc/testsuite/gcc.target/riscv/crc-9-zbkc.c
new file mode 100644
index 00000000000..1dfd1802e41
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/crc-9-zbkc.c
@@ -0,0 +1,11 @@ 
+/* { dg-do run } */
+/* { dg-options "-fdump-tree-crc -fdump-rtl-dfinish " } */
+/* { dg-additional-options "-march=rv64gc_zbkc" { target { rv64 } } } */
+/* { dg-additional-options "-march=rv32gc_zbkc" { target { rv32 } } } */
+/* { dg-skip-if "" { *-*-* } { "-O0" "-O1" "-O3" "-Os" "-Oz" "-Og" "-flto"} } */
+
+#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 "clmul" "dfinish"} } */
diff --git a/gcc/testsuite/gcc.target/riscv/crc-CCIT-data16-zbc.c b/gcc/testsuite/gcc.target/riscv/crc-CCIT-data16-zbc.c
new file mode 100644
index 00000000000..79bb48d33b1
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/crc-CCIT-data16-zbc.c
@@ -0,0 +1,11 @@ 
+/* { dg-do run } */
+/* { dg-options "-w -fdump-tree-crc -fdump-rtl-dfinish " } */
+/* { dg-additional-options "-march=rv64gc_zbc" { target { rv64 } } } */
+/* { dg-additional-options "-march=rv32gc_zbc" { target { rv32 } } } */
+/* { dg-skip-if "" { *-*-* } { "-O0" "-O1" "-Os" "-Oz" "-Og" "-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 "clmul" "dfinish"} } */
\ No newline at end of file
diff --git a/gcc/testsuite/gcc.target/riscv/crc-CCIT-data16-zbkc.c b/gcc/testsuite/gcc.target/riscv/crc-CCIT-data16-zbkc.c
new file mode 100644
index 00000000000..4018dfa8e69
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/crc-CCIT-data16-zbkc.c
@@ -0,0 +1,11 @@ 
+/* { dg-do run } */
+/* { dg-options "-w -fdump-tree-crc -fdump-rtl-dfinish " } */
+/* { dg-additional-options "-march=rv64gc_zbkc" { target { rv64 } } } */
+/* { dg-additional-options "-march=rv32gc_zbkc" { target { rv32 } } } */
+/* { dg-skip-if "" { *-*-* } { "-O0" "-O1" "-Os" "-Oz" "-Og" "-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 "clmul" "dfinish"} } */
\ No newline at end of file
diff --git a/gcc/testsuite/gcc.target/riscv/crc-CCIT-data8-zbc.c b/gcc/testsuite/gcc.target/riscv/crc-CCIT-data8-zbc.c
new file mode 100644
index 00000000000..fcc413c7d76
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/crc-CCIT-data8-zbc.c
@@ -0,0 +1,11 @@ 
+/* { dg-do run } */
+/* { dg-options "-w -fdump-tree-crc -fdump-rtl-dfinish " } */
+/* { dg-additional-options "-march=rv64gc_zbc" { target { rv64 } } } */
+/* { dg-additional-options "-march=rv32gc_zbc" { target { rv32 } } } */
+/* { dg-skip-if "" { *-*-* } { "-O0" "-O1" "-Os" "-Oz" "-Og" "-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 "clmul" "dfinish"} } */
\ No newline at end of file
diff --git a/gcc/testsuite/gcc.target/riscv/crc-CCIT-data8-zbkc.c b/gcc/testsuite/gcc.target/riscv/crc-CCIT-data8-zbkc.c
new file mode 100644
index 00000000000..7e4a36dd7bf
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/crc-CCIT-data8-zbkc.c
@@ -0,0 +1,11 @@ 
+/* { dg-do run } */
+/* { dg-options "-w -fdump-tree-crc -fdump-rtl-dfinish " } */
+/* { dg-additional-options "-march=rv64gc_zbkc" { target { rv64 } } } */
+/* { dg-additional-options "-march=rv32gc_zbkc" { target { rv32 } } } */
+/* { dg-skip-if "" { *-*-* } { "-O0" "-O1" "-Os" "-Oz" "-Og" "-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 "clmul" "dfinish"} } */
\ No newline at end of file
diff --git a/gcc/testsuite/gcc.target/riscv/crc-coremark-16bitdata-zbc.c b/gcc/testsuite/gcc.target/riscv/crc-coremark-16bitdata-zbc.c
new file mode 100644
index 00000000000..88da999c4e3
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/crc-coremark-16bitdata-zbc.c
@@ -0,0 +1,11 @@ 
+/* { dg-do run } */
+/* { dg-options "-w -fdump-tree-crc -fdump-rtl-dfinish " } */
+/* { dg-additional-options "-march=rv64gc_zbc" { target { rv64 } } } */
+/* { dg-additional-options "-march=rv32gc_zbc" { target { rv32 } } } */
+/* { dg-skip-if "" { *-*-* } { "-O0" "-O1" "-Os" "-Oz" "-Og" "-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 "clmul" "dfinish"} } */
\ No newline at end of file
diff --git a/gcc/testsuite/gcc.target/riscv/crc-coremark-16bitdata-zbkc.c b/gcc/testsuite/gcc.target/riscv/crc-coremark-16bitdata-zbkc.c
new file mode 100644
index 00000000000..ef0083e33c2
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/crc-coremark-16bitdata-zbkc.c
@@ -0,0 +1,11 @@ 
+/* { dg-do run } */
+/* { dg-options "-w -fdump-tree-crc -fdump-rtl-dfinish " } */
+/* { dg-additional-options "-march=rv64gc_zbkc" { target { rv64 } } } */
+/* { dg-additional-options "-march=rv32gc_zbkc" { target { rv32 } } } */
+/* { dg-skip-if "" { *-*-* } { "-O0" "-O1" "-Os" "-Oz" "-Og" "-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 "clmul" "dfinish"} } */
\ No newline at end of file
-- 
2.25.1