public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* [PATCH v2 0/1] RISC-V: Support CORE-V XCVBITMAIP extension
       [not found] <20231109105542.4013483-1-mary.bennett@embecosm.com^Cthread>
@ 2024-01-16 16:25 ` Mary Bennett
  2024-01-16 16:25   ` [PATCH v2 1/1] RISC-V: Add support for XCVbitmanip extension in CV32E40P Mary Bennett
  2024-01-22 17:15   ` [PATCH v3 0/1] RISC-V: Support CORE-V XCVBITMAIP extension Mary Bennett
  0 siblings, 2 replies; 7+ messages in thread
From: Mary Bennett @ 2024-01-16 16:25 UTC (permalink / raw)
  To: gcc-patches; +Cc: mary.bennett

v1 -> v2:
 * Updated rtl for bclr, bset, insert and extract[u].

This patch series presents the comprehensive implementation of the BITMANIP
extension for CORE-V.

Tested with riscv-gnu-toolchain on binutils, ld, gas and gcc testsuites to
ensure its correctness and compatibility with the existing codebase.
However, your input, reviews, and suggestions are invaluable in making this
extension even more robust.

The CORE-V builtins are described in the specification [1] and work can be
found in the OpenHW group's Github repository [2].

[1] github.com/openhwgroup/core-v-sw/blob/master/specifications/corev-builtin-spec.md

[2] github.com/openhwgroup/corev-gcc

Contributors:
  Mary Bennett <mary.bennett@embecosm.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>

RISC-V: Add support for XCVbitmanip extension in CV32E40P

 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                     | 164 ++++++++++++++++++
 gcc/config/riscv/predicates.md                |  16 ++
 gcc/config/riscv/riscv-builtins.cc            |   1 +
 gcc/config/riscv/riscv-ftypes.def             |   5 +
 gcc/config/riscv/riscv.cc                     |  13 ++
 gcc/config/riscv/riscv.opt                    |   2 +
 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, 791 insertions(+)
 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

-- 
2.34.1


^ permalink raw reply	[flat|nested] 7+ messages in thread

* [PATCH v2 1/1] RISC-V: Add support for XCVbitmanip extension in CV32E40P
  2024-01-16 16:25 ` [PATCH v2 0/1] RISC-V: Support CORE-V XCVBITMAIP extension Mary Bennett
