diff mbox series

[V1,1/1] UNRATIFIED RISC-V: Add 'ZiCond' extension

Message ID 20230209110617.3370-2-shiyulong@iscas.ac.cn
State New
Headers show
Series UNRATIFIED RISC-V:Add 'ZiCond' extension | expand

Commit Message

yulong Feb. 9, 2023, 11:06 a.m. UTC
From: yulong <shiyulong@iscas.ac.cn>

[DO NOT MERGE]
Until 'ZiCond' extension is frozen/ratified and final version number is
determined, this patch should not be merged upstream.  This commit uses
version 1.0 as in the documentation.

This commit adds support for the latest draft of RISC-V Integer Conditional
(ZiCond) extension consisting of 2 new instructions.

This is based on the early draft of ZiCond on GitHub:
<https://github.com/riscv/riscv-zicondops/commit/394e243769390025893b1a855071f5fffc659f36>

gcc/ChangeLog:

        * common/config/riscv/riscv-common.cc: Add zicond ext.
        * config/riscv/riscv-builtins.cc (RISCV_FTYPE_NAME2): New.
        (AVAIL): New.
        (RISCV_FTYPE_ATYPES2): New.
        * config/riscv/riscv-ftypes.def (2): New.
        * config/riscv/riscv-opts.h (MASK_ZICOND): New.
        (TARGET_ZICOND): New.
        * config/riscv/riscv.md (riscv_eqz_<mode>): Add new mode.
        (riscv_nez_<mode>): Add new mode.
        * config/riscv/riscv.opt: New.
        * config/riscv/riscv-zicond.def: New file.

gcc/testsuite/ChangeLog:

        * gcc.target/riscv/zicond-1.c: New test.
        * gcc.target/riscv/zicond-2.c: New test.
---
 gcc/common/config/riscv/riscv-common.cc   |  4 ++++
 gcc/config/riscv/riscv-builtins.cc        |  8 ++++++++
 gcc/config/riscv/riscv-ftypes.def         |  2 ++
 gcc/config/riscv/riscv-opts.h             |  3 +++
 gcc/config/riscv/riscv-zicond.def         |  5 +++++
 gcc/config/riscv/riscv.md                 | 22 ++++++++++++++++++++++
 gcc/config/riscv/riscv.opt                |  3 +++
 gcc/testsuite/gcc.target/riscv/zicond-1.c | 15 +++++++++++++++
 gcc/testsuite/gcc.target/riscv/zicond-2.c | 15 +++++++++++++++
 9 files changed, 77 insertions(+)
 create mode 100644 gcc/config/riscv/riscv-zicond.def
 create mode 100644 gcc/testsuite/gcc.target/riscv/zicond-1.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/zicond-2.c

Comments

Philipp Tomsich Feb. 9, 2023, 1:08 p.m. UTC | #1
Just a quick heads-up to avoid duplication of work: we have a series
queued up for later this week (right now, SPEC2017 is still running
for QA purposes) that adds if-conversion support and converts that
into Zicond operations.
It doesn't have much overlap (except handling the "zicond" flag), as
we don't use builtins but a new canonical pattern.

Philipp.


