RISC-V: Added support clmul[r,h] instructions for Zbc extension.

Message ID CACofN_76PcS3FbFQL2K2rXKPuov5JaT-jwAMTut0QuwAjN6hGg@mail.gmail.com
State Accepted
Headers
Series RISC-V: Added support clmul[r,h] instructions for Zbc extension. |

Checks

Context Check Description
snail/gcc-patch-check success Github commit url

Commit Message

Karen Sargsyan April 27, 2023, 2:29 p.m. UTC
  clmul[h] instructions were added only for the ZBKC extension.
This patch includes them in the ZBC extension too.
Besides, added support of 'clmulr' instructions for ZBC extension.

gcc/ChangeLog:

     * config/riscv/bitmanip.md: Added clmulr instruction.
     * config/riscv/riscv-builtins.cc (AVAIL): Add new.
     * config/riscv/riscv.md: (UNSPEC_CLMULR): Add new unspec type.
     * config/riscv/riscv-cmo.def: Added built-in function for clmulr.
     * config/riscv/crypto.md: Move clmul[h] instructions to bitmanip.md.
     * config/riscv/riscv-scalar-crypto.def: Move clmul[h] built-in
functions to riscv-cmo.def.

gcc/testsuite/ChangeLog:

   * gcc.target/riscv/zbc32.c: New test.
   * gcc.target/riscv/zbc64.c: New test.
  

Comments

Jeff Law April 28, 2023, 6:50 p.m. UTC | #1
On 4/27/23 08:29, Karen Sargsyan via Gcc-patches wrote:
> clmul[h] instructions were added only for the ZBKC extension.
> This patch includes them in the ZBC extension too.
> Besides, added support of 'clmulr' instructions for ZBC extension.
> 
> gcc/ChangeLog:
> 
>       * config/riscv/bitmanip.md: Added clmulr instruction.
>       * config/riscv/riscv-builtins.cc (AVAIL): Add new.
>       * config/riscv/riscv.md: (UNSPEC_CLMULR): Add new unspec type.
>       * config/riscv/riscv-cmo.def: Added built-in function for clmulr.
>       * config/riscv/crypto.md: Move clmul[h] instructions to bitmanip.md.
>       * config/riscv/riscv-scalar-crypto.def: Move clmul[h] built-in
> functions to riscv-cmo.def.
> 
> gcc/testsuite/ChangeLog:
> 
>     * gcc.target/riscv/zbc32.c: New test.
>     * gcc.target/riscv/zbc64.c: New test.
THanks.  I made a couple of minor changes.  Specifically rather than 
using the "bitmanip" type, I added a "clmul" type.  These instructions 
are typically not going to be single cycle and thus uarchs probably want 
to schedule them differently than a generic bitmanip instruction.  I 
also added the clmul type to the generic pipeline desription, routing 
into the generic_imul unit which seemed like the best fit.

Attached is the actual patch I committed.

Jeff
commit d9df45a66b2c8f543106be0a2387bbe6195b00a6
Author: Karen Sargsyan <karen1999411@gmail.com>
Date:   Fri Apr 28 12:45:34 2023 -0600

    RISC-V: Added support clmul[r,h] instructions for Zbc extension.
    
    clmul[h] instructions were added only for the ZBKC extension.
    This patch includes them in the ZBC extension too.
    Besides, added support of 'clmulr' instructions for ZBC extension.
    
    gcc/ChangeLog:
    
            * config/riscv/bitmanip.md: Added clmulr instruction.
            * config/riscv/riscv-builtins.cc (AVAIL): Add new.
            * config/riscv/riscv.md: (UNSPEC_CLMULR): Add new unspec type.
            (type): Add clmul
            * config/riscv/riscv-cmo.def: Added built-in function for clmulr.
            * config/riscv/crypto.md: Move clmul[h] instructions to bitmanip.md.
            * config/riscv/riscv-scalar-crypto.def: Move clmul[h] built-in
            functions to riscv-cmo.def.
            * config/riscv/generic.md: Add clmul to list of instructions
            using the generic_imul reservation.
    
    gcc/testsuite/ChangeLog:
    
            * gcc.target/riscv/zbc32.c: New test.
            * gcc.target/riscv/zbc64.c: New test.

