[v5,1/1] RISC-V: Add support for XCVbitmanip extension in CV32E40P

Message ID 20240804183544.691898-2-mary.bennett682@gmail.com
State Deferred
Delegated to: Jeff Law
Headers
Series RISC-V: Support CORE-V XCVBITMAIP extension |

Checks

Context Check Description
rivoscibot/toolchain-ci-rivos-apply-patch success Patch applied
rivoscibot/toolchain-ci-rivos-lint warning Lint failed
rivoscibot/toolchain-ci-rivos-build--newlib-rv64gcv-lp64d-multilib success Build passed
rivoscibot/toolchain-ci-rivos-build--linux-rv64gc_zba_zbb_zbc_zbs-lp64d-multilib success Build passed
rivoscibot/toolchain-ci-rivos-build--linux-rv64gcv-lp64d-multilib success Build passed
rivoscibot/toolchain-ci-rivos-build--newlib-rv64gc-lp64d-non-multilib success Build passed
rivoscibot/toolchain-ci-rivos-build--linux-rv64gc-lp64d-non-multilib success Build passed
linaro-tcwg-bot/tcwg_gcc_build--master-arm success Build passed
rivoscibot/toolchain-ci-rivos-test success Testing passed
linaro-tcwg-bot/tcwg_gcc_check--master-arm success Test passed
linaro-tcwg-bot/tcwg_gcc_build--master-aarch64 success Build passed
linaro-tcwg-bot/tcwg_gcc_check--master-aarch64 success Test passed

Commit Message

Mary Bennett Aug. 4, 2024, 6:35 p.m. UTC
  Spec: github.com/openhwgroup/core-v-sw/blob/master/specifications/corev-builtin-spec.md

Contributors:
  Mary Bennett <mary.bennett682@gmail.com>
  Nandni Jamnadas <nandni.jamnadas@embecosm.com>
  Pietra Ferreira <pietra.ferreira@embecosm.com>
  Charlie Keaney
  Jessica Mills
  Craig Blackmore <craig.blackmore@embecosm.com>
  Simon Cook <simon.cook@embecosm.com>
  Jeremy Bennett <jeremy.bennett@embecosm.com>
  Helene Chelin <helene.chelin@embecosm.com>

gcc/ChangeLog:
	* common/config/riscv/riscv-common.cc: Add XCVbitmanip.
	* config/riscv/constraints.md: Likewise.
	* config/riscv/corev.def: Likewise.
	* config/riscv/corev.md: Likewise.
	* config/riscv/predicates.md: Likewise.
	* config/riscv/riscv-builtins.cc (AVAIL): Likewise.
	* config/riscv/riscv-ftypes.def: Likewise.
	* config/riscv/riscv.opt: Likewise.
	* doc/extend.texi: Add XCVbitmanip builtin documentation.
	* doc/sourcebuild.texi: Likewise.

gcc/testsuite/ChangeLog:
	* gcc.target/riscv/cv-bitmanip-compile-bclr.c: New test.
	* gcc.target/riscv/cv-bitmanip-compile-bclrr.c: New test.
	* gcc.target/riscv/cv-bitmanip-compile-bitrev.c: New test.
	* gcc.target/riscv/cv-bitmanip-compile-bset.c: New test.
	* gcc.target/riscv/cv-bitmanip-compile-bsetr.c: New test.
	* gcc.target/riscv/cv-bitmanip-compile-clb.c: New test.
	* gcc.target/riscv/cv-bitmanip-compile-cnt.c: New test.
	* gcc.target/riscv/cv-bitmanip-compile-extract.c: New test.
	* gcc.target/riscv/cv-bitmanip-compile-extractr.c: New test.
	* gcc.target/riscv/cv-bitmanip-compile-extractu.c: New test.
	* gcc.target/riscv/cv-bitmanip-compile-extractur.c: New test.
	* gcc.target/riscv/cv-bitmanip-compile-ff1.c: New test.
	* gcc.target/riscv/cv-bitmanip-compile-fl1.c: New test.
	* gcc.target/riscv/cv-bitmanip-compile-insert.c: New test.
	* gcc.target/riscv/cv-bitmanip-compile-insertr.c: New test.
	* gcc.target/riscv/cv-bitmanip-compile-ror.c: New test.
	* gcc.target/riscv/cv-bitmanip-fail-compile-bclr.c: New test.
	* gcc.target/riscv/cv-bitmanip-fail-compile-bitrev.c: New test.
	* gcc.target/riscv/cv-bitmanip-fail-compile-bset.c: New test.
	* gcc.target/riscv/cv-bitmanip-fail-compile-extract.c: New test.
	* gcc.target/riscv/cv-bitmanip-fail-compile-extractu.c: New test.
	* gcc.target/riscv/cv-bitmanip-fail-compile-insert.c: New test.
	* lib/target-supports.exp: Add proc for the XCVbitmanip extension.
---
 gcc/common/config/riscv/riscv-common.cc       |   2 +
 gcc/config/riscv/constraints.md               |  16 ++
 gcc/config/riscv/corev.def                    |  13 ++
 gcc/config/riscv/corev.md                     | 188 ++++++++++++++++++
 gcc/config/riscv/predicates.md                |  11 +
 gcc/config/riscv/riscv-builtins.cc            |   1 +
 gcc/config/riscv/riscv-ftypes.def             |   3 +
 gcc/config/riscv/riscv.cc                     |  13 ++
 gcc/config/riscv/riscv.opt                    |   5 +-
 gcc/doc/extend.texi                           |  53 +++++
 gcc/doc/sourcebuild.texi                      |   3 +
 .../riscv/cv-bitmanip-compile-bclr.c          |  27 +++
 .../riscv/cv-bitmanip-compile-bclrr.c         |  18 ++
 .../riscv/cv-bitmanip-compile-bitrev.c        |  30 +++
 .../riscv/cv-bitmanip-compile-bset.c          |  27 +++
 .../riscv/cv-bitmanip-compile-bsetr.c         |  18 ++
 .../riscv/cv-bitmanip-compile-clb.c           |  18 ++
 .../riscv/cv-bitmanip-compile-cnt.c           |  18 ++
 .../riscv/cv-bitmanip-compile-extract.c       |  27 +++
 .../riscv/cv-bitmanip-compile-extractr.c      |  18 ++
 .../riscv/cv-bitmanip-compile-extractu.c      |  27 +++
 .../riscv/cv-bitmanip-compile-extractur.c     |  18 ++
 .../riscv/cv-bitmanip-compile-ff1.c           |  18 ++
 .../riscv/cv-bitmanip-compile-fl1.c           |  18 ++
 .../riscv/cv-bitmanip-compile-insert.c        |  24 +++
 .../riscv/cv-bitmanip-compile-insertr.c       |  18 ++
 .../riscv/cv-bitmanip-compile-ror.c           |  18 ++
 .../riscv/cv-bitmanip-fail-compile-bclr.c     |  25 +++
 .../riscv/cv-bitmanip-fail-compile-bitrev.c   |  23 +++
 .../riscv/cv-bitmanip-fail-compile-bset.c     |  25 +++
 .../riscv/cv-bitmanip-fail-compile-extract.c  |  25 +++
 .../riscv/cv-bitmanip-fail-compile-extractu.c |  25 +++
 .../riscv/cv-bitmanip-fail-compile-insert.c   |  25 +++
 gcc/testsuite/lib/target-supports.exp         |  13 ++
 34 files changed, 810 insertions(+), 1 deletion(-)
 create mode 100644 gcc/testsuite/gcc.target/riscv/cv-bitmanip-compile-bclr.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/cv-bitmanip-compile-bclrr.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/cv-bitmanip-compile-bitrev.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/cv-bitmanip-compile-bset.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/cv-bitmanip-compile-bsetr.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/cv-bitmanip-compile-clb.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/cv-bitmanip-compile-cnt.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/cv-bitmanip-compile-extract.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/cv-bitmanip-compile-extractr.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/cv-bitmanip-compile-extractu.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/cv-bitmanip-compile-extractur.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/cv-bitmanip-compile-ff1.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/cv-bitmanip-compile-fl1.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/cv-bitmanip-compile-insert.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/cv-bitmanip-compile-insertr.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/cv-bitmanip-compile-ror.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/cv-bitmanip-fail-compile-bclr.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/cv-bitmanip-fail-compile-bitrev.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/cv-bitmanip-fail-compile-bset.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/cv-bitmanip-fail-compile-extract.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/cv-bitmanip-fail-compile-extractu.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/cv-bitmanip-fail-compile-insert.c
  

Comments

Jeff Law Aug. 6, 2024, 2:25 p.m. UTC | #1
On 8/4/24 12:35 PM, Mary Bennett wrote:
> Spec: github.com/openhwgroup/core-v-sw/blob/master/specifications/corev-builtin-spec.md
> 
> Contributors:
>    Mary Bennett <mary.bennett682@gmail.com>
>    Nandni Jamnadas <nandni.jamnadas@embecosm.com>
>    Pietra Ferreira <pietra.ferreira@embecosm.com>
>    Charlie Keaney
>    Jessica Mills
>    Craig Blackmore <craig.blackmore@embecosm.com>
>    Simon Cook <simon.cook@embecosm.com>
>    Jeremy Bennett <jeremy.bennett@embecosm.com>
>    Helene Chelin <helene.chelin@embecosm.com>
> 
> gcc/ChangeLog:
> 	* common/config/riscv/riscv-common.cc: Add XCVbitmanip.
> 	* config/riscv/constraints.md: Likewise.
> 	* config/riscv/corev.def: Likewise.
> 	* config/riscv/corev.md: Likewise.
> 	* config/riscv/predicates.md: Likewise.
> 	* config/riscv/riscv-builtins.cc (AVAIL): Likewise.
> 	* config/riscv/riscv-ftypes.def: Likewise.
> 	* config/riscv/riscv.opt: Likewise.
> 	* doc/extend.texi: Add XCVbitmanip builtin documentation.
> 	* doc/sourcebuild.texi: Likewise.
> 
> gcc/testsuite/ChangeLog:
> 	* gcc.target/riscv/cv-bitmanip-compile-bclr.c: New test.
> 	* gcc.target/riscv/cv-bitmanip-compile-bclrr.c: New test.
> 	* gcc.target/riscv/cv-bitmanip-compile-bitrev.c: New test.
> 	* gcc.target/riscv/cv-bitmanip-compile-bset.c: New test.
> 	* gcc.target/riscv/cv-bitmanip-compile-bsetr.c: New test.
> 	* gcc.target/riscv/cv-bitmanip-compile-clb.c: New test.
> 	* gcc.target/riscv/cv-bitmanip-compile-cnt.c: New test.
> 	* gcc.target/riscv/cv-bitmanip-compile-extract.c: New test.
> 	* gcc.target/riscv/cv-bitmanip-compile-extractr.c: New test.
> 	* gcc.target/riscv/cv-bitmanip-compile-extractu.c: New test.
> 	* gcc.target/riscv/cv-bitmanip-compile-extractur.c: New test.
> 	* gcc.target/riscv/cv-bitmanip-compile-ff1.c: New test.
> 	* gcc.target/riscv/cv-bitmanip-compile-fl1.c: New test.
> 	* gcc.target/riscv/cv-bitmanip-compile-insert.c: New test.
> 	* gcc.target/riscv/cv-bitmanip-compile-insertr.c: New test.
> 	* gcc.target/riscv/cv-bitmanip-compile-ror.c: New test.
> 	* gcc.target/riscv/cv-bitmanip-fail-compile-bclr.c: New test.
> 	* gcc.target/riscv/cv-bitmanip-fail-compile-bitrev.c: New test.
> 	* gcc.target/riscv/cv-bitmanip-fail-compile-bset.c: New test.
> 	* gcc.target/riscv/cv-bitmanip-fail-compile-extract.c: New test.
> 	* gcc.target/riscv/cv-bitmanip-fail-compile-extractu.c: New test.
> 	* gcc.target/riscv/cv-bitmanip-fail-compile-insert.c: New test.
> 	* lib/target-supports.exp: Add proc for the XCVbitmanip extension.
> ---



