[V4,2/3] RISC-V:Cache Management Operation instructions

Message ID 20220510032526.11560-3-shiyulong@iscas.ac.cn
State Deferred, archived
Headers
Series RISC-V:Add mininal support for Zicbo[mzp] |

Commit Message

yulong May 10, 2022, 3:25 a.m. UTC
  From: yulong <shiyulong@iscas.ac.cn>

This commit adds cbo.clea,cbo.flush,cbo.inval,cbo.zero,prefetch.i,prefetch.r and prefetch.w instructions.
  

Comments

Simon Cook May 26, 2022, 11:58 a.m. UTC | #1
Hi,

I've just tried using these builtins now these have landed in trunk, and 
I have a question about the cbo builtins.

Looking at the code being generated it looks like these builtins return 
an int and take no arguments, but reading the instructions these should 
instead take an int and return nothing. As an example using one of the 
tests,

int foo1()
{
     return __builtin_riscv_zicbom_cbo_clean();
}

generates

foo1:
	addi	sp,sp,-16
	sw	s0,12(sp)
	addi	s0,sp,16
	cbo.clean	0(a5)
	mv	a0,a5
	lw	s0,12(sp)
	addi	sp,sp,16
	jr	ra
	.size	foo1, .-foo1

This reads to me like GCC is expecting the cbo.clean to have placed a 
value in a5, which is then moved to a0 for returning.

Is this a bug with these builtins, or have I misunderstood these 
instructions?

Thanks,
Simon