diff --git a/gcc/config/riscv/bitmanip.md b/gcc/config/riscv/bitmanip.md
index 6617876bb0b..a27fc3e34a1 100644
--- a/gcc/config/riscv/bitmanip.md
+++ b/gcc/config/riscv/bitmanip.md
@@ -719,3 +719,32 @@ (define_insn_and_split "*branch<X:mode>_mask_twobits_equals_singlebit"
    operands[8] = GEN_INT (setbit);
    operands[9] = GEN_INT (clearbit);
 })
+
+;; ZBKC or ZBC extension
+(define_insn "riscv_clmul_<mode>"
+  [(set (match_operand:X 0 "register_operand" "=r")
+        (unspec:X [(match_operand:X 1 "register_operand" "r")
+                  (match_operand:X 2 "register_operand" "r")]
+                  UNSPEC_CLMUL))]
+  "TARGET_ZBKC || TARGET_ZBC"
+  "clmul\t%0,%1,%2"
+  [(set_attr "type" "clmul")])
+
+(define_insn "riscv_clmulh_<mode>"
+  [(set (match_operand:X 0 "register_operand" "=r")
+        (unspec:X [(match_operand:X 1 "register_operand" "r")
+                  (match_operand:X 2 "register_operand" "r")]
+                  UNSPEC_CLMULH))]
+  "TARGET_ZBKC || TARGET_ZBC"
+  "clmulh\t%0,%1,%2"
+  [(set_attr "type" "clmul")])
+
+;; ZBC extension
+(define_insn "riscv_clmulr_<mode>"
+  [(set (match_operand:X 0 "register_operand" "=r")
+        (unspec:X [(match_operand:X 1 "register_operand" "r")
+                  (match_operand:X 2 "register_operand" "r")]
+                  UNSPEC_CLMULR))]
+  "TARGET_ZBC"
+  "clmulr\t%0,%1,%2"
+  [(set_attr "type" "clmul")])
diff --git a/gcc/config/riscv/crypto.md b/gcc/config/riscv/crypto.md
index 777aa529005..e4b7f0190df 100644
--- a/gcc/config/riscv/crypto.md
+++ b/gcc/config/riscv/crypto.md
@@ -26,10 +26,6 @@ (define_c_enum "unspec" [
     UNSPEC_PACKH
     UNSPEC_PACKW
 
-    ;; Zbkc unspecs
-    UNSPEC_CLMUL
-    UNSPEC_CLMULH
-
     ;; Zbkx unspecs
     UNSPEC_XPERM8
     UNSPEC_XPERM4
@@ -126,26 +122,6 @@ (define_insn "riscv_packw"
   "packw\t%0,%1,%2"
   [(set_attr "type" "crypto")])
 
-;; ZBKC extension
-
-(define_insn "riscv_clmul_<mode>"
-  [(set (match_operand:X 0 "register_operand" "=r")
-        (unspec:X [(match_operand:X 1 "register_operand" "r")
-                  (match_operand:X 2 "register_operand" "r")]
-                  UNSPEC_CLMUL))]
-  "TARGET_ZBKC"
-  "clmul\t%0,%1,%2"
-  [(set_attr "type" "crypto")])
-
-(define_insn "riscv_clmulh_<mode>"
-  [(set (match_operand:X 0 "register_operand" "=r")
-        (unspec:X [(match_operand:X 1 "register_operand" "r")
-                  (match_operand:X 2 "register_operand" "r")]
-                  UNSPEC_CLMULH))]
-  "TARGET_ZBKC"
-  "clmulh\t%0,%1,%2"
-  [(set_attr "type" "crypto")])
-
 ;; ZBKX extension
 
 (define_insn "riscv_xperm4_<mode>"
diff --git a/gcc/config/riscv/generic.md b/gcc/config/riscv/generic.md
index 2c3376628c3..57d3c3b4adc 100644
--- a/gcc/config/riscv/generic.md
+++ b/gcc/config/riscv/generic.md
@@ -52,7 +52,7 @@ (define_insn_reservation "generic_branch" 1
 
 (define_insn_reservation "generic_imul" 10
   (and (eq_attr "tune" "generic")
-       (eq_attr "type" "imul"))
+       (eq_attr "type" "imul,clmul"))
   "imuldiv*10")
 
 (define_insn_reservation "generic_idivsi" 34
diff --git a/gcc/config/riscv/riscv-builtins.cc b/gcc/config/riscv/riscv-builtins.cc
index b1c4b7547d7..79681d75962 100644
--- a/gcc/config/riscv/riscv-builtins.cc
+++ b/gcc/config/riscv/riscv-builtins.cc
@@ -105,8 +105,6 @@ AVAIL (prefetchi32, TARGET_ZICBOP && !TARGET_64BIT)
 AVAIL (prefetchi64, TARGET_ZICBOP && TARGET_64BIT)
 AVAIL (crypto_zbkb32, TARGET_ZBKB && !TARGET_64BIT)
 AVAIL (crypto_zbkb64, TARGET_ZBKB && TARGET_64BIT)
-AVAIL (crypto_zbkc32, TARGET_ZBKC && !TARGET_64BIT)
-AVAIL (crypto_zbkc64, TARGET_ZBKC && TARGET_64BIT)
 AVAIL (crypto_zbkx32, TARGET_ZBKX && !TARGET_64BIT)
 AVAIL (crypto_zbkx64, TARGET_ZBKX && TARGET_64BIT)
 AVAIL (crypto_zknd32, TARGET_ZKND && !TARGET_64BIT)
@@ -120,6 +118,10 @@ AVAIL (crypto_zksh32, TARGET_ZKSH && !TARGET_64BIT)
 AVAIL (crypto_zksh64, TARGET_ZKSH && TARGET_64BIT)
 AVAIL (crypto_zksed32, TARGET_ZKSED && !TARGET_64BIT)
 AVAIL (crypto_zksed64, TARGET_ZKSED && TARGET_64BIT)
+AVAIL (clmul_zbkc32_or_zbc32, (TARGET_ZBKC || TARGET_ZBC) && !TARGET_64BIT)
+AVAIL (clmul_zbkc64_or_zbc64, (TARGET_ZBKC || TARGET_ZBC) && TARGET_64BIT)
+AVAIL (clmulr_zbc32, TARGET_ZBC && !TARGET_64BIT)
+AVAIL (clmulr_zbc64, TARGET_ZBC && TARGET_64BIT)
 AVAIL (always,     (!0))
 
 /* Construct a riscv_builtin_description from the given arguments.
diff --git a/gcc/config/riscv/riscv-cmo.def b/gcc/config/riscv/riscv-cmo.def
index 9fe5094ce1a..b92044dc6ff 100644
--- a/gcc/config/riscv/riscv-cmo.def
+++ b/gcc/config/riscv/riscv-cmo.def
@@ -15,3 +15,13 @@ RISCV_BUILTIN (zero_di, "zicboz_cbo_zero", RISCV_BUILTIN_DIRECT_NO_TARGET, RISCV
 // zicbop
 RISCV_BUILTIN (prefetchi_si, "zicbop_cbo_prefetchi", RISCV_BUILTIN_DIRECT, RISCV_SI_FTYPE_SI, prefetchi32),
 RISCV_BUILTIN (prefetchi_di, "zicbop_cbo_prefetchi", RISCV_BUILTIN_DIRECT, RISCV_DI_FTYPE_DI, prefetchi64),
+
+// zbkc or zbc
+RISCV_BUILTIN (clmul_si, "clmul", RISCV_BUILTIN_DIRECT, RISCV_SI_FTYPE_SI_SI, clmul_zbkc32_or_zbc32),
+RISCV_BUILTIN (clmul_di, "clmul", RISCV_BUILTIN_DIRECT, RISCV_DI_FTYPE_DI_DI, clmul_zbkc64_or_zbc64),
+RISCV_BUILTIN (clmulh_si, "clmulh", RISCV_BUILTIN_DIRECT, RISCV_SI_FTYPE_SI_SI, clmul_zbkc32_or_zbc32),
+RISCV_BUILTIN (clmulh_di, "clmulh", RISCV_BUILTIN_DIRECT, RISCV_DI_FTYPE_DI_DI, clmul_zbkc64_or_zbc64),
+
+// zbc
+RISCV_BUILTIN (clmulr_si, "clmulr", RISCV_BUILTIN_DIRECT, RISCV_SI_FTYPE_SI_SI, clmulr_zbc32),
+RISCV_BUILTIN (clmulr_di, "clmulr", RISCV_BUILTIN_DIRECT, RISCV_DI_FTYPE_DI_DI, clmulr_zbc64),
diff --git a/gcc/config/riscv/riscv-scalar-crypto.def b/gcc/config/riscv/riscv-scalar-crypto.def
index 139793c6360..c2caed5151d 100644
--- a/gcc/config/riscv/riscv-scalar-crypto.def
+++ b/gcc/config/riscv/riscv-scalar-crypto.def
@@ -32,12 +32,6 @@ RISCV_BUILTIN (unzip, "unzip", RISCV_BUILTIN_DIRECT, RISCV_SI_FTYPE_SI, crypto_z
 RISCV_BUILTIN (brev8_si, "brev8", RISCV_BUILTIN_DIRECT, RISCV_SI_FTYPE_SI, crypto_zbkb32),
 RISCV_BUILTIN (brev8_di, "brev8", RISCV_BUILTIN_DIRECT, RISCV_DI_FTYPE_DI, crypto_zbkb64),
 
-// ZBKC
-RISCV_BUILTIN (clmul_si, "clmul", RISCV_BUILTIN_DIRECT, RISCV_SI_FTYPE_SI_SI, crypto_zbkc32),
-RISCV_BUILTIN (clmul_di, "clmul", RISCV_BUILTIN_DIRECT, RISCV_DI_FTYPE_DI_DI, crypto_zbkc64),
-RISCV_BUILTIN (clmulh_si, "clmulh", RISCV_BUILTIN_DIRECT, RISCV_SI_FTYPE_SI_SI, crypto_zbkc32),
-RISCV_BUILTIN (clmulh_di, "clmulh", RISCV_BUILTIN_DIRECT, RISCV_DI_FTYPE_DI_DI, crypto_zbkc64),
-
 // ZBKX
 RISCV_BUILTIN (xperm4_si, "xperm4", RISCV_BUILTIN_DIRECT, RISCV_SI_FTYPE_SI_SI, crypto_zbkx32),
 RISCV_BUILTIN (xperm4_di, "xperm4", RISCV_BUILTIN_DIRECT, RISCV_DI_FTYPE_DI_DI, crypto_zbkx64),
diff --git a/gcc/config/riscv/riscv.md b/gcc/config/riscv/riscv.md
index dd845cc1ed3..376a8831820 100644
--- a/gcc/config/riscv/riscv.md
+++ b/gcc/config/riscv/riscv.md
@@ -65,6 +65,11 @@ (define_c_enum "unspec" [
 
   ;; OR-COMBINE
   UNSPEC_ORC_B
+
+  ;; Zbc unspecs
+  UNSPEC_CLMUL
+  UNSPEC_CLMULH
+  UNSPEC_CLMULR
 ])
 
 (define_c_enum "unspecv" [
@@ -244,6 +249,7 @@ (define_attr "enabled" "no,yes"
 ;; nop		no operation
 ;; ghost	an instruction that produces no real code
 ;; bitmanip	bit manipulation instructions
+;; clmul    clmul, clmulh, clmulr
 ;; rotate   rotation instructions
 ;; atomic   atomic instructions
 ;; condmove	conditional moves
@@ -344,7 +350,7 @@ (define_attr "type"
   "unknown,branch,jump,call,load,fpload,store,fpstore,
    mtc,mfc,const,arith,logical,shift,slt,imul,idiv,move,fmove,fadd,fmul,
    fmadd,fdiv,fcmp,fcvt,fsqrt,multi,auipc,sfb_alu,nop,ghost,bitmanip,rotate,
-   min,max,minu,maxu,clz,ctz,cpop,
+   clmul,min,max,minu,maxu,clz,ctz,cpop,
    atomic,condmove,crypto,rdvlenb,rdvl,vsetvl,vlde,vste,vldm,vstm,vlds,vsts,
    vldux,vldox,vstux,vstox,vldff,vldr,vstr,
    vialu,viwalu,vext,vicalu,vshift,vnshift,vicmp,viminmax,
diff --git a/gcc/testsuite/gcc.target/riscv/zbc32.c b/gcc/testsuite/gcc.target/riscv/zbc32.c
new file mode 100644
index 00000000000..08705c4a687
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/zbc32.c
@@ -0,0 +1,23 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -march=rv32gc_zbc -mabi=ilp32" } */
+/* { dg-skip-if "" { *-*-* } { "-g" "-flto"} } */
+#include <stdint-gcc.h>
+
+int32_t foo1(int32_t rs1, int32_t rs2)
+{
+    return __builtin_riscv_clmul(rs1, rs2);
+}
+
+int32_t foo2(int32_t rs1, int32_t rs2)
+{
+    return __builtin_riscv_clmulh(rs1, rs2);
+}
+
+int32_t foo3(int32_t rs1, int32_t rs2)
+{
+    return __builtin_riscv_clmulr(rs1, rs2);
+}
+
+/* { dg-final { scan-assembler-times "clmul\t" 1 } } */
+/* { dg-final { scan-assembler-times "clmulh" 1 } } */
+/* { dg-final { scan-assembler-times "clmulr" 1 } } */
diff --git a/gcc/testsuite/gcc.target/riscv/zbc64.c b/gcc/testsuite/gcc.target/riscv/zbc64.c
new file mode 100644
index 00000000000..a19f42b2883
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/zbc64.c
@@ -0,0 +1,23 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -march=rv64gc_zbc -mabi=lp64" } */
+/* { dg-skip-if "" { *-*-* } { "-g" "-flto"} } */
+#include <stdint-gcc.h>
+
+int64_t foo1(int64_t rs1, int64_t rs2)
+{
+    return __builtin_riscv_clmul(rs1, rs2);
+}
+
+int64_t foo2(int64_t rs1, int64_t rs2)
+{
+    return __builtin_riscv_clmulh(rs1, rs2);
+}
+
+int64_t foo3(int64_t rs1, int64_t rs2)
+{
+    return __builtin_riscv_clmulr(rs1, rs2);
+}
+
+/* { dg-final { scan-assembler-times "clmul\t" 1 } } */
+/* { dg-final { scan-assembler-times "clmulh" 1 } } */
+/* { dg-final { scan-assembler-times "clmulr" 1 } } */
  

Patch

diff --git a/gcc/config/riscv/bitmanip.md b/gcc/config/riscv/bitmanip.md
index 44ad350c747..10ffb2d3f51 100644
--- a/gcc/config/riscv/bitmanip.md
+++ b/gcc/config/riscv/bitmanip.md
@@ -696,3 +696,32 @@ 
    operands[8] = GEN_INT (setbit);
    operands[9] = GEN_INT (clearbit);
 })
+
+;; ZBKC or ZBC extension
+(define_insn "riscv_clmul_<mode>"
+  [(set (match_operand:X 0 "register_operand" "=r")
+        (unspec:X [(match_operand:X 1 "register_operand" "r")
+                  (match_operand:X 2 "register_operand" "r")]
+                  UNSPEC_CLMUL))]
+  "TARGET_ZBKC || TARGET_ZBC"
+  "clmul\t%0,%1,%2"
+  [(set_attr "type" "bitmanip")])
+
+(define_insn "riscv_clmulh_<mode>"
+  [(set (match_operand:X 0 "register_operand" "=r")
+        (unspec:X [(match_operand:X 1 "register_operand" "r")
+                  (match_operand:X 2 "register_operand" "r")]
+                  UNSPEC_CLMULH))]
+  "TARGET_ZBKC || TARGET_ZBC"
+  "clmulh\t%0,%1,%2"
+  [(set_attr "type" "bitmanip")])
+
+;; ZBC extension
+(define_insn "riscv_clmulr_<mode>"
+  [(set (match_operand:X 0 "register_operand" "=r")
+        (unspec:X [(match_operand:X 1 "register_operand" "r")
+                  (match_operand:X 2 "register_operand" "r")]
+                  UNSPEC_CLMULR))]
+  "TARGET_ZBC"
+  "clmulr\t%0,%1,%2"
+  [(set_attr "type" "bitmanip")])
diff --git a/gcc/config/riscv/crypto.md b/gcc/config/riscv/crypto.md
index 777aa529005..e4b7f0190df 100644
--- a/gcc/config/riscv/crypto.md
+++ b/gcc/config/riscv/crypto.md
@@ -26,10 +26,6 @@ 
     UNSPEC_PACKH
     UNSPEC_PACKW
 
-    ;; Zbkc unspecs
-    UNSPEC_CLMUL
-    UNSPEC_CLMULH
-
     ;; Zbkx unspecs
     UNSPEC_XPERM8
     UNSPEC_XPERM4
@@ -126,26 +122,6 @@ 
   "packw\t%0,%1,%2"
   [(set_attr "type" "crypto")])
 
-;; ZBKC extension
-
-(define_insn "riscv_clmul_<mode>"
-  [(set (match_operand:X 0 "register_operand" "=r")
-        (unspec:X [(match_operand:X 1 "register_operand" "r")
-                  (match_operand:X 2 "register_operand" "r")]
-                  UNSPEC_CLMUL))]
-  "TARGET_ZBKC"
-  "clmul\t%0,%1,%2"
-  [(set_attr "type" "crypto")])
-
-(define_insn "riscv_clmulh_<mode>"
-  [(set (match_operand:X 0 "register_operand" "=r")
-        (unspec:X [(match_operand:X 1 "register_operand" "r")
-                  (match_operand:X 2 "register_operand" "r")]
-                  UNSPEC_CLMULH))]
-  "TARGET_ZBKC"
-  "clmulh\t%0,%1,%2"
-  [(set_attr "type" "crypto")])
-
 ;; ZBKX extension
 
 (define_insn "riscv_xperm4_<mode>"
diff --git a/gcc/config/riscv/riscv-builtins.cc b/gcc/config/riscv/riscv-builtins.cc
index b1c4b7547d7..79681d75962 100644
--- a/gcc/config/riscv/riscv-builtins.cc
+++ b/gcc/config/riscv/riscv-builtins.cc
@@ -105,8 +105,6 @@  AVAIL (prefetchi32, TARGET_ZICBOP && !TARGET_64BIT)
 AVAIL (prefetchi64, TARGET_ZICBOP && TARGET_64BIT)
 AVAIL (crypto_zbkb32, TARGET_ZBKB && !TARGET_64BIT)
 AVAIL (crypto_zbkb64, TARGET_ZBKB && TARGET_64BIT)
-AVAIL (crypto_zbkc32, TARGET_ZBKC && !TARGET_64BIT)
-AVAIL (crypto_zbkc64, TARGET_ZBKC && TARGET_64BIT)
 AVAIL (crypto_zbkx32, TARGET_ZBKX && !TARGET_64BIT)
 AVAIL (crypto_zbkx64, TARGET_ZBKX && TARGET_64BIT)
 AVAIL (crypto_zknd32, TARGET_ZKND && !TARGET_64BIT)
@@ -120,6 +118,10 @@  AVAIL (crypto_zksh32, TARGET_ZKSH && !TARGET_64BIT)
 AVAIL (crypto_zksh64, TARGET_ZKSH && TARGET_64BIT)
 AVAIL (crypto_zksed32, TARGET_ZKSED && !TARGET_64BIT)
 AVAIL (crypto_zksed64, TARGET_ZKSED && TARGET_64BIT)
+AVAIL (clmul_zbkc32_or_zbc32, (TARGET_ZBKC || TARGET_ZBC) && !TARGET_64BIT)
+AVAIL (clmul_zbkc64_or_zbc64, (TARGET_ZBKC || TARGET_ZBC) && TARGET_64BIT)
+AVAIL (clmulr_zbc32, TARGET_ZBC && !TARGET_64BIT)
+AVAIL (clmulr_zbc64, TARGET_ZBC && TARGET_64BIT)
 AVAIL (always,     (!0))
 
 /* Construct a riscv_builtin_description from the given arguments.
diff --git a/gcc/config/riscv/riscv-cmo.def b/gcc/config/riscv/riscv-cmo.def
index 9fe5094ce1a..b92044dc6ff 100644
--- a/gcc/config/riscv/riscv-cmo.def
+++ b/gcc/config/riscv/riscv-cmo.def
@@ -15,3 +15,13 @@  RISCV_BUILTIN (zero_di, "zicboz_cbo_zero", RISCV_BUILTIN_DIRECT_NO_TARGET, RISCV
 // zicbop
 RISCV_BUILTIN (prefetchi_si, "zicbop_cbo_prefetchi", RISCV_BUILTIN_DIRECT, RISCV_SI_FTYPE_SI, prefetchi32),
 RISCV_BUILTIN (prefetchi_di, "zicbop_cbo_prefetchi", RISCV_BUILTIN_DIRECT, RISCV_DI_FTYPE_DI, prefetchi64),
+
+// zbkc or zbc
+RISCV_BUILTIN (clmul_si, "clmul", RISCV_BUILTIN_DIRECT, RISCV_SI_FTYPE_SI_SI, clmul_zbkc32_or_zbc32),
+RISCV_BUILTIN (clmul_di, "clmul", RISCV_BUILTIN_DIRECT, RISCV_DI_FTYPE_DI_DI, clmul_zbkc64_or_zbc64),
+RISCV_BUILTIN (clmulh_si, "clmulh", RISCV_BUILTIN_DIRECT, RISCV_SI_FTYPE_SI_SI, clmul_zbkc32_or_zbc32),
+RISCV_BUILTIN (clmulh_di, "clmulh", RISCV_BUILTIN_DIRECT, RISCV_DI_FTYPE_DI_DI, clmul_zbkc64_or_zbc64),
+
+// zbc
+RISCV_BUILTIN (clmulr_si, "clmulr", RISCV_BUILTIN_DIRECT, RISCV_SI_FTYPE_SI_SI, clmulr_zbc32),
+RISCV_BUILTIN (clmulr_di, "clmulr", RISCV_BUILTIN_DIRECT, RISCV_DI_FTYPE_DI_DI, clmulr_zbc64),
diff --git a/gcc/config/riscv/riscv-scalar-crypto.def b/gcc/config/riscv/riscv-scalar-crypto.def
index 139793c6360..c2caed5151d 100644
--- a/gcc/config/riscv/riscv-scalar-crypto.def
+++ b/gcc/config/riscv/riscv-scalar-crypto.def
@@ -32,12 +32,6 @@  RISCV_BUILTIN (unzip, "unzip", RISCV_BUILTIN_DIRECT, RISCV_SI_FTYPE_SI, crypto_z
 RISCV_BUILTIN (brev8_si, "brev8", RISCV_BUILTIN_DIRECT, RISCV_SI_FTYPE_SI, crypto_zbkb32),
 RISCV_BUILTIN (brev8_di, "brev8", RISCV_BUILTIN_DIRECT, RISCV_DI_FTYPE_DI, crypto_zbkb64),
 
-// ZBKC
-RISCV_BUILTIN (clmul_si, "clmul", RISCV_BUILTIN_DIRECT, RISCV_SI_FTYPE_SI_SI, crypto_zbkc32),
-RISCV_BUILTIN (clmul_di, "clmul", RISCV_BUILTIN_DIRECT, RISCV_DI_FTYPE_DI_DI, crypto_zbkc64),
-RISCV_BUILTIN (clmulh_si, "clmulh", RISCV_BUILTIN_DIRECT, RISCV_SI_FTYPE_SI_SI, crypto_zbkc32),
-RISCV_BUILTIN (clmulh_di, "clmulh", RISCV_BUILTIN_DIRECT, RISCV_DI_FTYPE_DI_DI, crypto_zbkc64),
-
 // ZBKX
 RISCV_BUILTIN (xperm4_si, "xperm4", RISCV_BUILTIN_DIRECT, RISCV_SI_FTYPE_SI_SI, crypto_zbkx32),
 RISCV_BUILTIN (xperm4_di, "xperm4", RISCV_BUILTIN_DIRECT, RISCV_DI_FTYPE_DI_DI, crypto_zbkx64),
diff --git a/gcc/config/riscv/riscv.md b/gcc/config/riscv/riscv.md
index 0c69407ac09..dc758b15dd1 100644
--- a/gcc/config/riscv/riscv.md
+++ b/gcc/config/riscv/riscv.md
@@ -65,6 +65,11 @@ 
 
   ;; OR-COMBINE
   UNSPEC_ORC_B
+
+  ;; Zbc unspecs
+  UNSPEC_CLMUL
+  UNSPEC_CLMULH
+  UNSPEC_CLMULR
 ])
 
 (define_c_enum "unspecv" [
diff --git a/gcc/testsuite/gcc.target/riscv/zbc32.c b/gcc/testsuite/gcc.target/riscv/zbc32.c
new file mode 100644
index 00000000000..08705c4a687
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/zbc32.c
@@ -0,0 +1,23 @@ 
+/* { dg-do compile } */
+/* { dg-options "-O2 -march=rv32gc_zbc -mabi=ilp32" } */
+/* { dg-skip-if "" { *-*-* } { "-g" "-flto"} } */
+#include <stdint-gcc.h>
+
+int32_t foo1(int32_t rs1, int32_t rs2)
+{
+    return __builtin_riscv_clmul(rs1, rs2);
+}
+
+int32_t foo2(int32_t rs1, int32_t rs2)
+{
+    return __builtin_riscv_clmulh(rs1, rs2);
+}
+
+int32_t foo3(int32_t rs1, int32_t rs2)
+{
+    return __builtin_riscv_clmulr(rs1, rs2);
+}
+
+/* { dg-final { scan-assembler-times "clmul\t" 1 } } */
+/* { dg-final { scan-assembler-times "clmulh" 1 } } */
+/* { dg-final { scan-assembler-times "clmulr" 1 } } */
diff --git a/gcc/testsuite/gcc.target/riscv/zbc64.c b/gcc/testsuite/gcc.target/riscv/zbc64.c
new file mode 100644
index 00000000000..a19f42b2883
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/zbc64.c
@@ -0,0 +1,23 @@ 
+/* { dg-do compile } */
+/* { dg-options "-O2 -march=rv64gc_zbc -mabi=lp64" } */
+/* { dg-skip-if "" { *-*-* } { "-g" "-flto"} } */
+#include <stdint-gcc.h>
+
+int64_t foo1(int64_t rs1, int64_t rs2)
+{
+    return __builtin_riscv_clmul(rs1, rs2);
+}
+
+int64_t foo2(int64_t rs1, int64_t rs2)
+{
+    return __builtin_riscv_clmulh(rs1, rs2);
+}
+
+int64_t foo3(int64_t rs1, int64_t rs2)
+{
+    return __builtin_riscv_clmulr(rs1, rs2);
+}
+
+/* { dg-final { scan-assembler-times "clmul\t" 1 } } */
+/* { dg-final { scan-assembler-times "clmulh" 1 } } */
+/* { dg-final { scan-assembler-times "clmulr" 1 } } */