@ 2024-01-16 16:25   ` Mary Bennett
  2024-01-21 23:21     ` Jeff Law
  2024-01-22 17:15   ` [PATCH v3 0/1] RISC-V: Support CORE-V XCVBITMAIP extension Mary Bennett
  1 sibling, 1 reply; 7+ messages in thread
From: Mary Bennett @ 2024-01-16 16:25 UTC (permalink / raw)
  To: gcc-patches; +Cc: mary.bennett

Spec: github.com/openhwgroup/core-v-sw/blob/master/specifications/corev-builtin-spec.md

Contributors:
  Mary Bennett <mary.bennett@embecosm.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                     | 164 ++++++++++++++++++
 gcc/config/riscv/predicates.md                |  16 ++
 gcc/config/riscv/riscv-builtins.cc            |   1 +
 gcc/config/riscv/riscv-ftypes.def             |   5 +
 gcc/config/riscv/riscv.cc                     |  13 ++
 gcc/config/riscv/riscv.opt                    |   2 +
 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, 791 insertions(+)
 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

diff --git a/gcc/common/config/riscv/riscv-common.cc b/gcc/common/config/riscv/riscv-common.cc
index 0301d170a41..9e7808b8014 100644
--- a/gcc/common/config/riscv/riscv-common.cc
+++ b/gcc/common/config/riscv/riscv-common.cc
@@ -355,6 +355,7 @@ static const struct riscv_ext_version riscv_ext_version_table[] =
   {"xcvmac", ISA_SPEC_CLASS_NONE, 1, 0},
   {"xcvalu", ISA_SPEC_CLASS_NONE, 1, 0},
   {"xcvelw", 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},
@@ -1730,6 +1731,7 @@ static const riscv_ext_flag_table_t riscv_ext_flag_table[] =
   {"xcvmac",        &gcc_options::x_riscv_xcv_subext, MASK_XCVMAC},
   {"xcvalu",        &gcc_options::x_riscv_xcv_subext, MASK_XCVALU},
   {"xcvelw",        &gcc_options::x_riscv_xcv_subext, MASK_XCVELW},
+  {"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 ee1c12b2e51..8923bd431ce 100644
--- a/gcc/config/riscv/constraints.md
+++ b/gcc/config/riscv/constraints.md
@@ -103,6 +103,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"
@@ -262,3 +267,14 @@
   (and (match_code "const_int")
        (and (match_test "IN_RANGE (ival, 0, 1073741823)")
             (match_test "exact_log2 (ival + 1) != -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 3b9ec029d06..509f33b98f8 100644
--- a/gcc/config/riscv/corev.def
+++ b/gcc/config/riscv/corev.def
@@ -44,3 +44,16 @@ RISCV_BUILTIN (cv_alu_subuRN,   "cv_alu_subuRN",RISCV_BUILTIN_DIRECT, RISCV_USI_
 
 // XCVELW
 RISCV_BUILTIN (cv_elw_elw_si, "cv_elw_elw", RISCV_BUILTIN_DIRECT, RISCV_USI_FTYPE_VOID_PTR, cvelw),
+
+// 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_UQI_FTYPE_USI,            cvbitmanip),
+RISCV_BUILTIN (cv_bitmanip_fl1,         "cv_bitmanip_fl1",         RISCV_BUILTIN_DIRECT, RISCV_UQI_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_UQI_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 adad2409fb6..9afd69ec080 100644
--- a/gcc/config/riscv/corev.md
+++ b/gcc/config/riscv/corev.md
@@ -27,6 +27,10 @@
 
   ;;CORE-V EVENT LOAD
   UNSPECV_CV_ELW
+
+  ;;CORE-V BITMANIP
+  UNSPEC_CV_BITMANIP_BITREV
+  UNSPEC_CV_BITMANIP_FL1
 ])
 
 ;; XCVMAC extension.
@@ -706,3 +710,163 @@
 
   [(set_attr "type" "load")
   (set_attr "mode" "SI")])
+
+;; XCVBITMANIP builtins
+
+(define_insn "riscv_cv_bitmanip_extract"
+  [(set (match_operand:SI 0 "register_operand" "=r,r")
+        (sign_extend:SI (and:SI (rotate:SI (ashift:SI (const_int 1)
+                                (ashiftrt:HI
+                                        (match_operand:HI 2 "bit_extract_operand" "CV_bit_si10,r")
+                                        (const_int 5)))
+                        (and:HI (match_dup 2)
+                                (const_int 31)))
+		(match_operand:SI 1 "register_operand" "r,r"))))]
+
+  "TARGET_XCVBITMANIP && !TARGET_64BIT"
+  "@
+   cv.extract\t%0,%1,%Z2,%Y2
+   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_extend:SI (and:SI (rotate:SI (ashift:SI (const_int 1)
+                                (ashiftrt:HI
+                                        (match_operand:HI 2 "bit_extract_operand" "CV_bit_si10,r")
+                                        (const_int 5)))
+                        (and:HI (match_dup 2)
+                                (const_int 31)))
+                (match_operand:SI 1 "register_operand" "r,r"))))]
+
+  "TARGET_XCVBITMANIP && !TARGET_64BIT"
+  "@
+   cv.extractu\t%0,%1,%Z2,%Y2
+   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
+		 (rotate:SI (ashift:SI (const_int -2)
+                                (ashiftrt:HI
+                                        (match_operand:HI 2 "bit_extract_operand" "CV_bit_si10,r")
+                                        (const_int 5)))
+                        (and:HI (match_dup 2)
+                                (const_int 31)))
+		 (match_operand:SI 3 "register_operand" "0,0"))
+		(and:SI
+		 (rotate:SI (ashift:SI (const_int 1)
+                                (ashiftrt:HI
+                                        (match_dup:HI 2)
+                                        (const_int 5)))
+                        (and:HI (match_dup 2)
+                                (const_int 31)))
+		 (match_operand:SI 1 "register_operand" "r,r"))))]
+
+  "TARGET_XCVBITMANIP && !TARGET_64BIT"
+  "@
+   cv.insert\t%0,%1,%Z2,%Y2
+   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 (rotate:SI (ashift:SI (const_int -2)
+				(ashiftrt:HI
+					(match_operand:HI 2 "bit_extract_operand" "CV_bit_si10,r")
+					(const_int 5)))
+			(and:HI (match_dup 2)
+				(const_int 31)))
+               (match_operand:SI 1 "register_operand" "r,r")))]
+
+  "TARGET_XCVBITMANIP && !TARGET_64BIT"
+  "@
+   cv.bclr\t%0,%1,%Z2,%Y2
+   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 (rotate:SI (ashift:SI (const_int 1)
+                                (ashiftrt:HI
+                                        (match_operand:HI 2 "bit_extract_operand" "CV_bit_si10,r")
+                                        (const_int 5)))
+                        (and:HI (match_dup 2)
+                                (const_int 31)))
+               (match_operand:SI 1 "register_operand" "r,r")))]
+
+  "TARGET_XCVBITMANIP && !TARGET_64BIT"
+  "@
+   cv.bset\t%0,%1,%Z2,%Y2
+   cv.bsetr\t%0,%1,%2"
+  [(set_attr "type" "bitmanip")
+  (set_attr "mode" "SI")])
+
+(define_insn "riscv_cv_bitmanip_ff1"
+  [(set (match_operand:QI 0 "register_operand" "=r")
+        (if_then_else (eq:SI (match_operand:SI 1 "register_operand" "r") (const_int 0))
+                      (const_int 32)
+                      (minus:SI (ffs:SI (match_dup 1))
+                                (const_int 1))))]
+
+  "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:QI 0 "register_operand" "=r")
+        (unspec:QI [(match_operand:SI 1 "register_operand" "r")]
+         UNSPEC_CV_BITMANIP_FL1))]
+
+  "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")
+        (if_then_else (eq:SI (match_operand:SI 1 "register_operand" "r") (const_int 0))
+                      (const_int 0)
+                      (truncate:QI (clrsb:SI (match_dup 1)))))]
+
+  "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:QI 0 "register_operand" "=r")
+        (truncate:QI (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 b1a79cae50a..57ac9cb92ae 100644
--- a/gcc/config/riscv/predicates.md
+++ b/gcc/config/riscv/predicates.md
@@ -425,6 +425,22 @@
   (ior (match_operand 0 "register_operand")
        (match_code "const_int")))
 
+(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")
+       (match_test "IN_RANGE (INTVAL (op), 0, 3)")))
+
 ;; Predicates for the V extension.
 (define_special_predicate "vector_length_operand"
   (ior (match_operand 0 "pmode_register_operand")
diff --git a/gcc/config/riscv/riscv-builtins.cc b/gcc/config/riscv/riscv-builtins.cc
index 1932ff069c6..0c3a87f9926 100644
--- a/gcc/config/riscv/riscv-builtins.cc
+++ b/gcc/config/riscv/riscv-builtins.cc
@@ -135,6 +135,7 @@ AVAIL (hint_pause, (!0))
 AVAIL (cvmac, TARGET_XCVMAC && !TARGET_64BIT)
 AVAIL (cvalu, TARGET_XCVALU && !TARGET_64BIT)
 AVAIL (cvelw, TARGET_XCVELW && !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 5f051df2277..5c0ec6c3ed1 100644
--- a/gcc/config/riscv/riscv-ftypes.def
+++ b/gcc/config/riscv/riscv-ftypes.def
@@ -35,10 +35,13 @@ DEF_RISCV_FTYPE (1, (USI, USI))
 DEF_RISCV_FTYPE (1, (UDI, UDI))
 DEF_RISCV_FTYPE (1, (USI, UQI))
 DEF_RISCV_FTYPE (1, (USI, UHI))
+DEF_RISCV_FTYPE (1, (UQI, USI))
 DEF_RISCV_FTYPE (1, (SI, QI))
 DEF_RISCV_FTYPE (1, (SI, HI))
 DEF_RISCV_FTYPE (2, (USI, UQI, UQI))
 DEF_RISCV_FTYPE (2, (USI, UHI, UHI))
+DEF_RISCV_FTYPE (2, (SI, USI, UHI))
+DEF_RISCV_FTYPE (2, (USI, USI, UHI))
 DEF_RISCV_FTYPE (2, (USI, USI, USI))
 DEF_RISCV_FTYPE (2, (USI, USI, UQI))
 DEF_RISCV_FTYPE (2, (UDI, UQI, UQI))
@@ -52,6 +55,8 @@ DEF_RISCV_FTYPE (2, (SI, SI, SI))
 DEF_RISCV_FTYPE (3, (USI, USI, USI, UQI))
 DEF_RISCV_FTYPE (3, (USI, USI, USI, USI))
 DEF_RISCV_FTYPE (3, (SI, SI, SI, UQI))
+DEF_RISCV_FTYPE (3, (USI, USI, UHI, USI))
+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 41626fa34e4..27a183b858e 100644
--- a/gcc/config/riscv/riscv.cc
+++ b/gcc/config/riscv/riscv.cc
@@ -5842,6 +5842,19 @@ riscv_print_operand (FILE *file, rtx op, int letter)
 	output_addr_const (file, newop);
 	break;
       }
+    case 'Y':
+      {
+	rtx newop = GEN_INT (INTVAL (op) & 31);
+	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 44ed6d69da2..0860cfb521c 100644
--- a/gcc/config/riscv/riscv.opt
+++ b/gcc/config/riscv/riscv.opt
@@ -425,6 +425,8 @@ Mask(XCVALU) Var(riscv_xcv_subext)
 
 Mask(XCVELW) 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 b9129d1b464..8a2ba805b40 100644
--- a/gcc/doc/extend.texi
+++ b/gcc/doc/extend.texi
@@ -24407,6 +24407,59 @@ architecture. For more information on CORE-V ELW builtins, please see
 Generated assembler @code{cv.elw}
 @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 8082100a3c9..3795489c9ad 100644
--- a/gcc/doc/sourcebuild.texi
+++ b/gcc/doc/sourcebuild.texi
@@ -2505,6 +2505,9 @@ Test system has support for the CORE-V ALU extension.
 @item cv_elw
 Test system has support for the CORE-V ELW 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..6b40efef2c2
--- /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 } } */
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 fac32fb3d0e..c15d10f1363 100644
--- a/gcc/testsuite/lib/target-supports.exp
+++ b/gcc/testsuite/lib/target-supports.exp
@@ -13345,6 +13345,19 @@ proc check_effective_target_cv_elw { } {
     } "-march=rv32i_xcvelw" ]
 }
 
+# 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)
-- 
2.34.1


^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH v2 1/1] RISC-V: Add support for XCVbitmanip extension in CV32E40P
  2024-01-16 16:25   ` [PATCH v2 1/1] RISC-V: Add support for XCVbitmanip extension in CV32E40P Mary Bennett