On Thu, 9 Feb 2023 at 12:06, <shiyulong@iscas.ac.cn> wrote:
>
> From: yulong <shiyulong@iscas.ac.cn>
>
> [DO NOT MERGE]
> Until 'ZiCond' extension is frozen/ratified and final version number is
> determined, this patch should not be merged upstream.  This commit uses
> version 1.0 as in the documentation.
>
> This commit adds support for the latest draft of RISC-V Integer Conditional
> (ZiCond) extension consisting of 2 new instructions.
>
> This is based on the early draft of ZiCond on GitHub:
> <https://github.com/riscv/riscv-zicondops/commit/394e243769390025893b1a855071f5fffc659f36>
>
> gcc/ChangeLog:
>
>         * common/config/riscv/riscv-common.cc: Add zicond ext.
>         * config/riscv/riscv-builtins.cc (RISCV_FTYPE_NAME2): New.
>         (AVAIL): New.
>         (RISCV_FTYPE_ATYPES2): New.
>         * config/riscv/riscv-ftypes.def (2): New.
>         * config/riscv/riscv-opts.h (MASK_ZICOND): New.
>         (TARGET_ZICOND): New.
>         * config/riscv/riscv.md (riscv_eqz_<mode>): Add new mode.
>         (riscv_nez_<mode>): Add new mode.
>         * config/riscv/riscv.opt: New.
>         * config/riscv/riscv-zicond.def: New file.
>
> gcc/testsuite/ChangeLog:
>
>         * gcc.target/riscv/zicond-1.c: New test.
>         * gcc.target/riscv/zicond-2.c: New test.
> ---
>  gcc/common/config/riscv/riscv-common.cc   |  4 ++++
>  gcc/config/riscv/riscv-builtins.cc        |  8 ++++++++
>  gcc/config/riscv/riscv-ftypes.def         |  2 ++
>  gcc/config/riscv/riscv-opts.h             |  3 +++
>  gcc/config/riscv/riscv-zicond.def         |  5 +++++
>  gcc/config/riscv/riscv.md                 | 22 ++++++++++++++++++++++
>  gcc/config/riscv/riscv.opt                |  3 +++
>  gcc/testsuite/gcc.target/riscv/zicond-1.c | 15 +++++++++++++++
>  gcc/testsuite/gcc.target/riscv/zicond-2.c | 15 +++++++++++++++
>  9 files changed, 77 insertions(+)
>  create mode 100644 gcc/config/riscv/riscv-zicond.def
>  create mode 100644 gcc/testsuite/gcc.target/riscv/zicond-1.c
>  create mode 100644 gcc/testsuite/gcc.target/riscv/zicond-2.c
>
> diff --git a/gcc/common/config/riscv/riscv-common.cc b/gcc/common/config/riscv/riscv-common.cc
> index 787674003cb..5a8b1278ac8 100644
> --- a/gcc/common/config/riscv/riscv-common.cc
> +++ b/gcc/common/config/riscv/riscv-common.cc
> @@ -190,6 +190,8 @@ static const struct riscv_ext_version riscv_ext_version_table[] =
>    {"zicbom",ISA_SPEC_CLASS_NONE, 1, 0},
>    {"zicbop",ISA_SPEC_CLASS_NONE, 1, 0},
>
> +  {"zicond",ISA_SPEC_CLASS_NONE, 1, 0},
> +
>    {"zk",    ISA_SPEC_CLASS_NONE, 1, 0},
>    {"zkn",   ISA_SPEC_CLASS_NONE, 1, 0},
>    {"zks",   ISA_SPEC_CLASS_NONE, 1, 0},
> @@ -1209,6 +1211,8 @@ static const riscv_ext_flag_table_t riscv_ext_flag_table[] =
>    {"zicbom", &gcc_options::x_riscv_zicmo_subext, MASK_ZICBOM},
>    {"zicbop", &gcc_options::x_riscv_zicmo_subext, MASK_ZICBOP},
>
> +  {"zicond", &gcc_options::x_riscv_zicond_subext, MASK_ZICOND},
> +
>    {"zve32x",   &gcc_options::x_target_flags, MASK_VECTOR},
>    {"zve32f",   &gcc_options::x_target_flags, MASK_VECTOR},
>    {"zve64x",   &gcc_options::x_target_flags, MASK_VECTOR},
> diff --git a/gcc/config/riscv/riscv-builtins.cc b/gcc/config/riscv/riscv-builtins.cc
> index 25ca407f9a9..66a8126b2b4 100644
> --- a/gcc/config/riscv/riscv-builtins.cc
> +++ b/gcc/config/riscv/riscv-builtins.cc
> @@ -42,6 +42,7 @@ along with GCC; see the file COPYING3.  If not see
>  /* Macros to create an enumeration identifier for a function prototype.  */
>  #define RISCV_FTYPE_NAME0(A) RISCV_##A##_FTYPE
>  #define RISCV_FTYPE_NAME1(A, B) RISCV_##A##_FTYPE_##B
> +#define RISCV_FTYPE_NAME2(A, B, C) RISCV_##A##_FTYPE_##B##_##C
>
>  /* Classifies the prototype of a built-in function.  */
>  enum riscv_function_type {
> @@ -99,6 +100,10 @@ AVAIL (zero64,  TARGET_ZICBOZ && TARGET_64BIT)
>  AVAIL (prefetchi32, TARGET_ZICBOP && !TARGET_64BIT)
>  AVAIL (prefetchi64, TARGET_ZICBOP && TARGET_64BIT)
>  AVAIL (always,     (!0))
> +AVAIL (nez32, TARGET_ZICOND && !TARGET_64BIT)
> +AVAIL (nez64, TARGET_ZICOND && TARGET_64BIT)
> +AVAIL (eqz32, TARGET_ZICOND && !TARGET_64BIT)
> +AVAIL (eqz64, TARGET_ZICOND && TARGET_64BIT)
>
>  /* Construct a riscv_builtin_description from the given arguments.
>
> @@ -142,9 +147,12 @@ AVAIL (always,     (!0))
>    RISCV_ATYPE_##A
>  #define RISCV_FTYPE_ATYPES1(A, B) \
>    RISCV_ATYPE_##A, RISCV_ATYPE_##B
> +#define RISCV_FTYPE_ATYPES2(A, B, C) \
> +  RISCV_ATYPE_##A, RISCV_ATYPE_##B, RISCV_ATYPE_##C
>
>  static const struct riscv_builtin_description riscv_builtins[] = {
>    #include "riscv-cmo.def"
> +  #include "riscv-zicond.def"
>
>    DIRECT_BUILTIN (frflags, RISCV_USI_FTYPE, hard_float),
>    DIRECT_NO_TARGET_BUILTIN (fsflags, RISCV_VOID_FTYPE_USI, hard_float),
> diff --git a/gcc/config/riscv/riscv-ftypes.def b/gcc/config/riscv/riscv-ftypes.def
> index 3a40c33e7c2..d305282d811 100644
> --- a/gcc/config/riscv/riscv-ftypes.def
> +++ b/gcc/config/riscv/riscv-ftypes.def
> @@ -32,3 +32,5 @@ DEF_RISCV_FTYPE (1, (VOID, USI))
>  DEF_RISCV_FTYPE (1, (VOID, VOID_PTR))
>  DEF_RISCV_FTYPE (1, (SI, SI))
>  DEF_RISCV_FTYPE (1, (DI, DI))
> +DEF_RISCV_FTYPE (2, (SI, SI, SI))
> +DEF_RISCV_FTYPE (2, (DI, DI, DI))
> diff --git a/gcc/config/riscv/riscv-opts.h b/gcc/config/riscv/riscv-opts.h
> index ff398c0a2ae..0baf6553913 100644
> --- a/gcc/config/riscv/riscv-opts.h
> +++ b/gcc/config/riscv/riscv-opts.h
> @@ -166,6 +166,9 @@ enum stack_protector_guard {
>  #define TARGET_ZICBOM ((riscv_zicmo_subext & MASK_ZICBOM) != 0)
>  #define TARGET_ZICBOP ((riscv_zicmo_subext & MASK_ZICBOP) != 0)
>
> +#define MASK_ZICOND   (1 << 0)
> +#define TARGET_ZICOND ((riscv_zicond_subext & MASK_ZICOND) != 0)
> +
>  #define MASK_ZFHMIN   (1 << 0)
>  #define MASK_ZFH      (1 << 1)
>
> diff --git a/gcc/config/riscv/riscv-zicond.def b/gcc/config/riscv/riscv-zicond.def
> new file mode 100644
> index 00000000000..ceacb825933
> --- /dev/null
> +++ b/gcc/config/riscv/riscv-zicond.def
> @@ -0,0 +1,5 @@
> +RISCV_BUILTIN (nez_si, "zicond_nez", RISCV_BUILTIN_DIRECT, RISCV_SI_FTYPE_SI_SI, nez32),
> +RISCV_BUILTIN (nez_di, "zicond_nez", RISCV_BUILTIN_DIRECT, RISCV_DI_FTYPE_DI_DI, nez64),
> +
> +RISCV_BUILTIN (eqz_si, "zicond_eqz", RISCV_BUILTIN_DIRECT, RISCV_SI_FTYPE_SI_SI, eqz32),
> +RISCV_BUILTIN (eqz_di, "zicond_eqz", RISCV_BUILTIN_DIRECT, RISCV_DI_FTYPE_DI_DI, eqz64),
> \ No newline at end of file
> diff --git a/gcc/config/riscv/riscv.md b/gcc/config/riscv/riscv.md
> index c8adc5af5d2..1b1979df0c9 100644
> --- a/gcc/config/riscv/riscv.md
> +++ b/gcc/config/riscv/riscv.md
> @@ -98,6 +98,10 @@
>    UNSPECV_ZERO
>    UNSPECV_PREI
>
> +  ;;ZICOND instructions
> +  UNSPECV_EQZ
> +  UNSPECV_NEZ
> +
>    ;; Zihintpause unspec
>    UNSPECV_PAUSE
>  ])
> @@ -3085,6 +3089,24 @@
>    "prefetch.i\t%a0"
>  )
>
> +(define_insn "riscv_eqz_<mode>"
> +  [(set (match_operand:X 0 "register_operand" "=r")
> +        (unspec_volatile:X [(match_operand:X 1 "register_operand" " r")
> +          (match_operand:X 2 "register_operand" " r")]
> +         UNSPECV_EQZ))]
> +      "TARGET_ZICOND"
> +      "czero.eqz\t%0,%1,%2"
> +)
> +
> +(define_insn "riscv_nez_<mode>"
> +  [(set (match_operand:X 0 "register_operand" "=r")
> +        (unspec_volatile:X [(match_operand:X 1 "register_operand" " r")
> +          (match_operand:X 2 "register_operand" " r")]
> +         UNSPECV_NEZ))]
> +      "TARGET_ZICOND"
> +      "czero.nez\t%0,%1,%2"
> +)
> +
>  (include "bitmanip.md")
>  (include "sync.md")
>  (include "peephole.md")
> diff --git a/gcc/config/riscv/riscv.opt b/gcc/config/riscv/riscv.opt
> index e78c99382cd..a422b16a02f 100644
> --- a/gcc/config/riscv/riscv.opt
> +++ b/gcc/config/riscv/riscv.opt
> @@ -224,6 +224,9 @@ int riscv_zvl_flags
>  TargetVariable
>  int riscv_zicmo_subext
>
> +TargetVariable
> +int riscv_zicond_subext
> +
>  TargetVariable
>  int riscv_zf_subext
>
> diff --git a/gcc/testsuite/gcc.target/riscv/zicond-1.c b/gcc/testsuite/gcc.target/riscv/zicond-1.c
> new file mode 100644
> index 00000000000..395e53f870f
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/riscv/zicond-1.c
> @@ -0,0 +1,15 @@
> +/* { dg-do compile } */
> +/* { dg-options "-march=rv32i_zicond -mabi=ilp32" } */
> +
> +void foo1()
> +{
> +    __builtin_riscv_zicond_nez(1,1);
> +}
> +
> +void foo2()
> +{
> +    __builtin_riscv_zicond_eqz(1,1);
> +}
> +
> +/* { dg-final { scan-assembler-times "czero.nez" 1 } } */
> +/* { dg-final { scan-assembler-times "czero.eqz" 1 } } */
> diff --git a/gcc/testsuite/gcc.target/riscv/zicond-2.c b/gcc/testsuite/gcc.target/riscv/zicond-2.c
> new file mode 100644
> index 00000000000..4ae01cb8bfa
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/riscv/zicond-2.c
> @@ -0,0 +1,15 @@
> +/* { dg-do compile } */
> +/* { dg-options "-march=rv64i_zicond -mabi=lp64" } */
> +
> +void foo1()
> +{
> +    __builtin_riscv_zicond_nez(1,1);
> +}
> +
> +void foo2()
> +{
> +    __builtin_riscv_zicond_eqz(1,1);
> +}
> +
> +/* { dg-final { scan-assembler-times "czero.nez" 1 } } */
> +/* { dg-final { scan-assembler-times "czero.eqz" 1 } } */
> --
> 2.25.1
>
Jeff Law April 18, 2023, 12:45 a.m. UTC | #2
On 2/9/23 04:06, shiyulong@iscas.ac.cn wrote:
> From: yulong <shiyulong@iscas.ac.cn>
> 
> [DO NOT MERGE]
> Until 'ZiCond' extension is frozen/ratified and final version number is
> determined, this patch should not be merged upstream.  This commit uses
> version 1.0 as in the documentation.
> 
> This commit adds support for the latest draft of RISC-V Integer Conditional
> (ZiCond) extension consisting of 2 new instructions.
> 
> This is based on the early draft of ZiCond on GitHub:
> <https://github.com/riscv/riscv-zicondops/commit/394e243769390025893b1a855071f5fffc659f36>
> 
> gcc/ChangeLog:
> 
>          * common/config/riscv/riscv-common.cc: Add zicond ext.
>          * config/riscv/riscv-builtins.cc (RISCV_FTYPE_NAME2): New.
>          (AVAIL): New.
>          (RISCV_FTYPE_ATYPES2): New.
>          * config/riscv/riscv-ftypes.def (2): New.
>          * config/riscv/riscv-opts.h (MASK_ZICOND): New.
>          (TARGET_ZICOND): New.
>          * config/riscv/riscv.md (riscv_eqz_<mode>): Add new mode.
>          (riscv_nez_<mode>): Add new mode.
>          * config/riscv/riscv.opt: New.
>          * config/riscv/riscv-zicond.def: New file.
> 
> gcc/testsuite/ChangeLog:
> 
>          * gcc.target/riscv/zicond-1.c: New test.
>          * gcc.target/riscv/zicond-2.c: New test.

>   
> +(define_insn "riscv_eqz_<mode>"
> +  [(set (match_operand:X 0 "register_operand" "=r")
> +        (unspec_volatile:X [(match_operand:X 1 "register_operand" " r")
> +          (match_operand:X 2 "register_operand" " r")]
> +         UNSPECV_EQZ))]
> +      "TARGET_ZICOND"
> +      "czero.eqz\t%0,%1,%2"
> +)
> +
> +(define_insn "riscv_nez_<mode>"
> +  [(set (match_operand:X 0 "register_operand" "=r")
> +        (unspec_volatile:X [(match_operand:X 1 "register_operand" " r")
> +          (match_operand:X 2 "register_operand" " r")]
> +         UNSPECV_NEZ))]
> +      "TARGET_ZICOND"
> +      "czero.nez\t%0,%1,%2"
Why use UNSPEC here?  The semantics of these instructions can be fully 
expressed in RTL.  Using an UNSPEC just prevents optimization and will 
ultimately require adding more patterns to utilize these instructions 
automatically.

Based on the work we've been doing here at Ventana, I would strongly 
suggest moving to a conditional zero idiom like

(set (dest) (if_then_else (cond) (reg) (const_int 0)))

That has the advantage that many passes know how to form it rather than 
the form VRULL originally used which looked something like

(set (dest) (and (neg (cond) (reg)))


Jeff
diff mbox series

Patch

diff --git a/gcc/common/config/riscv/riscv-common.cc b/gcc/common/config/riscv/riscv-common.cc
index 787674003cb..5a8b1278ac8 100644
--- a/gcc/common/config/riscv/riscv-common.cc
+++ b/gcc/common/config/riscv/riscv-common.cc
@@ -190,6 +190,8 @@  static const struct riscv_ext_version riscv_ext_version_table[] =
   {"zicbom",ISA_SPEC_CLASS_NONE, 1, 0},
   {"zicbop",ISA_SPEC_CLASS_NONE, 1, 0},
 
+  {"zicond",ISA_SPEC_CLASS_NONE, 1, 0},
+
   {"zk",    ISA_SPEC_CLASS_NONE, 1, 0},
   {"zkn",   ISA_SPEC_CLASS_NONE, 1, 0},
   {"zks",   ISA_SPEC_CLASS_NONE, 1, 0},
@@ -1209,6 +1211,8 @@  static const riscv_ext_flag_table_t riscv_ext_flag_table[] =
   {"zicbom", &gcc_options::x_riscv_zicmo_subext, MASK_ZICBOM},
   {"zicbop", &gcc_options::x_riscv_zicmo_subext, MASK_ZICBOP},
 
+  {"zicond", &gcc_options::x_riscv_zicond_subext, MASK_ZICOND},
+
   {"zve32x",   &gcc_options::x_target_flags, MASK_VECTOR},
   {"zve32f",   &gcc_options::x_target_flags, MASK_VECTOR},
   {"zve64x",   &gcc_options::x_target_flags, MASK_VECTOR},
diff --git a/gcc/config/riscv/riscv-builtins.cc b/gcc/config/riscv/riscv-builtins.cc
index 25ca407f9a9..66a8126b2b4 100644
--- a/gcc/config/riscv/riscv-builtins.cc
+++ b/gcc/config/riscv/riscv-builtins.cc
@@ -42,6 +42,7 @@  along with GCC; see the file COPYING3.  If not see
 /* Macros to create an enumeration identifier for a function prototype.  */
 #define RISCV_FTYPE_NAME0(A) RISCV_##A##_FTYPE
 #define RISCV_FTYPE_NAME1(A, B) RISCV_##A##_FTYPE_##B
+#define RISCV_FTYPE_NAME2(A, B, C) RISCV_##A##_FTYPE_##B##_##C
 
 /* Classifies the prototype of a built-in function.  */
 enum riscv_function_type {
@@ -99,6 +100,10 @@  AVAIL (zero64,  TARGET_ZICBOZ && TARGET_64BIT)
 AVAIL (prefetchi32, TARGET_ZICBOP && !TARGET_64BIT)
 AVAIL (prefetchi64, TARGET_ZICBOP && TARGET_64BIT)
 AVAIL (always,     (!0))
+AVAIL (nez32, TARGET_ZICOND && !TARGET_64BIT)
+AVAIL (nez64, TARGET_ZICOND && TARGET_64BIT)
+AVAIL (eqz32, TARGET_ZICOND && !TARGET_64BIT)
+AVAIL (eqz64, TARGET_ZICOND && TARGET_64BIT)
 
 /* Construct a riscv_builtin_description from the given arguments.
 
@@ -142,9 +147,12 @@  AVAIL (always,     (!0))
   RISCV_ATYPE_##A
 #define RISCV_FTYPE_ATYPES1(A, B) \
   RISCV_ATYPE_##A, RISCV_ATYPE_##B
+#define RISCV_FTYPE_ATYPES2(A, B, C) \
+  RISCV_ATYPE_##A, RISCV_ATYPE_##B, RISCV_ATYPE_##C
 
 static const struct riscv_builtin_description riscv_builtins[] = {
   #include "riscv-cmo.def"
+  #include "riscv-zicond.def"
 
   DIRECT_BUILTIN (frflags, RISCV_USI_FTYPE, hard_float),
   DIRECT_NO_TARGET_BUILTIN (fsflags, RISCV_VOID_FTYPE_USI, hard_float),
diff --git a/gcc/config/riscv/riscv-ftypes.def b/gcc/config/riscv/riscv-ftypes.def
index 3a40c33e7c2..d305282d811 100644
--- a/gcc/config/riscv/riscv-ftypes.def
+++ b/gcc/config/riscv/riscv-ftypes.def
@@ -32,3 +32,5 @@  DEF_RISCV_FTYPE (1, (VOID, USI))
 DEF_RISCV_FTYPE (1, (VOID, VOID_PTR))
 DEF_RISCV_FTYPE (1, (SI, SI))
 DEF_RISCV_FTYPE (1, (DI, DI))
+DEF_RISCV_FTYPE (2, (SI, SI, SI))
+DEF_RISCV_FTYPE (2, (DI, DI, DI))
diff --git a/gcc/config/riscv/riscv-opts.h b/gcc/config/riscv/riscv-opts.h
index ff398c0a2ae..0baf6553913 100644
--- a/gcc/config/riscv/riscv-opts.h
+++ b/gcc/config/riscv/riscv-opts.h
@@ -166,6 +166,9 @@  enum stack_protector_guard {
 #define TARGET_ZICBOM ((riscv_zicmo_subext & MASK_ZICBOM) != 0)
 #define TARGET_ZICBOP ((riscv_zicmo_subext & MASK_ZICBOP) != 0)
 
+#define MASK_ZICOND   (1 << 0)
+#define TARGET_ZICOND ((riscv_zicond_subext & MASK_ZICOND) != 0)
+
 #define MASK_ZFHMIN   (1 << 0)
 #define MASK_ZFH      (1 << 1)
 
diff --git a/gcc/config/riscv/riscv-zicond.def b/gcc/config/riscv/riscv-zicond.def
new file mode 100644
index 00000000000..ceacb825933
--- /dev/null
+++ b/gcc/config/riscv/riscv-zicond.def
@@ -0,0 +1,5 @@ 
+RISCV_BUILTIN (nez_si, "zicond_nez", RISCV_BUILTIN_DIRECT, RISCV_SI_FTYPE_SI_SI, nez32),
+RISCV_BUILTIN (nez_di, "zicond_nez", RISCV_BUILTIN_DIRECT, RISCV_DI_FTYPE_DI_DI, nez64),
+
+RISCV_BUILTIN (eqz_si, "zicond_eqz", RISCV_BUILTIN_DIRECT, RISCV_SI_FTYPE_SI_SI, eqz32),
+RISCV_BUILTIN (eqz_di, "zicond_eqz", RISCV_BUILTIN_DIRECT, RISCV_DI_FTYPE_DI_DI, eqz64),
\ No newline at end of file
diff --git a/gcc/config/riscv/riscv.md b/gcc/config/riscv/riscv.md
index c8adc5af5d2..1b1979df0c9 100644
--- a/gcc/config/riscv/riscv.md
+++ b/gcc/config/riscv/riscv.md
@@ -98,6 +98,10 @@ 
   UNSPECV_ZERO
   UNSPECV_PREI
 
+  ;;ZICOND instructions
+  UNSPECV_EQZ
+  UNSPECV_NEZ
+
   ;; Zihintpause unspec
   UNSPECV_PAUSE
 ])
@@ -3085,6 +3089,24 @@ 
   "prefetch.i\t%a0"
 )
 
+(define_insn "riscv_eqz_<mode>"
+  [(set (match_operand:X 0 "register_operand" "=r")
+        (unspec_volatile:X [(match_operand:X 1 "register_operand" " r")
+          (match_operand:X 2 "register_operand" " r")]
+         UNSPECV_EQZ))]
+      "TARGET_ZICOND"
+      "czero.eqz\t%0,%1,%2"
+)
+
+(define_insn "riscv_nez_<mode>"
+  [(set (match_operand:X 0 "register_operand" "=r")
+        (unspec_volatile:X [(match_operand:X 1 "register_operand" " r")
+          (match_operand:X 2 "register_operand" " r")]
+         UNSPECV_NEZ))]
+      "TARGET_ZICOND"
+      "czero.nez\t%0,%1,%2"
+)
+
 (include "bitmanip.md")
 (include "sync.md")
 (include "peephole.md")
diff --git a/gcc/config/riscv/riscv.opt b/gcc/config/riscv/riscv.opt
index e78c99382cd..a422b16a02f 100644
--- a/gcc/config/riscv/riscv.opt
+++ b/gcc/config/riscv/riscv.opt
@@ -224,6 +224,9 @@  int riscv_zvl_flags
 TargetVariable
 int riscv_zicmo_subext
 
+TargetVariable
+int riscv_zicond_subext
+
 TargetVariable
 int riscv_zf_subext
 
diff --git a/gcc/testsuite/gcc.target/riscv/zicond-1.c b/gcc/testsuite/gcc.target/riscv/zicond-1.c
new file mode 100644
index 00000000000..395e53f870f
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/zicond-1.c
@@ -0,0 +1,15 @@ 
+/* { dg-do compile } */
+/* { dg-options "-march=rv32i_zicond -mabi=ilp32" } */
+
+void foo1()
+{
+    __builtin_riscv_zicond_nez(1,1);
+}
+
+void foo2()
+{
+    __builtin_riscv_zicond_eqz(1,1);
+}
+
+/* { dg-final { scan-assembler-times "czero.nez" 1 } } */ 
+/* { dg-final { scan-assembler-times "czero.eqz" 1 } } */ 
diff --git a/gcc/testsuite/gcc.target/riscv/zicond-2.c b/gcc/testsuite/gcc.target/riscv/zicond-2.c
new file mode 100644
index 00000000000..4ae01cb8bfa
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/zicond-2.c
@@ -0,0 +1,15 @@ 
+/* { dg-do compile } */
+/* { dg-options "-march=rv64i_zicond -mabi=lp64" } */
+
+void foo1()
+{
+    __builtin_riscv_zicond_nez(1,1);
+}
+
+void foo2()
+{
+    __builtin_riscv_zicond_eqz(1,1);
+}
+
+/* { dg-final { scan-assembler-times "czero.nez" 1 } } */ 
+/* { dg-final { scan-assembler-times "czero.eqz" 1 } } */