On 10/05/2022 04:25, shiyulong@iscas.ac.cn wrote:
> From: yulong <shiyulong@iscas.ac.cn>
> 
> This commit adds cbo.clea,cbo.flush,cbo.inval,cbo.zero,prefetch.i,prefetch.r and prefetch.w instructions.
> diff with the previous version:
> We use unspec_volatile instead of unspec for those cache operations. We use UNSPECV instead of UNSPEC and move them to unspecv.
> 
> gcc/ChangeLog:
> 
>          * config/riscv/predicates.md (imm5_operand): Add a new operand type for prefetch instructions.
>          * config/riscv/riscv-builtins.cc (AVAIL): Add new AVAILs for CMO ISA Extensions.
>          (RISCV_ATYPE_SI): New.
>          (RISCV_ATYPE_DI): New.
>          * config/riscv/riscv-ftypes.def (0): New.
>          (1): New.
>          * config/riscv/riscv.md (riscv_clean_<mode>): New.
>          (riscv_flush_<mode>): New.
>          (riscv_inval_<mode>): New.
>          (riscv_zero_<mode>): New.
>          (prefetch): New.
>          (riscv_prefetchi_<mode>): New.
>          * config/riscv/riscv-cmo.def: New file.
> ---
>   gcc/config/riscv/predicates.md     |  4 +++
>   gcc/config/riscv/riscv-builtins.cc | 16 ++++++++++
>   gcc/config/riscv/riscv-cmo.def     | 17 ++++++++++
>   gcc/config/riscv/riscv-ftypes.def  |  4 +++
>   gcc/config/riscv/riscv.md          | 51 ++++++++++++++++++++++++++++++
>   5 files changed, 92 insertions(+)
>   create mode 100644 gcc/config/riscv/riscv-cmo.def
> 
> diff --git a/gcc/config/riscv/predicates.md b/gcc/config/riscv/predicates.md
> index 97cdbdf053b..3fb4d95ab08 100644
> --- a/gcc/config/riscv/predicates.md
> +++ b/gcc/config/riscv/predicates.md
> @@ -239,3 +239,7 @@
>   (define_predicate "const63_operand"
>     (and (match_code "const_int")
>          (match_test "INTVAL (op) == 63")))
> +
> +(define_predicate "imm5_operand"
> +  (and (match_code "const_int")
> +       (match_test "INTVAL (op) < 5")))
> \ No newline at end of file
> diff --git a/gcc/config/riscv/riscv-builtins.cc b/gcc/config/riscv/riscv-builtins.cc
> index 0658f8d3047..795132a0c16 100644
> --- a/gcc/config/riscv/riscv-builtins.cc
> +++ b/gcc/config/riscv/riscv-builtins.cc
> @@ -87,6 +87,18 @@ struct riscv_builtin_description {
>   
>   AVAIL (hard_float, TARGET_HARD_FLOAT)
>   
> +
> +AVAIL (clean32, TARGET_ZICBOM && !TARGET_64BIT)
> +AVAIL (clean64, TARGET_ZICBOM && TARGET_64BIT)
> +AVAIL (flush32, TARGET_ZICBOM && !TARGET_64BIT)
> +AVAIL (flush64, TARGET_ZICBOM && TARGET_64BIT)
> +AVAIL (inval32, TARGET_ZICBOM && !TARGET_64BIT)
> +AVAIL (inval64, TARGET_ZICBOM && TARGET_64BIT)
> +AVAIL (zero32,  TARGET_ZICBOZ && !TARGET_64BIT)
> +AVAIL (zero64,  TARGET_ZICBOZ && TARGET_64BIT)
> +AVAIL (prefetchi32, TARGET_ZICBOP && !TARGET_64BIT)
> +AVAIL (prefetchi64, TARGET_ZICBOP && TARGET_64BIT)
> +
>   /* Construct a riscv_builtin_description from the given arguments.
>   
>      INSN is the name of the associated instruction pattern, without the
> @@ -119,6 +131,8 @@ AVAIL (hard_float, TARGET_HARD_FLOAT)
>   /* Argument types.  */
>   #define RISCV_ATYPE_VOID void_type_node
>   #define RISCV_ATYPE_USI unsigned_intSI_type_node
> +#define RISCV_ATYPE_SI intSI_type_node
> +#define RISCV_ATYPE_DI intDI_type_node
>   
>   /* RISCV_FTYPE_ATYPESN takes N RISCV_FTYPES-like type codes and lists
>      their associated RISCV_ATYPEs.  */
> @@ -128,6 +142,8 @@ AVAIL (hard_float, TARGET_HARD_FLOAT)
>     RISCV_ATYPE_##A, RISCV_ATYPE_##B
>   
>   static const struct riscv_builtin_description riscv_builtins[] = {
> +  #include "riscv-cmo.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-cmo.def b/gcc/config/riscv/riscv-cmo.def
> new file mode 100644
> index 00000000000..01cbf6ad64f
> --- /dev/null
> +++ b/gcc/config/riscv/riscv-cmo.def
> @@ -0,0 +1,17 @@
> +// zicbom
> +RISCV_BUILTIN (clean_si, "zicbom_cbo_clean", RISCV_BUILTIN_DIRECT, RISCV_SI_FTYPE, clean32),
> +RISCV_BUILTIN (clean_di, "zicbom_cbo_clean", RISCV_BUILTIN_DIRECT, RISCV_DI_FTYPE, clean64),
> +
> +RISCV_BUILTIN (flush_si, "zicbom_cbo_flush", RISCV_BUILTIN_DIRECT, RISCV_SI_FTYPE, flush32),
> +RISCV_BUILTIN (flush_di, "zicbom_cbo_flush", RISCV_BUILTIN_DIRECT, RISCV_DI_FTYPE, flush64),
> +
> +RISCV_BUILTIN (inval_si, "zicbom_cbo_inval", RISCV_BUILTIN_DIRECT, RISCV_SI_FTYPE, inval32),
> +RISCV_BUILTIN (inval_di, "zicbom_cbo_inval", RISCV_BUILTIN_DIRECT, RISCV_DI_FTYPE, inval64),
> +
> +// zicboz
> +RISCV_BUILTIN (zero_si, "zicboz_cbo_zero", RISCV_BUILTIN_DIRECT, RISCV_SI_FTYPE, zero32),
> +RISCV_BUILTIN (zero_di, "zicboz_cbo_zero", RISCV_BUILTIN_DIRECT, RISCV_DI_FTYPE, zero64),
> +
> +// 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),
> \ No newline at end of file
> diff --git a/gcc/config/riscv/riscv-ftypes.def b/gcc/config/riscv/riscv-ftypes.def
> index 2214c496f9b..62421292ce7 100644
> --- a/gcc/config/riscv/riscv-ftypes.def
> +++ b/gcc/config/riscv/riscv-ftypes.def
> @@ -28,3 +28,7 @@ along with GCC; see the file COPYING3.  If not see
>   
>   DEF_RISCV_FTYPE (0, (USI))
>   DEF_RISCV_FTYPE (1, (VOID, USI))
> +DEF_RISCV_FTYPE (0, (SI))
> +DEF_RISCV_FTYPE (0, (DI))
> +DEF_RISCV_FTYPE (1, (SI, SI))
> +DEF_RISCV_FTYPE (1, (DI, DI))
> diff --git a/gcc/config/riscv/riscv.md b/gcc/config/riscv/riscv.md
> index b3c5bce842a..b96d0c30e59 100644
> --- a/gcc/config/riscv/riscv.md
> +++ b/gcc/config/riscv/riscv.md
> @@ -69,6 +69,11 @@
>     ;; Stack Smash Protector
>     UNSPEC_SSP_SET
>     UNSPEC_SSP_TEST
> +  UNSPECV_CLEAN
> +  UNSPECV_FLUSH
> +  UNSPECV_INVAL
> +  UNSPECV_ZERO
> +  UNSPECV_PREI
>   ])
>   
>   (define_constants
> @@ -2863,6 +2868,52 @@
>     "<load>\t%3, %1\;<load>\t%0, %2\;xor\t%0, %3, %0\;li\t%3, 0"
>     [(set_attr "length" "12")])
>   
> +(define_insn "riscv_clean_<mode>"
> +[(unspec_volatile:X [(match_operand:X 0 "register_operand" "r")] UNSPECV_CLEAN)]
> +"TARGET_ZICBOM"
> +"cbo.clean\t%a0"
> +)
> +
> +(define_insn "riscv_flush_<mode>"
> +[(unspec_volatile:X [(match_operand:X 0 "register_operand" "r")] UNSPECV_FLUSH)]
> +"TARGET_ZICBOM"
> +"cbo.flush\t%a0"
> +)
> +
> +(define_insn "riscv_inval_<mode>"
> +[(unspec_volatile:X [(match_operand:X 0 "register_operand" "r")] UNSPECV_INVAL)]
> +"TARGET_ZICBOM"
> +"cbo.inval\t%a0"
> +)
> +
> +(define_insn "riscv_zero_<mode>"
> +[(unspec_volatile:X [(match_operand:X 0 "register_operand" "r")] UNSPECV_ZERO)]
> +"TARGET_ZICBOZ"
> +"cbo.zero\t%a0"
> +)
> +
> +(define_insn "prefetch"
> +[(prefetch (match_operand 0 "address_operand" "p")
> +           (match_operand 1 "imm5_operand" "i")
> +           (match_operand 2 "const_int_operand" "n"))]
> +"TARGET_ZICBOP"
> +{
> +  switch (INTVAL (operands[1]))
> +  {
> +    case 0: return "prefetch.r\t%a0";
> +    case 1: return "prefetch.w\t%a0";
> +    default: gcc_unreachable ();
> +  }
> +})
> +
> +(define_insn "riscv_prefetchi_<mode>"
> +[(unspec_volatile:X [(match_operand:X 0 "address_operand" "p")
> +            (match_operand:X 1 "imm5_operand" "i")]
> +            UNSPECV_PREI)]
> +"TARGET_ZICBOP"
> +"prefetch.i\t%a0"
> +)
> +
>   (include "bitmanip.md")
>   (include "sync.md")
>   (include "peephole.md")
  