@ 2024-01-21 23:21     ` Jeff Law
  0 siblings, 0 replies; 7+ messages in thread
From: Jeff Law @ 2024-01-21 23:21 UTC (permalink / raw)
  To: Mary Bennett, gcc-patches



On 1/16/24 09:25, Mary Bennett wrote:
> Spec: github.com/openhwgroup/core-v-sw/blob/master/specifications/corev-builtin-spec.md
> 
> Contributors:
>    Mary Bennett <mary.bennett@embecosm.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.
> ---




> diff --git a/gcc/config/riscv/corev.md b/gcc/config/riscv/corev.md
> index adad2409fb6..9afd69ec080 100644
> --- a/gcc/config/riscv/corev.md
> +++ b/gcc/config/riscv/corev.md
> @@ -706,3 +710,163 @@
>   
>     [(set_attr "type" "load")
>     (set_attr "mode" "SI")])
> +
> +;; XCVBITMANIP builtins
> +
> +(define_insn "riscv_cv_bitmanip_extract"
> +  [(set (match_operand:SI 0 "register_operand" "=r,r")
> +        (sign_extend:SI (and:SI (rotate:SI (ashift:SI (const_int 1)
> +                                (ashiftrt:HI
> +                                        (match_operand:HI 2 "bit_extract_operand" "CV_bit_si10,r")
> +                                        (const_int 5)))
> +                        (and:HI (match_dup 2)
> +                                (const_int 31)))
> +		(match_operand:SI 1 "register_operand" "r,r"))))]
So it looks like the you've got an ashift:SI where the shift amount of 
the result of an ashiftrt:HI -- note the difference in the modes.  That 
doesn't seem right.  It also looks like the indentation on the RTL 
pattern is wrong -- that ashiftrt is an argument of the ashift:SI, so it 
should line up with the (const_int 1) argument.

It looks like the same issue is repeated on the extractu pattern.  Which 
leads to a second comment.  I think the two patterns can be combined. 
There'a an "any_extend" iterator that you could use in place of the 
sign_extend/zero_extend.  And there's a "u" iterator that you can use in 
the output template to conditionally emit a "u".

The insertion, bclr, and bset patterns seem to be goofy on their modes 
in a similar way.


> +
> +(define_insn "riscv_cv_bitmanip_ff1"
> +  [(set (match_operand:QI 0 "register_operand" "=r")
> +        (if_then_else (eq:SI (match_operand:SI 1 "register_operand" "r") (const_int 0))
> +                      (const_int 32)
> +                      (minus:SI (ffs:SI (match_dup 1))
> +                                (const_int 1))))]
Presumably this is an if-then-else to deal with the case when the input 
value is zero?  Is there any way to use ctz/clz in combination with 
C[LT]Z_DEFINED_VALUE_AT_ZERO instead of ffs with a conditional?

More generally, can we avoid the UNSPECs in here by defining these 
operations in terms of ffs, clz, ctz?


> +
> +(define_insn "riscv_cv_bitmanip_cnt"
> +  [(set (match_operand:QI 0 "register_operand" "=r")
> +        (truncate:QI (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")])
Interesting truncation here?  Does the cv.cnt instruction really just 
write the result in QImode?  Or are you trying to express that the 
number of bits must be in the range 0..32 inclusive?  The former would 
make your code correct, the latter is better left to the generic VRP 
optimizer to discover.


> +
> +(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))]
Note I think there's a bitreverse opcode now.


Jeff

^ permalink raw reply	[flat|nested] 7+ messages in thread

* [PATCH v3 0/1] RISC-V: Support CORE-V XCVBITMAIP extension
  2024-01-16 16:25 ` [PATCH v2 0/1] RISC-V: Support CORE-V XCVBITMAIP extension Mary Bennett
  2024-01-16 16:25   ` [PATCH v2 1/1] RISC-V: Add support for XCVbitmanip extension in CV32E40P Mary Bennett
@ 2024-01-22 17:15   ` Mary Bennett
  2024-01-22 17:15     ` [PATCH v3 1/1] RISC-V: Add support for XCVbitmanip extension in CV32E40P Mary Bennett
  1 sibling, 1 reply; 7+ messages in thread
From: Mary Bennett @ 2024-01-22 17:15 UTC (permalink / raw)
  To: gcc-patches; +Cc: mary.bennett

v2 -> v3:
 * Updated rtl for cnt, ff1, fl1, bclr, bset, insert and extract[u].
 * cv.bitrev requires groups of bits to reverse order. bitreverse does not
   support this.

This patch series presents the comprehensive implementation of the BITMANIP
extension for CORE-V.

Tested with riscv-gnu-toolchain on binutils, ld, gas and gcc testsuites to
ensure its correctness and compatibility with the existing codebase.
However, your input, reviews, and suggestions are invaluable in making this
extension even more robust.

The CORE-V builtins are described in the specification [1] and work can be
found in the OpenHW group's Github repository [2].

[1] github.com/openhwgroup/core-v-sw/blob/master/specifications/corev-builtin-spec.md

[2] github.com/openhwgroup/corev-gcc

Contributors:
  Mary Bennett <mary.bennett@embecosm.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>

RISC-V: Add support for XCVbitmanip extension in CV32E40P

 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                     | 184 ++++++++++++++++++
 gcc/config/riscv/predicates.md                |  16 ++
 gcc/config/riscv/riscv-builtins.cc            |   1 +
 gcc/config/riscv/riscv-ftypes.def             |   5 +
 gcc/config/riscv/riscv.cc                     |  13 ++
 gcc/config/riscv/riscv.opt                    |   2 +
 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, 811 insertions(+)
 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

-- 
2.34.1


^ permalink raw reply	[flat|nested] 7+ messages in thread

* [PATCH v3 1/1] RISC-V: Add support for XCVbitmanip extension in CV32E40P
  2024-01-22 17:15   ` [PATCH v3 0/1] RISC-V: Support CORE-V XCVBITMAIP extension Mary Bennett