> @@ -2651,3 +2653,189 @@
>   }
>     [(set_attr "type" "branch")
>      (set_attr "mode" "none")])
> +
> +;; XCVBITMANIP builtins
> +
> +(define_insn "riscv_cv_bitmanip_extract"
> +  [(set (match_operand:SI 0 "register_operand" "=r,r")
> +        (sign_extract:SI
> +          (match_operand:SI 1 "register_operand" "r,r")
> +          (ashiftrt:SI
> +            (match_operand:HI 2 "bit_extract_operand" "CV_bit_si10,r")
> +            (const_int 5))
> +          (plus:SI
> +            (and:SI
> +              (match_dup 2)
> +              (const_int 31))
> +            (const_int 1))))]
> +
> +  "TARGET_XCVBITMANIP && !TARGET_64BIT"
> +  "@
> +   cv.extract\t%0,%1,%Z2,%W2
> +   cv.extractr\t%0,%1,%2"
> +  [(set_attr "type" "bitmanip")
> +  (set_attr "mode" "SI")])
> +
> +(define_insn "riscv_cv_bitmanip_extractu"
I would combine this with the previous pattern.  There's already a code 
iterator "any_extract" you can use in the RTL template.  And there's a 
<u> code attribute that could be extended to handle sign/zero extract so 
that you conditionally generate the "u" in the assembly code.

Why aren't the position and size arguments just registers?  I didn't see 
anything in the spec that would suggest that we'd want to match those 
shift and plus expressions in the pos/size arguments to the extraction. 
But given the insert/clear/set patterns are using the same basic 
structure I think I must be misunderstanding something.

*If* the semantics of the thead extensions are compatible with the Zbs 
extension, then we ought to be able to just reuse the existing patterns. 
  So for example a bclr has two major forms:


> (define_insn "*bclr<mode>"
>   [(set (match_operand:X 0 "register_operand" "=r")
>         (and:X (rotate:X (const_int -2)
>                          (match_operand:QI 2 "register_operand" "r"))
>                (match_operand:X 1 "register_operand" "r")))]
>   "TARGET_ZBS"
>   "bclr\t%0,%1,%2"
>   [(set_attr "type" "bitmanip")])
> 
> (define_insn "*bclri<mode>"
>   [(set (match_operand:X 0 "register_operand" "=r")
>         (and:X (match_operand:X 1 "register_operand" "r")
>                (match_operand:X 2 "not_single_bit_mask_operand" "DnS")))]
>   "TARGET_ZBS"
>   "bclri\t%0,%1,%T2"
>   [(set_attr "type" "bitmanip")])

There's other variants and if the semantics are compatible I'd think 
we'd want to take advantage of the work that's already been done to 
recognize the other forms that combine might generate such as:


> ;; Yet another form of a bset/bclr that can be created by combine.
> (define_insn "*bsetclr_zero_extract"
>   [(set (zero_extract:X (match_operand:X 0 "register_operand" "+r")
>                         (const_int 1)
>                         (zero_extend:X
>                           (match_operand:QI 1 "register_operand" "r")))
>         (match_operand 2 "immediate_operand" "n"))]
>   "TARGET_ZBS 
>    && (operands[2] == CONST0_RTX (<MODE>mode)
>        || operands[2] == CONST1_RTX (<MODE>mode))"
>   {               
>     return (operands[2] == CONST0_RTX (<MODE>mode)
>             ? "bclr\t%0,%0,%1"
>             : "bset\t%0,%0,%1");
>   }
>   [(set_attr "type" "bitmanip")])



)
> +
> +(define_predicate "register_UHI_operand"
> +  (and (match_code "reg,subreg")
> +       (match_test "GET_MODE (op) == HImode")))
Is this really needed?  In the places where it's used (via 
bit_extract_operand) we already force the operand to be HImode.  So 
can't we just use "register_operand" instead of "register_UHI_operand" 
in bit_extract_operand instead?


Most of the other patterns looked sensible.  Though I think it's 
possible we might want to combine them with existing standard patterns 
as well.  Take something like clz/ctz.  We've got some bits to recognize 
additional variants of those as well.  Rotates have Zbb equivalents I 
think as well.  Happy to entertain thoughts on how we want to manage 
this policy-wise going forward (and I'll raise that today in the 
patchwork meeting).

jeff
  
Jeff Law Aug. 25, 2024, 10:26 p.m. UTC | #2
On 8/4/24 12:35 PM, Mary Bennett wrote:
> Spec: github.com/openhwgroup/core-v-sw/blob/master/specifications/corev-builtin-spec.md
> 
> Contributors:
>    Mary Bennett <mary.bennett682@gmail.com>
>    Nandni Jamnadas <nandni.jamnadas@embecosm.com>
>    Pietra Ferreira <pietra.ferreira@embecosm.com>
>    Charlie Keaney
>    Jessica Mills
>    Craig Blackmore <craig.blackmore@embecosm.com>
>    Simon Cook <simon.cook@embecosm.com>
>    Jeremy Bennett <jeremy.bennett@embecosm.com>
>    Helene Chelin <helene.chelin@embecosm.com>
> 
> gcc/ChangeLog:
> 	* common/config/riscv/riscv-common.cc: Add XCVbitmanip.
> 	* config/riscv/constraints.md: Likewise.
> 	* config/riscv/corev.def: Likewise.
> 	* config/riscv/corev.md: Likewise.
> 	* config/riscv/predicates.md: Likewise.
> 	* config/riscv/riscv-builtins.cc (AVAIL): Likewise.
> 	* config/riscv/riscv-ftypes.def: Likewise.
> 	* config/riscv/riscv.opt: Likewise.
> 	* doc/extend.texi: Add XCVbitmanip builtin documentation.
> 	* doc/sourcebuild.texi: Likewise.
> 
> gcc/testsuite/ChangeLog:
> 	* gcc.target/riscv/cv-bitmanip-compile-bclr.c: New test.
> 	* gcc.target/riscv/cv-bitmanip-compile-bclrr.c: New test.
> 	* gcc.target/riscv/cv-bitmanip-compile-bitrev.c: New test.
> 	* gcc.target/riscv/cv-bitmanip-compile-bset.c: New test.
> 	* gcc.target/riscv/cv-bitmanip-compile-bsetr.c: New test.
> 	* gcc.target/riscv/cv-bitmanip-compile-clb.c: New test.
> 	* gcc.target/riscv/cv-bitmanip-compile-cnt.c: New test.
> 	* gcc.target/riscv/cv-bitmanip-compile-extract.c: New test.
> 	* gcc.target/riscv/cv-bitmanip-compile-extractr.c: New test.
> 	* gcc.target/riscv/cv-bitmanip-compile-extractu.c: New test.
> 	* gcc.target/riscv/cv-bitmanip-compile-extractur.c: New test.
> 	* gcc.target/riscv/cv-bitmanip-compile-ff1.c: New test.
> 	* gcc.target/riscv/cv-bitmanip-compile-fl1.c: New test.
> 	* gcc.target/riscv/cv-bitmanip-compile-insert.c: New test.
> 	* gcc.target/riscv/cv-bitmanip-compile-insertr.c: New test.
> 	* gcc.target/riscv/cv-bitmanip-compile-ror.c: New test.
> 	* gcc.target/riscv/cv-bitmanip-fail-compile-bclr.c: New test.
> 	* gcc.target/riscv/cv-bitmanip-fail-compile-bitrev.c: New test.
> 	* gcc.target/riscv/cv-bitmanip-fail-compile-bset.c: New test.
> 	* gcc.target/riscv/cv-bitmanip-fail-compile-extract.c: New test.
> 	* gcc.target/riscv/cv-bitmanip-fail-compile-extractu.c: New test.
> 	* gcc.target/riscv/cv-bitmanip-fail-compile-insert.c: New test.
> 	* lib/target-supports.exp: Add proc for the XCVbitmanip extension.
> ---

> @@ -281,3 +286,14 @@
>     "Shifting immediate for SIMD shufflei3."
>     (and (match_code "const_int")
>          (match_test "IN_RANGE (ival, -64, -1)")))
> +
> +(define_constraint "CV_bit_si10"
> +  "A 10-bit unsigned immediate for CORE-V bitmanip."
> +  (and (match_code "const_int")
> +       (match_test "IN_RANGE (ival, 0, 1023)")))
> +
> +(define_constraint "CV_bit_in10"
> +  "A 10-bit unsigned immediate for CORE-V bitmanip insert."
> +  (and (match_code "const_int")
> +       (and (match_test "IN_RANGE (ival, 0, 1023)")
> +	    (match_test "(ival & 31) + ((ival >> 5) & 31) <= 32"))))
I probably asked this before, but this seems really odd.  why would we 
need 10 bits for a bitmanip operations?