Kito Cheng May 26, 2022, 3:37 p.m. UTC | #2
Hi Simon:

Good catch, those cache operations should take an address operand.



On Thu, May 26, 2022 at 7:58 PM Simon Cook <simon.cook@embecosm.com> wrote:
>
> Hi,
>
> I've just tried using these builtins now these have landed in trunk, and
> I have a question about the cbo builtins.
>
> Looking at the code being generated it looks like these builtins return
> an int and take no arguments, but reading the instructions these should
> instead take an int and return nothing. As an example using one of the
> tests,
>
> int foo1()
> {
>      return __builtin_riscv_zicbom_cbo_clean();
> }
>
> generates
>
> foo1:
>         addi    sp,sp,-16
>         sw      s0,12(sp)
>         addi    s0,sp,16
>         cbo.clean       0(a5)
>         mv      a0,a5
>         lw      s0,12(sp)
>         addi    sp,sp,16
>         jr      ra
>         .size   foo1, .-foo1
>
> This reads to me like GCC is expecting the cbo.clean to have placed a
> value in a5, which is then moved to a0 for returning.
>
> Is this a bug with these builtins, or have I misunderstood these
> instructions?
>
> Thanks,
> Simon
>
>
> On 10/05/2022 04:25, shiyulong@iscas.ac.cn wrote:
> > From: yulong <shiyulong@iscas.ac.cn>
> >
> > This commit adds cbo.clea,cbo.flush,cbo.inval,cbo.zero,prefetch.i,prefetch.r and prefetch.w instructions.
> > diff with the previous version:
> > We use unspec_volatile instead of unspec for those cache operations. We use UNSPECV instead of UNSPEC and move them to unspecv.
> >
> > gcc/ChangeLog:
> >
> >          * config/riscv/predicates.md (imm5_operand): Add a new operand type for prefetch instructions.
> >          * config/riscv/riscv-builtins.cc (AVAIL): Add new AVAILs for CMO ISA Extensions.
> >          (RISCV_ATYPE_SI): New.
> >          (RISCV_ATYPE_DI): New.
> >          * config/riscv/riscv-ftypes.def (0): New.
> >          (1): New.
> >          * config/riscv/riscv.md (riscv_clean_<mode>): New.
> >          (riscv_flush_<mode>): New.
> >          (riscv_inval_<mode>): New.
> >          (riscv_zero_<mode>): New.
> >          (prefetch): New.
> >          (riscv_prefetchi_<mode>): New.
> >          * config/riscv/riscv-cmo.def: New file.
> > ---
> >   gcc/config/riscv/predicates.md     |  4 +++
> >   gcc/config/riscv/riscv-builtins.cc | 16 ++++++++++
> >   gcc/config/riscv/riscv-cmo.def     | 17 ++++++++++
> >   gcc/config/riscv/riscv-ftypes.def  |  4 +++
> >   gcc/config/riscv/riscv.md          | 51 ++++++++++++++++++++++++++++++
> >   5 files changed, 92 insertions(+)
> >   create mode 100644 gcc/config/riscv/riscv-cmo.def
> >
> > diff --git a/gcc/config/riscv/predicates.md b/gcc/config/riscv/predicates.md
> > index 97cdbdf053b..3fb4d95ab08 100644
> > --- a/gcc/config/riscv/predicates.md
> > +++ b/gcc/config/riscv/predicates.md
> > @@ -239,3 +239,7 @@
> >   (define_predicate "const63_operand"
> >     (and (match_code "const_int")
> >          (match_test "INTVAL (op) == 63")))
> > +
> > +(define_predicate "imm5_operand"
> > +  (and (match_code "const_int")
> > +       (match_test "INTVAL (op) < 5")))
> > \ No newline at end of file
> > diff --git a/gcc/config/riscv/riscv-builtins.cc b/gcc/config/riscv/riscv-builtins.cc
> > index 0658f8d3047..795132a0c16 100644
> > --- a/gcc/config/riscv/riscv-builtins.cc
> > +++ b/gcc/config/riscv/riscv-builtins.cc
> > @@ -87,6 +87,18 @@ struct riscv_builtin_description {
> >
> >   AVAIL (hard_float, TARGET_HARD_FLOAT)
> >
> > +
> > +AVAIL (clean32, TARGET_ZICBOM && !TARGET_64BIT)
> > +AVAIL (clean64, TARGET_ZICBOM && TARGET_64BIT)
> > +AVAIL (flush32, TARGET_ZICBOM && !TARGET_64BIT)
> > +AVAIL (flush64, TARGET_ZICBOM && TARGET_64BIT)
> > +AVAIL (inval32, TARGET_ZICBOM && !TARGET_64BIT)
> > +AVAIL (inval64, TARGET_ZICBOM && TARGET_64BIT)
> > +AVAIL (zero32,  TARGET_ZICBOZ && !TARGET_64BIT)
> > +AVAIL (zero64,  TARGET_ZICBOZ && TARGET_64BIT)
> > +AVAIL (prefetchi32, TARGET_ZICBOP && !TARGET_64BIT)
> > +AVAIL (prefetchi64, TARGET_ZICBOP && TARGET_64BIT)
> > +
> >   /* Construct a riscv_builtin_description from the given arguments.
> >
> >      INSN is the name of the associated instruction pattern, without the
> > @@ -119,6 +131,8 @@ AVAIL (hard_float, TARGET_HARD_FLOAT)
> >   /* Argument types.  */
> >   #define RISCV_ATYPE_VOID void_type_node
> >   #define RISCV_ATYPE_USI unsigned_intSI_type_node
> > +#define RISCV_ATYPE_SI intSI_type_node
> > +#define RISCV_ATYPE_DI intDI_type_node
> >
> >   /* RISCV_FTYPE_ATYPESN takes N RISCV_FTYPES-like type codes and lists
> >      their associated RISCV_ATYPEs.  */
> > @@ -128,6 +142,8 @@ AVAIL (hard_float, TARGET_HARD_FLOAT)
> >     RISCV_ATYPE_##A, RISCV_ATYPE_##B
> >
> >   static const struct riscv_builtin_description riscv_builtins[] = {
> > +  #include "riscv-cmo.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-cmo.def b/gcc/config/riscv/riscv-cmo.def
> > new file mode 100644
> > index 00000000000..01cbf6ad64f
> > --- /dev/null
> > +++ b/gcc/config/riscv/riscv-cmo.def
> > @@ -0,0 +1,17 @@
> > +// zicbom
> > +RISCV_BUILTIN (clean_si, "zicbom_cbo_clean", RISCV_BUILTIN_DIRECT, RISCV_SI_FTYPE, clean32),
> > +RISCV_BUILTIN (clean_di, "zicbom_cbo_clean", RISCV_BUILTIN_DIRECT, RISCV_DI_FTYPE, clean64),
> > +
> > +RISCV_BUILTIN (flush_si, "zicbom_cbo_flush", RISCV_BUILTIN_DIRECT, RISCV_SI_FTYPE, flush32),
> > +RISCV_BUILTIN (flush_di, "zicbom_cbo_flush", RISCV_BUILTIN_DIRECT, RISCV_DI_FTYPE, flush64),
> > +
> > +RISCV_BUILTIN (inval_si, "zicbom_cbo_inval", RISCV_BUILTIN_DIRECT, RISCV_SI_FTYPE, inval32),
> > +RISCV_BUILTIN (inval_di, "zicbom_cbo_inval", RISCV_BUILTIN_DIRECT, RISCV_DI_FTYPE, inval64),
> > +
> > +// zicboz
> > +RISCV_BUILTIN (zero_si, "zicboz_cbo_zero", RISCV_BUILTIN_DIRECT, RISCV_SI_FTYPE, zero32),
> > +RISCV_BUILTIN (zero_di, "zicboz_cbo_zero", RISCV_BUILTIN_DIRECT, RISCV_DI_FTYPE, zero64),
> > +
> > +// 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),
> > \ No newline at end of file
> > diff --git a/gcc/config/riscv/riscv-ftypes.def b/gcc/config/riscv/riscv-ftypes.def
> > index 2214c496f9b..62421292ce7 100644
> > --- a/gcc/config/riscv/riscv-ftypes.def
> > +++ b/gcc/config/riscv/riscv-ftypes.def
> > @@ -28,3 +28,7 @@ along with GCC; see the file COPYING3.  If not see
> >
> >   DEF_RISCV_FTYPE (0, (USI))
> >   DEF_RISCV_FTYPE (1, (VOID, USI))
> > +DEF_RISCV_FTYPE (0, (SI))
> > +DEF_RISCV_FTYPE (0, (DI))
> > +DEF_RISCV_FTYPE (1, (SI, SI))
> > +DEF_RISCV_FTYPE (1, (DI, DI))
> > diff --git a/gcc/config/riscv/riscv.md b/gcc/config/riscv/riscv.md
> > index b3c5bce842a..b96d0c30e59 100644
> > --- a/gcc/config/riscv/riscv.md
> > +++ b/gcc/config/riscv/riscv.md
> > @@ -69,6 +69,11 @@
> >     ;; Stack Smash Protector
> >     UNSPEC_SSP_SET
> >     UNSPEC_SSP_TEST
> > +  UNSPECV_CLEAN
> > +  UNSPECV_FLUSH
> > +  UNSPECV_INVAL
> > +  UNSPECV_ZERO
> > +  UNSPECV_PREI
> >   ])
> >
> >   (define_constants
> > @@ -2863,6 +2868,52 @@
> >     "<load>\t%3, %1\;<load>\t%0, %2\;xor\t%0, %3, %0\;li\t%3, 0"
> >     [(set_attr "length" "12")])
> >
> > +(define_insn "riscv_clean_<mode>"
> > +[(unspec_volatile:X [(match_operand:X 0 "register_operand" "r")] UNSPECV_CLEAN)]
> > +"TARGET_ZICBOM"
> > +"cbo.clean\t%a0"
> > +)
> > +
> > +(define_insn "riscv_flush_<mode>"
> > +[(unspec_volatile:X [(match_operand:X 0 "register_operand" "r")] UNSPECV_FLUSH)]
> > +"TARGET_ZICBOM"
> > +"cbo.flush\t%a0"
> > +)
> > +
> > +(define_insn "riscv_inval_<mode>"
> > +[(unspec_volatile:X [(match_operand:X 0 "register_operand" "r")] UNSPECV_INVAL)]
> > +"TARGET_ZICBOM"
> > +"cbo.inval\t%a0"
> > +)
> > +
> > +(define_insn "riscv_zero_<mode>"
> > +[(unspec_volatile:X [(match_operand:X 0 "register_operand" "r")] UNSPECV_ZERO)]
> > +"TARGET_ZICBOZ"
> > +"cbo.zero\t%a0"
> > +)
> > +
> > +(define_insn "prefetch"
> > +[(prefetch (match_operand 0 "address_operand" "p")
> > +           (match_operand 1 "imm5_operand" "i")
> > +           (match_operand 2 "const_int_operand" "n"))]
> > +"TARGET_ZICBOP"
> > +{
> > +  switch (INTVAL (operands[1]))
> > +  {
> > +    case 0: return "prefetch.r\t%a0";
> > +    case 1: return "prefetch.w\t%a0";
> > +    default: gcc_unreachable ();
> > +  }
> > +})
> > +
> > +(define_insn "riscv_prefetchi_<mode>"
> > +[(unspec_volatile:X [(match_operand:X 0 "address_operand" "p")
> > +            (match_operand:X 1 "imm5_operand" "i")]
> > +            UNSPECV_PREI)]
> > +"TARGET_ZICBOP"
> > +"prefetch.i\t%a0"
> > +)
> > +
> >   (include "bitmanip.md")
> >   (include "sync.md")
> >   (include "peephole.md")
  