@ 2024-01-22 17:15     ` Mary Bennett
  2024-01-25 14:09       ` [PATCH v4 0/1] RISC-V: Support CORE-V XCVBITMAIP extension Mary Bennett
  0 siblings, 1 reply; 7+ messages in thread
From: Mary Bennett @ 2024-01-22 17:15 UTC (permalink / raw)
  To: gcc-patches; +Cc: mary.bennett

Spec: github.com/openhwgroup/core-v-sw/blob/master/specifications/corev-builtin-spec.md

Contributors:
  Mary Bennett <mary.bennett@embecosm.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                     | 184 ++++++++++++++++++
 gcc/config/riscv/predicates.md                |  16 ++
 gcc/config/riscv/riscv-builtins.cc            |   1 +
 gcc/config/riscv/riscv-ftypes.def             |   5 +
 gcc/config/riscv/riscv.cc                     |  13 ++
 gcc/config/riscv/riscv.opt                    |   2 +
 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, 811 insertions(+)
 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

diff --git a/gcc/common/config/riscv/riscv-common.cc b/gcc/common/config/riscv/riscv-common.cc
index 4da7f37303b..ad131155255 100644
--- a/gcc/common/config/riscv/riscv-common.cc
+++ b/gcc/common/config/riscv/riscv-common.cc
@@ -358,6 +358,7 @@ static const struct riscv_ext_version riscv_ext_version_table[] =
   {"xcvmac", ISA_SPEC_CLASS_NONE, 1, 0},
   {"xcvalu", ISA_SPEC_CLASS_NONE, 1, 0},
   {"xcvelw", 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},