> @@ -2651,3 +2653,189 @@
>   }
>     [(set_attr "type" "branch")
>      (set_attr "mode" "none")])
> +
> +;; XCVBITMANIP builtins
> +
> +(define_insn "riscv_cv_bitmanip_extract"
> +  [(set (match_operand:SI 0 "register_operand" "=r,r")
> +        (sign_extract:SI
> +          (match_operand:SI 1 "register_operand" "r,r")
> +          (ashiftrt:SI
> +            (match_operand:HI 2 "bit_extract_operand" "CV_bit_si10,r")
> +            (const_int 5))
> +          (plus:SI
> +            (and:SI
> +              (match_dup 2)
> +              (const_int 31))
> +            (const_int 1))))]
That (ashiftrt (operand) (const_int 5) seems really weird to me and it's 
almost certainly related to the question about needing 10 bits in 
predicates.

> +
> +(define_insn "riscv_cv_bitmanip_ff1"
> +  [(set (match_operand:SI 0 "register_operand" "=r")
> +        (ctz:SI (match_operand:SI 1 "register_operand" "r")))]
> +
> +  "TARGET_XCVBITMANIP && !TARGET_64BIT"
> +  "cv.ff1\t%0,%1"
> +  [(set_attr "type" "bitmanip")
> +  (set_attr "mode" "SI")])
> +
> +(define_insn "riscv_cv_bitmanip_fl1"
> +  [(set (match_operand:SI 0 "register_operand" "=r")
> +	(minus:SI
> +	  (const_int 31)
> +	  (clz:SI (match_operand:SI 1 "register_operand" "r"))))]
> +
> +  "TARGET_XCVBITMANIP && !TARGET_64BIT"
> +  "cv.fl1\t%0,%1"
> +  [(set_attr "type" "bitmanip")
> +  (set_attr "mode" "SI")])
So presumably only available in 32bit mode?  Which means they're no 
great candidates for merging with the standard patterns  since they use 
the GPR iterator.  Similarly for popcount.


I'm leaning more and more against trying to merge any of this with 
bitmanip.md.  I think it'll largely come down to whether or not there 
appears to be an ability to merge the single bit manipulation patterns. 
Right now with the weird 10 bit stuff above, that doesn't look likely 
either.


Jeff
  

Patch

diff --git a/gcc/common/config/riscv/riscv-common.cc b/gcc/common/config/riscv/riscv-common.cc
index 1944c7785c4..f5ee7319cf0 100644
--- a/gcc/common/config/riscv/riscv-common.cc
+++ b/gcc/common/config/riscv/riscv-common.cc
@@ -402,6 +402,7 @@  static const struct riscv_ext_version riscv_ext_version_table[] =
   {"xcvelw", ISA_SPEC_CLASS_NONE, 1, 0},
   {"xcvsimd", ISA_SPEC_CLASS_NONE, 1, 0},
   {"xcvbi", ISA_SPEC_CLASS_NONE, 1, 0},
+  {"xcvbitmanip", ISA_SPEC_CLASS_NONE, 1, 0},
 
   {"xtheadba", ISA_SPEC_CLASS_NONE, 1, 0},
   {"xtheadbb", ISA_SPEC_CLASS_NONE, 1, 0},
@@ -1711,6 +1712,7 @@  static const riscv_ext_flag_table_t riscv_ext_flag_table[] =
   {"xcvelw",        &gcc_options::x_riscv_xcv_subext, MASK_XCVELW},
   {"xcvsimd",       &gcc_options::x_riscv_xcv_subext, MASK_XCVSIMD},
   {"xcvbi",         &gcc_options::x_riscv_xcv_subext, MASK_XCVBI},
+  {"xcvbitmanip",   &gcc_options::x_riscv_xcv_subext, MASK_XCVBITMANIP},
 
   {"xtheadba",      &gcc_options::x_riscv_xthead_subext, MASK_XTHEADBA},
   {"xtheadbb",      &gcc_options::x_riscv_xthead_subext, MASK_XTHEADBB},
diff --git a/gcc/config/riscv/constraints.md b/gcc/config/riscv/constraints.md
index a9ee346af6f..5ef1021bf09 100644
--- a/gcc/config/riscv/constraints.md
+++ b/gcc/config/riscv/constraints.md
@@ -114,6 +114,11 @@ 
   (and (match_code "const_int")
        (match_test "SINGLE_BIT_MASK_OPERAND (~ival)")))
 
+(define_constraint "D03"
+  "@internal
+   0, 1, 2 or 3 immediate"
+  (match_test "IN_RANGE (ival, 0, 3)"))
+
 ;; Floating-point constant +0.0, used for FCVT-based moves when FMV is
 ;; not available in RV32.
 (define_constraint "G"
@@ -281,3 +286,14 @@ 
   "Shifting immediate for SIMD shufflei3."
   (and (match_code "const_int")
        (match_test "IN_RANGE (ival, -64, -1)")))
+
+(define_constraint "CV_bit_si10"
+  "A 10-bit unsigned immediate for CORE-V bitmanip."
+  (and (match_code "const_int")
+       (match_test "IN_RANGE (ival, 0, 1023)")))
+
+(define_constraint "CV_bit_in10"
+  "A 10-bit unsigned immediate for CORE-V bitmanip insert."
+  (and (match_code "const_int")
+       (and (match_test "IN_RANGE (ival, 0, 1023)")
+	    (match_test "(ival & 31) + ((ival >> 5) & 31) <= 32"))))
diff --git a/gcc/config/riscv/corev.def b/gcc/config/riscv/corev.def
index 9157529fd4c..d4b22a97110 100644
--- a/gcc/config/riscv/corev.def
+++ b/gcc/config/riscv/corev.def
@@ -200,3 +200,16 @@  RISCV_BUILTIN (cv_simd_cplxmul_r_si,		"cv_simd_cplxmul_r",	RISCV_BUILTIN_DIRECT,
 RISCV_BUILTIN (cv_simd_cplxmul_i_si,		"cv_simd_cplxmul_i",	RISCV_BUILTIN_DIRECT, RISCV_USI_FTYPE_USI_USI_USI_UQI, 	cvsimd),
 RISCV_BUILTIN (cv_simd_cplxconj_si,		"cv_simd_cplxconj",	RISCV_BUILTIN_DIRECT, RISCV_USI_FTYPE_USI, 		cvsimd),
 RISCV_BUILTIN (cv_simd_subrotmj_si,		"cv_simd_subrotmj",	RISCV_BUILTIN_DIRECT, RISCV_USI_FTYPE_USI_USI_UQI, 	cvsimd),
+
+// XCVBITMANIP
+RISCV_BUILTIN (cv_bitmanip_extract,     "cv_bitmanip_extract",     RISCV_BUILTIN_DIRECT, RISCV_SI_FTYPE_USI_UHI,         cvbitmanip),
+RISCV_BUILTIN (cv_bitmanip_extractu,    "cv_bitmanip_extractu",    RISCV_BUILTIN_DIRECT, RISCV_USI_FTYPE_USI_UHI,        cvbitmanip),
+RISCV_BUILTIN (cv_bitmanip_insert,      "cv_bitmanip_insert",      RISCV_BUILTIN_DIRECT, RISCV_USI_FTYPE_USI_UHI_USI,    cvbitmanip),
+RISCV_BUILTIN (cv_bitmanip_bclr,        "cv_bitmanip_bclr",        RISCV_BUILTIN_DIRECT, RISCV_USI_FTYPE_USI_UHI,        cvbitmanip),
+RISCV_BUILTIN (cv_bitmanip_bset,        "cv_bitmanip_bset",        RISCV_BUILTIN_DIRECT, RISCV_USI_FTYPE_USI_UHI,        cvbitmanip),
+RISCV_BUILTIN (cv_bitmanip_ff1,         "cv_bitmanip_ff1",         RISCV_BUILTIN_DIRECT, RISCV_USI_FTYPE_USI,            cvbitmanip),
+RISCV_BUILTIN (cv_bitmanip_fl1,         "cv_bitmanip_fl1",         RISCV_BUILTIN_DIRECT, RISCV_USI_FTYPE_USI,            cvbitmanip),
+RISCV_BUILTIN (cv_bitmanip_clb,         "cv_bitmanip_clb",         RISCV_BUILTIN_DIRECT, RISCV_UQI_FTYPE_USI,            cvbitmanip),
+RISCV_BUILTIN (cv_bitmanip_cnt,         "cv_bitmanip_cnt",         RISCV_BUILTIN_DIRECT, RISCV_USI_FTYPE_USI,            cvbitmanip),
+RISCV_BUILTIN (cv_bitmanip_ror,         "cv_bitmanip_ror",         RISCV_BUILTIN_DIRECT, RISCV_USI_FTYPE_USI_USI,        cvbitmanip),
+RISCV_BUILTIN (cv_bitmanip_bitrev,      "cv_bitmanip_bitrev",      RISCV_BUILTIN_DIRECT, RISCV_USI_FTYPE_USI_UQI_UQI,    cvbitmanip),
diff --git a/gcc/config/riscv/corev.md b/gcc/config/riscv/corev.md
index e2db8f31130..6d997c4192c 100644
--- a/gcc/config/riscv/corev.md
+++ b/gcc/config/riscv/corev.md
@@ -185,6 +185,8 @@ 
   UNSPEC_CV_CPLXCONJ
   UNSPEC_CV_SUBROTMJ
 
+  ;;CORE-V BITMANIP
+  UNSPEC_CV_BITMANIP_BITREV
 ])
 
 ;; XCVMAC extension.
@@ -2651,3 +2653,189 @@ 
 }
   [(set_attr "type" "branch")
    (set_attr "mode" "none")])