Patch

diff with the previous version:
We use unspec_volatile instead of unspec for those cache operations. We use UNSPECV instead of UNSPEC and move them to unspecv.

gcc/ChangeLog:

        * config/riscv/predicates.md (imm5_operand): Add a new operand type for prefetch instructions.
        * config/riscv/riscv-builtins.cc (AVAIL): Add new AVAILs for CMO ISA Extensions.
        (RISCV_ATYPE_SI): New.
        (RISCV_ATYPE_DI): New.
        * config/riscv/riscv-ftypes.def (0): New.
        (1): New.
        * config/riscv/riscv.md (riscv_clean_<mode>): New.
        (riscv_flush_<mode>): New.
        (riscv_inval_<mode>): New.
        (riscv_zero_<mode>): New.
        (prefetch): New.
        (riscv_prefetchi_<mode>): New.
        * config/riscv/riscv-cmo.def: New file.
---
 gcc/config/riscv/predicates.md     |  4 +++
 gcc/config/riscv/riscv-builtins.cc | 16 ++++++++++
 gcc/config/riscv/riscv-cmo.def     | 17 ++++++++++
 gcc/config/riscv/riscv-ftypes.def  |  4 +++
 gcc/config/riscv/riscv.md          | 51 ++++++++++++++++++++++++++++++
 5 files changed, 92 insertions(+)
 create mode 100644 gcc/config/riscv/riscv-cmo.def