@@ -1602,6 +1603,7 @@ static const riscv_ext_flag_table_t riscv_ext_flag_table[] =
   {"xcvmac",        &gcc_options::x_riscv_xcv_subext, MASK_XCVMAC},
   {"xcvalu",        &gcc_options::x_riscv_xcv_subext, MASK_XCVALU},
   {"xcvelw",        &gcc_options::x_riscv_xcv_subext, MASK_XCVELW},
+  {"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 ee1c12b2e51..8923bd431ce 100644
--- a/gcc/config/riscv/constraints.md
+++ b/gcc/config/riscv/constraints.md
@@ -103,6 +103,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"
@@ -262,3 +267,14 @@
   (and (match_code "const_int")
        (and (match_test "IN_RANGE (ival, 0, 1073741823)")
             (match_test "exact_log2 (ival + 1) != -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 3b9ec029d06..19a2a9c7a85 100644
--- a/gcc/config/riscv/corev.def
+++ b/gcc/config/riscv/corev.def
@@ -44,3 +44,16 @@ RISCV_BUILTIN (cv_alu_subuRN,   "cv_alu_subuRN",RISCV_BUILTIN_DIRECT, RISCV_USI_
 
 // XCVELW
 RISCV_BUILTIN (cv_elw_elw_si, "cv_elw_elw", RISCV_BUILTIN_DIRECT, RISCV_USI_FTYPE_VOID_PTR, cvelw),
+
+// 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 adad2409fb6..d3f19ed7cd5 100644
--- a/gcc/config/riscv/corev.md
+++ b/gcc/config/riscv/corev.md
@@ -27,6 +27,9 @@
 
   ;;CORE-V EVENT LOAD
   UNSPECV_CV_ELW
+
+  ;;CORE-V BITMANIP
+  UNSPEC_CV_BITMANIP_BITREV
 ])
 
 ;; XCVMAC extension.
@@ -706,3 +709,184 @@
 
   [(set_attr "type" "load")
   (set_attr "mode" "SI")])
+
+;; 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,%Y2
+   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,%Y2
+   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,%Y2
+   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")
+	  (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)))))]
+
+  "TARGET_XCVBITMANIP && !TARGET_64BIT"
+  "@
+   cv.bclr\t%0,%1,%Z2,%Y2
+   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")
+          (sign_extract:SI
+            (const_int -2)
+          (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.bset\t%0,%1,%Z2,%Y2
+   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")
+        (if_then_else (eq:SI (match_operand:SI 1 "register_operand" "r") (const_int 0))
+                      (const_int 0)
+                      (clrsb:QI (match_dup 1))))]
+
+  "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 0337da88284..2dd487296c4 100644
--- a/gcc/config/riscv/predicates.md
+++ b/gcc/config/riscv/predicates.md
@@ -425,6 +425,22 @@
   (ior (match_operand 0 "register_operand")
        (match_code "const_int")))
 