+
+;; XCVBITMANIP builtins
+
+(define_insn "riscv_cv_bitmanip_extract"
+  [(set (match_operand:SI 0 "register_operand" "=r,r")
+        (sign_extract:SI
+          (match_operand:SI 1 "register_operand" "r,r")
+          (ashiftrt:SI
+            (match_operand:HI 2 "bit_extract_operand" "CV_bit_si10,r")
+            (const_int 5))
+          (plus:SI
+            (and:SI
+              (match_dup 2)
+              (const_int 31))
+            (const_int 1))))]
+
+  "TARGET_XCVBITMANIP && !TARGET_64BIT"
+  "@
+   cv.extract\t%0,%1,%Z2,%W2
+   cv.extractr\t%0,%1,%2"
+  [(set_attr "type" "bitmanip")
+  (set_attr "mode" "SI")])
+
+(define_insn "riscv_cv_bitmanip_extractu"
+  [(set (match_operand:SI 0 "register_operand" "=r,r")
+        (zero_extract:SI
+	  (match_operand:SI 1 "register_operand" "r,r")
+          (ashiftrt:SI
+            (match_operand:HI 2 "bit_extract_operand" "CV_bit_si10,r")
+            (const_int 5))
+          (plus:SI
+	    (and:SI
+              (match_dup 2)
+              (const_int 31))
+            (const_int 1))))]
+
+  "TARGET_XCVBITMANIP && !TARGET_64BIT"
+  "@
+   cv.extractu\t%0,%1,%Z2,%W2
+   cv.extractur\t%0,%1,%2"
+  [(set_attr "type" "bitmanip")
+  (set_attr "mode" "SI")])
+
+(define_insn "riscv_cv_bitmanip_insert"
+  [(set (match_operand:SI 0 "register_operand" "=r,r")
+	(plus:SI
+          (and:SI
+            (match_operand:SI 3 "register_operand" "0,0")
+            (zero_extract:SI
+              (const_int 0)
+            (ashiftrt:SI
+              (match_operand:HI 2 "bit_extract_operand" "CV_bit_si10,r")
+              (const_int 5))
+            (plus:SI
+              (and:SI
+                (match_dup 2)
+                (const_int 31))
+              (const_int 1))))
+	  (sign_extract:SI
+            (match_operand:SI 1 "register_operand" "r,r")
+            (ashiftrt:SI
+              (match_dup 2)
+              (const_int 5))
+            (plus:SI
+              (and:SI
+                (match_dup 2)
+                (const_int 31))
+              (const_int 1)))))]
+
+  "TARGET_XCVBITMANIP && !TARGET_64BIT"
+  "@
+   cv.insert\t%0,%1,%Z2,%W2
+   cv.insertr\t%0,%1,%2"
+  [(set_attr "type" "bitmanip")
+  (set_attr "mode" "SI")])
+
+(define_insn "riscv_cv_bitmanip_bclr"
+  [(set (match_operand:SI 0 "register_operand" "=r,r")
+	(and:SI
+         (match_operand:SI 1 "register_operand" "r,r")
+	 (not:SI
+	  (ashift:SI
+	   (lshiftrt:SI
+	    (const_int -1)
+	    (minus:SI
+	     (const_int 31)
+             (lshiftrt:SI
+	      (and:SI
+               (match_operand:HI 2 "bit_extract_operand" "CV_bit_si10,r")
+	       (const_int 1023))
+              (const_int 5))))
+           (and:SI
+            (match_dup 2)
+            (const_int 31))))))]
+
+  "TARGET_XCVBITMANIP && !TARGET_64BIT"
+  "@
+   cv.bclr\t%0,%1,%Z2,%W2
+   cv.bclrr\t%0,%1,%2"
+  [(set_attr "type" "bitmanip")
+  (set_attr "mode" "SI")])
+
+(define_insn "riscv_cv_bitmanip_bset"
+  [(set (match_operand:SI 0 "register_operand" "=r,r")
+        (ior:SI
+          (match_operand:SI 1 "register_operand" "r,r")
+	  (ashift:SI
+	   (lshiftrt:SI
+	    (const_int -1)
+	    (minus:SI
+	     (const_int 31)
+             (lshiftrt:SI
+	      (and:SI
+               (match_operand:HI 2 "bit_extract_operand" "CV_bit_si10,r")
+	       (const_int 1023))
+              (const_int 5))))
+           (and:SI
+            (match_dup 2)
+            (const_int 31)))))]
+
+  "TARGET_XCVBITMANIP && !TARGET_64BIT"
+  "@
+   cv.bset\t%0,%1,%Z2,%W2
+   cv.bsetr\t%0,%1,%2"
+  [(set_attr "type" "bitmanip")
+  (set_attr "mode" "SI")])
+
+(define_insn "riscv_cv_bitmanip_ff1"
+  [(set (match_operand:SI 0 "register_operand" "=r")
+        (ctz:SI (match_operand:SI 1 "register_operand" "r")))]
+
+  "TARGET_XCVBITMANIP && !TARGET_64BIT"
+  "cv.ff1\t%0,%1"
+  [(set_attr "type" "bitmanip")
+  (set_attr "mode" "SI")])
+
+(define_insn "riscv_cv_bitmanip_fl1"
+  [(set (match_operand:SI 0 "register_operand" "=r")
+	(minus:SI
+	  (const_int 31)
+	  (clz:SI (match_operand:SI 1 "register_operand" "r"))))]
+
+  "TARGET_XCVBITMANIP && !TARGET_64BIT"
+  "cv.fl1\t%0,%1"
+  [(set_attr "type" "bitmanip")
+  (set_attr "mode" "SI")])
+
+(define_insn "riscv_cv_bitmanip_clb"
+  [(set (match_operand:QI 0 "register_operand" "=r")
+	(truncate:QI (clrsb:SI (match_operand:SI 1 "register_operand" "r"))))]
+
+  "TARGET_XCVBITMANIP && !TARGET_64BIT"
+  "cv.clb\t%0,%1"
+  [(set_attr "type" "bitmanip")
+  (set_attr "mode" "SI")])
+
+(define_insn "riscv_cv_bitmanip_cnt"
+  [(set (match_operand:SI 0 "register_operand" "=r")
+        (popcount:SI (match_operand:SI 1 "register_operand" "r")))]
+
+  "TARGET_XCVBITMANIP && !TARGET_64BIT"
+  "cv.cnt\t%0,%1"
+  [(set_attr "type" "bitmanip")
+  (set_attr "mode" "SI")])
+
+(define_insn "riscv_cv_bitmanip_ror"
+  [(set (match_operand:SI 0 "register_operand" "=r")
+        (rotatert:SI (match_operand:SI 1 "register_operand" "r")
+                     (match_operand:SI 2 "register_operand" "r")))]
+
+  "TARGET_XCVBITMANIP && !TARGET_64BIT"
+  "cv.ror\t%0,%1,%2"
+  [(set_attr "type" "bitmanip")
+  (set_attr "mode" "SI")])
+
+(define_insn "riscv_cv_bitmanip_bitrev"
+  [(set (match_operand:SI 0 "register_operand" "=r")
+        (unspec:SI [(match_operand:SI 1 "register_operand" "r")
+                    (match_operand:QI 2 "const_csr_operand" "K")
+                    (match_operand:QI 3 "const_int2_operand" "D03")]
+         UNSPEC_CV_BITMANIP_BITREV))]
+
+  "TARGET_XCVBITMANIP && !TARGET_64BIT"
+  "cv.bitrev\t%0,%1,%3,%2"
+  [(set_attr "type" "bitmanip")
+  (set_attr "mode" "SI")])
diff --git a/gcc/config/riscv/predicates.md b/gcc/config/riscv/predicates.md
index 9971fabc587..ddc8fbb0b1f 100644
--- a/gcc/config/riscv/predicates.md
+++ b/gcc/config/riscv/predicates.md
@@ -448,6 +448,17 @@ 
 (define_predicate "int6s_operand"
   (ior (match_operand 0 "const_int6s_operand")
        (match_operand 0 "register_operand")))