diff --git a/gcc/config/riscv/predicates.md b/gcc/config/riscv/predicates.md
index 97cdbdf053b..3fb4d95ab08 100644
--- a/gcc/config/riscv/predicates.md
+++ b/gcc/config/riscv/predicates.md
@@ -239,3 +239,7 @@ 
 (define_predicate "const63_operand"
   (and (match_code "const_int")
        (match_test "INTVAL (op) == 63")))
+
+(define_predicate "imm5_operand"
+  (and (match_code "const_int")
+       (match_test "INTVAL (op) < 5")))
\ No newline at end of file
diff --git a/gcc/config/riscv/riscv-builtins.cc b/gcc/config/riscv/riscv-builtins.cc
index 0658f8d3047..795132a0c16 100644
--- a/gcc/config/riscv/riscv-builtins.cc
+++ b/gcc/config/riscv/riscv-builtins.cc
@@ -87,6 +87,18 @@  struct riscv_builtin_description {
 
 AVAIL (hard_float, TARGET_HARD_FLOAT)
 
+
+AVAIL (clean32, TARGET_ZICBOM && !TARGET_64BIT)
+AVAIL (clean64, TARGET_ZICBOM && TARGET_64BIT)
+AVAIL (flush32, TARGET_ZICBOM && !TARGET_64BIT)
+AVAIL (flush64, TARGET_ZICBOM && TARGET_64BIT)
+AVAIL (inval32, TARGET_ZICBOM && !TARGET_64BIT)
+AVAIL (inval64, TARGET_ZICBOM && TARGET_64BIT)
+AVAIL (zero32,  TARGET_ZICBOZ && !TARGET_64BIT)
+AVAIL (zero64,  TARGET_ZICBOZ && TARGET_64BIT)
+AVAIL (prefetchi32, TARGET_ZICBOP && !TARGET_64BIT)
+AVAIL (prefetchi64, TARGET_ZICBOP && TARGET_64BIT)
+
 /* Construct a riscv_builtin_description from the given arguments.
 
    INSN is the name of the associated instruction pattern, without the
@@ -119,6 +131,8 @@  AVAIL (hard_float, TARGET_HARD_FLOAT)
 /* Argument types.  */
 #define RISCV_ATYPE_VOID void_type_node
 #define RISCV_ATYPE_USI unsigned_intSI_type_node
+#define RISCV_ATYPE_SI intSI_type_node
+#define RISCV_ATYPE_DI intDI_type_node
 
 /* RISCV_FTYPE_ATYPESN takes N RISCV_FTYPES-like type codes and lists
    their associated RISCV_ATYPEs.  */
@@ -128,6 +142,8 @@  AVAIL (hard_float, TARGET_HARD_FLOAT)
   RISCV_ATYPE_##A, RISCV_ATYPE_##B
 
 static const struct riscv_builtin_description riscv_builtins[] = {
+  #include "riscv-cmo.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-cmo.def b/gcc/config/riscv/riscv-cmo.def
new file mode 100644
index 00000000000..01cbf6ad64f
--- /dev/null
+++ b/gcc/config/riscv/riscv-cmo.def
@@ -0,0 +1,17 @@ 
+// zicbom
+RISCV_BUILTIN (clean_si, "zicbom_cbo_clean", RISCV_BUILTIN_DIRECT, RISCV_SI_FTYPE, clean32),
+RISCV_BUILTIN (clean_di, "zicbom_cbo_clean", RISCV_BUILTIN_DIRECT, RISCV_DI_FTYPE, clean64),
+
+RISCV_BUILTIN (flush_si, "zicbom_cbo_flush", RISCV_BUILTIN_DIRECT, RISCV_SI_FTYPE, flush32),
+RISCV_BUILTIN (flush_di, "zicbom_cbo_flush", RISCV_BUILTIN_DIRECT, RISCV_DI_FTYPE, flush64),
+
+RISCV_BUILTIN (inval_si, "zicbom_cbo_inval", RISCV_BUILTIN_DIRECT, RISCV_SI_FTYPE, inval32),
+RISCV_BUILTIN (inval_di, "zicbom_cbo_inval", RISCV_BUILTIN_DIRECT, RISCV_DI_FTYPE, inval64),
+
+// zicboz
+RISCV_BUILTIN (zero_si, "zicboz_cbo_zero", RISCV_BUILTIN_DIRECT, RISCV_SI_FTYPE, zero32),
+RISCV_BUILTIN (zero_di, "zicboz_cbo_zero", RISCV_BUILTIN_DIRECT, RISCV_DI_FTYPE, zero64),
+
+// 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),
\ No newline at end of file
diff --git a/gcc/config/riscv/riscv-ftypes.def b/gcc/config/riscv/riscv-ftypes.def
index 2214c496f9b..62421292ce7 100644
--- a/gcc/config/riscv/riscv-ftypes.def
+++ b/gcc/config/riscv/riscv-ftypes.def
@@ -28,3 +28,7 @@  along with GCC; see the file COPYING3.  If not see
 
 DEF_RISCV_FTYPE (0, (USI))
 DEF_RISCV_FTYPE (1, (VOID, USI))
+DEF_RISCV_FTYPE (0, (SI))
+DEF_RISCV_FTYPE (0, (DI))
+DEF_RISCV_FTYPE (1, (SI, SI))
+DEF_RISCV_FTYPE (1, (DI, DI))
diff --git a/gcc/config/riscv/riscv.md b/gcc/config/riscv/riscv.md
index b3c5bce842a..b96d0c30e59 100644
--- a/gcc/config/riscv/riscv.md
+++ b/gcc/config/riscv/riscv.md
@@ -69,6 +69,11 @@ 
   ;; Stack Smash Protector
   UNSPEC_SSP_SET
   UNSPEC_SSP_TEST
+  UNSPECV_CLEAN
+  UNSPECV_FLUSH
+  UNSPECV_INVAL
+  UNSPECV_ZERO
+  UNSPECV_PREI
 ])
 
 (define_constants
@@ -2863,6 +2868,52 @@ 
   "<load>\t%3, %1\;<load>\t%0, %2\;xor\t%0, %3, %0\;li\t%3, 0"
   [(set_attr "length" "12")])
 