+(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")
+       (match_test "IN_RANGE (INTVAL (op), 0, 3)")))
+
 ;; Predicates for the V extension.
 (define_special_predicate "vector_length_operand"
   (ior (match_operand 0 "pmode_register_operand")
diff --git a/gcc/config/riscv/riscv-builtins.cc b/gcc/config/riscv/riscv-builtins.cc
index 1932ff069c6..0c3a87f9926 100644
--- a/gcc/config/riscv/riscv-builtins.cc
+++ b/gcc/config/riscv/riscv-builtins.cc
@@ -135,6 +135,7 @@ AVAIL (hint_pause, (!0))
 AVAIL (cvmac, TARGET_XCVMAC && !TARGET_64BIT)
 AVAIL (cvalu, TARGET_XCVALU && !TARGET_64BIT)
 AVAIL (cvelw, TARGET_XCVELW && !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 5f051df2277..fad286ed24c 100644
--- a/gcc/config/riscv/riscv-ftypes.def
+++ b/gcc/config/riscv/riscv-ftypes.def
@@ -37,8 +37,11 @@ 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, UHI, UHI))
+DEF_RISCV_FTYPE (2, (SI, USI, UHI))
+DEF_RISCV_FTYPE (2, (USI, USI, UHI))
 DEF_RISCV_FTYPE (2, (USI, USI, USI))
 DEF_RISCV_FTYPE (2, (USI, USI, UQI))
 DEF_RISCV_FTYPE (2, (UDI, UQI, UQI))
@@ -52,6 +55,8 @@ DEF_RISCV_FTYPE (2, (SI, SI, SI))
 DEF_RISCV_FTYPE (3, (USI, USI, USI, UQI))
 DEF_RISCV_FTYPE (3, (USI, USI, USI, USI))
 DEF_RISCV_FTYPE (3, (SI, SI, SI, UQI))
+DEF_RISCV_FTYPE (3, (USI, USI, UHI, USI))
+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 3ba45ffaa74..3b4107b6f9f 100644
--- a/gcc/config/riscv/riscv.cc
+++ b/gcc/config/riscv/riscv.cc
@@ -5852,6 +5852,19 @@ riscv_print_operand (FILE *file, rtx op, int letter)
 	output_addr_const (file, newop);
 	break;
       }
+    case 'Y':
+      {
+	rtx newop = GEN_INT (INTVAL (op) & 31);
+	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 65c656204ca..719d078c56f 100644
--- a/gcc/config/riscv/riscv.opt
+++ b/gcc/config/riscv/riscv.opt
@@ -425,6 +425,8 @@ Mask(XCVALU) Var(riscv_xcv_subext)
 
 Mask(XCVELW) 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 0bc586d120e..ac92b3da828 100644
--- a/gcc/doc/extend.texi
+++ b/gcc/doc/extend.texi
@@ -24467,6 +24467,59 @@ architecture. For more information on CORE-V ELW builtins, please see
 Generated assembler @code{cv.elw}
 @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 8082100a3c9..3795489c9ad 100644
--- a/gcc/doc/sourcebuild.texi
+++ b/gcc/doc/sourcebuild.texi
@@ -2505,6 +2505,9 @@ Test system has support for the CORE-V ALU extension.
 @item cv_elw
 Test system has support for the CORE-V ELW 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 73360cd3a0d..0ac040b1358 100644
--- a/gcc/testsuite/lib/target-supports.exp
+++ b/gcc/testsuite/lib/target-supports.exp
@@ -13357,6 +13357,19 @@ proc check_effective_target_cv_elw { } {
     } "-march=rv32i_xcvelw" ]
 }
 
+# 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)
-- 
2.34.1


^ permalink raw reply	[flat|nested] 7+ messages in thread