+(define_predicate "const_int10_operand"
+  (and (match_code "const_int")
+       (match_test "IN_RANGE (INTVAL (op), 0, 1023)")))
+
+(define_predicate "register_UHI_operand"
+  (and (match_code "reg,subreg")
+       (match_test "GET_MODE (op) == HImode")))
+
+(define_predicate "bit_extract_operand"
+  (ior (match_operand 0 "const_int10_operand")
+       (match_operand 0 "register_UHI_operand")))
 
 (define_predicate "const_int2_operand"
   (and (match_code "const_int")
diff --git a/gcc/config/riscv/riscv-builtins.cc b/gcc/config/riscv/riscv-builtins.cc
index dc54e1a59b5..40a79281a75 100644
--- a/gcc/config/riscv/riscv-builtins.cc
+++ b/gcc/config/riscv/riscv-builtins.cc
@@ -136,6 +136,7 @@  AVAIL (cvmac, TARGET_XCVMAC && !TARGET_64BIT)
 AVAIL (cvalu, TARGET_XCVALU && !TARGET_64BIT)
 AVAIL (cvelw, TARGET_XCVELW && !TARGET_64BIT)
 AVAIL (cvsimd, TARGET_XCVSIMD && !TARGET_64BIT)
+AVAIL (cvbitmanip, TARGET_XCVBITMANIP && !TARGET_64BIT)
 
 /* Construct a riscv_builtin_description from the given arguments.
 
diff --git a/gcc/config/riscv/riscv-ftypes.def b/gcc/config/riscv/riscv-ftypes.def
index baea490f91c..499feae4f37 100644
--- a/gcc/config/riscv/riscv-ftypes.def
+++ b/gcc/config/riscv/riscv-ftypes.def
@@ -37,11 +37,13 @@  DEF_RISCV_FTYPE (1, (USI, UQI))
 DEF_RISCV_FTYPE (1, (USI, UHI))
 DEF_RISCV_FTYPE (1, (SI, QI))
 DEF_RISCV_FTYPE (1, (SI, HI))
+DEF_RISCV_FTYPE (1, (UQI, USI))
 DEF_RISCV_FTYPE (2, (USI, UQI, UQI))
 DEF_RISCV_FTYPE (2, (USI, USI, UHI))
 DEF_RISCV_FTYPE (2, (USI, USI, QI))
 DEF_RISCV_FTYPE (2, (USI, USI, HI))
 DEF_RISCV_FTYPE (2, (USI, UHI, UHI))
+DEF_RISCV_FTYPE (2, (SI, USI, UHI))
 DEF_RISCV_FTYPE (2, (USI, USI, USI))
 DEF_RISCV_FTYPE (2, (USI, USI, UQI))
 DEF_RISCV_FTYPE (2, (UDI, UQI, UQI))
@@ -60,6 +62,7 @@  DEF_RISCV_FTYPE (3, (USI, USI, UHI, USI))
 DEF_RISCV_FTYPE (3, (USI, USI, HI, USI))
 DEF_RISCV_FTYPE (3, (USI, USI, USI, USI))
 DEF_RISCV_FTYPE (3, (SI, SI, SI, UQI))
+DEF_RISCV_FTYPE (3, (USI, USI, UQI, UQI))
 DEF_RISCV_FTYPE (3, (SI, SI, SI, SI))
 DEF_RISCV_FTYPE (4, (USI, USI, USI, USI, UQI))
 DEF_RISCV_FTYPE (4, (SI, SI, SI, SI, UQI))
diff --git a/gcc/config/riscv/riscv.cc b/gcc/config/riscv/riscv.cc
index b19d56149e7..079de2a40de 100644
--- a/gcc/config/riscv/riscv.cc
+++ b/gcc/config/riscv/riscv.cc
@@ -6735,6 +6735,12 @@  riscv_print_operand (FILE *file, rtx op, int letter)
 	output_addr_const (file, newop);
 	break;
       }
+    case 'W':
+      {
+	rtx newop = GEN_INT (INTVAL (op) & 31);
+	output_addr_const (file, newop);
+	break;
+      }
     case 'X':
       {
 	int ival = INTVAL (op) + 1;
@@ -6750,6 +6756,13 @@  riscv_print_operand (FILE *file, rtx op, int letter)
 	output_addr_const (file, newop);
 	break;
       }
+    case 'Z':
+      {
+	int ival = INTVAL (op) >> 5;
+	rtx newop = GEN_INT (ival & 31);
+	output_addr_const (file, newop);
+	break;
+      }
     default:
       switch (code)
 	{
diff --git a/gcc/config/riscv/riscv.opt b/gcc/config/riscv/riscv.opt
index 2e340e5324f..5b3c9838bc4 100644
--- a/gcc/config/riscv/riscv.opt
+++ b/gcc/config/riscv/riscv.opt
@@ -450,7 +450,6 @@  Mask(ZCMP) Var(riscv_zc_subext)
 
 Mask(ZCMT) Var(riscv_zc_subext)
 
-Mask(XCVBI) Var(riscv_xcv_subext)
 
 TargetVariable
 int riscv_sv_subext
@@ -475,6 +474,10 @@  Mask(XCVELW) Var(riscv_xcv_subext)
 
 Mask(XCVSIMD) Var(riscv_xcv_subext)
 
+Mask(XCVBI) Var(riscv_xcv_subext)
+
+Mask(XCVBITMANIP) Var(riscv_xcv_subext)
+
 TargetVariable
 int riscv_xthead_subext
 
diff --git a/gcc/doc/extend.texi b/gcc/doc/extend.texi
index 48b27ff9f39..ac4f209c6d5 100644
--- a/gcc/doc/extend.texi
+++ b/gcc/doc/extend.texi
@@ -25614,6 +25614,59 @@  Generated assembler @code{cv.sub.div4}
 Generated assembler @code{cv.sub.div8}
 @end deftypefn
 
+These built-in functions are available for the CORE-V bit manipulation machine
+architecture. For more information on CORE-V built-ins, please see
+@uref{https://github.com/openhwgroup/core-v-sw/blob/master/specifications/corev-builtin-spec.md#pulp-bit-manipulation-builtins-for-32-bit-cores}
+
+@deftypefn {Built-in Function} {int32_t} __builtin_riscv_cv_bitmanip_extract (uint32_t, uint16_t)
+Generated assembler @code{cv.extract} if the uint16_t operand is a constant. Generated assembler
+@code{cv.extractr} if the uint16_t operand is a register.
+@end deftypefn
+
+@deftypefn {Built-in Function} {uint32_t} __builtin_riscv_cv_bitmanip_extractu (uint32_t, uint16_t)
+Generated assembler @code{cv.extractu} if the uint16_t operand is a constant. Generated assembler
+@code{cv.extractur} if the uint16_t operand is a register.
+@end deftypefn
+
+@deftypefn {Built-in Function} {uint32_t} __builtin_riscv_cv_bitmanip_insert (uint32_t, uint16_t, uint32_t)
+Generated assembler @code{cv.insert} if the uint16_t operand is a constant. Generated assembler
+@code{cv.insertr} if the uint16_t operand is a register.
+@end deftypefn
+
+@deftypefn {Built-in Function} {uint32_t} __builtin_riscv_cv_bitmanip_bclr (uint32_t, uint16_t)
+Generated assembler @code{cv.bclr} if the uint16_t operand is a constant. Generated assembler
+@code{cv.bclrr} if the uint16_t operand is a register.
+@end deftypefn
+
+@deftypefn {Built-in Function} {uint32_t} __builtin_riscv_cv_bitmanip_bset (uint32_t, uint16_t)
+Generated assembler @code{cv.bset} if the uint16_t operand is a constant. Generated assembler
+@code{cv.bsetr} if the uint16_t operand is a register.
+@end deftypefn
+
+@deftypefn {Built-in Function} {uint8_t} __builtin_riscv_cv_bitmanip_ff1 (uint32_t)
+Generated assembler @code{cv.ff1}
+@end deftypefn
+
+@deftypefn {Built-in Function} {uint8_t} __builtin_riscv_cv_bitmanip_fl1 (uint32_t)
+Generated assembler @code{cv.fl1}
+@end deftypefn
+
+@deftypefn {Built-in Function} {uint8_t} __builtin_riscv_cv_bitmanip_clb (uint32_t)
+Generated assembler @code{cv.clb}
+@end deftypefn
+
+@deftypefn {Built-in Function} {uint8_t} __builtin_riscv_cv_bitmanip_cnt (uint32_t)
+Generated assembler @code{cv.cnt}
+@end deftypefn
+
+@deftypefn {Built-in Function} {uint32_t} __builtin_riscv_cv_bitmanip_ror (uint32_t, uint32_t)
+Generated assembler @code{cv.ror}
+@end deftypefn
+
+@deftypefn {Built-in Function} {uint32_t} __builtin_riscv_cv_bitmanip_bitrev (uint32_t, uint8_t, uint8_t)
+Generated assembler @code{cv.bitrev}
+@end deftypefn
+
 @node RX Built-in Functions
 @subsection RX Built-in Functions
 GCC supports some of the RX instructions which cannot be expressed in
diff --git a/gcc/doc/sourcebuild.texi b/gcc/doc/sourcebuild.texi
index d5c48e67b71..ef78399840c 100644
--- a/gcc/doc/sourcebuild.texi
+++ b/gcc/doc/sourcebuild.texi
@@ -2560,6 +2560,9 @@  Test system has support for the CORE-V SIMD extension.
 @item cv_bi
 Test system has support for the CORE-V BI extension.
 
+@item cv_bitmanip
+Test system has support for the CORE-V BITMANIP extension.
+
 @end table
 
 @subsubsection Other hardware attributes
diff --git a/gcc/testsuite/gcc.target/riscv/cv-bitmanip-compile-bclr.c b/gcc/testsuite/gcc.target/riscv/cv-bitmanip-compile-bclr.c
new file mode 100644
index 00000000000..0cb2c6c5b81
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/cv-bitmanip-compile-bclr.c
@@ -0,0 +1,27 @@ 
+/* { dg-do compile } */
+/* { dg-require-effective-target cv_bitmanip } */
+/* { dg-options "-march=rv32i_xcvbitmanip -mabi=ilp32" } */
+
+#include <stdint.h>
+#include <stdio.h>
+
+extern uint32_t res1;
+extern uint32_t res2;
+extern uint32_t res3;
+extern uint32_t res4;
+
+uint32_t
+foo (uint32_t a)
+{
+  res1 = __builtin_riscv_cv_bitmanip_bclr (a, 200);
+  res2 = __builtin_riscv_cv_bitmanip_bclr (a, 0);
+  res3 = __builtin_riscv_cv_bitmanip_bclr (a, 31);
+  res4 = __builtin_riscv_cv_bitmanip_bclr (a, 1023);
+
+  return res1 + res2 + res3 + res4;
+}
+
+/* { dg-final { scan-assembler-times "cv\.bclr\t\(\?\:t\[0-6\]\|a\[0-7\]\|s\[1-11\]\),\(\?\:t\[0-6\]\|a\[0-7\]\|s\[1-11\]\),6,8" 1 } } */
+/* { dg-final { scan-assembler-times "cv\.bclr\t\(\?\:t\[0-6\]\|a\[0-7\]\|s\[1-11\]\),\(\?\:t\[0-6\]\|a\[0-7\]\|s\[1-11\]\),0,0" 1 { target { any-opts "-O0" } } } } */
+/* { dg-final { scan-assembler-times "cv\.bclr\t\(\?\:t\[0-6\]\|a\[0-7\]\|s\[1-11\]\),\(\?\:t\[0-6\]\|a\[0-7\]\|s\[1-11\]\),0,31" 1 } } */
+/* { dg-final { scan-assembler-times "cv\.bclr\t\(\?\:t\[0-6\]\|a\[0-7\]\|s\[1-11\]\),\(\?\:t\[0-6\]\|a\[0-7\]\|s\[1-11\]\),31,31" 1 { target { any-opts "-O0" } } } } */
diff --git a/gcc/testsuite/gcc.target/riscv/cv-bitmanip-compile-bclrr.c b/gcc/testsuite/gcc.target/riscv/cv-bitmanip-compile-bclrr.c
new file mode 100644
index 00000000000..211a76a470e
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/cv-bitmanip-compile-bclrr.c
@@ -0,0 +1,18 @@ 
+/* { dg-do compile } */
+/* { dg-require-effective-target cv_bitmanip } */
+/* { dg-options "-march=rv32i_xcvbitmanip -mabi=ilp32" } */
+
+#include <stdint.h>
+#include <stdio.h>
+
+extern uint32_t res1;
+
+uint32_t
+foo (uint32_t a, uint16_t b)
+{
+  res1 = __builtin_riscv_cv_bitmanip_bclr (a, b);
+
+  return res1;
+}
+
+/* { dg-final { scan-assembler-times "cv\.bclrr\t\(\?\:t\[0-6\]\|a\[0-7\]\|s\[1-11\]\),\(\?\:t\[0-6\]\|a\[0-7\]\|s\[1-11\]\),\(\?\:t\[0-6\]\|a\[0-7\]\|s\[1-11\]\)" 1 } } */
diff --git a/gcc/testsuite/gcc.target/riscv/cv-bitmanip-compile-bitrev.c b/gcc/testsuite/gcc.target/riscv/cv-bitmanip-compile-bitrev.c
new file mode 100644
index 00000000000..89af9eacbb2
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/cv-bitmanip-compile-bitrev.c
@@ -0,0 +1,30 @@ 
+/* { dg-do compile } */
+/* { dg-require-effective-target cv_bitmanip } */
+/* { dg-options "-march=rv32i_xcvbitmanip -mabi=ilp32" } */
+
+#include <stdint.h>
+#include <stdio.h>
+
+extern uint32_t res1;
+extern uint32_t res2;
+extern uint32_t res3;
+extern uint32_t res4;
+extern uint32_t res5;
+
+uint32_t
+foo (uint32_t a)
+{
+  res1 = __builtin_riscv_cv_bitmanip_bitrev (a, 20, 2);
+  res2 = __builtin_riscv_cv_bitmanip_bitrev (a, 0, 0);
+  res3 = __builtin_riscv_cv_bitmanip_bitrev (a, 31, 0);
+  res4 = __builtin_riscv_cv_bitmanip_bitrev (a, 0, 3);
+  res5 = __builtin_riscv_cv_bitmanip_bitrev (a, 31, 3);
+
+  return res1 + res2 + res3 + res4 + res5;
+}
+
+/* { dg-final { scan-assembler-times "cv\.bitrev\t\(\?\:t\[0-6\]\|a\[0-7\]\|s\[1-11\]\),\(\?\:t\[0-6\]\|a\[0-7\]\|s\[1-11\]\),2,20" 1 } } */
+/* { dg-final { scan-assembler-times "cv\.bitrev\t\(\?\:t\[0-6\]\|a\[0-7\]\|s\[1-11\]\),\(\?\:t\[0-6\]\|a\[0-7\]\|s\[1-11\]\),0,0" 1 } } */
+/* { dg-final { scan-assembler-times "cv\.bitrev\t\(\?\:t\[0-6\]\|a\[0-7\]\|s\[1-11\]\),\(\?\:t\[0-6\]\|a\[0-7\]\|s\[1-11\]\),0,31" 1 } } */
+/* { dg-final { scan-assembler-times "cv\.bitrev\t\(\?\:t\[0-6\]\|a\[0-7\]\|s\[1-11\]\),\(\?\:t\[0-6\]\|a\[0-7\]\|s\[1-11\]\),3,0" 1 } } */
+/* { dg-final { scan-assembler-times "cv\.bitrev\t\(\?\:t\[0-6\]\|a\[0-7\]\|s\[1-11\]\),\(\?\:t\[0-6\]\|a\[0-7\]\|s\[1-11\]\),3,31" 1 } } */
diff --git a/gcc/testsuite/gcc.target/riscv/cv-bitmanip-compile-bset.c b/gcc/testsuite/gcc.target/riscv/cv-bitmanip-compile-bset.c
new file mode 100644
index 00000000000..72970123700
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/cv-bitmanip-compile-bset.c
@@ -0,0 +1,27 @@ 
+/* { dg-do compile } */
+/* { dg-require-effective-target cv_bitmanip } */
+/* { dg-options "-march=rv32i_xcvbitmanip -mabi=ilp32" } */
+
+#include <stdint.h>
+#include <stdio.h>
+
+extern uint32_t res1;
+extern uint32_t res2;
+extern uint32_t res3;
+extern uint32_t res4;
+
+uint32_t
+foo (uint32_t a)
+{
+  res1 = __builtin_riscv_cv_bitmanip_bset (a, 200);
+  res2 = __builtin_riscv_cv_bitmanip_bset (a, 0);
+  res3 = __builtin_riscv_cv_bitmanip_bset (a, 31);
+  res4 = __builtin_riscv_cv_bitmanip_bset (a, 1023);
+
+  return res1 + res2 + res3 + res4;
+}
+
+/* { dg-final { scan-assembler-times "cv\.bset\t\(\?\:t\[0-6\]\|a\[0-7\]\|s\[1-11\]\),\(\?\:t\[0-6\]\|a\[0-7\]\|s\[1-11\]\),6,8" 1 } } */
+/* { dg-final { scan-assembler-times "cv\.bset\t\(\?\:t\[0-6\]\|a\[0-7\]\|s\[1-11\]\),\(\?\:t\[0-6\]\|a\[0-7\]\|s\[1-11\]\),0,0" 1 { target { any-opts "-O0" } } } } */
+/* { dg-final { scan-assembler-times "cv\.bset\t\(\?\:t\[0-6\]\|a\[0-7\]\|s\[1-11\]\),\(\?\:t\[0-6\]\|a\[0-7\]\|s\[1-11\]\),0,31" 1 } } */
+/* { dg-final { scan-assembler-times "cv\.bset\t\(\?\:t\[0-6\]\|a\[0-7\]\|s\[1-11\]\),\(\?\:t\[0-6\]\|a\[0-7\]\|s\[1-11\]\),31,31" 1 } } */
diff --git a/gcc/testsuite/gcc.target/riscv/cv-bitmanip-compile-bsetr.c b/gcc/testsuite/gcc.target/riscv/cv-bitmanip-compile-bsetr.c
new file mode 100644
index 00000000000..6e3790a9e91
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/cv-bitmanip-compile-bsetr.c
@@ -0,0 +1,18 @@ 
+/* { dg-do compile } */
+/* { dg-require-effective-target cv_bitmanip } */
+/* { dg-options "-march=rv32i_xcvbitmanip -mabi=ilp32" } */
+
+#include <stdint.h>
+#include <stdio.h>
+
+extern uint32_t res1;
+
+uint32_t
+foo (uint32_t a, uint16_t b)
+{
+  res1 = __builtin_riscv_cv_bitmanip_bset (a, b);
+
+  return res1;
+}
+
+/* { dg-final { scan-assembler-times "cv\.bsetr\t\(\?\:t\[0-6\]\|a\[0-7\]\|s\[1-11\]\),\(\?\:t\[0-6\]\|a\[0-7\]\|s\[1-11\]\),\(\?\:t\[0-6\]\|a\[0-7\]\|s\[1-11\]\)" 1 } } */
diff --git a/gcc/testsuite/gcc.target/riscv/cv-bitmanip-compile-clb.c b/gcc/testsuite/gcc.target/riscv/cv-bitmanip-compile-clb.c
new file mode 100644
index 00000000000..34a2784a6af
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/cv-bitmanip-compile-clb.c
@@ -0,0 +1,18 @@ 
+/* { dg-do compile } */
+/* { dg-require-effective-target cv_bitmanip } */
+/* { dg-options "-march=rv32i_xcvbitmanip -mabi=ilp32" } */
+
+#include <stdint.h>
+#include <stdio.h>
+
+extern uint8_t res1;
+
+uint8_t
+foo (uint32_t a)
+{
+  res1 = __builtin_riscv_cv_bitmanip_clb (a);
+
+  return res1;
+}
+
+/* { dg-final { scan-assembler-times "cv\.clb\t\(\?\:t\[0-6\]\|a\[0-7\]\|s\[1-11\]\),\(\?\:t\[0-6\]\|a\[0-7\]\|s\[1-11\]\)" 1 } } */
diff --git a/gcc/testsuite/gcc.target/riscv/cv-bitmanip-compile-cnt.c b/gcc/testsuite/gcc.target/riscv/cv-bitmanip-compile-cnt.c
new file mode 100644
index 00000000000..dd9398c45c1
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/cv-bitmanip-compile-cnt.c
@@ -0,0 +1,18 @@ 
+/* { dg-do compile } */
+/* { dg-require-effective-target cv_bitmanip } */
+/* { dg-options "-march=rv32i_xcvbitmanip -mabi=ilp32" } */
+
+#include <stdint.h>
+#include <stdio.h>
+
+extern uint8_t res1;
+
+uint8_t
+foo (uint32_t a)
+{
+  res1 = __builtin_riscv_cv_bitmanip_cnt (a);
+
+  return res1;
+}
+
+/* { dg-final { scan-assembler-times "cv\.cnt\t\(\?\:t\[0-6\]\|a\[0-7\]\|s\[1-11\]\),\(\?\:t\[0-6\]\|a\[0-7\]\|s\[1-11\]\)" 1 } } */
diff --git a/gcc/testsuite/gcc.target/riscv/cv-bitmanip-compile-extract.c b/gcc/testsuite/gcc.target/riscv/cv-bitmanip-compile-extract.c
new file mode 100644
index 00000000000..09ddbbb76ee
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/cv-bitmanip-compile-extract.c
@@ -0,0 +1,27 @@ 
+/* { dg-do compile } */
+/* { dg-require-effective-target cv_bitmanip } */
+/* { dg-options "-march=rv32i_xcvbitmanip -mabi=ilp32" } */
+
+#include <stdint.h>
+#include <stdio.h>
+
+extern int32_t res1;
+extern int32_t res2;
+extern int32_t res3;
+extern int32_t res4;
+
+int32_t
+foo (int32_t a)
+{
+  res1 = __builtin_riscv_cv_bitmanip_extract (a, 200);
+  res2 = __builtin_riscv_cv_bitmanip_extract (a, 0);
+  res3 = __builtin_riscv_cv_bitmanip_extract (a, 31);
+  res4 = __builtin_riscv_cv_bitmanip_extract (a, 1023);
+
+  return res1 + res2 + res3 + res4;
+}
+
+/* { dg-final { scan-assembler-times "cv\.extract\t\(\?\:t\[0-6\]\|a\[0-7\]\|s\[1-11\]\),\(\?\:t\[0-6\]\|a\[0-7\]\|s\[1-11\]\),6,8" 1 } } */
+/* { dg-final { scan-assembler-times "cv\.extract\t\(\?\:t\[0-6\]\|a\[0-7\]\|s\[1-11\]\),\(\?\:t\[0-6\]\|a\[0-7\]\|s\[1-11\]\),0,0" 1 { target { any-opts "-O0" } } } } */
+/* { dg-final { scan-assembler-times "cv\.extract\t\(\?\:t\[0-6\]\|a\[0-7\]\|s\[1-11\]\),\(\?\:t\[0-6\]\|a\[0-7\]\|s\[1-11\]\),0,31" 1 } } */
+/* { dg-final { scan-assembler-times "cv\.extract\t\(\?\:t\[0-6\]\|a\[0-7\]\|s\[1-11\]\),\(\?\:t\[0-6\]\|a\[0-7\]\|s\[1-11\]\),31,31" 1 } } */
diff --git a/gcc/testsuite/gcc.target/riscv/cv-bitmanip-compile-extractr.c b/gcc/testsuite/gcc.target/riscv/cv-bitmanip-compile-extractr.c
new file mode 100644
index 00000000000..3b935c53ac5
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/cv-bitmanip-compile-extractr.c
@@ -0,0 +1,18 @@ 
+/* { dg-do compile } */
+/* { dg-require-effective-target cv_bitmanip } */
+/* { dg-options "-march=rv32i_xcvbitmanip -mabi=ilp32" } */
+
+#include <stdint.h>
+#include <stdio.h>
+
+extern int32_t res1;
+
+int32_t
+foo (int32_t a, uint16_t b)
+{
+  res1 = __builtin_riscv_cv_bitmanip_extract (a, b);
+
+  return res1;
+}
+
+/* { dg-final { scan-assembler-times "cv\.extractr\t\(\?\:t\[0-6\]\|a\[0-7\]\|s\[1-11\]\),\(\?\:t\[0-6\]\|a\[0-7\]\|s\[1-11\]\),\(\?\:t\[0-6\]\|a\[0-7\]\|s\[1-11\]\)" 1 } } */
diff --git a/gcc/testsuite/gcc.target/riscv/cv-bitmanip-compile-extractu.c b/gcc/testsuite/gcc.target/riscv/cv-bitmanip-compile-extractu.c
new file mode 100644
index 00000000000..cbe494c0968
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/cv-bitmanip-compile-extractu.c
@@ -0,0 +1,27 @@ 
+/* { dg-do compile } */
+/* { dg-require-effective-target cv_bitmanip } */
+/* { dg-options "-march=rv32i_xcvbitmanip -mabi=ilp32" } */
+
+#include <stdint.h>
+#include <stdio.h>
+
+extern uint32_t res1;
+extern uint32_t res2;
+extern uint32_t res3;
+extern uint32_t res4;
+
+uint32_t
+foo (uint32_t a)
+{
+  res1 = __builtin_riscv_cv_bitmanip_extractu (a, 200);
+  res2 = __builtin_riscv_cv_bitmanip_extractu (a, 0);
+  res3 = __builtin_riscv_cv_bitmanip_extractu (a, 31);
+  res4 = __builtin_riscv_cv_bitmanip_extractu (a, 1023);
+
+  return res1 + res2 + res3 + res4;
+}
+
+/* { dg-final { scan-assembler-times "cv\.extractu\t\(\?\:t\[0-6\]\|a\[0-7\]\|s\[1-11\]\),\(\?\:t\[0-6\]\|a\[0-7\]\|s\[1-11\]\),6,8" 1 } } */
+/* { dg-final { scan-assembler-times "cv\.extractu\t\(\?\:t\[0-6\]\|a\[0-7\]\|s\[1-11\]\),\(\?\:t\[0-6\]\|a\[0-7\]\|s\[1-11\]\),0,0" 1 { target { any-opts "-O0" } } } } */
+/* { dg-final { scan-assembler-times "cv\.extractu\t\(\?\:t\[0-6\]\|a\[0-7\]\|s\[1-11\]\),\(\?\:t\[0-6\]\|a\[0-7\]\|s\[1-11\]\),0,31" 1 } } */
+/* { dg-final { scan-assembler-times "cv\.extractu\t\(\?\:t\[0-6\]\|a\[0-7\]\|s\[1-11\]\),\(\?\:t\[0-6\]\|a\[0-7\]\|s\[1-11\]\),31,31" 1 } } */
diff --git a/gcc/testsuite/gcc.target/riscv/cv-bitmanip-compile-extractur.c b/gcc/testsuite/gcc.target/riscv/cv-bitmanip-compile-extractur.c
new file mode 100644
index 00000000000..742803ecc19
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/cv-bitmanip-compile-extractur.c
@@ -0,0 +1,18 @@ 
+/* { dg-do compile } */
+/* { dg-require-effective-target cv_bitmanip } */
+/* { dg-options "-march=rv32i_xcvbitmanip -mabi=ilp32" } */
+
+#include <stdint.h>
+#include <stdio.h>
+
+extern uint32_t res1;
+
+uint32_t
+foo (uint32_t a, uint16_t b)
+{
+  res1 = __builtin_riscv_cv_bitmanip_extractu (a, b);
+
+  return res1;
+}
+
+/* { dg-final { scan-assembler-times "cv\.extractur\t\(\?\:t\[0-6\]\|a\[0-7\]\|s\[1-11\]\),\(\?\:t\[0-6\]\|a\[0-7\]\|s\[1-11\]\),\(\?\:t\[0-6\]\|a\[0-7\]\|s\[1-11\]\)" 1 } } */
diff --git a/gcc/testsuite/gcc.target/riscv/cv-bitmanip-compile-ff1.c b/gcc/testsuite/gcc.target/riscv/cv-bitmanip-compile-ff1.c
new file mode 100644
index 00000000000..eab4e4df7f7
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/cv-bitmanip-compile-ff1.c
@@ -0,0 +1,18 @@ 
+/* { dg-do compile } */
+/* { dg-require-effective-target cv_bitmanip } */
+/* { dg-options "-march=rv32i_xcvbitmanip -mabi=ilp32" } */
+
+#include <stdint.h>
+#include <stdio.h>
+
+extern uint8_t res1;
+
+uint8_t
+foo (uint32_t a)
+{
+  res1 = __builtin_riscv_cv_bitmanip_ff1 (a);
+
+  return res1;
+}
+
+/* { dg-final { scan-assembler-times "cv\.ff1\t\(\?\:t\[0-6\]\|a\[0-7\]\|s\[1-11\]\),\(\?\:t\[0-6\]\|a\[0-7\]\|s\[1-11\]\)" 1 } } */
diff --git a/gcc/testsuite/gcc.target/riscv/cv-bitmanip-compile-fl1.c b/gcc/testsuite/gcc.target/riscv/cv-bitmanip-compile-fl1.c
new file mode 100644
index 00000000000..2ea8686d2e2
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/cv-bitmanip-compile-fl1.c
@@ -0,0 +1,18 @@ 
+/* { dg-do compile } */
+/* { dg-require-effective-target cv_bitmanip } */
+/* { dg-options "-march=rv32i_xcvbitmanip -mabi=ilp32" } */
+
+#include <stdint.h>
+#include <stdio.h>
+
+extern uint8_t res1;
+
+uint8_t
+foo (uint32_t a)
+{
+  res1 = __builtin_riscv_cv_bitmanip_fl1 (a);
+
+  return res1;
+}
+
+/* { dg-final { scan-assembler-times "cv\.fl1\t\(\?\:t\[0-6\]\|a\[0-7\]\|s\[1-11\]\),\(\?\:t\[0-6\]\|a\[0-7\]\|s\[1-11\]\)" 1 } } */
diff --git a/gcc/testsuite/gcc.target/riscv/cv-bitmanip-compile-insert.c b/gcc/testsuite/gcc.target/riscv/cv-bitmanip-compile-insert.c
new file mode 100644
index 00000000000..de58df9e3f2
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/cv-bitmanip-compile-insert.c
@@ -0,0 +1,24 @@ 
+/* { dg-do compile } */
+/* { dg-require-effective-target cv_bitmanip } */
+/* { dg-options "-march=rv32i_xcvbitmanip -mabi=ilp32" } */
+
+#include <stdint.h>
+#include <stdio.h>
+
+extern uint32_t res1;
+extern uint32_t res2;
+extern uint32_t res3;
+
+uint32_t
+foo (uint32_t a, uint32_t b)
+{
+  res1 = __builtin_riscv_cv_bitmanip_insert (a, 200, b);
+  res2 = __builtin_riscv_cv_bitmanip_insert (a, 0, b);
+  res3 = __builtin_riscv_cv_bitmanip_insert (a, 31, b);
+
+  return res1 + res2 + res3;
+}
+
+/* { dg-final { scan-assembler-times "cv\.insert\t\(\?\:t\[0-6\]\|a\[0-7\]\|s\[1-11\]\),\(\?\:t\[0-6\]\|a\[0-7\]\|s\[1-11\]\),6,8" 1 } } */
+/* { dg-final { scan-assembler-times "cv\.insert\t\(\?\:t\[0-6\]\|a\[0-7\]\|s\[1-11\]\),\(\?\:t\[0-6\]\|a\[0-7\]\|s\[1-11\]\),0,0" 1 } } */
+/* { dg-final { scan-assembler-times "cv\.insert\t\(\?\:t\[0-6\]\|a\[0-7\]\|s\[1-11\]\),\(\?\:t\[0-6\]\|a\[0-7\]\|s\[1-11\]\),0,31" 1 } } */
diff --git a/gcc/testsuite/gcc.target/riscv/cv-bitmanip-compile-insertr.c b/gcc/testsuite/gcc.target/riscv/cv-bitmanip-compile-insertr.c
new file mode 100644
index 00000000000..9b67c64ccd0
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/cv-bitmanip-compile-insertr.c
@@ -0,0 +1,18 @@ 
+/* { dg-do compile } */
+/* { dg-require-effective-target cv_bitmanip } */
+/* { dg-options "-march=rv32i_xcvbitmanip -mabi=ilp32" } */
+
+#include <stdint.h>
+#include <stdio.h>
+
+extern uint32_t res1;
+
+uint32_t
+foo (uint32_t a, uint16_t b, uint32_t c)
+{
+  res1 = __builtin_riscv_cv_bitmanip_insert (a, b, c);
+
+  return res1;
+}
+
+/* { dg-final { scan-assembler-times "cv\.insertr\t\(\?\:t\[0-6\]\|a\[0-7\]\|s\[1-11\]\),\(\?\:t\[0-6\]\|a\[0-7\]\|s\[1-11\]\),\(\?\:t\[0-6\]\|a\[0-7\]\|s\[1-11\]\)" 1 } } */
diff --git a/gcc/testsuite/gcc.target/riscv/cv-bitmanip-compile-ror.c b/gcc/testsuite/gcc.target/riscv/cv-bitmanip-compile-ror.c
new file mode 100644
index 00000000000..67de86306bf
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/cv-bitmanip-compile-ror.c
@@ -0,0 +1,18 @@ 
+/* { dg-do compile } */
+/* { dg-require-effective-target cv_bitmanip } */
+/* { dg-options "-march=rv32i_xcvbitmanip -mabi=ilp32" } */
+
+#include <stdint.h>
+#include <stdio.h>
+
+extern uint32_t res1;
+
+uint32_t
+foo (uint32_t a, uint32_t b)
+{
+  res1 = __builtin_riscv_cv_bitmanip_ror (a, b);
+
+  return res1;
+}
+
+/* { dg-final { scan-assembler-times "cv\.ror\t\(\?\:t\[0-6\]\|a\[0-7\]\|s\[1-11\]\),\(\?\:t\[0-6\]\|a\[0-7\]\|s\[1-11\]\),\(\?\:t\[0-6\]\|a\[0-7\]\|s\[1-11\]\)" 1 } } */
diff --git a/gcc/testsuite/gcc.target/riscv/cv-bitmanip-fail-compile-bclr.c b/gcc/testsuite/gcc.target/riscv/cv-bitmanip-fail-compile-bclr.c
new file mode 100644
index 00000000000..12aca4ed945
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/cv-bitmanip-fail-compile-bclr.c
@@ -0,0 +1,25 @@ 
+/* { dg-do compile } */
+/* { dg-require-effective-target cv_bitmanip } */
+/* { dg-options "-march=rv32i_xcvbitmanip -mabi=ilp32" } */
+/* { dg-skip-if "Skip LTO tests of builtin compilation" { *-*-* } { "-flto" } } */
+
+#include <stdint.h>
+#include <stdio.h>
+
+extern uint32_t res1, res2, res3, res4, res5, res6;
+
+uint32_t
+foo (void)
+{
+  res1 = __builtin_riscv_cv_bitmanip_bclr (648, -1);
+  res2 = __builtin_riscv_cv_bitmanip_bclr (648, 1);
+  res3 = __builtin_riscv_cv_bitmanip_bclr (648, 4);
+  res4 = __builtin_riscv_cv_bitmanip_bclr (684, 1023);
+  res5 = __builtin_riscv_cv_bitmanip_bclr (648, 1024);
+  res6 = __builtin_riscv_cv_bitmanip_bclr (648, 65536); /* { dg-warning "unsigned conversion from \'int\' to \'short unsigned int\' changes value from \'65536\' to \'0\'" "" { target *-*-* } } */
+
+  return res1 + res2 + res3 + res4 + res5 + res6;
+}
+
+/* { dg-final { scan-assembler-times "cv\.bclr\t" 4 { target { any-opts "-O0" } } } } */
+/* { dg-final { scan-assembler-times "cv\.bclrr\t" 2 { target { any-opts "-O0" } } } } */
diff --git a/gcc/testsuite/gcc.target/riscv/cv-bitmanip-fail-compile-bitrev.c b/gcc/testsuite/gcc.target/riscv/cv-bitmanip-fail-compile-bitrev.c
new file mode 100644
index 00000000000..33650dd2e2d
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/cv-bitmanip-fail-compile-bitrev.c
@@ -0,0 +1,23 @@ 
+/* { dg-do compile } */
+/* { dg-require-effective-target cv_bitmanip } */
+/* { dg-options "-march=rv32i_xcvbitmanip -mabi=ilp32" } */
+/* { dg-skip-if "Skip LTO tests of builtin compilation" { *-*-* } { "-flto" } } */
+
+#include <stdint.h>
+#include <stdio.h>
+
+extern uint32_t res1;
+extern uint32_t res2;
+extern uint32_t res3;
+extern uint32_t res4;
+
+uint32_t
+foo (void)
+{
+  res1 = __builtin_riscv_cv_bitmanip_bitrev (648, 0, -1); /* { dg-error "invalid argument to built-in function" "" { target *-*-* } } */
+  res2 = __builtin_riscv_cv_bitmanip_bitrev (648, -1, 0); /* { dg-error "invalid argument to built-in function" "" { target *-*-* } } */
+  res3 = __builtin_riscv_cv_bitmanip_bitrev (648, 21, 4); /* { dg-error "invalid argument to built-in function" "" { target *-*-* } } */
+  res4 = __builtin_riscv_cv_bitmanip_bitrev (648, 32, 2); /* { dg-error "invalid argument to built-in function" "" { target *-*-* } } */
+
+  return res1+res2+res3+res4;
+}
diff --git a/gcc/testsuite/gcc.target/riscv/cv-bitmanip-fail-compile-bset.c b/gcc/testsuite/gcc.target/riscv/cv-bitmanip-fail-compile-bset.c
new file mode 100644
index 00000000000..e16cc4915ea
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/cv-bitmanip-fail-compile-bset.c
@@ -0,0 +1,25 @@ 
+/* { dg-do compile } */
+/* { dg-require-effective-target cv_bitmanip } */
+/* { dg-options "-march=rv32i_xcvbitmanip -mabi=ilp32" } */
+/* { dg-skip-if "Skip LTO tests of builtin compilation" { *-*-* } { "-flto" } } */
+
+#include <stdint.h>
+#include <stdio.h>
+
+extern uint32_t res1, res2, res3, res4, res5, res6;
+
+uint32_t
+foo (void)
+{
+  res1 = __builtin_riscv_cv_bitmanip_bset (648, -1);
+  res2 = __builtin_riscv_cv_bitmanip_bset (648, 1);
+  res3 = __builtin_riscv_cv_bitmanip_bset (648, 4);
+  res4 = __builtin_riscv_cv_bitmanip_bset (648, 1023);
+  res5 = __builtin_riscv_cv_bitmanip_bset (648, 1024);
+  res6 = __builtin_riscv_cv_bitmanip_bset (648, 65536); /* { dg-warning "unsigned conversion from \'int\' to \'short unsigned int\' changes value from \'65536\' to \'0\'" "" { target *-*-* } } */
+
+  return res1 + res2 + res3 + res4 + res5 + res6;
+}
+
+/* { dg-final { scan-assembler-times "cv\.bset\t" 4 { target { any-opts "-O0" } } } } */
+/* { dg-final { scan-assembler-times "cv\.bsetr\t" 2 { target { any-opts "-O0" } }  } } */
diff --git a/gcc/testsuite/gcc.target/riscv/cv-bitmanip-fail-compile-extract.c b/gcc/testsuite/gcc.target/riscv/cv-bitmanip-fail-compile-extract.c
new file mode 100644
index 00000000000..1dcef511670
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/cv-bitmanip-fail-compile-extract.c
@@ -0,0 +1,25 @@ 
+/* { dg-do compile } */
+/* { dg-require-effective-target cv_bitmanip } */
+/* { dg-options "-march=rv32i_xcvbitmanip -mabi=ilp32" } */
+/* { dg-skip-if "Skip LTO tests of builtin compilation" { *-*-* } { "-flto" } } */
+
+#include <stdint.h>
+#include <stdio.h>
+
+extern uint32_t res1, res2, res3, res4, res5, res6;
+
+uint32_t
+foo (void)
+{
+  res1 = __builtin_riscv_cv_bitmanip_extract (648, -1);
+  res2 = __builtin_riscv_cv_bitmanip_extract (648, 1);
+  res3 = __builtin_riscv_cv_bitmanip_extract (648, 230);
+  res4 = __builtin_riscv_cv_bitmanip_extract (648, 1023);
+  res5 = __builtin_riscv_cv_bitmanip_extract (648, 1024);
+  res6 =  __builtin_riscv_cv_bitmanip_extract (648, 65536); /* { dg-warning "unsigned conversion from \'int\' to \'short unsigned int\' changes value from \'65536\' to \'0\'" "" { target *-*-* } } */
+
+  return res1 + res2 + res3 + res4 + res5 + res6;
+}
+
+/* { dg-final { scan-assembler-times "cv\.extract\t" 4 { target { any-opts "-O0" } } } } */
+/* { dg-final { scan-assembler-times "cv\.extractr\t" 2 { target { any-opts "-O0" } } } } */
diff --git a/gcc/testsuite/gcc.target/riscv/cv-bitmanip-fail-compile-extractu.c b/gcc/testsuite/gcc.target/riscv/cv-bitmanip-fail-compile-extractu.c
new file mode 100644
index 00000000000..fbb44cbd3ee
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/cv-bitmanip-fail-compile-extractu.c
@@ -0,0 +1,25 @@ 
+/* { dg-do compile } */
+/* { dg-require-effective-target cv_bitmanip } */
+/* { dg-options "-march=rv32i_xcvbitmanip -mabi=ilp32" } */
+/* { dg-skip-if "Skip LTO tests of builtin compilation" { *-*-* } { "-flto" } } */
+
+#include <stdint.h>
+#include <stdio.h>
+
+extern uint32_t res1, res2, res3, res4, res5, res6;
+
+uint32_t
+foo (void)
+{
+  res1 = __builtin_riscv_cv_bitmanip_extractu (648, -1);
+  res2 = __builtin_riscv_cv_bitmanip_extractu (648, 1);
+  res3 = __builtin_riscv_cv_bitmanip_extractu (648, 230);
+  res4 = __builtin_riscv_cv_bitmanip_extractu (648, 1023);
+  res5 = __builtin_riscv_cv_bitmanip_extractu (648, 1024);
+  res6 =  __builtin_riscv_cv_bitmanip_extractu (648, 65536); /* { dg-warning "unsigned conversion from \'int\' to \'short unsigned int\' changes value from \'65536\' to \'0\'" "" { target *-*-* } } */
+
+  return res1 + res2 + res3 + res4 + res5 + res6;
+}
+
+/* { dg-final { scan-assembler-times "cv\.extractu\t" 4 { target { any-opts "-O0" } } } } */
+/* { dg-final { scan-assembler-times "cv\.extractur\t" 2 { target { any-opts "-O0" } } } } */
diff --git a/gcc/testsuite/gcc.target/riscv/cv-bitmanip-fail-compile-insert.c b/gcc/testsuite/gcc.target/riscv/cv-bitmanip-fail-compile-insert.c
new file mode 100644
index 00000000000..47ebec613fb
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/cv-bitmanip-fail-compile-insert.c
@@ -0,0 +1,25 @@ 
+/* { dg-do compile } */
+/* { dg-require-effective-target cv_bitmanip } */
+/* { dg-options "-march=rv32i_xcvbitmanip -mabi=ilp32" } */
+/* { dg-skip-if "Skip LTO tests of builtin compilation" { *-*-* } { "-flto" } } */
+
+#include <stdint.h>
+#include <stdio.h>
+
+extern uint32_t res1, res2, res3, res4, res5, res6;
+
+uint32_t
+foo (void)
+{
+  res1 = __builtin_riscv_cv_bitmanip_insert (648, -1, 645);
+  res2 = __builtin_riscv_cv_bitmanip_insert (648, 1, 645);
+  res3 = __builtin_riscv_cv_bitmanip_insert (648, 200, 645);
+  res4 = __builtin_riscv_cv_bitmanip_insert (1648, 1023, 1645);
+  res5 = __builtin_riscv_cv_bitmanip_insert (1648, 1024, 1645);
+  res6 =  __builtin_riscv_cv_bitmanip_insert (1648, 65536, 1645); /* { dg-warning "unsigned conversion from \'int\' to \'short unsigned int\' changes value from \'65536\' to \'0\'" } */
+
+  return res1 + res2 + res3 + res4 + res5 + res6;
+}
+
+/* { dg-final { scan-assembler-times "cv\.insert\t" 4 { target { any-opts "-O0" } } } } */
+/* { dg-final { scan-assembler-times "cv\.insertr\t" 2 { target { any-opts "-O0" } } } } */
diff --git a/gcc/testsuite/lib/target-supports.exp b/gcc/testsuite/lib/target-supports.exp
index f8e5f5f36d0..917fad731a9 100644
--- a/gcc/testsuite/lib/target-supports.exp
+++ b/gcc/testsuite/lib/target-supports.exp
@@ -13534,6 +13534,19 @@  proc check_effective_target_cv_bi { } {
     } "-march=rv32i_xcvbi" ]
 }
 
+# Return 1 if the CORE-V BITMANIP extension is available.
+proc check_effective_target_cv_bitmanip { } {
+    if { !([istarget riscv*-*-*]) } {
+         return 0
+     }
+    return [check_no_compiler_messages cv_bitmanip object {
+        void foo (void)
+        {
+          asm ("cv.extract t0, t1, 20, 20");
+        }
+    } "-march=rv32i_xcvbitmanip" ]
+}
+
 proc check_effective_target_loongarch_sx { } {
     return [check_no_compiler_messages loongarch_lsx assembly {
        #if !defined(__loongarch_sx)