+(define_insn "riscv_clean_<mode>"
+[(unspec_volatile:X [(match_operand:X 0 "register_operand" "r")] UNSPECV_CLEAN)]
+"TARGET_ZICBOM"
+"cbo.clean\t%a0"
+)
+
+(define_insn "riscv_flush_<mode>"
+[(unspec_volatile:X [(match_operand:X 0 "register_operand" "r")] UNSPECV_FLUSH)]
+"TARGET_ZICBOM"
+"cbo.flush\t%a0"
+)
+
+(define_insn "riscv_inval_<mode>"
+[(unspec_volatile:X [(match_operand:X 0 "register_operand" "r")] UNSPECV_INVAL)]
+"TARGET_ZICBOM"
+"cbo.inval\t%a0"
+)
+
+(define_insn "riscv_zero_<mode>"
+[(unspec_volatile:X [(match_operand:X 0 "register_operand" "r")] UNSPECV_ZERO)]
+"TARGET_ZICBOZ"
+"cbo.zero\t%a0"
+)
+
+(define_insn "prefetch"
+[(prefetch (match_operand 0 "address_operand" "p")
+           (match_operand 1 "imm5_operand" "i")
+           (match_operand 2 "const_int_operand" "n"))]
+"TARGET_ZICBOP"
+{
+  switch (INTVAL (operands[1]))
+  {
+    case 0: return "prefetch.r\t%a0";
+    case 1: return "prefetch.w\t%a0";
+    default: gcc_unreachable ();
+  }
+})
+
+(define_insn "riscv_prefetchi_<mode>"
+[(unspec_volatile:X [(match_operand:X 0 "address_operand" "p")
+            (match_operand:X 1 "imm5_operand" "i")]
+            UNSPECV_PREI)]
+"TARGET_ZICBOP"
+"prefetch.i\t%a0"
+)
+
 (include "bitmanip.md")
 (include "sync.md")
 (include "peephole.md")