* [PATCH v4 0/1] RISC-V: Support CORE-V XCVBITMAIP extension
  2024-01-22 17:15     ` [PATCH v3 1/1] RISC-V: Add support for XCVbitmanip extension in CV32E40P Mary Bennett
@ 2024-01-25 14:09       ` Mary Bennett
  2024-01-25 14:09         ` [PATCH v4 1/1] RISC-V: Add support for XCVbitmanip extension in CV32E40P Mary Bennett
  0 siblings, 1 reply; 7+ messages in thread
From: Mary Bennett @ 2024-01-25 14:09 UTC (permalink / raw)
  To: gcc-patches; +Cc: mary.bennett

This patch series presents the comprehensive implementation of the BITMANIP
extension for CORE-V.

Tested with riscv-gnu-toolchain on binutils, ld, gas and gcc testsuites to
ensure its correctness and compatibility with the existing codebase.
However, your input, reviews, and suggestions are invaluable in making this
extension even more robust.

The CORE-V builtins are described in the specification [1] and work can be
found in the OpenHW group's Github repository [2].

[1] github.com/openhwgroup/core-v-sw/blob/master/specifications/corev-builtin-spec.md

[2] github.com/openhwgroup/corev-gcc

Contributors:
  Mary Bennett <mary.bennett@embecosm.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>

RISC-V: Add support for XCVbitmanip extension in CV32E40P

 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                     | 182 ++++++++++++++++++
 gcc/config/riscv/predicates.md                |  16 ++
 gcc/config/riscv/riscv-builtins.cc            |   1 +
 gcc/config/riscv/riscv-ftypes.def             |   5 +
 gcc/config/riscv/riscv.cc                     |  13 ++
 gcc/config/riscv/riscv.opt                    |   2 +
 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, 809 insertions(+)
 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

-- 
2.34.1


^ permalink raw reply	[flat|nested] 7+ messages in thread

* [PATCH v4 1/1] RISC-V: Add support for XCVbitmanip extension in CV32E40P
  2024-01-25 14:09       ` [PATCH v4 0/1] RISC-V: Support CORE-V XCVBITMAIP extension Mary Bennett
@ 2024-01-25 14:09         ` Mary Bennett
  0 siblings, 0 replies; 7+ messages in thread
From: Mary Bennett @ 2024-01-25 14:09 UTC (permalink / raw)
  To: gcc-patches; +Cc: mary.bennett

Spec: github.com/openhwgroup/core-v-sw/blob/master/specifications/corev-builtin-spec.md

Contributors:
  Mary Bennett <mary.bennett@embecosm.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                     | 182 ++++++++++++++++++
 gcc/config/riscv/predicates.md                |  16 ++
 gcc/config/riscv/riscv-builtins.cc            |   1 +
 gcc/config/riscv/riscv-ftypes.def             |   5 +
 gcc/config/riscv/riscv.cc                     |  13 ++
 gcc/config/riscv/riscv.opt                    |   2 +
 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, 809 insertions(+)
 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

diff --git a/gcc/common/config/riscv/riscv-common.cc b/gcc/common/config/riscv/riscv-common.cc
index 4da7f37303b..ad131155255 100644
--- a/gcc/common/config/riscv/riscv-common.cc
+++ b/gcc/common/config/riscv/riscv-common.cc
@@ -358,6 +358,7 @@ static const struct riscv_ext_version riscv_ext_version_table[] =
   {"xcvmac", ISA_SPEC_CLASS_NONE, 1, 0},
   {"xcvalu", ISA_SPEC_CLASS_NONE, 1, 0},
   {"xcvelw", 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},
@@ -1602,6 +1603,7 @@ static const riscv_ext_flag_table_t riscv_ext_flag_table[] =
   {"xcvmac",        &gcc_options::x_riscv_xcv_subext, MASK_XCVMAC},
   {"xcvalu",        &gcc_options::x_riscv_xcv_subext, MASK_XCVALU},
   {"xcvelw",        &gcc_options::x_riscv_xcv_subext, MASK_XCVELW},
+  {"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 ee1c12b2e51..8923bd431ce 100644
--- a/gcc/config/riscv/constraints.md
+++ b/gcc/config/riscv/constraints.md
@@ -103,6 +103,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"
@@ -262,3 +267,14 @@
   (and (match_code "const_int")
        (and (match_test "IN_RANGE (ival, 0, 1073741823)")
             (match_test "exact_log2 (ival + 1) != -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 3b9ec029d06..19a2a9c7a85 100644
--- a/gcc/config/riscv/corev.def
+++ b/gcc/config/riscv/corev.def
@@ -44,3 +44,16 @@ RISCV_BUILTIN (cv_alu_subuRN,   "cv_alu_subuRN",RISCV_BUILTIN_DIRECT, RISCV_USI_
 
 // XCVELW
 RISCV_BUILTIN (cv_elw_elw_si, "cv_elw_elw", RISCV_BUILTIN_DIRECT, RISCV_USI_FTYPE_VOID_PTR, cvelw),
+
+// 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 adad2409fb6..5e315274926 100644
--- a/gcc/config/riscv/corev.md
+++ b/gcc/config/riscv/corev.md
@@ -27,6 +27,9 @@
 
   ;;CORE-V EVENT LOAD
   UNSPECV_CV_ELW
+
+  ;;CORE-V BITMANIP
+  UNSPEC_CV_BITMANIP_BITREV
 ])
 
 ;; XCVMAC extension.
@@ -706,3 +709,182 @@
 
   [(set_attr "type" "load")
   (set_attr "mode" "SI")])
+
+;; 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,%Y2
+   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,%Y2
+   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,%Y2
+   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")
+	  (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)))))]
+
+  "TARGET_XCVBITMANIP && !TARGET_64BIT"
+  "@
+   cv.bclr\t%0,%1,%Z2,%Y2
+   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")
+          (sign_extract:SI
+            (const_int -2)
+          (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.bset\t%0,%1,%Z2,%Y2
+   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 0337da88284..2dd487296c4 100644
--- a/gcc/config/riscv/predicates.md
+++ b/gcc/config/riscv/predicates.md
@@ -425,6 +425,22 @@
   (ior (match_operand 0 "register_operand")
        (match_code "const_int")))
 
+(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")
+       (match_test "IN_RANGE (INTVAL (op), 0, 3)")))
+
 ;; Predicates for the V extension.
 (define_special_predicate "vector_length_operand"
   (ior (match_operand 0 "pmode_register_operand")
diff --git a/gcc/config/riscv/riscv-builtins.cc b/gcc/config/riscv/riscv-builtins.cc
index 1932ff069c6..0c3a87f9926 100644
--- a/gcc/config/riscv/riscv-builtins.cc
+++ b/gcc/config/riscv/riscv-builtins.cc
@@ -135,6 +135,7 @@ AVAIL (hint_pause, (!0))
 AVAIL (cvmac, TARGET_XCVMAC && !TARGET_64BIT)
 AVAIL (cvalu, TARGET_XCVALU && !TARGET_64BIT)
 AVAIL (cvelw, TARGET_XCVELW && !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 5f051df2277..fad286ed24c 100644
--- a/gcc/config/riscv/riscv-ftypes.def
+++ b/gcc/config/riscv/riscv-ftypes.def
@@ -37,8 +37,11 @@ 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, UHI, UHI))
+DEF_RISCV_FTYPE (2, (SI, USI, UHI))
+DEF_RISCV_FTYPE (2, (USI, USI, UHI))
 DEF_RISCV_FTYPE (2, (USI, USI, USI))
 DEF_RISCV_FTYPE (2, (USI, USI, UQI))
 DEF_RISCV_FTYPE (2, (UDI, UQI, UQI))
@@ -52,6 +55,8 @@ DEF_RISCV_FTYPE (2, (SI, SI, SI))
 DEF_RISCV_FTYPE (3, (USI, USI, USI, UQI))
 DEF_RISCV_FTYPE (3, (USI, USI, USI, USI))
 DEF_RISCV_FTYPE (3, (SI, SI, SI, UQI))
+DEF_RISCV_FTYPE (3, (USI, USI, UHI, USI))
+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 3ba45ffaa74..3b4107b6f9f 100644
--- a/gcc/config/riscv/riscv.cc
+++ b/gcc/config/riscv/riscv.cc
@@ -5852,6 +5852,19 @@ riscv_print_operand (FILE *file, rtx op, int letter)
 	output_addr_const (file, newop);
 	break;
       }
+    case 'Y':
+      {
+	rtx newop = GEN_INT (INTVAL (op) & 31);
+	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 65c656204ca..719d078c56f 100644
--- a/gcc/config/riscv/riscv.opt
+++ b/gcc/config/riscv/riscv.opt
@@ -425,6 +425,8 @@ Mask(XCVALU) Var(riscv_xcv_subext)
 
 Mask(XCVELW) 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 0bc586d120e..ac92b3da828 100644
--- a/gcc/doc/extend.texi
+++ b/gcc/doc/extend.texi
@@ -24467,6 +24467,59 @@ architecture. For more information on CORE-V ELW builtins, please see
 Generated assembler @code{cv.elw}
 @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 8082100a3c9..3795489c9ad 100644
--- a/gcc/doc/sourcebuild.texi
+++ b/gcc/doc/sourcebuild.texi
@@ -2505,6 +2505,9 @@ Test system has support for the CORE-V ALU extension.
 @item cv_elw
 Test system has support for the CORE-V ELW 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 73360cd3a0d..0ac040b1358 100644
--- a/gcc/testsuite/lib/target-supports.exp
+++ b/gcc/testsuite/lib/target-supports.exp
@@ -13357,6 +13357,19 @@ proc check_effective_target_cv_elw { } {
     } "-march=rv32i_xcvelw" ]
 }
 
+# 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)
-- 
2.34.1


^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2024-01-25 14:10 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
     [not found] <20231109105542.4013483-1-mary.bennett@embecosm.com^Cthread>
2024-01-16 16:25 ` [PATCH v2 0/1] RISC-V: Support CORE-V XCVBITMAIP extension Mary Bennett
2024-01-16 16:25   ` [PATCH v2 1/1] RISC-V: Add support for XCVbitmanip extension in CV32E40P Mary Bennett
2024-01-21 23:21     ` Jeff Law
2024-01-22 17:15   ` [PATCH v3 0/1] RISC-V: Support CORE-V XCVBITMAIP extension Mary Bennett
2024-01-22 17:15     ` [PATCH v3 1/1] RISC-V: Add support for XCVbitmanip extension in CV32E40P Mary Bennett
2024-01-25 14:09       ` [PATCH v4 0/1] RISC-V: Support CORE-V XCVBITMAIP extension Mary Bennett
2024-01-25 14:09         ` [PATCH v4 1/1] RISC-V: Add support for XCVbitmanip extension in CV32E40P Mary Bennett

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).