[clang] [llvm] [Clang][RISCV] Add CORE-V (XCV) builtins for CV32E40P (PR #204881)

via cfe-commits cfe-commits at lists.llvm.org
Fri Jun 19 11:38:07 PDT 2026


https://github.com/VittorioBurani created https://github.com/llvm/llvm-project/pull/204881

Add Clang builtins and user-facing headers for the CORE-V extensions `XCVmac`, `XCVelw`, `XCVsimd` and `XCVbitmanip`:

- builtin definitions in `BuiltinsRISCVXCV.td`, CodeGen dispatch in `TargetBuiltins/RISCV.cpp`, argument range checks in `SemaRISCV.cpp`, and ClangIR NYI stubs in `CIRGenBuiltinRISCV.cpp`;
- headers `riscv_corev_{mac,elw,simd,bitmanip}.h` (wired into `clang/lib/Headers/CMakeLists.txt`).

The XCVsimd builtins lower to the `llvm.riscv.cv.simd.*` intrinsics; the mac/elw/bitmanip builtins lower to intrinsics already present upstream.

**Tests:** `clang/test/CodeGen/RISCV/rvv-xcv*-builtins.c`, `clang/test/Sema/rvv-xcv-sema.c`.

**Depends on #204880** — the XCVsimd intrinsics must exist for the XCVsimd builtins to resolve (without them Clang's dispatch table will not compile). This PR will show that PR's commit until it merges; it will be rebased afterward. Marked Draft until then.

Part of a CORE-V (XCV) series; see RFC: https://discourse.llvm.org/t/rfc-core-v-xcv-support-for-cv32e40p-clang-builtins-xcvsimd-intrinsics-and-generic-auto-selection/91111


>From 593f42d47f03bc7dc76d0c59c44a1a7707ea4016 Mon Sep 17 00:00:00 2001
From: vitbur <vittorioburani at gmail.com>
Date: Wed, 1 Apr 2026 18:45:22 +0200
Subject: [PATCH 01/10] [RISCV][LLVM] Add LLVM intrinsics and patterns for
 XCVsimd

- add 150+ LLVM IR intrinsic declarations for all XCVsimd
  operations (add, sub, avg, min, max, shift, logic, dot product,
  extract, insert, shuffle, pack, compare, complex multiply,
  conjugate, subrotmj).
- add SelectionDAG patterns mapping each intrinsic to its
  corresponding CV32E40P machine instruction, including:
  - SCI immediate fallback patterns for scalar-constant operands
  - Divcode-based instruction selection for
    add_h/sub_h/subrotmj/cplxmul
  - CV_SHUFFLE_SCI_B_PSEUDO with RISCVExpandPseudoInsts expansion
- this enables the Clang builtins (__builtin_riscv_cv_simd_*)
- add xcvsimd.ll file to test XCVsimid intrinsics
---
 llvm/include/llvm/IR/IntrinsicsRISCVXCV.td    |  225 ++++
 .../Target/RISCV/RISCVExpandPseudoInsts.cpp   |   31 +
 llvm/lib/Target/RISCV/RISCVInstrInfoXCV.td    |  287 +++++
 llvm/test/CodeGen/RISCV/xcvsimd.ll            | 1115 +++++++++++++++++
 4 files changed, 1658 insertions(+)
 create mode 100644 llvm/test/CodeGen/RISCV/xcvsimd.ll

diff --git a/llvm/include/llvm/IR/IntrinsicsRISCVXCV.td b/llvm/include/llvm/IR/IntrinsicsRISCVXCV.td
index 465665c838bae..3dcc2b49f5f2c 100644
--- a/llvm/include/llvm/IR/IntrinsicsRISCVXCV.td
+++ b/llvm/include/llvm/IR/IntrinsicsRISCVXCV.td
@@ -42,6 +42,54 @@ class ScalarCoreVMacGprGprGprImmIntrinsic
   : Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty],
               [IntrNoMem, IntrWillReturn, IntrSpeculatable, ImmArg<ArgIndex<3>>]>;
 
+// Binary: (i32, i32) -> i32, pure
+class ScalarCoreVSimdGprGprIntrinsic
+    : DefaultAttrsIntrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty],
+                            [IntrNoMem, IntrSpeculatable]>;
+
+// Unary: (i32) -> i32, pure
+class ScalarCoreVSimdGprIntrinsic
+    : DefaultAttrsIntrinsic<[llvm_i32_ty], [llvm_i32_ty],
+                            [IntrNoMem, IntrSpeculatable]>;
+
+// Ternary: (i32, i32, i32) -> i32, pure (for accumulating ops like sdot)
+class ScalarCoreVSimdGprGprGprIntrinsic
+    : DefaultAttrsIntrinsic<[llvm_i32_ty],
+                            [llvm_i32_ty, llvm_i32_ty, llvm_i32_ty],
+                            [IntrNoMem, IntrSpeculatable]>;
+
+// Binary with immediate at arg2: (i32, i32, IMM) -> i32
+// Used for: add_h/sub_h (divcode), subrotmj (divcode)
+class ScalarCoreVSimdGprGprImmIntrinsic
+    : DefaultAttrsIntrinsic<[llvm_i32_ty],
+                            [llvm_i32_ty, llvm_i32_ty, llvm_i32_ty],
+                            [IntrNoMem, IntrSpeculatable,
+                             ImmArg<ArgIndex<2>>]>;
+
+// Unary with immediate at arg1: (i32, IMM) -> i32
+// Used for: extract, extractu, shuffle_sci_h, shuffle_sci_b
+class ScalarCoreVSimdGprImmIntrinsic
+    : DefaultAttrsIntrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty],
+                            [IntrNoMem, IntrSpeculatable,
+                             ImmArg<ArgIndex<1>>]>;
+
+// Ternary with immediate at arg2, where arg0 is rd (accumulator):
+// (rd_in, rs1, IMM) -> rd_out
+// Used for: insert_h, insert_b
+class ScalarCoreVSimdGprGprImm2WbIntrinsic
+    : DefaultAttrsIntrinsic<[llvm_i32_ty],
+                            [llvm_i32_ty, llvm_i32_ty, llvm_i32_ty],
+                            [IntrNoMem, IntrSpeculatable,
+                             ImmArg<ArgIndex<2>>]>;
+
+// Quaternary with immediate at arg3: (rs1, rs2, rd_in, IMM) -> rd_out
+// Used for: cplxmul_r, cplxmul_i
+class ScalarCoreVSimdGprGprGprImmIntrinsic
+    : DefaultAttrsIntrinsic<[llvm_i32_ty],
+                            [llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty],
+                            [IntrNoMem, IntrSpeculatable,
+                             ImmArg<ArgIndex<3>>]>;
+
 let TargetPrefix = "riscv" in {
   def int_riscv_cv_bitmanip_extract : ScalarCoreVBitManipGprGprIntrinsic;
   def int_riscv_cv_bitmanip_extractu : ScalarCoreVBitManipGprGprIntrinsic;
@@ -94,4 +142,181 @@ let TargetPrefix = "riscv" in {
   def int_riscv_cv_elw_elw
     : Intrinsic<[llvm_i32_ty], [llvm_ptr_ty],
                 [IntrReadMem, IntrArgMemOnly, IntrHasSideEffects]>;
+
+  // ==== XCVsimd — ADD/SUB ====
+  // add_h takes a divcode immediate (0=none, 1=/2, 2=/4, 3=/8)
+  def int_riscv_cv_simd_add_h     : ScalarCoreVSimdGprGprImmIntrinsic;
+  def int_riscv_cv_simd_add_b     : ScalarCoreVSimdGprGprIntrinsic;
+  def int_riscv_cv_simd_add_sc_h  : ScalarCoreVSimdGprGprIntrinsic;
+  def int_riscv_cv_simd_add_sc_b  : ScalarCoreVSimdGprGprIntrinsic;
+  def int_riscv_cv_simd_sub_h     : ScalarCoreVSimdGprGprImmIntrinsic;
+  def int_riscv_cv_simd_sub_b     : ScalarCoreVSimdGprGprIntrinsic;
+  def int_riscv_cv_simd_sub_sc_h  : ScalarCoreVSimdGprGprIntrinsic;
+  def int_riscv_cv_simd_sub_sc_b  : ScalarCoreVSimdGprGprIntrinsic;
+
+  // ==== XCVsimd — AVG / AVGU ====
+  def int_riscv_cv_simd_avg_h     : ScalarCoreVSimdGprGprIntrinsic;
+  def int_riscv_cv_simd_avg_b     : ScalarCoreVSimdGprGprIntrinsic;
+  def int_riscv_cv_simd_avg_sc_h  : ScalarCoreVSimdGprGprIntrinsic;
+  def int_riscv_cv_simd_avg_sc_b  : ScalarCoreVSimdGprGprIntrinsic;
+  def int_riscv_cv_simd_avgu_h    : ScalarCoreVSimdGprGprIntrinsic;
+  def int_riscv_cv_simd_avgu_b    : ScalarCoreVSimdGprGprIntrinsic;
+  def int_riscv_cv_simd_avgu_sc_h : ScalarCoreVSimdGprGprIntrinsic;
+  def int_riscv_cv_simd_avgu_sc_b : ScalarCoreVSimdGprGprIntrinsic;
+
+  // ==== XCVsimd — MIN / MINU / MAX / MAXU ====
+  def int_riscv_cv_simd_min_h     : ScalarCoreVSimdGprGprIntrinsic;
+  def int_riscv_cv_simd_min_b     : ScalarCoreVSimdGprGprIntrinsic;
+  def int_riscv_cv_simd_min_sc_h  : ScalarCoreVSimdGprGprIntrinsic;
+  def int_riscv_cv_simd_min_sc_b  : ScalarCoreVSimdGprGprIntrinsic;
+  def int_riscv_cv_simd_minu_h    : ScalarCoreVSimdGprGprIntrinsic;
+  def int_riscv_cv_simd_minu_b    : ScalarCoreVSimdGprGprIntrinsic;
+  def int_riscv_cv_simd_minu_sc_h : ScalarCoreVSimdGprGprIntrinsic;
+  def int_riscv_cv_simd_minu_sc_b : ScalarCoreVSimdGprGprIntrinsic;
+  def int_riscv_cv_simd_max_h     : ScalarCoreVSimdGprGprIntrinsic;
+  def int_riscv_cv_simd_max_b     : ScalarCoreVSimdGprGprIntrinsic;
+  def int_riscv_cv_simd_max_sc_h  : ScalarCoreVSimdGprGprIntrinsic;
+  def int_riscv_cv_simd_max_sc_b  : ScalarCoreVSimdGprGprIntrinsic;
+  def int_riscv_cv_simd_maxu_h    : ScalarCoreVSimdGprGprIntrinsic;
+  def int_riscv_cv_simd_maxu_b    : ScalarCoreVSimdGprGprIntrinsic;
+  def int_riscv_cv_simd_maxu_sc_h : ScalarCoreVSimdGprGprIntrinsic;
+  def int_riscv_cv_simd_maxu_sc_b : ScalarCoreVSimdGprGprIntrinsic;
+
+  // ==== XCVsimd — SRL / SRA / SLL ====
+  def int_riscv_cv_simd_srl_h     : ScalarCoreVSimdGprGprIntrinsic;
+  def int_riscv_cv_simd_srl_b     : ScalarCoreVSimdGprGprIntrinsic;
+  def int_riscv_cv_simd_srl_sc_h  : ScalarCoreVSimdGprGprIntrinsic;
+  def int_riscv_cv_simd_srl_sc_b  : ScalarCoreVSimdGprGprIntrinsic;
+  def int_riscv_cv_simd_sra_h     : ScalarCoreVSimdGprGprIntrinsic;
+  def int_riscv_cv_simd_sra_b     : ScalarCoreVSimdGprGprIntrinsic;
+  def int_riscv_cv_simd_sra_sc_h  : ScalarCoreVSimdGprGprIntrinsic;
+  def int_riscv_cv_simd_sra_sc_b  : ScalarCoreVSimdGprGprIntrinsic;
+  def int_riscv_cv_simd_sll_h     : ScalarCoreVSimdGprGprIntrinsic;
+  def int_riscv_cv_simd_sll_b     : ScalarCoreVSimdGprGprIntrinsic;
+  def int_riscv_cv_simd_sll_sc_h  : ScalarCoreVSimdGprGprIntrinsic;
+  def int_riscv_cv_simd_sll_sc_b  : ScalarCoreVSimdGprGprIntrinsic;
+
+  // ==== XCVsimd — OR / XOR / AND ====
+  def int_riscv_cv_simd_or_h      : ScalarCoreVSimdGprGprIntrinsic;
+  def int_riscv_cv_simd_or_b      : ScalarCoreVSimdGprGprIntrinsic;
+  def int_riscv_cv_simd_or_sc_h   : ScalarCoreVSimdGprGprIntrinsic;
+  def int_riscv_cv_simd_or_sc_b   : ScalarCoreVSimdGprGprIntrinsic;
+  def int_riscv_cv_simd_xor_h     : ScalarCoreVSimdGprGprIntrinsic;
+  def int_riscv_cv_simd_xor_b     : ScalarCoreVSimdGprGprIntrinsic;
+  def int_riscv_cv_simd_xor_sc_h  : ScalarCoreVSimdGprGprIntrinsic;
+  def int_riscv_cv_simd_xor_sc_b  : ScalarCoreVSimdGprGprIntrinsic;
+  def int_riscv_cv_simd_and_h     : ScalarCoreVSimdGprGprIntrinsic;
+  def int_riscv_cv_simd_and_b     : ScalarCoreVSimdGprGprIntrinsic;
+  def int_riscv_cv_simd_and_sc_h  : ScalarCoreVSimdGprGprIntrinsic;
+  def int_riscv_cv_simd_and_sc_b  : ScalarCoreVSimdGprGprIntrinsic;
+
+  // ==== XCVsimd — ABS ====
+  def int_riscv_cv_simd_abs_h     : ScalarCoreVSimdGprIntrinsic;
+  def int_riscv_cv_simd_abs_b     : ScalarCoreVSimdGprIntrinsic;
+
+  // ==== XCVsimd — DOT PRODUCTS (non-accumulating) ====
+  def int_riscv_cv_simd_dotup_h    : ScalarCoreVSimdGprGprIntrinsic;
+  def int_riscv_cv_simd_dotup_b    : ScalarCoreVSimdGprGprIntrinsic;
+  def int_riscv_cv_simd_dotup_sc_h : ScalarCoreVSimdGprGprIntrinsic;
+  def int_riscv_cv_simd_dotup_sc_b : ScalarCoreVSimdGprGprIntrinsic;
+  def int_riscv_cv_simd_dotusp_h    : ScalarCoreVSimdGprGprIntrinsic;
+  def int_riscv_cv_simd_dotusp_b    : ScalarCoreVSimdGprGprIntrinsic;
+  def int_riscv_cv_simd_dotusp_sc_h : ScalarCoreVSimdGprGprIntrinsic;
+  def int_riscv_cv_simd_dotusp_sc_b : ScalarCoreVSimdGprGprIntrinsic;
+  def int_riscv_cv_simd_dotsp_h    : ScalarCoreVSimdGprGprIntrinsic;
+  def int_riscv_cv_simd_dotsp_b    : ScalarCoreVSimdGprGprIntrinsic;
+  def int_riscv_cv_simd_dotsp_sc_h : ScalarCoreVSimdGprGprIntrinsic;
+  def int_riscv_cv_simd_dotsp_sc_b : ScalarCoreVSimdGprGprIntrinsic;
+
+  // ==== XCVsimd — SDOT (accumulating dot products): (rs1, rs2, acc) -> acc ====
+  def int_riscv_cv_simd_sdotup_h    : ScalarCoreVSimdGprGprGprIntrinsic;
+  def int_riscv_cv_simd_sdotup_b    : ScalarCoreVSimdGprGprGprIntrinsic;
+  def int_riscv_cv_simd_sdotup_sc_h : ScalarCoreVSimdGprGprGprIntrinsic;
+  def int_riscv_cv_simd_sdotup_sc_b : ScalarCoreVSimdGprGprGprIntrinsic;
+  def int_riscv_cv_simd_sdotusp_h    : ScalarCoreVSimdGprGprGprIntrinsic;
+  def int_riscv_cv_simd_sdotusp_b    : ScalarCoreVSimdGprGprGprIntrinsic;
+  def int_riscv_cv_simd_sdotusp_sc_h : ScalarCoreVSimdGprGprGprIntrinsic;
+  def int_riscv_cv_simd_sdotusp_sc_b : ScalarCoreVSimdGprGprGprIntrinsic;
+  def int_riscv_cv_simd_sdotsp_h    : ScalarCoreVSimdGprGprGprIntrinsic;
+  def int_riscv_cv_simd_sdotsp_b    : ScalarCoreVSimdGprGprGprIntrinsic;
+  def int_riscv_cv_simd_sdotsp_sc_h : ScalarCoreVSimdGprGprGprIntrinsic;
+  def int_riscv_cv_simd_sdotsp_sc_b : ScalarCoreVSimdGprGprGprIntrinsic;
+
+  // ==== XCVsimd — EXTRACT / EXTRACTU: (rs1, IMM) -> rd ====
+  def int_riscv_cv_simd_extract_h  : ScalarCoreVSimdGprImmIntrinsic;
+  def int_riscv_cv_simd_extract_b  : ScalarCoreVSimdGprImmIntrinsic;
+  def int_riscv_cv_simd_extractu_h : ScalarCoreVSimdGprImmIntrinsic;
+  def int_riscv_cv_simd_extractu_b : ScalarCoreVSimdGprImmIntrinsic;
+
+  // ==== XCVsimd — INSERT: (rd_in, rs1, IMM) -> rd_out ====
+  def int_riscv_cv_simd_insert_h   : ScalarCoreVSimdGprGprImm2WbIntrinsic;
+  def int_riscv_cv_simd_insert_b   : ScalarCoreVSimdGprGprImm2WbIntrinsic;
+
+  // ==== XCVsimd — SHUFFLE ====
+  def int_riscv_cv_simd_shuffle_h     : ScalarCoreVSimdGprGprIntrinsic;
+  def int_riscv_cv_simd_shuffle_b     : ScalarCoreVSimdGprGprIntrinsic;
+  def int_riscv_cv_simd_shuffle_sci_h : ScalarCoreVSimdGprImmIntrinsic;
+  def int_riscv_cv_simd_shuffle_sci_b : ScalarCoreVSimdGprImmIntrinsic;
+
+  // ==== XCVsimd — SHUFFLE2: (rs1, rs2, rd_in) -> rd_out ====
+  def int_riscv_cv_simd_shuffle2_h : ScalarCoreVSimdGprGprGprIntrinsic;
+  def int_riscv_cv_simd_shuffle2_b : ScalarCoreVSimdGprGprGprIntrinsic;
+
+  // ==== XCVsimd — PACK ====
+  // pack / pack.h: (rs1, rs2) -> rd
+  def int_riscv_cv_simd_packlo_h : ScalarCoreVSimdGprGprIntrinsic;
+  def int_riscv_cv_simd_packhi_h : ScalarCoreVSimdGprGprIntrinsic;
+  // packhi.b / packlo.b: (rd_in, rs1, rs2) -> rd_out  (read-modify-write)
+  def int_riscv_cv_simd_packhi_b : ScalarCoreVSimdGprGprGprIntrinsic;
+  def int_riscv_cv_simd_packlo_b : ScalarCoreVSimdGprGprGprIntrinsic;
+
+  // ==== XCVsimd — COMPARE ====
+  def int_riscv_cv_simd_cmpeq_h     : ScalarCoreVSimdGprGprIntrinsic;
+  def int_riscv_cv_simd_cmpeq_b     : ScalarCoreVSimdGprGprIntrinsic;
+  def int_riscv_cv_simd_cmpeq_sc_h  : ScalarCoreVSimdGprGprIntrinsic;
+  def int_riscv_cv_simd_cmpeq_sc_b  : ScalarCoreVSimdGprGprIntrinsic;
+  def int_riscv_cv_simd_cmpne_h     : ScalarCoreVSimdGprGprIntrinsic;
+  def int_riscv_cv_simd_cmpne_b     : ScalarCoreVSimdGprGprIntrinsic;
+  def int_riscv_cv_simd_cmpne_sc_h  : ScalarCoreVSimdGprGprIntrinsic;
+  def int_riscv_cv_simd_cmpne_sc_b  : ScalarCoreVSimdGprGprIntrinsic;
+  def int_riscv_cv_simd_cmpgt_h     : ScalarCoreVSimdGprGprIntrinsic;
+  def int_riscv_cv_simd_cmpgt_b     : ScalarCoreVSimdGprGprIntrinsic;
+  def int_riscv_cv_simd_cmpgt_sc_h  : ScalarCoreVSimdGprGprIntrinsic;
+  def int_riscv_cv_simd_cmpgt_sc_b  : ScalarCoreVSimdGprGprIntrinsic;
+  def int_riscv_cv_simd_cmpge_h     : ScalarCoreVSimdGprGprIntrinsic;
+  def int_riscv_cv_simd_cmpge_b     : ScalarCoreVSimdGprGprIntrinsic;
+  def int_riscv_cv_simd_cmpge_sc_h  : ScalarCoreVSimdGprGprIntrinsic;
+  def int_riscv_cv_simd_cmpge_sc_b  : ScalarCoreVSimdGprGprIntrinsic;
+  def int_riscv_cv_simd_cmplt_h     : ScalarCoreVSimdGprGprIntrinsic;
+  def int_riscv_cv_simd_cmplt_b     : ScalarCoreVSimdGprGprIntrinsic;
+  def int_riscv_cv_simd_cmplt_sc_h  : ScalarCoreVSimdGprGprIntrinsic;
+  def int_riscv_cv_simd_cmplt_sc_b  : ScalarCoreVSimdGprGprIntrinsic;
+  def int_riscv_cv_simd_cmple_h     : ScalarCoreVSimdGprGprIntrinsic;
+  def int_riscv_cv_simd_cmple_b     : ScalarCoreVSimdGprGprIntrinsic;
+  def int_riscv_cv_simd_cmple_sc_h  : ScalarCoreVSimdGprGprIntrinsic;
+  def int_riscv_cv_simd_cmple_sc_b  : ScalarCoreVSimdGprGprIntrinsic;
+  def int_riscv_cv_simd_cmpgtu_h    : ScalarCoreVSimdGprGprIntrinsic;
+  def int_riscv_cv_simd_cmpgtu_b    : ScalarCoreVSimdGprGprIntrinsic;
+  def int_riscv_cv_simd_cmpgtu_sc_h : ScalarCoreVSimdGprGprIntrinsic;
+  def int_riscv_cv_simd_cmpgtu_sc_b : ScalarCoreVSimdGprGprIntrinsic;
+  def int_riscv_cv_simd_cmpgeu_h    : ScalarCoreVSimdGprGprIntrinsic;
+  def int_riscv_cv_simd_cmpgeu_b    : ScalarCoreVSimdGprGprIntrinsic;
+  def int_riscv_cv_simd_cmpgeu_sc_h : ScalarCoreVSimdGprGprIntrinsic;
+  def int_riscv_cv_simd_cmpgeu_sc_b : ScalarCoreVSimdGprGprIntrinsic;
+  def int_riscv_cv_simd_cmpltu_h    : ScalarCoreVSimdGprGprIntrinsic;
+  def int_riscv_cv_simd_cmpltu_b    : ScalarCoreVSimdGprGprIntrinsic;
+  def int_riscv_cv_simd_cmpltu_sc_h : ScalarCoreVSimdGprGprIntrinsic;
+  def int_riscv_cv_simd_cmpltu_sc_b : ScalarCoreVSimdGprGprIntrinsic;
+  def int_riscv_cv_simd_cmpleu_h    : ScalarCoreVSimdGprGprIntrinsic;
+  def int_riscv_cv_simd_cmpleu_b    : ScalarCoreVSimdGprGprIntrinsic;
+  def int_riscv_cv_simd_cmpleu_sc_h : ScalarCoreVSimdGprGprIntrinsic;
+  def int_riscv_cv_simd_cmpleu_sc_b : ScalarCoreVSimdGprGprIntrinsic;
+
+  // ==== XCVsimd — COMPLEX ====
+  // cplxmul: (rs1, rs2, rd_in, divcode_IMM) -> rd_out
+  def int_riscv_cv_simd_cplxmul_r : ScalarCoreVSimdGprGprGprImmIntrinsic;
+  def int_riscv_cv_simd_cplxmul_i : ScalarCoreVSimdGprGprGprImmIntrinsic;
+  def int_riscv_cv_simd_cplxconj  : ScalarCoreVSimdGprIntrinsic;
+  // subrotmj: (rs1, rs2, divcode_IMM) -> rd
+  def int_riscv_cv_simd_subrotmj  : ScalarCoreVSimdGprGprImmIntrinsic;
 } // TargetPrefix = "riscv"
diff --git a/llvm/lib/Target/RISCV/RISCVExpandPseudoInsts.cpp b/llvm/lib/Target/RISCV/RISCVExpandPseudoInsts.cpp
index fdd98d03a77f1..d5a13a7e639fe 100644
--- a/llvm/lib/Target/RISCV/RISCVExpandPseudoInsts.cpp
+++ b/llvm/lib/Target/RISCV/RISCVExpandPseudoInsts.cpp
@@ -60,6 +60,8 @@ class RISCVExpandPseudo : public MachineFunctionPass {
                            MachineBasicBlock::iterator MBBI);
   bool expandPseudoReadVLENBViaVSETVLIX0(MachineBasicBlock &MBB,
                                          MachineBasicBlock::iterator MBBI);
+  bool expandVendorXcvsimdShuffle(MachineBasicBlock &MBB,
+                                  MachineBasicBlock::iterator MBBI);
 #ifndef NDEBUG
   unsigned getInstSizeInBytes(const MachineFunction &MF) const {
     unsigned Size = 0;
@@ -192,6 +194,8 @@ bool RISCVExpandPseudo::expandMI(MachineBasicBlock &MBB,
     return expandVMSET_VMCLR(MBB, MBBI, RISCV::VMXNOR_MM);
   case RISCV::PseudoReadVLENBViaVSETVLIX0:
     return expandPseudoReadVLENBViaVSETVLIX0(MBB, MBBI);
+  case RISCV::CV_SHUFFLE_SCI_B_PSEUDO:
+    return expandVendorXcvsimdShuffle(MBB, MBBI);
   }
 
   return false;
@@ -834,6 +838,33 @@ bool RISCVPreRAExpandPseudo::expandLoadTLSDescAddress(
   return true;
 }
 
+bool RISCVExpandPseudo::expandVendorXcvsimdShuffle(
+    MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI) {
+  // CV_SHUFFLE_SCI_B_PSEUDO takes an 8-bit immediate.
+  // Bits [7:6] select one of four cv.shuffleIx.sci.b instructions.
+  // Bits [5:0] become the 6-bit signed immediate payload.
+  DebugLoc DL = MBBI->getDebugLoc();
+  Register DstReg = MBBI->getOperand(0).getReg();
+  Register SrcReg = MBBI->getOperand(1).getReg();
+  unsigned Imm = MBBI->getOperand(2).getImm();
+
+  // Select the correct real instruction based on bits [7:6]
+  static const unsigned Opcodes[] = {
+      RISCV::CV_SHUFFLEI0_SCI_B,
+      RISCV::CV_SHUFFLEI1_SCI_B,
+      RISCV::CV_SHUFFLEI2_SCI_B,
+      RISCV::CV_SHUFFLEI3_SCI_B,
+  };
+  unsigned OpcIdx = (Imm >> 6) & 0x3;
+  unsigned Imm6 = Imm & 0x3F;
+
+  const MCInstrDesc &Desc = TII->get(Opcodes[OpcIdx]);
+  BuildMI(MBB, MBBI, DL, Desc, DstReg).addReg(SrcReg).addImm(Imm6);
+
+  MBBI->eraseFromParent();
+  return true;
+}
+
 } // end of anonymous namespace
 
 INITIALIZE_PASS(RISCVExpandPseudo, "riscv-expand-pseudo",
diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfoXCV.td b/llvm/lib/Target/RISCV/RISCVInstrInfoXCV.td
index ec93f60366e1e..281a9f1edff39 100644
--- a/llvm/lib/Target/RISCV/RISCVInstrInfoXCV.td
+++ b/llvm/lib/Target/RISCV/RISCVInstrInfoXCV.td
@@ -850,3 +850,290 @@ let Predicates = [HasVendorXCVmac] in {
   def : PatCoreVMacGprGprGprUimm5<"macsRN", "MACSRN">;
   def : PatCoreVMacGprGprGprUimm5<"machhsRN", "MACHHSRN">;
 }
+
+//===----------------------------------------------------------------------===//
+// XCVsimd pseudo-instruction for cv.shuffle.sci.b
+//===----------------------------------------------------------------------===//
+// The hardware encodes the 8-bit shuffle immediate by splitting it across
+// four different opcodes: cv.shufflei0/1/2/3.sci.b, where bits [7:6] select
+// the opcode and bits [5:0] are the payload. This pseudo absorbs the full
+// 8-bit immediate; RISCVExpandPseudoInsts splits it into the correct real
+// instruction.
+
+let Predicates = [HasVendorXCVsimd, IsRV32] in {
+  let hasSideEffects = 0, mayLoad = 0, mayStore = 0, isCodeGenOnly = 1 in
+  def CV_SHUFFLE_SCI_B_PSEUDO
+    : Pseudo<(outs GPR:$rd), (ins GPR:$rs1, i32imm:$imm), []>;
+}
+
+//===----------------------------------------------------------------------===//
+// Pattern helper multiclasses for XCVsimd
+//===----------------------------------------------------------------------===//
+
+// Binary signed: RR variants + SCI with simm6
+multiclass PatCoreVSimdSigned<string iname> {
+  def : PatGprGpr<!cast<Intrinsic>("int_riscv_cv_simd_" # iname # "_h"),
+                  !cast<RVInst>("CV_" # NAME # "_H")>;
+  def : PatGprGpr<!cast<Intrinsic>("int_riscv_cv_simd_" # iname # "_b"),
+                  !cast<RVInst>("CV_" # NAME # "_B")>;
+  def : PatGprGpr<!cast<Intrinsic>("int_riscv_cv_simd_" # iname # "_sc_h"),
+                  !cast<RVInst>("CV_" # NAME # "_SC_H")>;
+  def : PatGprGpr<!cast<Intrinsic>("int_riscv_cv_simd_" # iname # "_sc_b"),
+                  !cast<RVInst>("CV_" # NAME # "_SC_B")>;
+  // SCI: when the scalar fits in simm6, prefer the immediate instruction
+  def : Pat<(!cast<Intrinsic>("int_riscv_cv_simd_" # iname # "_sc_h")
+               GPR:$rs1, simm6:$imm),
+            (!cast<RVInst>("CV_" # NAME # "_SCI_H") GPR:$rs1, simm6:$imm)>;
+  def : Pat<(!cast<Intrinsic>("int_riscv_cv_simd_" # iname # "_sc_b")
+               GPR:$rs1, simm6:$imm),
+            (!cast<RVInst>("CV_" # NAME # "_SCI_B") GPR:$rs1, simm6:$imm)>;
+}
+
+// Binary unsigned: RR variants + SCI with uimm6
+multiclass PatCoreVSimdUnsigned<string iname> {
+  def : PatGprGpr<!cast<Intrinsic>("int_riscv_cv_simd_" # iname # "_h"),
+                  !cast<RVInst>("CV_" # NAME # "_H")>;
+  def : PatGprGpr<!cast<Intrinsic>("int_riscv_cv_simd_" # iname # "_b"),
+                  !cast<RVInst>("CV_" # NAME # "_B")>;
+  def : PatGprGpr<!cast<Intrinsic>("int_riscv_cv_simd_" # iname # "_sc_h"),
+                  !cast<RVInst>("CV_" # NAME # "_SC_H")>;
+  def : PatGprGpr<!cast<Intrinsic>("int_riscv_cv_simd_" # iname # "_sc_b"),
+                  !cast<RVInst>("CV_" # NAME # "_SC_B")>;
+  def : Pat<(!cast<Intrinsic>("int_riscv_cv_simd_" # iname # "_sc_h")
+               GPR:$rs1, uimm6:$imm),
+            (!cast<RVInst>("CV_" # NAME # "_SCI_H") GPR:$rs1, uimm6:$imm)>;
+  def : Pat<(!cast<Intrinsic>("int_riscv_cv_simd_" # iname # "_sc_b")
+               GPR:$rs1, uimm6:$imm),
+            (!cast<RVInst>("CV_" # NAME # "_SCI_B") GPR:$rs1, uimm6:$imm)>;
+}
+
+// Shift: RR variants + SCI with uimm4 for .h, uimm3 for .b
+multiclass PatCoreVSimdShift<string iname> {
+  def : PatGprGpr<!cast<Intrinsic>("int_riscv_cv_simd_" # iname # "_h"),
+                  !cast<RVInst>("CV_" # NAME # "_H")>;
+  def : PatGprGpr<!cast<Intrinsic>("int_riscv_cv_simd_" # iname # "_b"),
+                  !cast<RVInst>("CV_" # NAME # "_B")>;
+  def : PatGprGpr<!cast<Intrinsic>("int_riscv_cv_simd_" # iname # "_sc_h"),
+                  !cast<RVInst>("CV_" # NAME # "_SC_H")>;
+  def : PatGprGpr<!cast<Intrinsic>("int_riscv_cv_simd_" # iname # "_sc_b"),
+                  !cast<RVInst>("CV_" # NAME # "_SC_B")>;
+  def : Pat<(!cast<Intrinsic>("int_riscv_cv_simd_" # iname # "_sc_h")
+               GPR:$rs1, uimm4:$imm),
+            (!cast<RVInst>("CV_" # NAME # "_SCI_H") GPR:$rs1, uimm4:$imm)>;
+  def : Pat<(!cast<Intrinsic>("int_riscv_cv_simd_" # iname # "_sc_b")
+               GPR:$rs1, uimm3:$imm),
+            (!cast<RVInst>("CV_" # NAME # "_SCI_B") GPR:$rs1, uimm3:$imm)>;
+}
+
+// Accumulating signed (Wb): intrinsic(rs1, rs2, acc) → instr(acc, rs1, rs2)
+// + SCI variant where rs2 (arg1) is simm6
+multiclass PatCoreVSimdSignedWb<string iname> {
+  def : Pat<(!cast<Intrinsic>("int_riscv_cv_simd_" # iname # "_h")
+               GPR:$rs1, GPR:$rs2, GPR:$rd),
+            (!cast<RVInst>("CV_" # NAME # "_H") GPR:$rd, GPR:$rs1, GPR:$rs2)>;
+  def : Pat<(!cast<Intrinsic>("int_riscv_cv_simd_" # iname # "_b")
+               GPR:$rs1, GPR:$rs2, GPR:$rd),
+            (!cast<RVInst>("CV_" # NAME # "_B") GPR:$rd, GPR:$rs1, GPR:$rs2)>;
+  def : Pat<(!cast<Intrinsic>("int_riscv_cv_simd_" # iname # "_sc_h")
+               GPR:$rs1, GPR:$rs2, GPR:$rd),
+            (!cast<RVInst>("CV_" # NAME # "_SC_H") GPR:$rd, GPR:$rs1, GPR:$rs2)>;
+  def : Pat<(!cast<Intrinsic>("int_riscv_cv_simd_" # iname # "_sc_b")
+               GPR:$rs1, GPR:$rs2, GPR:$rd),
+            (!cast<RVInst>("CV_" # NAME # "_SC_B") GPR:$rd, GPR:$rs1, GPR:$rs2)>;
+  def : Pat<(!cast<Intrinsic>("int_riscv_cv_simd_" # iname # "_sc_h")
+               GPR:$rs1, simm6:$imm, GPR:$rd),
+            (!cast<RVInst>("CV_" # NAME # "_SCI_H") GPR:$rd, GPR:$rs1, simm6:$imm)>;
+  def : Pat<(!cast<Intrinsic>("int_riscv_cv_simd_" # iname # "_sc_b")
+               GPR:$rs1, simm6:$imm, GPR:$rd),
+            (!cast<RVInst>("CV_" # NAME # "_SCI_B") GPR:$rd, GPR:$rs1, simm6:$imm)>;
+}
+
+// Accumulating unsigned (Wb): same but SCI uses uimm6
+multiclass PatCoreVSimdUnsignedWb<string iname> {
+  def : Pat<(!cast<Intrinsic>("int_riscv_cv_simd_" # iname # "_h")
+               GPR:$rs1, GPR:$rs2, GPR:$rd),
+            (!cast<RVInst>("CV_" # NAME # "_H") GPR:$rd, GPR:$rs1, GPR:$rs2)>;
+  def : Pat<(!cast<Intrinsic>("int_riscv_cv_simd_" # iname # "_b")
+               GPR:$rs1, GPR:$rs2, GPR:$rd),
+            (!cast<RVInst>("CV_" # NAME # "_B") GPR:$rd, GPR:$rs1, GPR:$rs2)>;
+  def : Pat<(!cast<Intrinsic>("int_riscv_cv_simd_" # iname # "_sc_h")
+               GPR:$rs1, GPR:$rs2, GPR:$rd),
+            (!cast<RVInst>("CV_" # NAME # "_SC_H") GPR:$rd, GPR:$rs1, GPR:$rs2)>;
+  def : Pat<(!cast<Intrinsic>("int_riscv_cv_simd_" # iname # "_sc_b")
+               GPR:$rs1, GPR:$rs2, GPR:$rd),
+            (!cast<RVInst>("CV_" # NAME # "_SC_B") GPR:$rd, GPR:$rs1, GPR:$rs2)>;
+  def : Pat<(!cast<Intrinsic>("int_riscv_cv_simd_" # iname # "_sc_h")
+               GPR:$rs1, uimm6:$imm, GPR:$rd),
+            (!cast<RVInst>("CV_" # NAME # "_SCI_H") GPR:$rd, GPR:$rs1, uimm6:$imm)>;
+  def : Pat<(!cast<Intrinsic>("int_riscv_cv_simd_" # iname # "_sc_b")
+               GPR:$rs1, uimm6:$imm, GPR:$rd),
+            (!cast<RVInst>("CV_" # NAME # "_SCI_B") GPR:$rd, GPR:$rs1, uimm6:$imm)>;
+}
+
+//===----------------------------------------------------------------------===//
+// XCVsimd intrinsic-to-instruction patterns
+//===----------------------------------------------------------------------===//
+
+let Predicates = [HasVendorXCVsimd, IsRV32], AddedComplexity = 1 in {
+
+  // ---- ADD / SUB ----
+  // add_h / sub_h use a divcode immediate to select between 4 instructions
+  // intrinsic: (rs1, rs2, divcode_IMM) -> rd
+  def : Pat<(int_riscv_cv_simd_add_h GPR:$rs1, GPR:$rs2, 0),
+            (CV_ADD_H GPR:$rs1, GPR:$rs2)>;
+  def : Pat<(int_riscv_cv_simd_add_h GPR:$rs1, GPR:$rs2, 1),
+            (CV_ADD_DIV2 GPR:$rs1, GPR:$rs2)>;
+  def : Pat<(int_riscv_cv_simd_add_h GPR:$rs1, GPR:$rs2, 2),
+            (CV_ADD_DIV4 GPR:$rs1, GPR:$rs2)>;
+  def : Pat<(int_riscv_cv_simd_add_h GPR:$rs1, GPR:$rs2, 3),
+            (CV_ADD_DIV8 GPR:$rs1, GPR:$rs2)>;
+
+  def : PatGprGpr<int_riscv_cv_simd_add_b,    CV_ADD_B>;
+  def : PatGprGpr<int_riscv_cv_simd_add_sc_h,  CV_ADD_SC_H>;
+  def : PatGprGpr<int_riscv_cv_simd_add_sc_b,  CV_ADD_SC_B>;
+  def : Pat<(int_riscv_cv_simd_add_sc_h GPR:$rs1, simm6:$imm),
+            (CV_ADD_SCI_H GPR:$rs1, simm6:$imm)>;
+  def : Pat<(int_riscv_cv_simd_add_sc_b GPR:$rs1, simm6:$imm),
+            (CV_ADD_SCI_B GPR:$rs1, simm6:$imm)>;
+
+  def : Pat<(int_riscv_cv_simd_sub_h GPR:$rs1, GPR:$rs2, 0),
+            (CV_SUB_H GPR:$rs1, GPR:$rs2)>;
+  def : Pat<(int_riscv_cv_simd_sub_h GPR:$rs1, GPR:$rs2, 1),
+            (CV_SUB_DIV2 GPR:$rs1, GPR:$rs2)>;
+  def : Pat<(int_riscv_cv_simd_sub_h GPR:$rs1, GPR:$rs2, 2),
+            (CV_SUB_DIV4 GPR:$rs1, GPR:$rs2)>;
+  def : Pat<(int_riscv_cv_simd_sub_h GPR:$rs1, GPR:$rs2, 3),
+            (CV_SUB_DIV8 GPR:$rs1, GPR:$rs2)>;
+
+  def : PatGprGpr<int_riscv_cv_simd_sub_b,    CV_SUB_B>;
+  def : PatGprGpr<int_riscv_cv_simd_sub_sc_h,  CV_SUB_SC_H>;
+  def : PatGprGpr<int_riscv_cv_simd_sub_sc_b,  CV_SUB_SC_B>;
+  def : Pat<(int_riscv_cv_simd_sub_sc_h GPR:$rs1, simm6:$imm),
+            (CV_SUB_SCI_H GPR:$rs1, simm6:$imm)>;
+  def : Pat<(int_riscv_cv_simd_sub_sc_b GPR:$rs1, simm6:$imm),
+            (CV_SUB_SCI_B GPR:$rs1, simm6:$imm)>;
+
+  // ---- AVG / AVGU / MIN / MINU / MAX / MAXU ----
+  defm AVG  : PatCoreVSimdSigned<"avg">;
+  defm AVGU : PatCoreVSimdUnsigned<"avgu">;
+  defm MIN  : PatCoreVSimdSigned<"min">;
+  defm MINU : PatCoreVSimdUnsigned<"minu">;
+  defm MAX  : PatCoreVSimdSigned<"max">;
+  defm MAXU : PatCoreVSimdUnsigned<"maxu">;
+
+  // ---- SRL / SRA / SLL ----
+  defm SRL : PatCoreVSimdShift<"srl">;
+  defm SRA : PatCoreVSimdShift<"sra">;
+  defm SLL : PatCoreVSimdShift<"sll">;
+
+  // ---- OR / XOR / AND ----
+  defm OR  : PatCoreVSimdSigned<"or">;
+  defm XOR : PatCoreVSimdSigned<"xor">;
+  defm AND : PatCoreVSimdSigned<"and">;
+
+  // ---- ABS ----
+  def : PatGpr<int_riscv_cv_simd_abs_h, CV_ABS_H>;
+  def : PatGpr<int_riscv_cv_simd_abs_b, CV_ABS_B>;
+
+  // ---- DOT PRODUCTS (non-accumulating) ----
+  defm DOTUP  : PatCoreVSimdUnsigned<"dotup">;
+  defm DOTUSP : PatCoreVSimdSigned<"dotusp">;
+  defm DOTSP  : PatCoreVSimdSigned<"dotsp">;
+
+  // ---- SDOT (accumulating) ----
+  defm SDOTUP  : PatCoreVSimdUnsignedWb<"sdotup">;
+  defm SDOTUSP : PatCoreVSimdSignedWb<"sdotusp">;
+  defm SDOTSP  : PatCoreVSimdSignedWb<"sdotsp">;
+
+  // ---- EXTRACT / EXTRACTU ----
+  // intrinsic: (rs1, IMM) -> rd
+  def : Pat<(int_riscv_cv_simd_extract_h  GPR:$rs1, timm:$imm),
+            (CV_EXTRACT_H  GPR:$rs1, timm:$imm)>;
+  def : Pat<(int_riscv_cv_simd_extract_b  GPR:$rs1, timm:$imm),
+            (CV_EXTRACT_B  GPR:$rs1, timm:$imm)>;
+  def : Pat<(int_riscv_cv_simd_extractu_h GPR:$rs1, timm:$imm),
+            (CV_EXTRACTU_H GPR:$rs1, timm:$imm)>;
+  def : Pat<(int_riscv_cv_simd_extractu_b GPR:$rs1, timm:$imm),
+            (CV_EXTRACTU_B GPR:$rs1, timm:$imm)>;
+
+  // ---- INSERT ----
+  // intrinsic: (rd_in, rs1, IMM) -> rd_out
+  def : Pat<(int_riscv_cv_simd_insert_h GPR:$rd, GPR:$rs1, timm:$imm),
+            (CV_INSERT_H GPR:$rd, GPR:$rs1, timm:$imm)>;
+  def : Pat<(int_riscv_cv_simd_insert_b GPR:$rd, GPR:$rs1, timm:$imm),
+            (CV_INSERT_B GPR:$rd, GPR:$rs1, timm:$imm)>;
+
+  // ---- SHUFFLE ----
+  def : PatGprGpr<int_riscv_cv_simd_shuffle_h, CV_SHUFFLE_H>;
+  def : PatGprGpr<int_riscv_cv_simd_shuffle_b, CV_SHUFFLE_B>;
+  def : Pat<(int_riscv_cv_simd_shuffle_sci_h GPR:$rs1, timm:$imm),
+            (CV_SHUFFLE_SCI_H GPR:$rs1, timm:$imm)>;
+  // shuffle_sci_b goes through the pseudo (8-bit imm split by expander)
+  def : Pat<(int_riscv_cv_simd_shuffle_sci_b GPR:$rs1, timm:$imm),
+            (CV_SHUFFLE_SCI_B_PSEUDO GPR:$rs1, timm:$imm)>;
+
+  // ---- SHUFFLE2: (rs1, rs2, rd_in) -> rd_out ----
+  def : Pat<(int_riscv_cv_simd_shuffle2_h GPR:$rs1, GPR:$rs2, GPR:$rd),
+            (CV_SHUFFLE2_H GPR:$rd, GPR:$rs1, GPR:$rs2)>;
+  def : Pat<(int_riscv_cv_simd_shuffle2_b GPR:$rs1, GPR:$rs2, GPR:$rd),
+            (CV_SHUFFLE2_B GPR:$rd, GPR:$rs1, GPR:$rs2)>;
+
+  // ---- PACK ----
+  // pack (packlo_h) and pack.h (packhi_h) are plain binary: (rs1, rs2) -> rd
+  def : PatGprGpr<int_riscv_cv_simd_packlo_h, CV_PACK>;
+  def : PatGprGpr<int_riscv_cv_simd_packhi_h, CV_PACK_H>;
+  // packhi.b / packlo.b are accumulating: (rd_in, rs1, rs2) -> rd_out
+  def : Pat<(int_riscv_cv_simd_packhi_b GPR:$rd, GPR:$rs1, GPR:$rs2),
+            (CV_PACKHI_B GPR:$rd, GPR:$rs1, GPR:$rs2)>;
+  def : Pat<(int_riscv_cv_simd_packlo_b GPR:$rd, GPR:$rs1, GPR:$rs2),
+            (CV_PACKLO_B GPR:$rd, GPR:$rs1, GPR:$rs2)>;
+
+  // ---- COMPARE (signed) ----
+  defm CMPEQ : PatCoreVSimdSigned<"cmpeq">;
+  defm CMPNE : PatCoreVSimdSigned<"cmpne">;
+  defm CMPGT : PatCoreVSimdSigned<"cmpgt">;
+  defm CMPGE : PatCoreVSimdSigned<"cmpge">;
+  defm CMPLT : PatCoreVSimdSigned<"cmplt">;
+  defm CMPLE : PatCoreVSimdSigned<"cmple">;
+
+  // ---- COMPARE (unsigned) ----
+  defm CMPGTU : PatCoreVSimdUnsigned<"cmpgtu">;
+  defm CMPGEU : PatCoreVSimdUnsigned<"cmpgeu">;
+  defm CMPLTU : PatCoreVSimdUnsigned<"cmpltu">;
+  defm CMPLEU : PatCoreVSimdUnsigned<"cmpleu">;
+
+  // ---- COMPLEX: cplxmul ----
+  // intrinsic: (rs1, rs2, rd_in, divcode_IMM) -> rd_out
+  def : Pat<(int_riscv_cv_simd_cplxmul_r GPR:$rs1, GPR:$rs2, GPR:$rd, 0),
+            (CV_CPLXMUL_R GPR:$rd, GPR:$rs1, GPR:$rs2)>;
+  def : Pat<(int_riscv_cv_simd_cplxmul_r GPR:$rs1, GPR:$rs2, GPR:$rd, 1),
+            (CV_CPLXMUL_R_DIV2 GPR:$rd, GPR:$rs1, GPR:$rs2)>;
+  def : Pat<(int_riscv_cv_simd_cplxmul_r GPR:$rs1, GPR:$rs2, GPR:$rd, 2),
+            (CV_CPLXMUL_R_DIV4 GPR:$rd, GPR:$rs1, GPR:$rs2)>;
+  def : Pat<(int_riscv_cv_simd_cplxmul_r GPR:$rs1, GPR:$rs2, GPR:$rd, 3),
+            (CV_CPLXMUL_R_DIV8 GPR:$rd, GPR:$rs1, GPR:$rs2)>;
+
+  def : Pat<(int_riscv_cv_simd_cplxmul_i GPR:$rs1, GPR:$rs2, GPR:$rd, 0),
+            (CV_CPLXMUL_I GPR:$rd, GPR:$rs1, GPR:$rs2)>;
+  def : Pat<(int_riscv_cv_simd_cplxmul_i GPR:$rs1, GPR:$rs2, GPR:$rd, 1),
+            (CV_CPLXMUL_I_DIV2 GPR:$rd, GPR:$rs1, GPR:$rs2)>;
+  def : Pat<(int_riscv_cv_simd_cplxmul_i GPR:$rs1, GPR:$rs2, GPR:$rd, 2),
+            (CV_CPLXMUL_I_DIV4 GPR:$rd, GPR:$rs1, GPR:$rs2)>;
+  def : Pat<(int_riscv_cv_simd_cplxmul_i GPR:$rs1, GPR:$rs2, GPR:$rd, 3),
+            (CV_CPLXMUL_I_DIV8 GPR:$rd, GPR:$rs1, GPR:$rs2)>;
+
+  // ---- COMPLEX: cplxconj ----
+  def : PatGpr<int_riscv_cv_simd_cplxconj, CV_CPLXCONJ>;
+
+  // ---- COMPLEX: subrotmj ----
+  // intrinsic: (rs1, rs2, divcode_IMM) -> rd
+  def : Pat<(int_riscv_cv_simd_subrotmj GPR:$rs1, GPR:$rs2, 0),
+            (CV_SUBROTMJ GPR:$rs1, GPR:$rs2)>;
+  def : Pat<(int_riscv_cv_simd_subrotmj GPR:$rs1, GPR:$rs2, 1),
+            (CV_SUBROTMJ_DIV2 GPR:$rs1, GPR:$rs2)>;
+  def : Pat<(int_riscv_cv_simd_subrotmj GPR:$rs1, GPR:$rs2, 2),
+            (CV_SUBROTMJ_DIV4 GPR:$rs1, GPR:$rs2)>;
+  def : Pat<(int_riscv_cv_simd_subrotmj GPR:$rs1, GPR:$rs2, 3),
+            (CV_SUBROTMJ_DIV8 GPR:$rs1, GPR:$rs2)>;
+
+} // Predicates = [HasVendorXCVsimd, IsRV32], AddedComplexity = 1
diff --git a/llvm/test/CodeGen/RISCV/xcvsimd.ll b/llvm/test/CodeGen/RISCV/xcvsimd.ll
new file mode 100644
index 0000000000000..20cb4f787797d
--- /dev/null
+++ b/llvm/test/CodeGen/RISCV/xcvsimd.ll
@@ -0,0 +1,1115 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
+; RUN: llc -mtriple=riscv32 -mattr=+m,+xcvsimd -verify-machineinstrs < %s \
+; RUN:   | FileCheck %s
+
+; This file tests that all XCVsimd LLVM IR intrinsics are correctly lowered
+; to their corresponding CV32E40P machine instructions.
+
+;===----------------------------------------------------------------------===;
+; ADD / SUB
+;===----------------------------------------------------------------------===;
+
+define i32 @test_cv_simd_add_h(i32 %a, i32 %b) {
+; CHECK-LABEL: test_cv_simd_add_h:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    cv.add.h a0, a0, a1
+; CHECK-NEXT:    ret
+  %res = call i32 @llvm.riscv.cv.simd.add.h(i32 %a, i32 %b, i32 0)
+  ret i32 %res
+}
+
+define i32 @test_cv_simd_add_h_div2(i32 %a, i32 %b) {
+; CHECK-LABEL: test_cv_simd_add_h_div2:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    cv.add.div2 a0, a0, a1
+; CHECK-NEXT:    ret
+  %res = call i32 @llvm.riscv.cv.simd.add.h(i32 %a, i32 %b, i32 1)
+  ret i32 %res
+}
+
+define i32 @test_cv_simd_add_h_div4(i32 %a, i32 %b) {
+; CHECK-LABEL: test_cv_simd_add_h_div4:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    cv.add.div4 a0, a0, a1
+; CHECK-NEXT:    ret
+  %res = call i32 @llvm.riscv.cv.simd.add.h(i32 %a, i32 %b, i32 2)
+  ret i32 %res
+}
+
+define i32 @test_cv_simd_add_h_div8(i32 %a, i32 %b) {
+; CHECK-LABEL: test_cv_simd_add_h_div8:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    cv.add.div8 a0, a0, a1
+; CHECK-NEXT:    ret
+  %res = call i32 @llvm.riscv.cv.simd.add.h(i32 %a, i32 %b, i32 3)
+  ret i32 %res
+}
+
+define i32 @test_cv_simd_add_b(i32 %a, i32 %b) {
+; CHECK-LABEL: test_cv_simd_add_b:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    cv.add.b a0, a0, a1
+; CHECK-NEXT:    ret
+  %res = call i32 @llvm.riscv.cv.simd.add.b(i32 %a, i32 %b)
+  ret i32 %res
+}
+
+define i32 @test_cv_simd_add_sc_h(i32 %a, i32 %b) {
+; CHECK-LABEL: test_cv_simd_add_sc_h:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    cv.add.sc.h a0, a0, a1
+; CHECK-NEXT:    ret
+  %res = call i32 @llvm.riscv.cv.simd.add.sc.h(i32 %a, i32 %b)
+  ret i32 %res
+}
+
+define i32 @test_cv_simd_add_sc_b(i32 %a, i32 %b) {
+; CHECK-LABEL: test_cv_simd_add_sc_b:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    cv.add.sc.b a0, a0, a1
+; CHECK-NEXT:    ret
+  %res = call i32 @llvm.riscv.cv.simd.add.sc.b(i32 %a, i32 %b)
+  ret i32 %res
+}
+
+define i32 @test_cv_simd_sub_h(i32 %a, i32 %b) {
+; CHECK-LABEL: test_cv_simd_sub_h:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    cv.sub.h a0, a0, a1
+; CHECK-NEXT:    ret
+  %res = call i32 @llvm.riscv.cv.simd.sub.h(i32 %a, i32 %b, i32 0)
+  ret i32 %res
+}
+
+define i32 @test_cv_simd_sub_h_div2(i32 %a, i32 %b) {
+; CHECK-LABEL: test_cv_simd_sub_h_div2:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    cv.sub.div2 a0, a0, a1
+; CHECK-NEXT:    ret
+  %res = call i32 @llvm.riscv.cv.simd.sub.h(i32 %a, i32 %b, i32 1)
+  ret i32 %res
+}
+
+define i32 @test_cv_simd_sub_h_div4(i32 %a, i32 %b) {
+; CHECK-LABEL: test_cv_simd_sub_h_div4:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    cv.sub.div4 a0, a0, a1
+; CHECK-NEXT:    ret
+  %res = call i32 @llvm.riscv.cv.simd.sub.h(i32 %a, i32 %b, i32 2)
+  ret i32 %res
+}
+
+define i32 @test_cv_simd_sub_h_div8(i32 %a, i32 %b) {
+; CHECK-LABEL: test_cv_simd_sub_h_div8:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    cv.sub.div8 a0, a0, a1
+; CHECK-NEXT:    ret
+  %res = call i32 @llvm.riscv.cv.simd.sub.h(i32 %a, i32 %b, i32 3)
+  ret i32 %res
+}
+
+define i32 @test_cv_simd_sub_b(i32 %a, i32 %b) {
+; CHECK-LABEL: test_cv_simd_sub_b:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    cv.sub.b a0, a0, a1
+; CHECK-NEXT:    ret
+  %res = call i32 @llvm.riscv.cv.simd.sub.b(i32 %a, i32 %b)
+  ret i32 %res
+}
+
+define i32 @test_cv_simd_sub_sc_h(i32 %a, i32 %b) {
+; CHECK-LABEL: test_cv_simd_sub_sc_h:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    cv.sub.sc.h a0, a0, a1
+; CHECK-NEXT:    ret
+  %res = call i32 @llvm.riscv.cv.simd.sub.sc.h(i32 %a, i32 %b)
+  ret i32 %res
+}
+
+define i32 @test_cv_simd_sub_sc_b(i32 %a, i32 %b) {
+; CHECK-LABEL: test_cv_simd_sub_sc_b:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    cv.sub.sc.b a0, a0, a1
+; CHECK-NEXT:    ret
+  %res = call i32 @llvm.riscv.cv.simd.sub.sc.b(i32 %a, i32 %b)
+  ret i32 %res
+}
+
+;===----------------------------------------------------------------------===;
+; AVG / AVGU
+;===----------------------------------------------------------------------===;
+
+define i32 @test_cv_simd_avg_h(i32 %a, i32 %b) {
+; CHECK-LABEL: test_cv_simd_avg_h:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    cv.avg.h a0, a0, a1
+; CHECK-NEXT:    ret
+  %res = call i32 @llvm.riscv.cv.simd.avg.h(i32 %a, i32 %b)
+  ret i32 %res
+}
+
+define i32 @test_cv_simd_avg_b(i32 %a, i32 %b) {
+; CHECK-LABEL: test_cv_simd_avg_b:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    cv.avg.b a0, a0, a1
+; CHECK-NEXT:    ret
+  %res = call i32 @llvm.riscv.cv.simd.avg.b(i32 %a, i32 %b)
+  ret i32 %res
+}
+
+define i32 @test_cv_simd_avg_sc_h(i32 %a, i32 %b) {
+; CHECK-LABEL: test_cv_simd_avg_sc_h:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    cv.avg.sc.h a0, a0, a1
+; CHECK-NEXT:    ret
+  %res = call i32 @llvm.riscv.cv.simd.avg.sc.h(i32 %a, i32 %b)
+  ret i32 %res
+}
+
+define i32 @test_cv_simd_avg_sc_b(i32 %a, i32 %b) {
+; CHECK-LABEL: test_cv_simd_avg_sc_b:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    cv.avg.sc.b a0, a0, a1
+; CHECK-NEXT:    ret
+  %res = call i32 @llvm.riscv.cv.simd.avg.sc.b(i32 %a, i32 %b)
+  ret i32 %res
+}
+
+define i32 @test_cv_simd_avgu_h(i32 %a, i32 %b) {
+; CHECK-LABEL: test_cv_simd_avgu_h:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    cv.avgu.h a0, a0, a1
+; CHECK-NEXT:    ret
+  %res = call i32 @llvm.riscv.cv.simd.avgu.h(i32 %a, i32 %b)
+  ret i32 %res
+}
+
+define i32 @test_cv_simd_avgu_b(i32 %a, i32 %b) {
+; CHECK-LABEL: test_cv_simd_avgu_b:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    cv.avgu.b a0, a0, a1
+; CHECK-NEXT:    ret
+  %res = call i32 @llvm.riscv.cv.simd.avgu.b(i32 %a, i32 %b)
+  ret i32 %res
+}
+
+define i32 @test_cv_simd_avgu_sc_h(i32 %a, i32 %b) {
+; CHECK-LABEL: test_cv_simd_avgu_sc_h:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    cv.avgu.sc.h a0, a0, a1
+; CHECK-NEXT:    ret
+  %res = call i32 @llvm.riscv.cv.simd.avgu.sc.h(i32 %a, i32 %b)
+  ret i32 %res
+}
+
+define i32 @test_cv_simd_avgu_sc_b(i32 %a, i32 %b) {
+; CHECK-LABEL: test_cv_simd_avgu_sc_b:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    cv.avgu.sc.b a0, a0, a1
+; CHECK-NEXT:    ret
+  %res = call i32 @llvm.riscv.cv.simd.avgu.sc.b(i32 %a, i32 %b)
+  ret i32 %res
+}
+
+;===----------------------------------------------------------------------===;
+; MIN / MINU / MAX / MAXU (representative: _h and _sc_b for each)
+;===----------------------------------------------------------------------===;
+
+define i32 @test_cv_simd_min_h(i32 %a, i32 %b) {
+; CHECK-LABEL: test_cv_simd_min_h:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    cv.min.h a0, a0, a1
+; CHECK-NEXT:    ret
+  %res = call i32 @llvm.riscv.cv.simd.min.h(i32 %a, i32 %b)
+  ret i32 %res
+}
+
+define i32 @test_cv_simd_min_b(i32 %a, i32 %b) {
+; CHECK-LABEL: test_cv_simd_min_b:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    cv.min.b a0, a0, a1
+; CHECK-NEXT:    ret
+  %res = call i32 @llvm.riscv.cv.simd.min.b(i32 %a, i32 %b)
+  ret i32 %res
+}
+
+define i32 @test_cv_simd_min_sc_h(i32 %a, i32 %b) {
+; CHECK-LABEL: test_cv_simd_min_sc_h:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    cv.min.sc.h a0, a0, a1
+; CHECK-NEXT:    ret
+  %res = call i32 @llvm.riscv.cv.simd.min.sc.h(i32 %a, i32 %b)
+  ret i32 %res
+}
+
+define i32 @test_cv_simd_min_sc_b(i32 %a, i32 %b) {
+; CHECK-LABEL: test_cv_simd_min_sc_b:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    cv.min.sc.b a0, a0, a1
+; CHECK-NEXT:    ret
+  %res = call i32 @llvm.riscv.cv.simd.min.sc.b(i32 %a, i32 %b)
+  ret i32 %res
+}
+
+define i32 @test_cv_simd_minu_h(i32 %a, i32 %b) {
+; CHECK-LABEL: test_cv_simd_minu_h:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    cv.minu.h a0, a0, a1
+; CHECK-NEXT:    ret
+  %res = call i32 @llvm.riscv.cv.simd.minu.h(i32 %a, i32 %b)
+  ret i32 %res
+}
+
+define i32 @test_cv_simd_minu_b(i32 %a, i32 %b) {
+; CHECK-LABEL: test_cv_simd_minu_b:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    cv.minu.b a0, a0, a1
+; CHECK-NEXT:    ret
+  %res = call i32 @llvm.riscv.cv.simd.minu.b(i32 %a, i32 %b)
+  ret i32 %res
+}
+
+define i32 @test_cv_simd_max_h(i32 %a, i32 %b) {
+; CHECK-LABEL: test_cv_simd_max_h:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    cv.max.h a0, a0, a1
+; CHECK-NEXT:    ret
+  %res = call i32 @llvm.riscv.cv.simd.max.h(i32 %a, i32 %b)
+  ret i32 %res
+}
+
+define i32 @test_cv_simd_max_b(i32 %a, i32 %b) {
+; CHECK-LABEL: test_cv_simd_max_b:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    cv.max.b a0, a0, a1
+; CHECK-NEXT:    ret
+  %res = call i32 @llvm.riscv.cv.simd.max.b(i32 %a, i32 %b)
+  ret i32 %res
+}
+
+define i32 @test_cv_simd_maxu_h(i32 %a, i32 %b) {
+; CHECK-LABEL: test_cv_simd_maxu_h:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    cv.maxu.h a0, a0, a1
+; CHECK-NEXT:    ret
+  %res = call i32 @llvm.riscv.cv.simd.maxu.h(i32 %a, i32 %b)
+  ret i32 %res
+}
+
+define i32 @test_cv_simd_maxu_b(i32 %a, i32 %b) {
+; CHECK-LABEL: test_cv_simd_maxu_b:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    cv.maxu.b a0, a0, a1
+; CHECK-NEXT:    ret
+  %res = call i32 @llvm.riscv.cv.simd.maxu.b(i32 %a, i32 %b)
+  ret i32 %res
+}
+
+;===----------------------------------------------------------------------===;
+; SRL / SRA / SLL
+;===----------------------------------------------------------------------===;
+
+define i32 @test_cv_simd_srl_h(i32 %a, i32 %b) {
+; CHECK-LABEL: test_cv_simd_srl_h:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    cv.srl.h a0, a0, a1
+; CHECK-NEXT:    ret
+  %res = call i32 @llvm.riscv.cv.simd.srl.h(i32 %a, i32 %b)
+  ret i32 %res
+}
+
+define i32 @test_cv_simd_srl_b(i32 %a, i32 %b) {
+; CHECK-LABEL: test_cv_simd_srl_b:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    cv.srl.b a0, a0, a1
+; CHECK-NEXT:    ret
+  %res = call i32 @llvm.riscv.cv.simd.srl.b(i32 %a, i32 %b)
+  ret i32 %res
+}
+
+define i32 @test_cv_simd_srl_sc_h(i32 %a, i32 %b) {
+; CHECK-LABEL: test_cv_simd_srl_sc_h:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    cv.srl.sc.h a0, a0, a1
+; CHECK-NEXT:    ret
+  %res = call i32 @llvm.riscv.cv.simd.srl.sc.h(i32 %a, i32 %b)
+  ret i32 %res
+}
+
+define i32 @test_cv_simd_srl_sc_b(i32 %a, i32 %b) {
+; CHECK-LABEL: test_cv_simd_srl_sc_b:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    cv.srl.sc.b a0, a0, a1
+; CHECK-NEXT:    ret
+  %res = call i32 @llvm.riscv.cv.simd.srl.sc.b(i32 %a, i32 %b)
+  ret i32 %res
+}
+
+define i32 @test_cv_simd_sra_h(i32 %a, i32 %b) {
+; CHECK-LABEL: test_cv_simd_sra_h:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    cv.sra.h a0, a0, a1
+; CHECK-NEXT:    ret
+  %res = call i32 @llvm.riscv.cv.simd.sra.h(i32 %a, i32 %b)
+  ret i32 %res
+}
+
+define i32 @test_cv_simd_sra_b(i32 %a, i32 %b) {
+; CHECK-LABEL: test_cv_simd_sra_b:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    cv.sra.b a0, a0, a1
+; CHECK-NEXT:    ret
+  %res = call i32 @llvm.riscv.cv.simd.sra.b(i32 %a, i32 %b)
+  ret i32 %res
+}
+
+define i32 @test_cv_simd_sll_h(i32 %a, i32 %b) {
+; CHECK-LABEL: test_cv_simd_sll_h:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    cv.sll.h a0, a0, a1
+; CHECK-NEXT:    ret
+  %res = call i32 @llvm.riscv.cv.simd.sll.h(i32 %a, i32 %b)
+  ret i32 %res
+}
+
+define i32 @test_cv_simd_sll_b(i32 %a, i32 %b) {
+; CHECK-LABEL: test_cv_simd_sll_b:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    cv.sll.b a0, a0, a1
+; CHECK-NEXT:    ret
+  %res = call i32 @llvm.riscv.cv.simd.sll.b(i32 %a, i32 %b)
+  ret i32 %res
+}
+
+;===----------------------------------------------------------------------===;
+; OR / XOR / AND
+;===----------------------------------------------------------------------===;
+
+define i32 @test_cv_simd_or_h(i32 %a, i32 %b) {
+; CHECK-LABEL: test_cv_simd_or_h:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    cv.or.h a0, a0, a1
+; CHECK-NEXT:    ret
+  %res = call i32 @llvm.riscv.cv.simd.or.h(i32 %a, i32 %b)
+  ret i32 %res
+}
+
+define i32 @test_cv_simd_or_b(i32 %a, i32 %b) {
+; CHECK-LABEL: test_cv_simd_or_b:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    cv.or.b a0, a0, a1
+; CHECK-NEXT:    ret
+  %res = call i32 @llvm.riscv.cv.simd.or.b(i32 %a, i32 %b)
+  ret i32 %res
+}
+
+define i32 @test_cv_simd_xor_h(i32 %a, i32 %b) {
+; CHECK-LABEL: test_cv_simd_xor_h:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    cv.xor.h a0, a0, a1
+; CHECK-NEXT:    ret
+  %res = call i32 @llvm.riscv.cv.simd.xor.h(i32 %a, i32 %b)
+  ret i32 %res
+}
+
+define i32 @test_cv_simd_xor_b(i32 %a, i32 %b) {
+; CHECK-LABEL: test_cv_simd_xor_b:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    cv.xor.b a0, a0, a1
+; CHECK-NEXT:    ret
+  %res = call i32 @llvm.riscv.cv.simd.xor.b(i32 %a, i32 %b)
+  ret i32 %res
+}
+
+define i32 @test_cv_simd_and_h(i32 %a, i32 %b) {
+; CHECK-LABEL: test_cv_simd_and_h:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    cv.and.h a0, a0, a1
+; CHECK-NEXT:    ret
+  %res = call i32 @llvm.riscv.cv.simd.and.h(i32 %a, i32 %b)
+  ret i32 %res
+}
+
+define i32 @test_cv_simd_and_b(i32 %a, i32 %b) {
+; CHECK-LABEL: test_cv_simd_and_b:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    cv.and.b a0, a0, a1
+; CHECK-NEXT:    ret
+  %res = call i32 @llvm.riscv.cv.simd.and.b(i32 %a, i32 %b)
+  ret i32 %res
+}
+
+;===----------------------------------------------------------------------===;
+; ABS
+;===----------------------------------------------------------------------===;
+
+define i32 @test_cv_simd_abs_h(i32 %a) {
+; CHECK-LABEL: test_cv_simd_abs_h:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    cv.abs.h a0, a0
+; CHECK-NEXT:    ret
+  %res = call i32 @llvm.riscv.cv.simd.abs.h(i32 %a)
+  ret i32 %res
+}
+
+define i32 @test_cv_simd_abs_b(i32 %a) {
+; CHECK-LABEL: test_cv_simd_abs_b:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    cv.abs.b a0, a0
+; CHECK-NEXT:    ret
+  %res = call i32 @llvm.riscv.cv.simd.abs.b(i32 %a)
+  ret i32 %res
+}
+
+;===----------------------------------------------------------------------===;
+; DOT PRODUCTS (non-accumulating)
+;===----------------------------------------------------------------------===;
+
+define i32 @test_cv_simd_dotup_h(i32 %a, i32 %b) {
+; CHECK-LABEL: test_cv_simd_dotup_h:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    cv.dotup.h a0, a0, a1
+; CHECK-NEXT:    ret
+  %res = call i32 @llvm.riscv.cv.simd.dotup.h(i32 %a, i32 %b)
+  ret i32 %res
+}
+
+define i32 @test_cv_simd_dotup_b(i32 %a, i32 %b) {
+; CHECK-LABEL: test_cv_simd_dotup_b:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    cv.dotup.b a0, a0, a1
+; CHECK-NEXT:    ret
+  %res = call i32 @llvm.riscv.cv.simd.dotup.b(i32 %a, i32 %b)
+  ret i32 %res
+}
+
+define i32 @test_cv_simd_dotup_sc_h(i32 %a, i32 %b) {
+; CHECK-LABEL: test_cv_simd_dotup_sc_h:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    cv.dotup.sc.h a0, a0, a1
+; CHECK-NEXT:    ret
+  %res = call i32 @llvm.riscv.cv.simd.dotup.sc.h(i32 %a, i32 %b)
+  ret i32 %res
+}
+
+define i32 @test_cv_simd_dotup_sc_b(i32 %a, i32 %b) {
+; CHECK-LABEL: test_cv_simd_dotup_sc_b:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    cv.dotup.sc.b a0, a0, a1
+; CHECK-NEXT:    ret
+  %res = call i32 @llvm.riscv.cv.simd.dotup.sc.b(i32 %a, i32 %b)
+  ret i32 %res
+}
+
+define i32 @test_cv_simd_dotusp_h(i32 %a, i32 %b) {
+; CHECK-LABEL: test_cv_simd_dotusp_h:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    cv.dotusp.h a0, a0, a1
+; CHECK-NEXT:    ret
+  %res = call i32 @llvm.riscv.cv.simd.dotusp.h(i32 %a, i32 %b)
+  ret i32 %res
+}
+
+define i32 @test_cv_simd_dotsp_h(i32 %a, i32 %b) {
+; CHECK-LABEL: test_cv_simd_dotsp_h:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    cv.dotsp.h a0, a0, a1
+; CHECK-NEXT:    ret
+  %res = call i32 @llvm.riscv.cv.simd.dotsp.h(i32 %a, i32 %b)
+  ret i32 %res
+}
+
+;===----------------------------------------------------------------------===;
+; SDOT (accumulating dot products)
+;===----------------------------------------------------------------------===;
+
+define i32 @test_cv_simd_sdotup_h(i32 %a, i32 %b, i32 %acc) {
+; CHECK-LABEL: test_cv_simd_sdotup_h:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    cv.sdotup.h a2, a0, a1
+; CHECK-NEXT:    mv a0, a2
+; CHECK-NEXT:    ret
+  %res = call i32 @llvm.riscv.cv.simd.sdotup.h(i32 %a, i32 %b, i32 %acc)
+  ret i32 %res
+}
+
+define i32 @test_cv_simd_sdotup_b(i32 %a, i32 %b, i32 %acc) {
+; CHECK-LABEL: test_cv_simd_sdotup_b:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    cv.sdotup.b a2, a0, a1
+; CHECK-NEXT:    mv a0, a2
+; CHECK-NEXT:    ret
+  %res = call i32 @llvm.riscv.cv.simd.sdotup.b(i32 %a, i32 %b, i32 %acc)
+  ret i32 %res
+}
+
+define i32 @test_cv_simd_sdotusp_h(i32 %a, i32 %b, i32 %acc) {
+; CHECK-LABEL: test_cv_simd_sdotusp_h:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    cv.sdotusp.h a2, a0, a1
+; CHECK-NEXT:    mv a0, a2
+; CHECK-NEXT:    ret
+  %res = call i32 @llvm.riscv.cv.simd.sdotusp.h(i32 %a, i32 %b, i32 %acc)
+  ret i32 %res
+}
+
+define i32 @test_cv_simd_sdotsp_h(i32 %a, i32 %b, i32 %acc) {
+; CHECK-LABEL: test_cv_simd_sdotsp_h:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    cv.sdotsp.h a2, a0, a1
+; CHECK-NEXT:    mv a0, a2
+; CHECK-NEXT:    ret
+  %res = call i32 @llvm.riscv.cv.simd.sdotsp.h(i32 %a, i32 %b, i32 %acc)
+  ret i32 %res
+}
+
+;===----------------------------------------------------------------------===;
+; EXTRACT / EXTRACTU / INSERT
+;===----------------------------------------------------------------------===;
+
+define i32 @test_cv_simd_extract_h(i32 %a) {
+; CHECK-LABEL: test_cv_simd_extract_h:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    cv.extract.h a0, a0, 1
+; CHECK-NEXT:    ret
+  %res = call i32 @llvm.riscv.cv.simd.extract.h(i32 %a, i32 1)
+  ret i32 %res
+}
+
+define i32 @test_cv_simd_extract_b(i32 %a) {
+; CHECK-LABEL: test_cv_simd_extract_b:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    cv.extract.b a0, a0, 3
+; CHECK-NEXT:    ret
+  %res = call i32 @llvm.riscv.cv.simd.extract.b(i32 %a, i32 3)
+  ret i32 %res
+}
+
+define i32 @test_cv_simd_extractu_h(i32 %a) {
+; CHECK-LABEL: test_cv_simd_extractu_h:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    cv.extractu.h a0, a0, 0
+; CHECK-NEXT:    ret
+  %res = call i32 @llvm.riscv.cv.simd.extractu.h(i32 %a, i32 0)
+  ret i32 %res
+}
+
+define i32 @test_cv_simd_extractu_b(i32 %a) {
+; CHECK-LABEL: test_cv_simd_extractu_b:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    cv.extractu.b a0, a0, 2
+; CHECK-NEXT:    ret
+  %res = call i32 @llvm.riscv.cv.simd.extractu.b(i32 %a, i32 2)
+  ret i32 %res
+}
+
+define i32 @test_cv_simd_insert_h(i32 %rd, i32 %rs1) {
+; CHECK-LABEL: test_cv_simd_insert_h:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    cv.insert.h a0, a1, 1
+; CHECK-NEXT:    ret
+  %res = call i32 @llvm.riscv.cv.simd.insert.h(i32 %rd, i32 %rs1, i32 1)
+  ret i32 %res
+}
+
+define i32 @test_cv_simd_insert_b(i32 %rd, i32 %rs1) {
+; CHECK-LABEL: test_cv_simd_insert_b:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    cv.insert.b a0, a1, 2
+; CHECK-NEXT:    ret
+  %res = call i32 @llvm.riscv.cv.simd.insert.b(i32 %rd, i32 %rs1, i32 2)
+  ret i32 %res
+}
+
+;===----------------------------------------------------------------------===;
+; SHUFFLE / SHUFFLE2
+;===----------------------------------------------------------------------===;
+
+define i32 @test_cv_simd_shuffle_h(i32 %a, i32 %b) {
+; CHECK-LABEL: test_cv_simd_shuffle_h:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    cv.shuffle.h a0, a0, a1
+; CHECK-NEXT:    ret
+  %res = call i32 @llvm.riscv.cv.simd.shuffle.h(i32 %a, i32 %b)
+  ret i32 %res
+}
+
+define i32 @test_cv_simd_shuffle_b(i32 %a, i32 %b) {
+; CHECK-LABEL: test_cv_simd_shuffle_b:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    cv.shuffle.b a0, a0, a1
+; CHECK-NEXT:    ret
+  %res = call i32 @llvm.riscv.cv.simd.shuffle.b(i32 %a, i32 %b)
+  ret i32 %res
+}
+
+define i32 @test_cv_simd_shuffle_sci_h(i32 %a) {
+; CHECK-LABEL: test_cv_simd_shuffle_sci_h:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    cv.shuffle.sci.h a0, a0, 2
+; CHECK-NEXT:    ret
+  %res = call i32 @llvm.riscv.cv.simd.shuffle.sci.h(i32 %a, i32 2)
+  ret i32 %res
+}
+
+; Test shuffle_sci_b pseudo expansion: imm=0x45 → bits[7:6]=1 → shufflei1
+define i32 @test_cv_simd_shuffle_sci_b_i1(i32 %a) {
+; CHECK-LABEL: test_cv_simd_shuffle_sci_b_i1:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    cv.shufflei1.sci.b a0, a0, 5
+; CHECK-NEXT:    ret
+  %res = call i32 @llvm.riscv.cv.simd.shuffle.sci.b(i32 %a, i32 69)
+  ret i32 %res
+}
+
+; Test shuffle_sci_b pseudo expansion: imm=0x03 → bits[7:6]=0 → shufflei0
+define i32 @test_cv_simd_shuffle_sci_b_i0(i32 %a) {
+; CHECK-LABEL: test_cv_simd_shuffle_sci_b_i0:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    cv.shufflei0.sci.b a0, a0, 3
+; CHECK-NEXT:    ret
+  %res = call i32 @llvm.riscv.cv.simd.shuffle.sci.b(i32 %a, i32 3)
+  ret i32 %res
+}
+
+; Test shuffle_sci_b pseudo expansion: imm=0x83 → bits[7:6]=2 → shufflei2
+define i32 @test_cv_simd_shuffle_sci_b_i2(i32 %a) {
+; CHECK-LABEL: test_cv_simd_shuffle_sci_b_i2:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    cv.shufflei2.sci.b a0, a0, 3
+; CHECK-NEXT:    ret
+  %res = call i32 @llvm.riscv.cv.simd.shuffle.sci.b(i32 %a, i32 131)
+  ret i32 %res
+}
+
+; Test shuffle_sci_b pseudo expansion: imm=0xC0 → bits[7:6]=3 → shufflei3
+define i32 @test_cv_simd_shuffle_sci_b_i3(i32 %a) {
+; CHECK-LABEL: test_cv_simd_shuffle_sci_b_i3:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    cv.shufflei3.sci.b a0, a0, 0
+; CHECK-NEXT:    ret
+  %res = call i32 @llvm.riscv.cv.simd.shuffle.sci.b(i32 %a, i32 192)
+  ret i32 %res
+}
+
+define i32 @test_cv_simd_shuffle2_h(i32 %rd, i32 %rs1, i32 %rs2) {
+; CHECK-LABEL: test_cv_simd_shuffle2_h:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    cv.shuffle2.h a0, a1, a2
+; CHECK-NEXT:    ret
+  %res = call i32 @llvm.riscv.cv.simd.shuffle2.h(i32 %rs1, i32 %rs2, i32 %rd)
+  ret i32 %res
+}
+
+define i32 @test_cv_simd_shuffle2_b(i32 %rd, i32 %rs1, i32 %rs2) {
+; CHECK-LABEL: test_cv_simd_shuffle2_b:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    cv.shuffle2.b a0, a1, a2
+; CHECK-NEXT:    ret
+  %res = call i32 @llvm.riscv.cv.simd.shuffle2.b(i32 %rs1, i32 %rs2, i32 %rd)
+  ret i32 %res
+}
+
+;===----------------------------------------------------------------------===;
+; PACK
+;===----------------------------------------------------------------------===;
+
+define i32 @test_cv_simd_packlo_h(i32 %a, i32 %b) {
+; CHECK-LABEL: test_cv_simd_packlo_h:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    cv.pack a0, a0, a1
+; CHECK-NEXT:    ret
+  %res = call i32 @llvm.riscv.cv.simd.packlo.h(i32 %a, i32 %b)
+  ret i32 %res
+}
+
+define i32 @test_cv_simd_packhi_h(i32 %a, i32 %b) {
+; CHECK-LABEL: test_cv_simd_packhi_h:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    cv.pack.h a0, a0, a1
+; CHECK-NEXT:    ret
+  %res = call i32 @llvm.riscv.cv.simd.packhi.h(i32 %a, i32 %b)
+  ret i32 %res
+}
+
+define i32 @test_cv_simd_packhi_b(i32 %rd, i32 %rs1, i32 %rs2) {
+; CHECK-LABEL: test_cv_simd_packhi_b:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    cv.packhi.b a0, a1, a2
+; CHECK-NEXT:    ret
+  %res = call i32 @llvm.riscv.cv.simd.packhi.b(i32 %rd, i32 %rs1, i32 %rs2)
+  ret i32 %res
+}
+
+define i32 @test_cv_simd_packlo_b(i32 %rd, i32 %rs1, i32 %rs2) {
+; CHECK-LABEL: test_cv_simd_packlo_b:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    cv.packlo.b a0, a1, a2
+; CHECK-NEXT:    ret
+  %res = call i32 @llvm.riscv.cv.simd.packlo.b(i32 %rd, i32 %rs1, i32 %rs2)
+  ret i32 %res
+}
+
+;===----------------------------------------------------------------------===;
+; COMPARE (representative subset)
+;===----------------------------------------------------------------------===;
+
+define i32 @test_cv_simd_cmpeq_h(i32 %a, i32 %b) {
+; CHECK-LABEL: test_cv_simd_cmpeq_h:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    cv.cmpeq.h a0, a0, a1
+; CHECK-NEXT:    ret
+  %res = call i32 @llvm.riscv.cv.simd.cmpeq.h(i32 %a, i32 %b)
+  ret i32 %res
+}
+
+define i32 @test_cv_simd_cmpeq_b(i32 %a, i32 %b) {
+; CHECK-LABEL: test_cv_simd_cmpeq_b:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    cv.cmpeq.b a0, a0, a1
+; CHECK-NEXT:    ret
+  %res = call i32 @llvm.riscv.cv.simd.cmpeq.b(i32 %a, i32 %b)
+  ret i32 %res
+}
+
+define i32 @test_cv_simd_cmpne_h(i32 %a, i32 %b) {
+; CHECK-LABEL: test_cv_simd_cmpne_h:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    cv.cmpne.h a0, a0, a1
+; CHECK-NEXT:    ret
+  %res = call i32 @llvm.riscv.cv.simd.cmpne.h(i32 %a, i32 %b)
+  ret i32 %res
+}
+
+define i32 @test_cv_simd_cmpgt_h(i32 %a, i32 %b) {
+; CHECK-LABEL: test_cv_simd_cmpgt_h:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    cv.cmpgt.h a0, a0, a1
+; CHECK-NEXT:    ret
+  %res = call i32 @llvm.riscv.cv.simd.cmpgt.h(i32 %a, i32 %b)
+  ret i32 %res
+}
+
+define i32 @test_cv_simd_cmpge_b(i32 %a, i32 %b) {
+; CHECK-LABEL: test_cv_simd_cmpge_b:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    cv.cmpge.b a0, a0, a1
+; CHECK-NEXT:    ret
+  %res = call i32 @llvm.riscv.cv.simd.cmpge.b(i32 %a, i32 %b)
+  ret i32 %res
+}
+
+define i32 @test_cv_simd_cmplt_h(i32 %a, i32 %b) {
+; CHECK-LABEL: test_cv_simd_cmplt_h:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    cv.cmplt.h a0, a0, a1
+; CHECK-NEXT:    ret
+  %res = call i32 @llvm.riscv.cv.simd.cmplt.h(i32 %a, i32 %b)
+  ret i32 %res
+}
+
+define i32 @test_cv_simd_cmple_b(i32 %a, i32 %b) {
+; CHECK-LABEL: test_cv_simd_cmple_b:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    cv.cmple.b a0, a0, a1
+; CHECK-NEXT:    ret
+  %res = call i32 @llvm.riscv.cv.simd.cmple.b(i32 %a, i32 %b)
+  ret i32 %res
+}
+
+define i32 @test_cv_simd_cmpgtu_h(i32 %a, i32 %b) {
+; CHECK-LABEL: test_cv_simd_cmpgtu_h:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    cv.cmpgtu.h a0, a0, a1
+; CHECK-NEXT:    ret
+  %res = call i32 @llvm.riscv.cv.simd.cmpgtu.h(i32 %a, i32 %b)
+  ret i32 %res
+}
+
+define i32 @test_cv_simd_cmpgeu_b(i32 %a, i32 %b) {
+; CHECK-LABEL: test_cv_simd_cmpgeu_b:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    cv.cmpgeu.b a0, a0, a1
+; CHECK-NEXT:    ret
+  %res = call i32 @llvm.riscv.cv.simd.cmpgeu.b(i32 %a, i32 %b)
+  ret i32 %res
+}
+
+define i32 @test_cv_simd_cmpltu_h(i32 %a, i32 %b) {
+; CHECK-LABEL: test_cv_simd_cmpltu_h:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    cv.cmpltu.h a0, a0, a1
+; CHECK-NEXT:    ret
+  %res = call i32 @llvm.riscv.cv.simd.cmpltu.h(i32 %a, i32 %b)
+  ret i32 %res
+}
+
+define i32 @test_cv_simd_cmpleu_b(i32 %a, i32 %b) {
+; CHECK-LABEL: test_cv_simd_cmpleu_b:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    cv.cmpleu.b a0, a0, a1
+; CHECK-NEXT:    ret
+  %res = call i32 @llvm.riscv.cv.simd.cmpleu.b(i32 %a, i32 %b)
+  ret i32 %res
+}
+
+;===----------------------------------------------------------------------===;
+; COMPLEX: cplxmul / cplxconj / subrotmj
+;===----------------------------------------------------------------------===;
+
+define i32 @test_cv_simd_cplxmul_r(i32 %rs1, i32 %rs2, i32 %rd) {
+; CHECK-LABEL: test_cv_simd_cplxmul_r:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    cv.cplxmul.r a2, a0, a1
+; CHECK-NEXT:    mv a0, a2
+; CHECK-NEXT:    ret
+  %res = call i32 @llvm.riscv.cv.simd.cplxmul.r(i32 %rs1, i32 %rs2, i32 %rd, i32 0)
+  ret i32 %res
+}
+
+define i32 @test_cv_simd_cplxmul_r_div2(i32 %rs1, i32 %rs2, i32 %rd) {
+; CHECK-LABEL: test_cv_simd_cplxmul_r_div2:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    cv.cplxmul.r.div2 a2, a0, a1
+; CHECK-NEXT:    mv a0, a2
+; CHECK-NEXT:    ret
+  %res = call i32 @llvm.riscv.cv.simd.cplxmul.r(i32 %rs1, i32 %rs2, i32 %rd, i32 1)
+  ret i32 %res
+}
+
+define i32 @test_cv_simd_cplxmul_i(i32 %rs1, i32 %rs2, i32 %rd) {
+; CHECK-LABEL: test_cv_simd_cplxmul_i:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    cv.cplxmul.i a2, a0, a1
+; CHECK-NEXT:    mv a0, a2
+; CHECK-NEXT:    ret
+  %res = call i32 @llvm.riscv.cv.simd.cplxmul.i(i32 %rs1, i32 %rs2, i32 %rd, i32 0)
+  ret i32 %res
+}
+
+define i32 @test_cv_simd_cplxmul_i_div4(i32 %rs1, i32 %rs2, i32 %rd) {
+; CHECK-LABEL: test_cv_simd_cplxmul_i_div4:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    cv.cplxmul.i.div4 a2, a0, a1
+; CHECK-NEXT:    mv a0, a2
+; CHECK-NEXT:    ret
+  %res = call i32 @llvm.riscv.cv.simd.cplxmul.i(i32 %rs1, i32 %rs2, i32 %rd, i32 2)
+  ret i32 %res
+}
+
+define i32 @test_cv_simd_cplxconj(i32 %a) {
+; CHECK-LABEL: test_cv_simd_cplxconj:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    cv.cplxconj a0, a0
+; CHECK-NEXT:    ret
+  %res = call i32 @llvm.riscv.cv.simd.cplxconj(i32 %a)
+  ret i32 %res
+}
+
+define i32 @test_cv_simd_subrotmj(i32 %a, i32 %b) {
+; CHECK-LABEL: test_cv_simd_subrotmj:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    cv.subrotmj a0, a0, a1
+; CHECK-NEXT:    ret
+  %res = call i32 @llvm.riscv.cv.simd.subrotmj(i32 %a, i32 %b, i32 0)
+  ret i32 %res
+}
+
+define i32 @test_cv_simd_subrotmj_div2(i32 %a, i32 %b) {
+; CHECK-LABEL: test_cv_simd_subrotmj_div2:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    cv.subrotmj.div2 a0, a0, a1
+; CHECK-NEXT:    ret
+  %res = call i32 @llvm.riscv.cv.simd.subrotmj(i32 %a, i32 %b, i32 1)
+  ret i32 %res
+}
+
+define i32 @test_cv_simd_subrotmj_div4(i32 %a, i32 %b) {
+; CHECK-LABEL: test_cv_simd_subrotmj_div4:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    cv.subrotmj.div4 a0, a0, a1
+; CHECK-NEXT:    ret
+  %res = call i32 @llvm.riscv.cv.simd.subrotmj(i32 %a, i32 %b, i32 2)
+  ret i32 %res
+}
+
+define i32 @test_cv_simd_subrotmj_div8(i32 %a, i32 %b) {
+; CHECK-LABEL: test_cv_simd_subrotmj_div8:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    cv.subrotmj.div8 a0, a0, a1
+; CHECK-NEXT:    ret
+  %res = call i32 @llvm.riscv.cv.simd.subrotmj(i32 %a, i32 %b, i32 3)
+  ret i32 %res
+}
+
+;===----------------------------------------------------------------------===;
+; Intrinsic declarations
+;===----------------------------------------------------------------------===;
+
+; ADD/SUB
+declare i32 @llvm.riscv.cv.simd.add.h(i32, i32, i32 immarg)
+declare i32 @llvm.riscv.cv.simd.add.b(i32, i32)
+declare i32 @llvm.riscv.cv.simd.add.sc.h(i32, i32)
+declare i32 @llvm.riscv.cv.simd.add.sc.b(i32, i32)
+declare i32 @llvm.riscv.cv.simd.sub.h(i32, i32, i32 immarg)
+declare i32 @llvm.riscv.cv.simd.sub.b(i32, i32)
+declare i32 @llvm.riscv.cv.simd.sub.sc.h(i32, i32)
+declare i32 @llvm.riscv.cv.simd.sub.sc.b(i32, i32)
+
+; AVG/AVGU
+declare i32 @llvm.riscv.cv.simd.avg.h(i32, i32)
+declare i32 @llvm.riscv.cv.simd.avg.b(i32, i32)
+declare i32 @llvm.riscv.cv.simd.avg.sc.h(i32, i32)
+declare i32 @llvm.riscv.cv.simd.avg.sc.b(i32, i32)
+declare i32 @llvm.riscv.cv.simd.avgu.h(i32, i32)
+declare i32 @llvm.riscv.cv.simd.avgu.b(i32, i32)
+declare i32 @llvm.riscv.cv.simd.avgu.sc.h(i32, i32)
+declare i32 @llvm.riscv.cv.simd.avgu.sc.b(i32, i32)
+
+; MIN/MINU/MAX/MAXU
+declare i32 @llvm.riscv.cv.simd.min.h(i32, i32)
+declare i32 @llvm.riscv.cv.simd.min.b(i32, i32)
+declare i32 @llvm.riscv.cv.simd.min.sc.h(i32, i32)
+declare i32 @llvm.riscv.cv.simd.min.sc.b(i32, i32)
+declare i32 @llvm.riscv.cv.simd.minu.h(i32, i32)
+declare i32 @llvm.riscv.cv.simd.minu.b(i32, i32)
+declare i32 @llvm.riscv.cv.simd.minu.sc.h(i32, i32)
+declare i32 @llvm.riscv.cv.simd.minu.sc.b(i32, i32)
+declare i32 @llvm.riscv.cv.simd.max.h(i32, i32)
+declare i32 @llvm.riscv.cv.simd.max.b(i32, i32)
+declare i32 @llvm.riscv.cv.simd.max.sc.h(i32, i32)
+declare i32 @llvm.riscv.cv.simd.max.sc.b(i32, i32)
+declare i32 @llvm.riscv.cv.simd.maxu.h(i32, i32)
+declare i32 @llvm.riscv.cv.simd.maxu.b(i32, i32)
+declare i32 @llvm.riscv.cv.simd.maxu.sc.h(i32, i32)
+declare i32 @llvm.riscv.cv.simd.maxu.sc.b(i32, i32)
+
+; SRL/SRA/SLL
+declare i32 @llvm.riscv.cv.simd.srl.h(i32, i32)
+declare i32 @llvm.riscv.cv.simd.srl.b(i32, i32)
+declare i32 @llvm.riscv.cv.simd.srl.sc.h(i32, i32)
+declare i32 @llvm.riscv.cv.simd.srl.sc.b(i32, i32)
+declare i32 @llvm.riscv.cv.simd.sra.h(i32, i32)
+declare i32 @llvm.riscv.cv.simd.sra.b(i32, i32)
+declare i32 @llvm.riscv.cv.simd.sra.sc.h(i32, i32)
+declare i32 @llvm.riscv.cv.simd.sra.sc.b(i32, i32)
+declare i32 @llvm.riscv.cv.simd.sll.h(i32, i32)
+declare i32 @llvm.riscv.cv.simd.sll.b(i32, i32)
+declare i32 @llvm.riscv.cv.simd.sll.sc.h(i32, i32)
+declare i32 @llvm.riscv.cv.simd.sll.sc.b(i32, i32)
+
+; OR/XOR/AND
+declare i32 @llvm.riscv.cv.simd.or.h(i32, i32)
+declare i32 @llvm.riscv.cv.simd.or.b(i32, i32)
+declare i32 @llvm.riscv.cv.simd.or.sc.h(i32, i32)
+declare i32 @llvm.riscv.cv.simd.or.sc.b(i32, i32)
+declare i32 @llvm.riscv.cv.simd.xor.h(i32, i32)
+declare i32 @llvm.riscv.cv.simd.xor.b(i32, i32)
+declare i32 @llvm.riscv.cv.simd.xor.sc.h(i32, i32)
+declare i32 @llvm.riscv.cv.simd.xor.sc.b(i32, i32)
+declare i32 @llvm.riscv.cv.simd.and.h(i32, i32)
+declare i32 @llvm.riscv.cv.simd.and.b(i32, i32)
+declare i32 @llvm.riscv.cv.simd.and.sc.h(i32, i32)
+declare i32 @llvm.riscv.cv.simd.and.sc.b(i32, i32)
+
+; ABS
+declare i32 @llvm.riscv.cv.simd.abs.h(i32)
+declare i32 @llvm.riscv.cv.simd.abs.b(i32)
+
+; DOT (non-accumulating)
+declare i32 @llvm.riscv.cv.simd.dotup.h(i32, i32)
+declare i32 @llvm.riscv.cv.simd.dotup.b(i32, i32)
+declare i32 @llvm.riscv.cv.simd.dotup.sc.h(i32, i32)
+declare i32 @llvm.riscv.cv.simd.dotup.sc.b(i32, i32)
+declare i32 @llvm.riscv.cv.simd.dotusp.h(i32, i32)
+declare i32 @llvm.riscv.cv.simd.dotusp.b(i32, i32)
+declare i32 @llvm.riscv.cv.simd.dotusp.sc.h(i32, i32)
+declare i32 @llvm.riscv.cv.simd.dotusp.sc.b(i32, i32)
+declare i32 @llvm.riscv.cv.simd.dotsp.h(i32, i32)
+declare i32 @llvm.riscv.cv.simd.dotsp.b(i32, i32)
+declare i32 @llvm.riscv.cv.simd.dotsp.sc.h(i32, i32)
+declare i32 @llvm.riscv.cv.simd.dotsp.sc.b(i32, i32)
+
+; SDOT (accumulating)
+declare i32 @llvm.riscv.cv.simd.sdotup.h(i32, i32, i32)
+declare i32 @llvm.riscv.cv.simd.sdotup.b(i32, i32, i32)
+declare i32 @llvm.riscv.cv.simd.sdotup.sc.h(i32, i32, i32)
+declare i32 @llvm.riscv.cv.simd.sdotup.sc.b(i32, i32, i32)
+declare i32 @llvm.riscv.cv.simd.sdotusp.h(i32, i32, i32)
+declare i32 @llvm.riscv.cv.simd.sdotusp.b(i32, i32, i32)
+declare i32 @llvm.riscv.cv.simd.sdotusp.sc.h(i32, i32, i32)
+declare i32 @llvm.riscv.cv.simd.sdotusp.sc.b(i32, i32, i32)
+declare i32 @llvm.riscv.cv.simd.sdotsp.h(i32, i32, i32)
+declare i32 @llvm.riscv.cv.simd.sdotsp.b(i32, i32, i32)
+declare i32 @llvm.riscv.cv.simd.sdotsp.sc.h(i32, i32, i32)
+declare i32 @llvm.riscv.cv.simd.sdotsp.sc.b(i32, i32, i32)
+
+; EXTRACT/EXTRACTU/INSERT
+declare i32 @llvm.riscv.cv.simd.extract.h(i32, i32 immarg)
+declare i32 @llvm.riscv.cv.simd.extract.b(i32, i32 immarg)
+declare i32 @llvm.riscv.cv.simd.extractu.h(i32, i32 immarg)
+declare i32 @llvm.riscv.cv.simd.extractu.b(i32, i32 immarg)
+declare i32 @llvm.riscv.cv.simd.insert.h(i32, i32, i32 immarg)
+declare i32 @llvm.riscv.cv.simd.insert.b(i32, i32, i32 immarg)
+
+; SHUFFLE
+declare i32 @llvm.riscv.cv.simd.shuffle.h(i32, i32)
+declare i32 @llvm.riscv.cv.simd.shuffle.b(i32, i32)
+declare i32 @llvm.riscv.cv.simd.shuffle.sci.h(i32, i32 immarg)
+declare i32 @llvm.riscv.cv.simd.shuffle.sci.b(i32, i32 immarg)
+declare i32 @llvm.riscv.cv.simd.shuffle2.h(i32, i32, i32)
+declare i32 @llvm.riscv.cv.simd.shuffle2.b(i32, i32, i32)
+
+; PACK
+declare i32 @llvm.riscv.cv.simd.packlo.h(i32, i32)
+declare i32 @llvm.riscv.cv.simd.packhi.h(i32, i32)
+declare i32 @llvm.riscv.cv.simd.packhi.b(i32, i32, i32)
+declare i32 @llvm.riscv.cv.simd.packlo.b(i32, i32, i32)
+
+; COMPARE
+declare i32 @llvm.riscv.cv.simd.cmpeq.h(i32, i32)
+declare i32 @llvm.riscv.cv.simd.cmpeq.b(i32, i32)
+declare i32 @llvm.riscv.cv.simd.cmpeq.sc.h(i32, i32)
+declare i32 @llvm.riscv.cv.simd.cmpeq.sc.b(i32, i32)
+declare i32 @llvm.riscv.cv.simd.cmpne.h(i32, i32)
+declare i32 @llvm.riscv.cv.simd.cmpne.b(i32, i32)
+declare i32 @llvm.riscv.cv.simd.cmpne.sc.h(i32, i32)
+declare i32 @llvm.riscv.cv.simd.cmpne.sc.b(i32, i32)
+declare i32 @llvm.riscv.cv.simd.cmpgt.h(i32, i32)
+declare i32 @llvm.riscv.cv.simd.cmpgt.b(i32, i32)
+declare i32 @llvm.riscv.cv.simd.cmpgt.sc.h(i32, i32)
+declare i32 @llvm.riscv.cv.simd.cmpgt.sc.b(i32, i32)
+declare i32 @llvm.riscv.cv.simd.cmpge.h(i32, i32)
+declare i32 @llvm.riscv.cv.simd.cmpge.b(i32, i32)
+declare i32 @llvm.riscv.cv.simd.cmpge.sc.h(i32, i32)
+declare i32 @llvm.riscv.cv.simd.cmpge.sc.b(i32, i32)
+declare i32 @llvm.riscv.cv.simd.cmplt.h(i32, i32)
+declare i32 @llvm.riscv.cv.simd.cmplt.b(i32, i32)
+declare i32 @llvm.riscv.cv.simd.cmplt.sc.h(i32, i32)
+declare i32 @llvm.riscv.cv.simd.cmplt.sc.b(i32, i32)
+declare i32 @llvm.riscv.cv.simd.cmple.h(i32, i32)
+declare i32 @llvm.riscv.cv.simd.cmple.b(i32, i32)
+declare i32 @llvm.riscv.cv.simd.cmple.sc.h(i32, i32)
+declare i32 @llvm.riscv.cv.simd.cmple.sc.b(i32, i32)
+declare i32 @llvm.riscv.cv.simd.cmpgtu.h(i32, i32)
+declare i32 @llvm.riscv.cv.simd.cmpgtu.b(i32, i32)
+declare i32 @llvm.riscv.cv.simd.cmpgtu.sc.h(i32, i32)
+declare i32 @llvm.riscv.cv.simd.cmpgtu.sc.b(i32, i32)
+declare i32 @llvm.riscv.cv.simd.cmpgeu.h(i32, i32)
+declare i32 @llvm.riscv.cv.simd.cmpgeu.b(i32, i32)
+declare i32 @llvm.riscv.cv.simd.cmpgeu.sc.h(i32, i32)
+declare i32 @llvm.riscv.cv.simd.cmpgeu.sc.b(i32, i32)
+declare i32 @llvm.riscv.cv.simd.cmpltu.h(i32, i32)
+declare i32 @llvm.riscv.cv.simd.cmpltu.b(i32, i32)
+declare i32 @llvm.riscv.cv.simd.cmpltu.sc.h(i32, i32)
+declare i32 @llvm.riscv.cv.simd.cmpltu.sc.b(i32, i32)
+declare i32 @llvm.riscv.cv.simd.cmpleu.h(i32, i32)
+declare i32 @llvm.riscv.cv.simd.cmpleu.b(i32, i32)
+declare i32 @llvm.riscv.cv.simd.cmpleu.sc.h(i32, i32)
+declare i32 @llvm.riscv.cv.simd.cmpleu.sc.b(i32, i32)
+
+; COMPLEX
+declare i32 @llvm.riscv.cv.simd.cplxmul.r(i32, i32, i32, i32 immarg)
+declare i32 @llvm.riscv.cv.simd.cplxmul.i(i32, i32, i32, i32 immarg)
+declare i32 @llvm.riscv.cv.simd.cplxconj(i32)
+declare i32 @llvm.riscv.cv.simd.subrotmj(i32, i32, i32 immarg)

>From fdc2e1062f056ae553509f2e3dafb2d28d54dd72 Mon Sep 17 00:00:00 2001
From: vitbur <vittorioburani at gmail.com>
Date: Tue, 31 Mar 2026 18:37:47 +0200
Subject: [PATCH 02/10] [Clang][RISCV] Add Clang builtins for `XCVelw`
 extension

- `BuiltinsRISCVXCV.td`: add `elw_elw`
- `RISCV.cpp`: add dispatch cases
- `CIRGenBuiltinRISCV.cpp`: add NYI cases
- add `riscv_corev_elw.h` header file + addition in `CMakeLists.txt`
---
 clang/include/clang/Basic/BuiltinsRISCVXCV.td |  7 +++++++
 clang/lib/CIR/CodeGen/CIRGenBuiltinRISCV.cpp  |  2 ++
 clang/lib/CodeGen/TargetBuiltins/RISCV.cpp    |  9 +++++++++
 clang/lib/Headers/CMakeLists.txt              |  1 +
 clang/lib/Headers/riscv_corev_elw.h           | 20 +++++++++++++++++++
 5 files changed, 39 insertions(+)
 create mode 100644 clang/lib/Headers/riscv_corev_elw.h

diff --git a/clang/include/clang/Basic/BuiltinsRISCVXCV.td b/clang/include/clang/Basic/BuiltinsRISCVXCV.td
index 65eb52b198775..a51ca3ae097a8 100644
--- a/clang/include/clang/Basic/BuiltinsRISCVXCV.td
+++ b/clang/include/clang/Basic/BuiltinsRISCVXCV.td
@@ -39,3 +39,10 @@ def alu_subuN  : RISCVXCVBuiltin<"unsigned int(unsigned int, unsigned int, unsig
 def alu_subRN  : RISCVXCVBuiltin<"int(int, int, unsigned int)", "xcvalu">;
 def alu_subuRN : RISCVXCVBuiltin<"unsigned int(unsigned int, unsigned int, unsigned int)", "xcvalu">;
 } // Attributes = [NoThrow, Const]
+
+//===----------------------------------------------------------------------===//
+// XCVelw extension.
+//===----------------------------------------------------------------------===//
+let Attributes = [NoThrow] in {
+def elw_elw : RISCVXCVBuiltin<"int(int *)", "xcvelw">;
+} // Attributes = [NoThrow]
diff --git a/clang/lib/CIR/CodeGen/CIRGenBuiltinRISCV.cpp b/clang/lib/CIR/CodeGen/CIRGenBuiltinRISCV.cpp
index ec262922be942..c05a78c1aac16 100644
--- a/clang/lib/CIR/CodeGen/CIRGenBuiltinRISCV.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenBuiltinRISCV.cpp
@@ -184,6 +184,8 @@ CIRGenFunction::emitRISCVBuiltinExpr(unsigned builtinID, const CallExpr *e) {
   case RISCV::BI__builtin_riscv_cv_alu_subRN:
   case RISCV::BI__builtin_riscv_cv_alu_subuN:
   case RISCV::BI__builtin_riscv_cv_alu_subuRN:
+  // XCVelw
+  case RISCV::BI__builtin_riscv_cv_elw_elw:
   // XAndesPerf
   case RISCV::BI__builtin_riscv_nds_ffb_32:
   case RISCV::BI__builtin_riscv_nds_ffb_64:
diff --git a/clang/lib/CodeGen/TargetBuiltins/RISCV.cpp b/clang/lib/CodeGen/TargetBuiltins/RISCV.cpp
index a1e9acb7ec2c8..071c6df744cdc 100644
--- a/clang/lib/CodeGen/TargetBuiltins/RISCV.cpp
+++ b/clang/lib/CodeGen/TargetBuiltins/RISCV.cpp
@@ -1433,6 +1433,15 @@ Value *CodeGenFunction::EmitRISCVBuiltinExpr(unsigned BuiltinID,
     ID = Intrinsic::riscv_cv_alu_subuRN;
     break;
 
+  // XCVelw
+  case RISCV::BI__builtin_riscv_cv_elw_elw: {
+    // cv.elw rd, imm(rs1) — load word with event wait
+    // Emit as a volatile load from the memory-mapped address
+    // The builtin takes a pointer; emit as intrinsic call
+    ID = Intrinsic::riscv_cv_elw_elw;
+    break;
+  }
+
   // XAndesPerf
   case RISCV::BI__builtin_riscv_nds_ffb_32:
   case RISCV::BI__builtin_riscv_nds_ffb_64:
diff --git a/clang/lib/Headers/CMakeLists.txt b/clang/lib/Headers/CMakeLists.txt
index 439f2725168ba..0de1618a3d311 100644
--- a/clang/lib/Headers/CMakeLists.txt
+++ b/clang/lib/Headers/CMakeLists.txt
@@ -138,6 +138,7 @@ set(riscv_files
   # Vendor headers
   andes_vector.h
   riscv_corev_alu.h
+  riscv_corev_elw.h
   riscv_mips.h
   riscv_nds.h
   riscv_packed_simd.h
diff --git a/clang/lib/Headers/riscv_corev_elw.h b/clang/lib/Headers/riscv_corev_elw.h
new file mode 100644
index 0000000000000..9676799b5b2e0
--- /dev/null
+++ b/clang/lib/Headers/riscv_corev_elw.h
@@ -0,0 +1,20 @@
+#ifndef __RISCV_COREV_ELW_H
+#define __RISCV_COREV_ELW_H
+#include <stdint.h>
+#if defined(__cplusplus)
+extern "C" {
+#endif
+#if defined(__riscv_xcvelw)
+#define __DEFAULT_FN_ATTRS \
+  __attribute__((__always_inline__, __nodebug__, __artificial__))
+
+// cv.elw rd, imm(rs1): event load word
+static __inline__ int32_t __DEFAULT_FN_ATTRS
+__riscv_cv_elw_elw(int32_t *ptr) {
+  return __builtin_riscv_cv_elw_elw(ptr);
+}
+#endif
+#if defined(__cplusplus)
+}
+#endif
+#endif

>From 1f3d3167720fcfd4dd60b384cb597c649da427a9 Mon Sep 17 00:00:00 2001
From: vitbur <vittorioburani at gmail.com>
Date: Tue, 31 Mar 2026 18:43:53 +0200
Subject: [PATCH 03/10] [Clang][RISCV] Add Clang builtins for `XCVmac`
 extension

- `BuiltinsRISCVXCV.td`: add all mac attributes
- `SemaRISCV.cpp`: add range check for arg 1
- `RISCV.cpp`: add dispatch cases
- `CIRGenBuiltinRISCV.cpp`: add NYI cases
- add `riscv_corev_mac.h` header + `CMakeLists.txt` addition
---
 clang/include/clang/Basic/BuiltinsRISCVXCV.td |  24 +++
 clang/lib/CIR/CodeGen/CIRGenBuiltinRISCV.cpp  |  19 ++
 clang/lib/CodeGen/TargetBuiltins/RISCV.cpp    |  56 +++++
 clang/lib/Headers/CMakeLists.txt              |   1 +
 clang/lib/Headers/riscv_corev_mac.h           | 192 ++++++++++++++++++
 clang/lib/Sema/SemaRISCV.cpp                  |  21 +-
 6 files changed, 312 insertions(+), 1 deletion(-)
 create mode 100644 clang/lib/Headers/riscv_corev_mac.h

diff --git a/clang/include/clang/Basic/BuiltinsRISCVXCV.td b/clang/include/clang/Basic/BuiltinsRISCVXCV.td
index a51ca3ae097a8..0d6f2c56d19a3 100644
--- a/clang/include/clang/Basic/BuiltinsRISCVXCV.td
+++ b/clang/include/clang/Basic/BuiltinsRISCVXCV.td
@@ -46,3 +46,27 @@ def alu_subuRN : RISCVXCVBuiltin<"unsigned int(unsigned int, unsigned int, unsig
 let Attributes = [NoThrow] in {
 def elw_elw : RISCVXCVBuiltin<"int(int *)", "xcvelw">;
 } // Attributes = [NoThrow]
+
+//===----------------------------------------------------------------------===//
+// XCVmac extension.
+//===----------------------------------------------------------------------===//
+let Attributes = [NoThrow, Const] in {
+def mac_mac      : RISCVXCVBuiltin<"int(int, int, int)", "xcvmac">;
+def mac_msu      : RISCVXCVBuiltin<"int(int, int, int)", "xcvmac">;
+def mac_muluN    : RISCVXCVBuiltin<"unsigned int(unsigned int, unsigned int, _Constant unsigned int)", "xcvmac">;
+def mac_mulhhuN  : RISCVXCVBuiltin<"unsigned int(unsigned int, unsigned int, _Constant unsigned int)", "xcvmac">;
+def mac_mulsN    : RISCVXCVBuiltin<"int(unsigned int, unsigned int, _Constant unsigned int)", "xcvmac">;
+def mac_mulhhsN  : RISCVXCVBuiltin<"int(unsigned int, unsigned int, _Constant unsigned int)", "xcvmac">;
+def mac_muluRN   : RISCVXCVBuiltin<"unsigned int(unsigned int, unsigned int, _Constant unsigned int)", "xcvmac">;
+def mac_mulhhuRN : RISCVXCVBuiltin<"unsigned int(unsigned int, unsigned int, _Constant unsigned int)", "xcvmac">;
+def mac_mulsRN   : RISCVXCVBuiltin<"int(unsigned int, unsigned int, _Constant unsigned int)", "xcvmac">;
+def mac_mulhhsRN : RISCVXCVBuiltin<"int(unsigned int, unsigned int, _Constant unsigned int)", "xcvmac">;
+def mac_macuN    : RISCVXCVBuiltin<"unsigned int(unsigned int, unsigned int, unsigned int, _Constant unsigned int)", "xcvmac">;
+def mac_machhuN  : RISCVXCVBuiltin<"unsigned int(unsigned int, unsigned int, unsigned int, _Constant unsigned int)", "xcvmac">;
+def mac_macsN    : RISCVXCVBuiltin<"int(unsigned int, unsigned int, unsigned int, _Constant unsigned int)", "xcvmac">;
+def mac_machhsN  : RISCVXCVBuiltin<"int(unsigned int, unsigned int, unsigned int, _Constant unsigned int)", "xcvmac">;
+def mac_macuRN   : RISCVXCVBuiltin<"unsigned int(unsigned int, unsigned int, unsigned int, _Constant unsigned int)", "xcvmac">;
+def mac_machhuRN : RISCVXCVBuiltin<"unsigned int(unsigned int, unsigned int, unsigned int, _Constant unsigned int)", "xcvmac">;
+def mac_macsRN   : RISCVXCVBuiltin<"int(unsigned int, unsigned int, unsigned int, _Constant unsigned int)", "xcvmac">;
+def mac_machhsRN : RISCVXCVBuiltin<"int(unsigned int, unsigned int, unsigned int, _Constant unsigned int)", "xcvmac">;
+} // Attributes = [NoThrow, Const]
diff --git a/clang/lib/CIR/CodeGen/CIRGenBuiltinRISCV.cpp b/clang/lib/CIR/CodeGen/CIRGenBuiltinRISCV.cpp
index c05a78c1aac16..55b4d8ae8c60b 100644
--- a/clang/lib/CIR/CodeGen/CIRGenBuiltinRISCV.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenBuiltinRISCV.cpp
@@ -186,6 +186,25 @@ CIRGenFunction::emitRISCVBuiltinExpr(unsigned builtinID, const CallExpr *e) {
   case RISCV::BI__builtin_riscv_cv_alu_subuRN:
   // XCVelw
   case RISCV::BI__builtin_riscv_cv_elw_elw:
+  // XCVmac
+  case RISCV::BI__builtin_riscv_cv_mac_mac:
+  case RISCV::BI__builtin_riscv_cv_mac_msu:
+  case RISCV::BI__builtin_riscv_cv_mac_muluN:
+  case RISCV::BI__builtin_riscv_cv_mac_mulhhuN:
+  case RISCV::BI__builtin_riscv_cv_mac_mulsN:
+  case RISCV::BI__builtin_riscv_cv_mac_mulhhsN:
+  case RISCV::BI__builtin_riscv_cv_mac_muluRN:
+  case RISCV::BI__builtin_riscv_cv_mac_mulhhuRN:
+  case RISCV::BI__builtin_riscv_cv_mac_mulsRN:
+  case RISCV::BI__builtin_riscv_cv_mac_mulhhsRN:
+  case RISCV::BI__builtin_riscv_cv_mac_macuN:
+  case RISCV::BI__builtin_riscv_cv_mac_machhuN:
+  case RISCV::BI__builtin_riscv_cv_mac_macsN:
+  case RISCV::BI__builtin_riscv_cv_mac_machhsN:
+  case RISCV::BI__builtin_riscv_cv_mac_macuRN:
+  case RISCV::BI__builtin_riscv_cv_mac_machhuRN:
+  case RISCV::BI__builtin_riscv_cv_mac_macsRN:
+  case RISCV::BI__builtin_riscv_cv_mac_machhsRN:
   // XAndesPerf
   case RISCV::BI__builtin_riscv_nds_ffb_32:
   case RISCV::BI__builtin_riscv_nds_ffb_64:
diff --git a/clang/lib/CodeGen/TargetBuiltins/RISCV.cpp b/clang/lib/CodeGen/TargetBuiltins/RISCV.cpp
index 071c6df744cdc..07feb6296833e 100644
--- a/clang/lib/CodeGen/TargetBuiltins/RISCV.cpp
+++ b/clang/lib/CodeGen/TargetBuiltins/RISCV.cpp
@@ -1442,6 +1442,62 @@ Value *CodeGenFunction::EmitRISCVBuiltinExpr(unsigned BuiltinID,
     break;
   }
 
+  // XCVmac
+  case RISCV::BI__builtin_riscv_cv_mac_mac:
+    ID = Intrinsic::riscv_cv_mac_mac;
+    break;
+  case RISCV::BI__builtin_riscv_cv_mac_msu:
+    ID = Intrinsic::riscv_cv_mac_msu;
+    break;
+  case RISCV::BI__builtin_riscv_cv_mac_muluN:
+    ID = Intrinsic::riscv_cv_mac_muluN;
+    break;
+  case RISCV::BI__builtin_riscv_cv_mac_mulhhuN:
+    ID = Intrinsic::riscv_cv_mac_mulhhuN;
+    break;
+  case RISCV::BI__builtin_riscv_cv_mac_mulsN:
+    ID = Intrinsic::riscv_cv_mac_mulsN;
+    break;
+  case RISCV::BI__builtin_riscv_cv_mac_mulhhsN:
+    ID = Intrinsic::riscv_cv_mac_mulhhsN;
+    break;
+  case RISCV::BI__builtin_riscv_cv_mac_muluRN:
+    ID = Intrinsic::riscv_cv_mac_muluRN;
+    break;
+  case RISCV::BI__builtin_riscv_cv_mac_mulhhuRN:
+    ID = Intrinsic::riscv_cv_mac_mulhhuRN;
+    break;
+  case RISCV::BI__builtin_riscv_cv_mac_mulsRN:
+    ID = Intrinsic::riscv_cv_mac_mulsRN;
+    break;
+  case RISCV::BI__builtin_riscv_cv_mac_mulhhsRN:
+    ID = Intrinsic::riscv_cv_mac_mulhhsRN;
+    break;
+  case RISCV::BI__builtin_riscv_cv_mac_macuN:
+    ID = Intrinsic::riscv_cv_mac_macuN;
+    break;
+  case RISCV::BI__builtin_riscv_cv_mac_machhuN:
+    ID = Intrinsic::riscv_cv_mac_machhuN;
+    break;
+  case RISCV::BI__builtin_riscv_cv_mac_macsN:
+    ID = Intrinsic::riscv_cv_mac_macsN;
+    break;
+  case RISCV::BI__builtin_riscv_cv_mac_machhsN:
+    ID = Intrinsic::riscv_cv_mac_machhsN;
+    break;
+  case RISCV::BI__builtin_riscv_cv_mac_macuRN:
+    ID = Intrinsic::riscv_cv_mac_macuRN;
+    break;
+  case RISCV::BI__builtin_riscv_cv_mac_machhuRN:
+    ID = Intrinsic::riscv_cv_mac_machhuRN;
+    break;
+  case RISCV::BI__builtin_riscv_cv_mac_macsRN:
+    ID = Intrinsic::riscv_cv_mac_macsRN;
+    break;
+  case RISCV::BI__builtin_riscv_cv_mac_machhsRN:
+    ID = Intrinsic::riscv_cv_mac_machhsRN;
+    break;
+
   // XAndesPerf
   case RISCV::BI__builtin_riscv_nds_ffb_32:
   case RISCV::BI__builtin_riscv_nds_ffb_64:
diff --git a/clang/lib/Headers/CMakeLists.txt b/clang/lib/Headers/CMakeLists.txt
index 0de1618a3d311..e1021a6020305 100644
--- a/clang/lib/Headers/CMakeLists.txt
+++ b/clang/lib/Headers/CMakeLists.txt
@@ -139,6 +139,7 @@ set(riscv_files
   andes_vector.h
   riscv_corev_alu.h
   riscv_corev_elw.h
+  riscv_corev_mac.h
   riscv_mips.h
   riscv_nds.h
   riscv_packed_simd.h
diff --git a/clang/lib/Headers/riscv_corev_mac.h b/clang/lib/Headers/riscv_corev_mac.h
new file mode 100644
index 0000000000000..531c9b01f862f
--- /dev/null
+++ b/clang/lib/Headers/riscv_corev_mac.h
@@ -0,0 +1,192 @@
+/*===---- riscv_corev_mac.h - CORE-V multiply-accumulate intrinsics --------===
+ *
+ * Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+ * See https://llvm.org/LICENSE.txt for license information.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ *
+ *===-----------------------------------------------------------------------===
+ *
+ * This header provides C intrinsics for the CORE-V XCVmac ISA extension.
+ * Include this header when compiling with -march=..._xcvmac.
+ *
+ * Spec: https://github.com/openhwgroup/cv32e40p/blob/master/docs/source/
+ *       instruction_set_extensions.rst  (Multiply-Accumulate section)
+ *
+ *===-----------------------------------------------------------------------===
+ */
+
+#ifndef __RISCV_COREV_MAC_H
+#define __RISCV_COREV_MAC_H
+
+#include <stdint.h>
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+#if defined(__riscv_xcvmac)
+
+#define __DEFAULT_FN_ATTRS                                                      \
+  __attribute__((__always_inline__, __nodebug__, __artificial__))
+
+/* ---------------------------------------------------------------------------
+ * 32x32-bit MAC / MSU
+ *
+ *   cv.mac  rd, rs1, rs2  ->  rd += rs1 * rs2
+ *   cv.msu  rd, rs1, rs2  ->  rd -= rs1 * rs2
+ *
+ * These are the only two operations that take a plain GPR accumulator
+ * (no shift/round), so they can be static inline functions.
+ * --------------------------------------------------------------------------- */
+
+static __inline__ int32_t __DEFAULT_FN_ATTRS
+__riscv_cv_mac_mac(int32_t a, int32_t b, int32_t accumulator) {
+  return __builtin_riscv_cv_mac_mac(a, b, accumulator);
+}
+
+static __inline__ int32_t __DEFAULT_FN_ATTRS
+__riscv_cv_mac_msu(int32_t a, int32_t b, int32_t accumulator) {
+  return __builtin_riscv_cv_mac_msu(a, b, accumulator);
+}
+
+/* ---------------------------------------------------------------------------
+ * 16x16-bit multiply (lower halfwords), unsigned, with normalisation shift
+ *
+ *   cv.mulun   rd, rs1, rs2, imm5  ->  rd = (u16(rs1) * u16(rs2)) >> imm5
+ *   cv.mulhhun rd, rs1, rs2, imm5  ->  rd = (u16hi(rs1) * u16hi(rs2)) >> imm5
+ *   cv.mulurn  rd, rs1, rs2, imm5  ->  rd = (u16(rs1) * u16(rs2) + rnd) >> imm5
+ *   cv.mulhhurn rd, rs1, rs2, imm5 ->  rd = (u16hi(rs1)*u16hi(rs2) + rnd) >> imm5
+ *
+ * SHIFT must be a compile-time constant in [0, 31].
+ * These are macros so the SHIFT argument is passed as an immediate.
+ * --------------------------------------------------------------------------- */
+
+#define __riscv_cv_mac_muluN(__rs1, __rs2, __SHIFT)                            \
+  ((uint32_t)__builtin_riscv_cv_mac_muluN((uint32_t)(__rs1),                   \
+                                           (uint32_t)(__rs2),                   \
+                                           (uint32_t)(__SHIFT)))
+
+#define __riscv_cv_mac_mulhhuN(__rs1, __rs2, __SHIFT)                          \
+  ((uint32_t)__builtin_riscv_cv_mac_mulhhuN((uint32_t)(__rs1),                 \
+                                             (uint32_t)(__rs2),                 \
+                                             (uint32_t)(__SHIFT)))
+
+#define __riscv_cv_mac_muluRN(__rs1, __rs2, __SHIFT)                           \
+  ((uint32_t)__builtin_riscv_cv_mac_muluRN((uint32_t)(__rs1),                  \
+                                            (uint32_t)(__rs2),                  \
+                                            (uint32_t)(__SHIFT)))
+
+#define __riscv_cv_mac_mulhhuRN(__rs1, __rs2, __SHIFT)                         \
+  ((uint32_t)__builtin_riscv_cv_mac_mulhhuRN((uint32_t)(__rs1),                \
+                                              (uint32_t)(__rs2),                \
+                                              (uint32_t)(__SHIFT)))
+
+/* ---------------------------------------------------------------------------
+ * 16x16-bit multiply (lower halfwords), signed, with normalisation shift
+ *
+ *   cv.mulsn    rd, rs1, rs2, imm5  ->  rd = (s16(rs1) * s16(rs2)) >> imm5
+ *   cv.mulhhsn  rd, rs1, rs2, imm5  ->  rd = (s16hi(rs1)*s16hi(rs2)) >> imm5
+ *   cv.mulsrn   rd, rs1, rs2, imm5  ->  rd = (s16(rs1) * s16(rs2) + rnd) >> imm5
+ *   cv.mulhhsrn rd, rs1, rs2, imm5  ->  rd = (s16hi(rs1)*s16hi(rs2)+rnd) >> imm5
+ *
+ * SHIFT must be a compile-time constant in [0, 31].
+ * --------------------------------------------------------------------------- */
+
+#define __riscv_cv_mac_mulsN(__rs1, __rs2, __SHIFT)                            \
+  ((int32_t)__builtin_riscv_cv_mac_mulsN((uint32_t)(__rs1),                    \
+                                          (uint32_t)(__rs2),                    \
+                                          (uint32_t)(__SHIFT)))
+
+#define __riscv_cv_mac_mulhhsN(__rs1, __rs2, __SHIFT)                          \
+  ((int32_t)__builtin_riscv_cv_mac_mulhhsN((uint32_t)(__rs1),                  \
+                                            (uint32_t)(__rs2),                  \
+                                            (uint32_t)(__SHIFT)))
+
+#define __riscv_cv_mac_mulsRN(__rs1, __rs2, __SHIFT)                           \
+  ((int32_t)__builtin_riscv_cv_mac_mulsRN((uint32_t)(__rs1),                   \
+                                           (uint32_t)(__rs2),                   \
+                                           (uint32_t)(__SHIFT)))
+
+#define __riscv_cv_mac_mulhhsRN(__rs1, __rs2, __SHIFT)                         \
+  ((int32_t)__builtin_riscv_cv_mac_mulhhsRN((uint32_t)(__rs1),                 \
+                                             (uint32_t)(__rs2),                 \
+                                             (uint32_t)(__SHIFT)))
+
+/* ---------------------------------------------------------------------------
+ * 16x16-bit multiply-accumulate (lower halfwords), unsigned
+ *
+ *   cv.macun    rd, rs1, rs2, imm5  ->  rd = (rd + u16(rs1) * u16(rs2)) >> imm5
+ *   cv.machhun  rd, rs1, rs2, imm5  ->  rd = (rd + u16hi(rs1)*u16hi(rs2)) >> imm5
+ *   cv.macurn   rd, rs1, rs2, imm5  ->  rd = (rd + u16(rs1)*u16(rs2)+rnd) >> imm5
+ *   cv.machhurn rd, rs1, rs2, imm5  ->  rd = (rd+u16hi(rs1)*u16hi(rs2)+rnd)>>imm5
+ *
+ * SHIFT must be a compile-time constant in [0, 31].
+ * rD is the accumulator register (read-modify-write).
+ * --------------------------------------------------------------------------- */
+
+#define __riscv_cv_mac_macuN(__rD, __rs1, __rs2, __SHIFT)                      \
+  ((uint32_t)__builtin_riscv_cv_mac_macuN((uint32_t)(__rs1),                   \
+                                           (uint32_t)(__rs2),                   \
+                                           (uint32_t)(__rD),                    \
+                                           (uint32_t)(__SHIFT)))
+
+#define __riscv_cv_mac_machhuN(__rD, __rs1, __rs2, __SHIFT)                    \
+  ((uint32_t)__builtin_riscv_cv_mac_machhuN((uint32_t)(__rs1),                 \
+                                             (uint32_t)(__rs2),                 \
+                                             (uint32_t)(__rD),                  \
+                                             (uint32_t)(__SHIFT)))
+
+#define __riscv_cv_mac_macuRN(__rD, __rs1, __rs2, __SHIFT)                     \
+  ((uint32_t)__builtin_riscv_cv_mac_macuRN((uint32_t)(__rs1),                  \
+                                            (uint32_t)(__rs2),                  \
+                                            (uint32_t)(__rD),                   \
+                                            (uint32_t)(__SHIFT)))
+
+#define __riscv_cv_mac_machhuRN(__rD, __rs1, __rs2, __SHIFT)                   \
+  ((uint32_t)__builtin_riscv_cv_mac_machhuRN((uint32_t)(__rs1),                \
+                                              (uint32_t)(__rs2),                \
+                                              (uint32_t)(__rD),                 \
+                                              (uint32_t)(__SHIFT)))
+
+/* ---------------------------------------------------------------------------
+ * 16x16-bit multiply-accumulate (lower halfwords), signed
+ *
+ *   cv.macsn    rd, rs1, rs2, imm5  ->  rd = (rd + s16(rs1) * s16(rs2)) >> imm5
+ *   cv.machhsn  rd, rs1, rs2, imm5  ->  rd = (rd+s16hi(rs1)*s16hi(rs2)) >> imm5
+ *   cv.macsrn   rd, rs1, rs2, imm5  ->  rd = (rd+s16(rs1)*s16(rs2)+rnd) >> imm5
+ *   cv.machhsrn rd, rs1, rs2, imm5  ->  rd = (rd+s16hi*s16hi+rnd) >> imm5
+ *
+ * SHIFT must be a compile-time constant in [0, 31].
+ * --------------------------------------------------------------------------- */
+
+#define __riscv_cv_mac_macsN(__rD, __rs1, __rs2, __SHIFT)                      \
+  ((int32_t)__builtin_riscv_cv_mac_macsN((uint32_t)(__rs1),                    \
+                                          (uint32_t)(__rs2),                    \
+                                          (uint32_t)(__rD),                     \
+                                          (uint32_t)(__SHIFT)))
+
+#define __riscv_cv_mac_machhsN(__rD, __rs1, __rs2, __SHIFT)                    \
+  ((int32_t)__builtin_riscv_cv_mac_machhsN((uint32_t)(__rs1),                  \
+                                            (uint32_t)(__rs2),                  \
+                                            (uint32_t)(__rD),                   \
+                                            (uint32_t)(__SHIFT)))
+
+#define __riscv_cv_mac_macsRN(__rD, __rs1, __rs2, __SHIFT)                     \
+  ((int32_t)__builtin_riscv_cv_mac_macsRN((uint32_t)(__rs1),                   \
+                                           (uint32_t)(__rs2),                   \
+                                           (uint32_t)(__rD),                    \
+                                           (uint32_t)(__SHIFT)))
+
+#define __riscv_cv_mac_machhsRN(__rD, __rs1, __rs2, __SHIFT)                   \
+  ((int32_t)__builtin_riscv_cv_mac_machhsRN((uint32_t)(__rs1),                 \
+                                             (uint32_t)(__rs2),                 \
+                                             (uint32_t)(__rD),                  \
+                                             (uint32_t)(__SHIFT)))
+
+#endif /* __riscv_xcvmac */
+
+#if defined(__cplusplus)
+}
+#endif
+
+#endif /* __RISCV_COREV_MAC_H */
diff --git a/clang/lib/Sema/SemaRISCV.cpp b/clang/lib/Sema/SemaRISCV.cpp
index 9647a7d913744..5711d87300b05 100644
--- a/clang/lib/Sema/SemaRISCV.cpp
+++ b/clang/lib/Sema/SemaRISCV.cpp
@@ -652,7 +652,26 @@ bool SemaRISCV::CheckBuiltinFunctionCall(const TargetInfo &TI,
 
     break;
   }
-  }
+
+  // XCVmac — shift amount in [0, 31]
+  case RISCV::BI__builtin_riscv_cv_mac_muluN:
+  case RISCV::BI__builtin_riscv_cv_mac_mulhhuN:
+  case RISCV::BI__builtin_riscv_cv_mac_mulsN:
+  case RISCV::BI__builtin_riscv_cv_mac_mulhhsN:
+  case RISCV::BI__builtin_riscv_cv_mac_muluRN:
+  case RISCV::BI__builtin_riscv_cv_mac_mulhhuRN:
+  case RISCV::BI__builtin_riscv_cv_mac_mulsRN:
+  case RISCV::BI__builtin_riscv_cv_mac_mulhhsRN:
+    return SemaRef.BuiltinConstantArgRange(TheCall, 2, 0, 31);
+  case RISCV::BI__builtin_riscv_cv_mac_macuN:
+  case RISCV::BI__builtin_riscv_cv_mac_machhuN:
+  case RISCV::BI__builtin_riscv_cv_mac_macsN:
+  case RISCV::BI__builtin_riscv_cv_mac_machhsN:
+  case RISCV::BI__builtin_riscv_cv_mac_macuRN:
+  case RISCV::BI__builtin_riscv_cv_mac_machhuRN:
+  case RISCV::BI__builtin_riscv_cv_mac_macsRN:
+  case RISCV::BI__builtin_riscv_cv_mac_machhsRN:
+    return SemaRef.BuiltinConstantArgRange(TheCall, 3, 0, 31);
 
   auto CheckVSetVL = [&](unsigned SEWOffset, unsigned LMULOffset) -> bool {
     const FunctionDecl *FD = SemaRef.getCurFunctionDecl();

>From 691b15ccc7e74a9071e75b0b8dd79eec4a3b5b76 Mon Sep 17 00:00:00 2001
From: vitbur <vittorioburani at gmail.com>
Date: Tue, 31 Mar 2026 18:49:29 +0200
Subject: [PATCH 04/10] [Clang][RISCV] Add Clang builtins for `XCVsimd`
 extension

- `BuiltinsRISCVXCV.td`: add all simd attributes
- `SemaRISCV.cpp`: add range check for arg 1
- `RISCV.cpp`: add dispatch cases
- `CIRGenBuiltinRISCV.cpp`: add NYI cases
- add `riscv_corev_simd.h` header + `CMakeLists.txt` addition
---
 clang/include/clang/Basic/BuiltinsRISCVXCV.td | 177 +++++
 clang/lib/CIR/CodeGen/CIRGenBuiltinRISCV.cpp  | 156 ++++
 clang/lib/CodeGen/TargetBuiltins/RISCV.cpp    | 454 +++++++++++
 clang/lib/Headers/CMakeLists.txt              |   1 +
 clang/lib/Headers/riscv_corev_simd.h          | 707 ++++++++++++++++++
 clang/lib/Sema/SemaRISCV.cpp                  |  31 +
 6 files changed, 1526 insertions(+)
 create mode 100644 clang/lib/Headers/riscv_corev_simd.h

diff --git a/clang/include/clang/Basic/BuiltinsRISCVXCV.td b/clang/include/clang/Basic/BuiltinsRISCVXCV.td
index 0d6f2c56d19a3..eb0bb58e4814d 100644
--- a/clang/include/clang/Basic/BuiltinsRISCVXCV.td
+++ b/clang/include/clang/Basic/BuiltinsRISCVXCV.td
@@ -70,3 +70,180 @@ def mac_machhuRN : RISCVXCVBuiltin<"unsigned int(unsigned int, unsigned int, uns
 def mac_macsRN   : RISCVXCVBuiltin<"int(unsigned int, unsigned int, unsigned int, _Constant unsigned int)", "xcvmac">;
 def mac_machhsRN : RISCVXCVBuiltin<"int(unsigned int, unsigned int, unsigned int, _Constant unsigned int)", "xcvmac">;
 } // Attributes = [NoThrow, Const]
+
+//===----------------------------------------------------------------------===//
+// XCVsimd extension.
+//===----------------------------------------------------------------------===//
+let Attributes = [NoThrow, Const] in {
+
+// ADD/SUB — halfword has div immediate; byte is plain
+def simd_add_h   : RISCVXCVBuiltin<"unsigned int(unsigned int, unsigned int, _Constant unsigned int)", "xcvsimd">;
+def simd_add_b   : RISCVXCVBuiltin<"unsigned int(unsigned int, unsigned int)", "xcvsimd">;
+def simd_add_sc_h : RISCVXCVBuiltin<"unsigned int(unsigned int, unsigned int)", "xcvsimd">;
+def simd_add_sc_b : RISCVXCVBuiltin<"unsigned int(unsigned int, unsigned int)", "xcvsimd">;
+def simd_sub_h   : RISCVXCVBuiltin<"unsigned int(unsigned int, unsigned int, _Constant unsigned int)", "xcvsimd">;
+def simd_sub_b   : RISCVXCVBuiltin<"unsigned int(unsigned int, unsigned int)", "xcvsimd">;
+def simd_sub_sc_h : RISCVXCVBuiltin<"unsigned int(unsigned int, unsigned int)", "xcvsimd">;
+def simd_sub_sc_b : RISCVXCVBuiltin<"unsigned int(unsigned int, unsigned int)", "xcvsimd">;
+
+// AVG (signed)
+def simd_avg_h   : RISCVXCVBuiltin<"unsigned int(unsigned int, unsigned int)", "xcvsimd">;
+def simd_avg_b   : RISCVXCVBuiltin<"unsigned int(unsigned int, unsigned int)", "xcvsimd">;
+def simd_avg_sc_h : RISCVXCVBuiltin<"unsigned int(unsigned int, unsigned int)", "xcvsimd">;
+def simd_avg_sc_b : RISCVXCVBuiltin<"unsigned int(unsigned int, unsigned int)", "xcvsimd">;
+
+// AVGU (unsigned)
+def simd_avgu_h  : RISCVXCVBuiltin<"unsigned int(unsigned int, unsigned int)", "xcvsimd">;
+def simd_avgu_b  : RISCVXCVBuiltin<"unsigned int(unsigned int, unsigned int)", "xcvsimd">;
+def simd_avgu_sc_h : RISCVXCVBuiltin<"unsigned int(unsigned int, unsigned int)", "xcvsimd">;
+def simd_avgu_sc_b : RISCVXCVBuiltin<"unsigned int(unsigned int, unsigned int)", "xcvsimd">;
+
+// MIN / MINU / MAX / MAXU
+def simd_min_h   : RISCVXCVBuiltin<"unsigned int(unsigned int, unsigned int)", "xcvsimd">;
+def simd_min_b   : RISCVXCVBuiltin<"unsigned int(unsigned int, unsigned int)", "xcvsimd">;
+def simd_min_sc_h : RISCVXCVBuiltin<"unsigned int(unsigned int, unsigned int)", "xcvsimd">;
+def simd_min_sc_b : RISCVXCVBuiltin<"unsigned int(unsigned int, unsigned int)", "xcvsimd">;
+def simd_minu_h  : RISCVXCVBuiltin<"unsigned int(unsigned int, unsigned int)", "xcvsimd">;
+def simd_minu_b  : RISCVXCVBuiltin<"unsigned int(unsigned int, unsigned int)", "xcvsimd">;
+def simd_minu_sc_h : RISCVXCVBuiltin<"unsigned int(unsigned int, unsigned int)", "xcvsimd">;
+def simd_minu_sc_b : RISCVXCVBuiltin<"unsigned int(unsigned int, unsigned int)", "xcvsimd">;
+def simd_max_h   : RISCVXCVBuiltin<"unsigned int(unsigned int, unsigned int)", "xcvsimd">;
+def simd_max_b   : RISCVXCVBuiltin<"unsigned int(unsigned int, unsigned int)", "xcvsimd">;
+def simd_max_sc_h : RISCVXCVBuiltin<"unsigned int(unsigned int, unsigned int)", "xcvsimd">;
+def simd_max_sc_b : RISCVXCVBuiltin<"unsigned int(unsigned int, unsigned int)", "xcvsimd">;
+def simd_maxu_h  : RISCVXCVBuiltin<"unsigned int(unsigned int, unsigned int)", "xcvsimd">;
+def simd_maxu_b  : RISCVXCVBuiltin<"unsigned int(unsigned int, unsigned int)", "xcvsimd">;
+def simd_maxu_sc_h : RISCVXCVBuiltin<"unsigned int(unsigned int, unsigned int)", "xcvsimd">;
+def simd_maxu_sc_b : RISCVXCVBuiltin<"unsigned int(unsigned int, unsigned int)", "xcvsimd">;
+
+// SRL / SRA / SLL (shifts — immediate versions take uimm6)
+def simd_srl_h   : RISCVXCVBuiltin<"unsigned int(unsigned int, unsigned int)", "xcvsimd">;
+def simd_srl_b   : RISCVXCVBuiltin<"unsigned int(unsigned int, unsigned int)", "xcvsimd">;
+def simd_srl_sc_h : RISCVXCVBuiltin<"unsigned int(unsigned int, unsigned int)", "xcvsimd">;
+def simd_srl_sc_b : RISCVXCVBuiltin<"unsigned int(unsigned int, unsigned int)", "xcvsimd">;
+def simd_sra_h   : RISCVXCVBuiltin<"unsigned int(unsigned int, unsigned int)", "xcvsimd">;
+def simd_sra_b   : RISCVXCVBuiltin<"unsigned int(unsigned int, unsigned int)", "xcvsimd">;
+def simd_sra_sc_h : RISCVXCVBuiltin<"unsigned int(unsigned int, unsigned int)", "xcvsimd">;
+def simd_sra_sc_b : RISCVXCVBuiltin<"unsigned int(unsigned int, unsigned int)", "xcvsimd">;
+def simd_sll_h   : RISCVXCVBuiltin<"unsigned int(unsigned int, unsigned int)", "xcvsimd">;
+def simd_sll_b   : RISCVXCVBuiltin<"unsigned int(unsigned int, unsigned int)", "xcvsimd">;
+def simd_sll_sc_h : RISCVXCVBuiltin<"unsigned int(unsigned int, unsigned int)", "xcvsimd">;
+def simd_sll_sc_b : RISCVXCVBuiltin<"unsigned int(unsigned int, unsigned int)", "xcvsimd">;
+
+// OR / XOR / AND
+def simd_or_h    : RISCVXCVBuiltin<"unsigned int(unsigned int, unsigned int)", "xcvsimd">;
+def simd_or_b    : RISCVXCVBuiltin<"unsigned int(unsigned int, unsigned int)", "xcvsimd">;
+def simd_or_sc_h : RISCVXCVBuiltin<"unsigned int(unsigned int, unsigned int)", "xcvsimd">;
+def simd_or_sc_b : RISCVXCVBuiltin<"unsigned int(unsigned int, unsigned int)", "xcvsimd">;
+def simd_xor_h   : RISCVXCVBuiltin<"unsigned int(unsigned int, unsigned int)", "xcvsimd">;
+def simd_xor_b   : RISCVXCVBuiltin<"unsigned int(unsigned int, unsigned int)", "xcvsimd">;
+def simd_xor_sc_h : RISCVXCVBuiltin<"unsigned int(unsigned int, unsigned int)", "xcvsimd">;
+def simd_xor_sc_b : RISCVXCVBuiltin<"unsigned int(unsigned int, unsigned int)", "xcvsimd">;
+def simd_and_h   : RISCVXCVBuiltin<"unsigned int(unsigned int, unsigned int)", "xcvsimd">;
+def simd_and_b   : RISCVXCVBuiltin<"unsigned int(unsigned int, unsigned int)", "xcvsimd">;
+def simd_and_sc_h : RISCVXCVBuiltin<"unsigned int(unsigned int, unsigned int)", "xcvsimd">;
+def simd_and_sc_b : RISCVXCVBuiltin<"unsigned int(unsigned int, unsigned int)", "xcvsimd">;
+
+// ABS
+def simd_abs_h   : RISCVXCVBuiltin<"unsigned int(unsigned int)", "xcvsimd">;
+def simd_abs_b   : RISCVXCVBuiltin<"unsigned int(unsigned int)", "xcvsimd">;
+
+// DOT PRODUCTS
+def simd_dotup_h  : RISCVXCVBuiltin<"unsigned int(unsigned int, unsigned int)", "xcvsimd">;
+def simd_dotup_b  : RISCVXCVBuiltin<"unsigned int(unsigned int, unsigned int)", "xcvsimd">;
+def simd_dotup_sc_h : RISCVXCVBuiltin<"unsigned int(unsigned int, unsigned int)", "xcvsimd">;
+def simd_dotup_sc_b : RISCVXCVBuiltin<"unsigned int(unsigned int, unsigned int)", "xcvsimd">;
+def simd_dotusp_h : RISCVXCVBuiltin<"int(unsigned int, unsigned int)", "xcvsimd">;
+def simd_dotusp_b : RISCVXCVBuiltin<"int(unsigned int, unsigned int)", "xcvsimd">;
+def simd_dotusp_sc_h : RISCVXCVBuiltin<"int(unsigned int, unsigned int)", "xcvsimd">;
+def simd_dotusp_sc_b : RISCVXCVBuiltin<"int(unsigned int, unsigned int)", "xcvsimd">;
+def simd_dotsp_h : RISCVXCVBuiltin<"int(unsigned int, unsigned int)", "xcvsimd">;
+def simd_dotsp_b : RISCVXCVBuiltin<"int(unsigned int, unsigned int)", "xcvsimd">;
+def simd_dotsp_sc_h : RISCVXCVBuiltin<"int(unsigned int, unsigned int)", "xcvsimd">;
+def simd_dotsp_sc_b : RISCVXCVBuiltin<"int(unsigned int, unsigned int)", "xcvsimd">;
+
+// SDOT (accumulating dot products — rd is both input and output)
+def simd_sdotup_h  : RISCVXCVBuiltin<"unsigned int(unsigned int, unsigned int, unsigned int)", "xcvsimd">;
+def simd_sdotup_b  : RISCVXCVBuiltin<"unsigned int(unsigned int, unsigned int, unsigned int)", "xcvsimd">;
+def simd_sdotup_sc_h : RISCVXCVBuiltin<"unsigned int(unsigned int, unsigned int, unsigned int)", "xcvsimd">;
+def simd_sdotup_sc_b : RISCVXCVBuiltin<"unsigned int(unsigned int, unsigned int, unsigned int)", "xcvsimd">;
+def simd_sdotusp_h : RISCVXCVBuiltin<"int(unsigned int, unsigned int, int)", "xcvsimd">;
+def simd_sdotusp_b : RISCVXCVBuiltin<"int(unsigned int, unsigned int, int)", "xcvsimd">;
+def simd_sdotusp_sc_h : RISCVXCVBuiltin<"int(unsigned int, unsigned int, int)", "xcvsimd">;
+def simd_sdotusp_sc_b : RISCVXCVBuiltin<"int(unsigned int, unsigned int, int)", "xcvsimd">;
+def simd_sdotsp_h : RISCVXCVBuiltin<"int(unsigned int, unsigned int, int)", "xcvsimd">;
+def simd_sdotsp_b : RISCVXCVBuiltin<"int(unsigned int, unsigned int, int)", "xcvsimd">;
+def simd_sdotsp_sc_h : RISCVXCVBuiltin<"int(unsigned int, unsigned int, int)", "xcvsimd">;
+def simd_sdotsp_sc_b : RISCVXCVBuiltin<"int(unsigned int, unsigned int, int)", "xcvsimd">;
+
+// EXTRACT / INSERT
+def simd_extract_h  : RISCVXCVBuiltin<"int(unsigned int, _Constant unsigned int)", "xcvsimd">;
+def simd_extract_b  : RISCVXCVBuiltin<"int(unsigned int, _Constant unsigned int)", "xcvsimd">;
+def simd_extractu_h : RISCVXCVBuiltin<"unsigned int(unsigned int, _Constant unsigned int)", "xcvsimd">;
+def simd_extractu_b : RISCVXCVBuiltin<"unsigned int(unsigned int, _Constant unsigned int)", "xcvsimd">;
+def simd_insert_h   : RISCVXCVBuiltin<"unsigned int(unsigned int, unsigned int, _Constant unsigned int)", "xcvsimd">;
+def simd_insert_b   : RISCVXCVBuiltin<"unsigned int(unsigned int, unsigned int, _Constant unsigned int)", "xcvsimd">;
+
+// SHUFFLE / SHUFFLE2
+def simd_shuffle_h    : RISCVXCVBuiltin<"unsigned int(unsigned int, unsigned int)", "xcvsimd">;
+def simd_shuffle_b    : RISCVXCVBuiltin<"unsigned int(unsigned int, unsigned int)", "xcvsimd">;
+def simd_shuffle_sci_h : RISCVXCVBuiltin<"unsigned int(unsigned int, _Constant unsigned int)", "xcvsimd">;
+def simd_shuffle_sci_b : RISCVXCVBuiltin<"unsigned int(unsigned int, _Constant unsigned int)", "xcvsimd">;
+def simd_shuffle2_h   : RISCVXCVBuiltin<"unsigned int(unsigned int, unsigned int, unsigned int)", "xcvsimd">;
+def simd_shuffle2_b   : RISCVXCVBuiltin<"unsigned int(unsigned int, unsigned int, unsigned int)", "xcvsimd">;
+
+// PACK
+def simd_packhi_h : RISCVXCVBuiltin<"unsigned int(unsigned int, unsigned int)", "xcvsimd">;
+def simd_packlo_h : RISCVXCVBuiltin<"unsigned int(unsigned int, unsigned int)", "xcvsimd">;
+def simd_packhi_b : RISCVXCVBuiltin<"unsigned int(unsigned int, unsigned int, unsigned int)", "xcvsimd">;
+def simd_packlo_b : RISCVXCVBuiltin<"unsigned int(unsigned int, unsigned int, unsigned int)", "xcvsimd">;
+
+// COMPARE (result is mask in packed reg)
+def simd_cmpeq_h  : RISCVXCVBuiltin<"unsigned int(unsigned int, unsigned int)", "xcvsimd">;
+def simd_cmpeq_b  : RISCVXCVBuiltin<"unsigned int(unsigned int, unsigned int)", "xcvsimd">;
+def simd_cmpeq_sc_h : RISCVXCVBuiltin<"unsigned int(unsigned int, unsigned int)", "xcvsimd">;
+def simd_cmpeq_sc_b : RISCVXCVBuiltin<"unsigned int(unsigned int, unsigned int)", "xcvsimd">;
+def simd_cmpne_h  : RISCVXCVBuiltin<"unsigned int(unsigned int, unsigned int)", "xcvsimd">;
+def simd_cmpne_b  : RISCVXCVBuiltin<"unsigned int(unsigned int, unsigned int)", "xcvsimd">;
+def simd_cmpne_sc_h : RISCVXCVBuiltin<"unsigned int(unsigned int, unsigned int)", "xcvsimd">;
+def simd_cmpne_sc_b : RISCVXCVBuiltin<"unsigned int(unsigned int, unsigned int)", "xcvsimd">;
+def simd_cmpgt_h  : RISCVXCVBuiltin<"unsigned int(unsigned int, unsigned int)", "xcvsimd">;
+def simd_cmpgt_b  : RISCVXCVBuiltin<"unsigned int(unsigned int, unsigned int)", "xcvsimd">;
+def simd_cmpgt_sc_h : RISCVXCVBuiltin<"unsigned int(unsigned int, unsigned int)", "xcvsimd">;
+def simd_cmpgt_sc_b : RISCVXCVBuiltin<"unsigned int(unsigned int, unsigned int)", "xcvsimd">;
+def simd_cmpge_h  : RISCVXCVBuiltin<"unsigned int(unsigned int, unsigned int)", "xcvsimd">;
+def simd_cmpge_b  : RISCVXCVBuiltin<"unsigned int(unsigned int, unsigned int)", "xcvsimd">;
+def simd_cmpge_sc_h : RISCVXCVBuiltin<"unsigned int(unsigned int, unsigned int)", "xcvsimd">;
+def simd_cmpge_sc_b : RISCVXCVBuiltin<"unsigned int(unsigned int, unsigned int)", "xcvsimd">;
+def simd_cmplt_h  : RISCVXCVBuiltin<"unsigned int(unsigned int, unsigned int)", "xcvsimd">;
+def simd_cmplt_b  : RISCVXCVBuiltin<"unsigned int(unsigned int, unsigned int)", "xcvsimd">;
+def simd_cmplt_sc_h : RISCVXCVBuiltin<"unsigned int(unsigned int, unsigned int)", "xcvsimd">;
+def simd_cmplt_sc_b : RISCVXCVBuiltin<"unsigned int(unsigned int, unsigned int)", "xcvsimd">;
+def simd_cmple_h  : RISCVXCVBuiltin<"unsigned int(unsigned int, unsigned int)", "xcvsimd">;
+def simd_cmple_b  : RISCVXCVBuiltin<"unsigned int(unsigned int, unsigned int)", "xcvsimd">;
+def simd_cmple_sc_h : RISCVXCVBuiltin<"unsigned int(unsigned int, unsigned int)", "xcvsimd">;
+def simd_cmple_sc_b : RISCVXCVBuiltin<"unsigned int(unsigned int, unsigned int)", "xcvsimd">;
+def simd_cmpgtu_h : RISCVXCVBuiltin<"unsigned int(unsigned int, unsigned int)", "xcvsimd">;
+def simd_cmpgtu_b : RISCVXCVBuiltin<"unsigned int(unsigned int, unsigned int)", "xcvsimd">;
+def simd_cmpgtu_sc_h : RISCVXCVBuiltin<"unsigned int(unsigned int, unsigned int)", "xcvsimd">;
+def simd_cmpgtu_sc_b : RISCVXCVBuiltin<"unsigned int(unsigned int, unsigned int)", "xcvsimd">;
+def simd_cmpgeu_h : RISCVXCVBuiltin<"unsigned int(unsigned int, unsigned int)", "xcvsimd">;
+def simd_cmpgeu_b : RISCVXCVBuiltin<"unsigned int(unsigned int, unsigned int)", "xcvsimd">;
+def simd_cmpgeu_sc_h : RISCVXCVBuiltin<"unsigned int(unsigned int, unsigned int)", "xcvsimd">;
+def simd_cmpgeu_sc_b : RISCVXCVBuiltin<"unsigned int(unsigned int, unsigned int)", "xcvsimd">;
+def simd_cmpltu_h : RISCVXCVBuiltin<"unsigned int(unsigned int, unsigned int)", "xcvsimd">;
+def simd_cmpltu_b : RISCVXCVBuiltin<"unsigned int(unsigned int, unsigned int)", "xcvsimd">;
+def simd_cmpltu_sc_h : RISCVXCVBuiltin<"unsigned int(unsigned int, unsigned int)", "xcvsimd">;
+def simd_cmpltu_sc_b : RISCVXCVBuiltin<"unsigned int(unsigned int, unsigned int)", "xcvsimd">;
+def simd_cmpleu_h : RISCVXCVBuiltin<"unsigned int(unsigned int, unsigned int)", "xcvsimd">;
+def simd_cmpleu_b : RISCVXCVBuiltin<"unsigned int(unsigned int, unsigned int)", "xcvsimd">;
+def simd_cmpleu_sc_h : RISCVXCVBuiltin<"unsigned int(unsigned int, unsigned int)", "xcvsimd">;
+def simd_cmpleu_sc_b : RISCVXCVBuiltin<"unsigned int(unsigned int, unsigned int)", "xcvsimd">;
+
+// COMPLEX NUMBER OPS
+def simd_cplxmul_r : RISCVXCVBuiltin<"unsigned int(unsigned int, unsigned int, unsigned int, _Constant unsigned int)", "xcvsimd">;
+def simd_cplxmul_i : RISCVXCVBuiltin<"unsigned int(unsigned int, unsigned int, unsigned int, _Constant unsigned int)", "xcvsimd">;
+def simd_cplxconj   : RISCVXCVBuiltin<"unsigned int(unsigned int)", "xcvsimd">;
+def simd_subrotmj   : RISCVXCVBuiltin<"unsigned int(unsigned int, unsigned int, _Constant unsigned int)", "xcvsimd">;
+
+} // Attributes = [NoThrow, Const]
diff --git a/clang/lib/CIR/CodeGen/CIRGenBuiltinRISCV.cpp b/clang/lib/CIR/CodeGen/CIRGenBuiltinRISCV.cpp
index 55b4d8ae8c60b..23c497acb2447 100644
--- a/clang/lib/CIR/CodeGen/CIRGenBuiltinRISCV.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenBuiltinRISCV.cpp
@@ -205,6 +205,162 @@ CIRGenFunction::emitRISCVBuiltinExpr(unsigned builtinID, const CallExpr *e) {
   case RISCV::BI__builtin_riscv_cv_mac_machhuRN:
   case RISCV::BI__builtin_riscv_cv_mac_macsRN:
   case RISCV::BI__builtin_riscv_cv_mac_machhsRN:
+  // XCVsimd - ADD/SUB
+  case RISCV::BI__builtin_riscv_cv_simd_add_h:
+  case RISCV::BI__builtin_riscv_cv_simd_add_b:
+  case RISCV::BI__builtin_riscv_cv_simd_add_sc_h:
+  case RISCV::BI__builtin_riscv_cv_simd_add_sc_b:
+  case RISCV::BI__builtin_riscv_cv_simd_sub_h:
+  case RISCV::BI__builtin_riscv_cv_simd_sub_b:
+  case RISCV::BI__builtin_riscv_cv_simd_sub_sc_h:
+  case RISCV::BI__builtin_riscv_cv_simd_sub_sc_b:
+  // XCVsimd - AVG (signed)
+  case RISCV::BI__builtin_riscv_cv_simd_avg_h:
+  case RISCV::BI__builtin_riscv_cv_simd_avg_b:
+  case RISCV::BI__builtin_riscv_cv_simd_avg_sc_h:
+  case RISCV::BI__builtin_riscv_cv_simd_avg_sc_b:
+  // XCVsimd - AVGU (unsigned)
+  case RISCV::BI__builtin_riscv_cv_simd_avgu_h:
+  case RISCV::BI__builtin_riscv_cv_simd_avgu_b:
+  case RISCV::BI__builtin_riscv_cv_simd_avgu_sc_h:
+  case RISCV::BI__builtin_riscv_cv_simd_avgu_sc_b:
+  // XCVsimd - MIN / MINU / MAX / MAXU
+  case RISCV::BI__builtin_riscv_cv_simd_min_h:
+  case RISCV::BI__builtin_riscv_cv_simd_min_b:
+  case RISCV::BI__builtin_riscv_cv_simd_min_sc_h:
+  case RISCV::BI__builtin_riscv_cv_simd_min_sc_b:
+  case RISCV::BI__builtin_riscv_cv_simd_minu_h:
+  case RISCV::BI__builtin_riscv_cv_simd_minu_b:
+  case RISCV::BI__builtin_riscv_cv_simd_minu_sc_h:
+  case RISCV::BI__builtin_riscv_cv_simd_minu_sc_b:
+  case RISCV::BI__builtin_riscv_cv_simd_max_h:
+  case RISCV::BI__builtin_riscv_cv_simd_max_b:
+  case RISCV::BI__builtin_riscv_cv_simd_max_sc_h:
+  case RISCV::BI__builtin_riscv_cv_simd_max_sc_b:
+  case RISCV::BI__builtin_riscv_cv_simd_maxu_h:
+  case RISCV::BI__builtin_riscv_cv_simd_maxu_b:
+  case RISCV::BI__builtin_riscv_cv_simd_maxu_sc_h:
+  case RISCV::BI__builtin_riscv_cv_simd_maxu_sc_b:
+  // XCVsimd - SRL / SRA / SLL (shifts — immediate versions take uimm6)
+  case RISCV::BI__builtin_riscv_cv_simd_srl_h:
+  case RISCV::BI__builtin_riscv_cv_simd_srl_b:
+  case RISCV::BI__builtin_riscv_cv_simd_srl_sc_h:
+  case RISCV::BI__builtin_riscv_cv_simd_srl_sc_b:
+  case RISCV::BI__builtin_riscv_cv_simd_sra_h:
+  case RISCV::BI__builtin_riscv_cv_simd_sra_b:
+  case RISCV::BI__builtin_riscv_cv_simd_sra_sc_h:
+  case RISCV::BI__builtin_riscv_cv_simd_sra_sc_b:
+  case RISCV::BI__builtin_riscv_cv_simd_sll_h:
+  case RISCV::BI__builtin_riscv_cv_simd_sll_b:
+  case RISCV::BI__builtin_riscv_cv_simd_sll_sc_h:
+  case RISCV::BI__builtin_riscv_cv_simd_sll_sc_b:
+  // XCVsimd - OR / XOR / AND
+  case RISCV::BI__builtin_riscv_cv_simd_or_h:
+  case RISCV::BI__builtin_riscv_cv_simd_or_b:
+  case RISCV::BI__builtin_riscv_cv_simd_or_sc_h:
+  case RISCV::BI__builtin_riscv_cv_simd_or_sc_b:
+  case RISCV::BI__builtin_riscv_cv_simd_xor_h:
+  case RISCV::BI__builtin_riscv_cv_simd_xor_b:
+  case RISCV::BI__builtin_riscv_cv_simd_xor_sc_h:
+  case RISCV::BI__builtin_riscv_cv_simd_xor_sc_b:
+  case RISCV::BI__builtin_riscv_cv_simd_and_h:
+  case RISCV::BI__builtin_riscv_cv_simd_and_b:
+  case RISCV::BI__builtin_riscv_cv_simd_and_sc_h:
+  case RISCV::BI__builtin_riscv_cv_simd_and_sc_b:
+  // XCVsimd - ABS
+  case RISCV::BI__builtin_riscv_cv_simd_abs_h:
+  case RISCV::BI__builtin_riscv_cv_simd_abs_b:
+  // XCVsimd - DOT PRODUCTS
+  case RISCV::BI__builtin_riscv_cv_simd_dotup_h:
+  case RISCV::BI__builtin_riscv_cv_simd_dotup_b:
+  case RISCV::BI__builtin_riscv_cv_simd_dotup_sc_h:
+  case RISCV::BI__builtin_riscv_cv_simd_dotup_sc_b:
+  case RISCV::BI__builtin_riscv_cv_simd_dotusp_h:
+  case RISCV::BI__builtin_riscv_cv_simd_dotusp_b:
+  case RISCV::BI__builtin_riscv_cv_simd_dotusp_sc_h:
+  case RISCV::BI__builtin_riscv_cv_simd_dotusp_sc_b:
+  case RISCV::BI__builtin_riscv_cv_simd_dotsp_h:
+  case RISCV::BI__builtin_riscv_cv_simd_dotsp_b:
+  case RISCV::BI__builtin_riscv_cv_simd_dotsp_sc_h:
+  case RISCV::BI__builtin_riscv_cv_simd_dotsp_sc_b:
+  // XCVsimd - SDOT (accumulating dot products — rd is both input and output)
+  case RISCV::BI__builtin_riscv_cv_simd_sdotup_h:
+  case RISCV::BI__builtin_riscv_cv_simd_sdotup_b:
+  case RISCV::BI__builtin_riscv_cv_simd_sdotup_sc_h:
+  case RISCV::BI__builtin_riscv_cv_simd_sdotup_sc_b:
+  case RISCV::BI__builtin_riscv_cv_simd_sdotusp_h:
+  case RISCV::BI__builtin_riscv_cv_simd_sdotusp_b:
+  case RISCV::BI__builtin_riscv_cv_simd_sdotusp_sc_h:
+  case RISCV::BI__builtin_riscv_cv_simd_sdotusp_sc_b:
+  case RISCV::BI__builtin_riscv_cv_simd_sdotsp_h:
+  case RISCV::BI__builtin_riscv_cv_simd_sdotsp_b:
+  case RISCV::BI__builtin_riscv_cv_simd_sdotsp_sc_h:
+  case RISCV::BI__builtin_riscv_cv_simd_sdotsp_sc_b:
+  // XCVsimd - EXTRACT / INSERT
+  case RISCV::BI__builtin_riscv_cv_simd_extract_h:
+  case RISCV::BI__builtin_riscv_cv_simd_extract_b:
+  case RISCV::BI__builtin_riscv_cv_simd_extractu_h:
+  case RISCV::BI__builtin_riscv_cv_simd_extractu_b:
+  case RISCV::BI__builtin_riscv_cv_simd_insert_h:
+  case RISCV::BI__builtin_riscv_cv_simd_insert_b:
+  // XCVsimd - SHUFFLE / SHUFFLE2
+  case RISCV::BI__builtin_riscv_cv_simd_shuffle_h:
+  case RISCV::BI__builtin_riscv_cv_simd_shuffle_b:
+  case RISCV::BI__builtin_riscv_cv_simd_shuffle_sci_h:
+  case RISCV::BI__builtin_riscv_cv_simd_shuffle_sci_b:
+  case RISCV::BI__builtin_riscv_cv_simd_shuffle2_h:
+  case RISCV::BI__builtin_riscv_cv_simd_shuffle2_b:
+  // XCVsimd - PACK
+  case RISCV::BI__builtin_riscv_cv_simd_packhi_h:
+  case RISCV::BI__builtin_riscv_cv_simd_packlo_h:
+  case RISCV::BI__builtin_riscv_cv_simd_packhi_b:
+  case RISCV::BI__builtin_riscv_cv_simd_packlo_b:
+  // XCVsimd - COMPARE (result is mask in packed reg)
+  case RISCV::BI__builtin_riscv_cv_simd_cmpeq_h:
+  case RISCV::BI__builtin_riscv_cv_simd_cmpeq_b:
+  case RISCV::BI__builtin_riscv_cv_simd_cmpeq_sc_h:
+  case RISCV::BI__builtin_riscv_cv_simd_cmpeq_sc_b:
+  case RISCV::BI__builtin_riscv_cv_simd_cmpne_h:
+  case RISCV::BI__builtin_riscv_cv_simd_cmpne_b:
+  case RISCV::BI__builtin_riscv_cv_simd_cmpne_sc_h:
+  case RISCV::BI__builtin_riscv_cv_simd_cmpne_sc_b:
+  case RISCV::BI__builtin_riscv_cv_simd_cmpgt_h:
+  case RISCV::BI__builtin_riscv_cv_simd_cmpgt_b:
+  case RISCV::BI__builtin_riscv_cv_simd_cmpgt_sc_h:
+  case RISCV::BI__builtin_riscv_cv_simd_cmpgt_sc_b:
+  case RISCV::BI__builtin_riscv_cv_simd_cmpge_h:
+  case RISCV::BI__builtin_riscv_cv_simd_cmpge_b:
+  case RISCV::BI__builtin_riscv_cv_simd_cmpge_sc_h:
+  case RISCV::BI__builtin_riscv_cv_simd_cmpge_sc_b:
+  case RISCV::BI__builtin_riscv_cv_simd_cmplt_h:
+  case RISCV::BI__builtin_riscv_cv_simd_cmplt_b:
+  case RISCV::BI__builtin_riscv_cv_simd_cmplt_sc_h:
+  case RISCV::BI__builtin_riscv_cv_simd_cmplt_sc_b:
+  case RISCV::BI__builtin_riscv_cv_simd_cmple_h:
+  case RISCV::BI__builtin_riscv_cv_simd_cmple_b:
+  case RISCV::BI__builtin_riscv_cv_simd_cmple_sc_h:
+  case RISCV::BI__builtin_riscv_cv_simd_cmple_sc_b:
+  case RISCV::BI__builtin_riscv_cv_simd_cmpgtu_h:
+  case RISCV::BI__builtin_riscv_cv_simd_cmpgtu_b:
+  case RISCV::BI__builtin_riscv_cv_simd_cmpgtu_sc_h:
+  case RISCV::BI__builtin_riscv_cv_simd_cmpgtu_sc_b:
+  case RISCV::BI__builtin_riscv_cv_simd_cmpgeu_h:
+  case RISCV::BI__builtin_riscv_cv_simd_cmpgeu_b:
+  case RISCV::BI__builtin_riscv_cv_simd_cmpgeu_sc_h:
+  case RISCV::BI__builtin_riscv_cv_simd_cmpgeu_sc_b:
+  case RISCV::BI__builtin_riscv_cv_simd_cmpltu_h:
+  case RISCV::BI__builtin_riscv_cv_simd_cmpltu_b:
+  case RISCV::BI__builtin_riscv_cv_simd_cmpltu_sc_h:
+  case RISCV::BI__builtin_riscv_cv_simd_cmpltu_sc_b:
+  case RISCV::BI__builtin_riscv_cv_simd_cmpleu_h:
+  case RISCV::BI__builtin_riscv_cv_simd_cmpleu_b:
+  case RISCV::BI__builtin_riscv_cv_simd_cmpleu_sc_h:
+  case RISCV::BI__builtin_riscv_cv_simd_cmpleu_sc_b:
+  // XCVsimd - COMPLEX
+  case RISCV::BI__builtin_riscv_cv_simd_cplxmul_r:
+  case RISCV::BI__builtin_riscv_cv_simd_cplxmul_i:
+  case RISCV::BI__builtin_riscv_cv_simd_cplxconj:
+  case RISCV::BI__builtin_riscv_cv_simd_subrotmj:
   // XAndesPerf
   case RISCV::BI__builtin_riscv_nds_ffb_32:
   case RISCV::BI__builtin_riscv_nds_ffb_64:
diff --git a/clang/lib/CodeGen/TargetBuiltins/RISCV.cpp b/clang/lib/CodeGen/TargetBuiltins/RISCV.cpp
index 07feb6296833e..1338eda9f876b 100644
--- a/clang/lib/CodeGen/TargetBuiltins/RISCV.cpp
+++ b/clang/lib/CodeGen/TargetBuiltins/RISCV.cpp
@@ -1498,6 +1498,460 @@ Value *CodeGenFunction::EmitRISCVBuiltinExpr(unsigned BuiltinID,
     ID = Intrinsic::riscv_cv_mac_machhsRN;
     break;
 
+  // XCVsimd - ADD/SUB
+  case RISCV::BI__builtin_riscv_cv_simd_add_h:
+    ID = Intrinsic::riscv_cv_simd_add_h;
+    break;
+  case RISCV::BI__builtin_riscv_cv_simd_add_b:
+    ID = Intrinsic::riscv_cv_simd_add_b;
+    break;
+  case RISCV::BI__builtin_riscv_cv_simd_add_sc_h:
+    ID = Intrinsic::riscv_cv_simd_add_sc_h;
+    break;
+  case RISCV::BI__builtin_riscv_cv_simd_add_sc_b:
+    ID = Intrinsic::riscv_cv_simd_add_sc_b;
+    break;
+  case RISCV::BI__builtin_riscv_cv_simd_sub_h:
+    ID = Intrinsic::riscv_cv_simd_sub_h;
+    break;
+  case RISCV::BI__builtin_riscv_cv_simd_sub_b:
+    ID = Intrinsic::riscv_cv_simd_sub_b;
+    break;
+  case RISCV::BI__builtin_riscv_cv_simd_sub_sc_h:
+    ID = Intrinsic::riscv_cv_simd_sub_sc_h;
+    break;
+  case RISCV::BI__builtin_riscv_cv_simd_sub_sc_b:
+    ID = Intrinsic::riscv_cv_simd_sub_sc_b;
+    break;
+
+  // XCVsimd - AVG (signed)
+  case RISCV::BI__builtin_riscv_cv_simd_avg_h:
+    ID = Intrinsic::riscv_cv_simd_avg_h;
+    break;
+  case RISCV::BI__builtin_riscv_cv_simd_avg_b:
+    ID = Intrinsic::riscv_cv_simd_avg_b;
+    break;
+  case RISCV::BI__builtin_riscv_cv_simd_avg_sc_h:
+    ID = Intrinsic::riscv_cv_simd_avg_sc_h;
+    break;
+  case RISCV::BI__builtin_riscv_cv_simd_avg_sc_b:
+    ID = Intrinsic::riscv_cv_simd_avg_sc_b;
+    break;
+
+  // XCVsimd - AVGU (unsigned)
+  case RISCV::BI__builtin_riscv_cv_simd_avgu_h:
+    ID = Intrinsic::riscv_cv_simd_avgu_h;
+    break;
+  case RISCV::BI__builtin_riscv_cv_simd_avgu_b:
+    ID = Intrinsic::riscv_cv_simd_avgu_b;
+    break;
+  case RISCV::BI__builtin_riscv_cv_simd_avgu_sc_h:
+    ID = Intrinsic::riscv_cv_simd_avgu_sc_h;
+    break;
+  case RISCV::BI__builtin_riscv_cv_simd_avgu_sc_b:
+    ID = Intrinsic::riscv_cv_simd_avgu_sc_b;
+    break;
+
+  // XCVsimd - MIN / MINU / MAX / MAXU
+  case RISCV::BI__builtin_riscv_cv_simd_min_h:
+    ID = Intrinsic::riscv_cv_simd_min_h;
+    break;
+  case RISCV::BI__builtin_riscv_cv_simd_min_b:
+    ID = Intrinsic::riscv_cv_simd_min_b;
+    break;
+  case RISCV::BI__builtin_riscv_cv_simd_min_sc_h:
+    ID = Intrinsic::riscv_cv_simd_min_sc_h;
+    break;
+  case RISCV::BI__builtin_riscv_cv_simd_min_sc_b:
+    ID = Intrinsic::riscv_cv_simd_min_sc_b;
+    break;
+  case RISCV::BI__builtin_riscv_cv_simd_minu_h:
+    ID = Intrinsic::riscv_cv_simd_minu_h;
+    break;
+  case RISCV::BI__builtin_riscv_cv_simd_minu_b:
+    ID = Intrinsic::riscv_cv_simd_minu_b;
+    break;
+  case RISCV::BI__builtin_riscv_cv_simd_minu_sc_h:
+    ID = Intrinsic::riscv_cv_simd_minu_sc_h;
+    break;
+  case RISCV::BI__builtin_riscv_cv_simd_minu_sc_b:
+    ID = Intrinsic::riscv_cv_simd_minu_sc_b;
+    break;
+  case RISCV::BI__builtin_riscv_cv_simd_max_h:
+    ID = Intrinsic::riscv_cv_simd_max_h;
+    break;
+  case RISCV::BI__builtin_riscv_cv_simd_max_b:
+    ID = Intrinsic::riscv_cv_simd_max_b;
+    break;
+  case RISCV::BI__builtin_riscv_cv_simd_max_sc_h:
+    ID = Intrinsic::riscv_cv_simd_max_sc_h;
+    break;
+  case RISCV::BI__builtin_riscv_cv_simd_max_sc_b:
+    ID = Intrinsic::riscv_cv_simd_max_sc_b;
+    break;
+  case RISCV::BI__builtin_riscv_cv_simd_maxu_h:
+    ID = Intrinsic::riscv_cv_simd_maxu_h;
+    break;
+  case RISCV::BI__builtin_riscv_cv_simd_maxu_b:
+    ID = Intrinsic::riscv_cv_simd_maxu_b;
+    break;
+  case RISCV::BI__builtin_riscv_cv_simd_maxu_sc_h:
+    ID = Intrinsic::riscv_cv_simd_maxu_sc_h;
+    break;
+  case RISCV::BI__builtin_riscv_cv_simd_maxu_sc_b:
+    ID = Intrinsic::riscv_cv_simd_maxu_sc_b;
+    break;
+
+  // XCVsimd - SRL / SRA / SLL (shifts — immediate versions take uimm6)
+  case RISCV::BI__builtin_riscv_cv_simd_srl_h:
+    ID = Intrinsic::riscv_cv_simd_srl_h;
+    break;
+  case RISCV::BI__builtin_riscv_cv_simd_srl_b:
+    ID = Intrinsic::riscv_cv_simd_srl_b;
+    break;
+  case RISCV::BI__builtin_riscv_cv_simd_srl_sc_h:
+    ID = Intrinsic::riscv_cv_simd_srl_sc_h;
+    break;
+  case RISCV::BI__builtin_riscv_cv_simd_srl_sc_b:
+    ID = Intrinsic::riscv_cv_simd_srl_sc_b;
+    break;
+  case RISCV::BI__builtin_riscv_cv_simd_sra_h:
+    ID = Intrinsic::riscv_cv_simd_sra_h;
+    break;
+  case RISCV::BI__builtin_riscv_cv_simd_sra_b:
+    ID = Intrinsic::riscv_cv_simd_sra_b;
+    break;
+  case RISCV::BI__builtin_riscv_cv_simd_sra_sc_h:
+    ID = Intrinsic::riscv_cv_simd_sra_sc_h;
+    break;
+  case RISCV::BI__builtin_riscv_cv_simd_sra_sc_b:
+    ID = Intrinsic::riscv_cv_simd_sra_sc_b;
+    break;
+  case RISCV::BI__builtin_riscv_cv_simd_sll_h:
+    ID = Intrinsic::riscv_cv_simd_sll_h;
+    break;
+  case RISCV::BI__builtin_riscv_cv_simd_sll_b:
+    ID = Intrinsic::riscv_cv_simd_sll_b;
+    break;
+  case RISCV::BI__builtin_riscv_cv_simd_sll_sc_h:
+    ID = Intrinsic::riscv_cv_simd_sll_sc_h;
+    break;
+  case RISCV::BI__builtin_riscv_cv_simd_sll_sc_b:
+    ID = Intrinsic::riscv_cv_simd_sll_sc_b;
+    break;
+
+  // XCVsimd - OR / XOR / AND
+  case RISCV::BI__builtin_riscv_cv_simd_or_h:
+    ID = Intrinsic::riscv_cv_simd_or_h;
+    break;
+  case RISCV::BI__builtin_riscv_cv_simd_or_b:
+    ID = Intrinsic::riscv_cv_simd_or_b;
+    break;
+  case RISCV::BI__builtin_riscv_cv_simd_or_sc_h:
+    ID = Intrinsic::riscv_cv_simd_or_sc_h;
+    break;
+  case RISCV::BI__builtin_riscv_cv_simd_or_sc_b:
+    ID = Intrinsic::riscv_cv_simd_or_sc_b;
+    break;
+  case RISCV::BI__builtin_riscv_cv_simd_xor_h:
+    ID = Intrinsic::riscv_cv_simd_xor_h;
+    break;
+  case RISCV::BI__builtin_riscv_cv_simd_xor_b:
+    ID = Intrinsic::riscv_cv_simd_xor_b;
+    break;
+  case RISCV::BI__builtin_riscv_cv_simd_xor_sc_h:
+    ID = Intrinsic::riscv_cv_simd_xor_sc_h;
+    break;
+  case RISCV::BI__builtin_riscv_cv_simd_xor_sc_b:
+    ID = Intrinsic::riscv_cv_simd_xor_sc_b;
+    break;
+  case RISCV::BI__builtin_riscv_cv_simd_and_h:
+    ID = Intrinsic::riscv_cv_simd_and_h;
+    break;
+  case RISCV::BI__builtin_riscv_cv_simd_and_b:
+    ID = Intrinsic::riscv_cv_simd_and_b;
+    break;
+  case RISCV::BI__builtin_riscv_cv_simd_and_sc_h:
+    ID = Intrinsic::riscv_cv_simd_and_sc_h;
+    break;
+  case RISCV::BI__builtin_riscv_cv_simd_and_sc_b:
+    ID = Intrinsic::riscv_cv_simd_and_sc_b;
+    break;
+
+  // XCVsimd - ABS
+  case RISCV::BI__builtin_riscv_cv_simd_abs_h:
+    ID = Intrinsic::riscv_cv_simd_abs_h;
+    break;
+  case RISCV::BI__builtin_riscv_cv_simd_abs_b:
+    ID = Intrinsic::riscv_cv_simd_abs_b;
+    break;
+
+  // XCVsimd - DOT PRODUCTS
+  case RISCV::BI__builtin_riscv_cv_simd_dotup_h:
+    ID = Intrinsic::riscv_cv_simd_dotup_h;
+    break;
+  case RISCV::BI__builtin_riscv_cv_simd_dotup_b:
+    ID = Intrinsic::riscv_cv_simd_dotup_b;
+    break;
+  case RISCV::BI__builtin_riscv_cv_simd_dotup_sc_h:
+    ID = Intrinsic::riscv_cv_simd_dotup_sc_h;
+    break;
+  case RISCV::BI__builtin_riscv_cv_simd_dotup_sc_b:
+    ID = Intrinsic::riscv_cv_simd_dotup_sc_b;
+    break;
+  case RISCV::BI__builtin_riscv_cv_simd_dotusp_h:
+    ID = Intrinsic::riscv_cv_simd_dotusp_h;
+    break;
+  case RISCV::BI__builtin_riscv_cv_simd_dotusp_b:
+    ID = Intrinsic::riscv_cv_simd_dotusp_b;
+    break;
+  case RISCV::BI__builtin_riscv_cv_simd_dotusp_sc_h:
+    ID = Intrinsic::riscv_cv_simd_dotusp_sc_h;
+    break;
+  case RISCV::BI__builtin_riscv_cv_simd_dotusp_sc_b:
+    ID = Intrinsic::riscv_cv_simd_dotusp_sc_b;
+    break;
+  case RISCV::BI__builtin_riscv_cv_simd_dotsp_h:
+    ID = Intrinsic::riscv_cv_simd_dotsp_h;
+    break;
+  case RISCV::BI__builtin_riscv_cv_simd_dotsp_b:
+    ID = Intrinsic::riscv_cv_simd_dotsp_b;
+    break;
+  case RISCV::BI__builtin_riscv_cv_simd_dotsp_sc_h:
+    ID = Intrinsic::riscv_cv_simd_dotsp_sc_h;
+    break;
+  case RISCV::BI__builtin_riscv_cv_simd_dotsp_sc_b:
+    ID = Intrinsic::riscv_cv_simd_dotsp_sc_b;
+    break;
+
+  // XCVsimd - SDOT (accumulating dot products — rd is both input and output)
+  case RISCV::BI__builtin_riscv_cv_simd_sdotup_h:
+    ID = Intrinsic::riscv_cv_simd_sdotup_h;
+    break;
+  case RISCV::BI__builtin_riscv_cv_simd_sdotup_b:
+    ID = Intrinsic::riscv_cv_simd_sdotup_b;
+    break;
+  case RISCV::BI__builtin_riscv_cv_simd_sdotup_sc_h:
+    ID = Intrinsic::riscv_cv_simd_sdotup_sc_h;
+    break;
+  case RISCV::BI__builtin_riscv_cv_simd_sdotup_sc_b:
+    ID = Intrinsic::riscv_cv_simd_sdotup_sc_b;
+    break;
+  case RISCV::BI__builtin_riscv_cv_simd_sdotusp_h:
+    ID = Intrinsic::riscv_cv_simd_sdotusp_h;
+    break;
+  case RISCV::BI__builtin_riscv_cv_simd_sdotusp_b:
+    ID = Intrinsic::riscv_cv_simd_sdotusp_b;
+    break;
+  case RISCV::BI__builtin_riscv_cv_simd_sdotusp_sc_h:
+    ID = Intrinsic::riscv_cv_simd_sdotusp_sc_h;
+    break;
+  case RISCV::BI__builtin_riscv_cv_simd_sdotusp_sc_b:
+    ID = Intrinsic::riscv_cv_simd_sdotusp_sc_b;
+    break;
+  case RISCV::BI__builtin_riscv_cv_simd_sdotsp_h:
+    ID = Intrinsic::riscv_cv_simd_sdotsp_h;
+    break;
+  case RISCV::BI__builtin_riscv_cv_simd_sdotsp_b:
+    ID = Intrinsic::riscv_cv_simd_sdotsp_b;
+    break;
+  case RISCV::BI__builtin_riscv_cv_simd_sdotsp_sc_h:
+    ID = Intrinsic::riscv_cv_simd_sdotsp_sc_h;
+    break;
+  case RISCV::BI__builtin_riscv_cv_simd_sdotsp_sc_b:
+    ID = Intrinsic::riscv_cv_simd_sdotsp_sc_b;
+    break;
+
+  // XCVsimd - EXTRACT / INSERT
+  case RISCV::BI__builtin_riscv_cv_simd_extract_h:
+    ID = Intrinsic::riscv_cv_simd_extract_h;
+    break;
+  case RISCV::BI__builtin_riscv_cv_simd_extract_b:
+    ID = Intrinsic::riscv_cv_simd_extract_b;
+    break;
+  case RISCV::BI__builtin_riscv_cv_simd_extractu_h:
+    ID = Intrinsic::riscv_cv_simd_extractu_h;
+    break;
+  case RISCV::BI__builtin_riscv_cv_simd_extractu_b:
+    ID = Intrinsic::riscv_cv_simd_extractu_b;
+    break;
+  case RISCV::BI__builtin_riscv_cv_simd_insert_h:
+    ID = Intrinsic::riscv_cv_simd_insert_h;
+    break;
+  case RISCV::BI__builtin_riscv_cv_simd_insert_b:
+    ID = Intrinsic::riscv_cv_simd_insert_b;
+    break;
+
+  // XCVsimd - SHUFFLE / SHUFFLE2
+  case RISCV::BI__builtin_riscv_cv_simd_shuffle_h:
+    ID = Intrinsic::riscv_cv_simd_shuffle_h;
+    break;
+  case RISCV::BI__builtin_riscv_cv_simd_shuffle_b:
+    ID = Intrinsic::riscv_cv_simd_shuffle_b;
+    break;
+  case RISCV::BI__builtin_riscv_cv_simd_shuffle_sci_h:
+    ID = Intrinsic::riscv_cv_simd_shuffle_sci_h;
+    break;
+  case RISCV::BI__builtin_riscv_cv_simd_shuffle_sci_b:
+    ID = Intrinsic::riscv_cv_simd_shuffle_sci_b;
+    break;
+  case RISCV::BI__builtin_riscv_cv_simd_shuffle2_h:
+    ID = Intrinsic::riscv_cv_simd_shuffle2_h;
+    break;
+  case RISCV::BI__builtin_riscv_cv_simd_shuffle2_b:
+    ID = Intrinsic::riscv_cv_simd_shuffle2_b;
+    break;
+
+  // XCVsimd - PACK
+  case RISCV::BI__builtin_riscv_cv_simd_packhi_h:
+    ID = Intrinsic::riscv_cv_simd_packhi_h;
+    break;
+  case RISCV::BI__builtin_riscv_cv_simd_packlo_h:
+    ID = Intrinsic::riscv_cv_simd_packlo_h;
+    break;
+  case RISCV::BI__builtin_riscv_cv_simd_packhi_b:
+    ID = Intrinsic::riscv_cv_simd_packhi_b;
+    break;
+  case RISCV::BI__builtin_riscv_cv_simd_packlo_b:
+    ID = Intrinsic::riscv_cv_simd_packlo_b;
+    break;
+
+  // XCVsimd - COMPARE (result is mask in packed reg)
+  case RISCV::BI__builtin_riscv_cv_simd_cmpeq_h:
+    ID = Intrinsic::riscv_cv_simd_cmpeq_h;
+    break;
+  case RISCV::BI__builtin_riscv_cv_simd_cmpeq_b:
+    ID = Intrinsic::riscv_cv_simd_cmpeq_b;
+    break;
+  case RISCV::BI__builtin_riscv_cv_simd_cmpeq_sc_h:
+    ID = Intrinsic::riscv_cv_simd_cmpeq_sc_h;
+    break;
+  case RISCV::BI__builtin_riscv_cv_simd_cmpeq_sc_b:
+    ID = Intrinsic::riscv_cv_simd_cmpeq_sc_b;
+    break;
+  case RISCV::BI__builtin_riscv_cv_simd_cmpne_h:
+    ID = Intrinsic::riscv_cv_simd_cmpne_h;
+    break;
+  case RISCV::BI__builtin_riscv_cv_simd_cmpne_b:
+    ID = Intrinsic::riscv_cv_simd_cmpne_b;
+    break;
+  case RISCV::BI__builtin_riscv_cv_simd_cmpne_sc_h:
+    ID = Intrinsic::riscv_cv_simd_cmpne_sc_h;
+    break;
+  case RISCV::BI__builtin_riscv_cv_simd_cmpne_sc_b:
+    ID = Intrinsic::riscv_cv_simd_cmpne_sc_b;
+    break;
+  case RISCV::BI__builtin_riscv_cv_simd_cmpgt_h:
+    ID = Intrinsic::riscv_cv_simd_cmpgt_h;
+    break;
+  case RISCV::BI__builtin_riscv_cv_simd_cmpgt_b:
+    ID = Intrinsic::riscv_cv_simd_cmpgt_b;
+    break;
+  case RISCV::BI__builtin_riscv_cv_simd_cmpgt_sc_h:
+    ID = Intrinsic::riscv_cv_simd_cmpgt_sc_h;
+    break;
+  case RISCV::BI__builtin_riscv_cv_simd_cmpgt_sc_b:
+    ID = Intrinsic::riscv_cv_simd_cmpgt_sc_b;
+    break;
+  case RISCV::BI__builtin_riscv_cv_simd_cmpge_h:
+    ID = Intrinsic::riscv_cv_simd_cmpge_h;
+    break;
+  case RISCV::BI__builtin_riscv_cv_simd_cmpge_b:
+    ID = Intrinsic::riscv_cv_simd_cmpge_b;
+    break;
+  case RISCV::BI__builtin_riscv_cv_simd_cmpge_sc_h:
+    ID = Intrinsic::riscv_cv_simd_cmpge_sc_h;
+    break;
+  case RISCV::BI__builtin_riscv_cv_simd_cmpge_sc_b:
+    ID = Intrinsic::riscv_cv_simd_cmpge_sc_b;
+    break;
+  case RISCV::BI__builtin_riscv_cv_simd_cmplt_h:
+    ID = Intrinsic::riscv_cv_simd_cmplt_h;
+    break;
+  case RISCV::BI__builtin_riscv_cv_simd_cmplt_b:
+    ID = Intrinsic::riscv_cv_simd_cmplt_b;
+    break;
+  case RISCV::BI__builtin_riscv_cv_simd_cmplt_sc_h:
+    ID = Intrinsic::riscv_cv_simd_cmplt_sc_h;
+    break;
+  case RISCV::BI__builtin_riscv_cv_simd_cmplt_sc_b:
+    ID = Intrinsic::riscv_cv_simd_cmplt_sc_b;
+    break;
+  case RISCV::BI__builtin_riscv_cv_simd_cmple_h:
+    ID = Intrinsic::riscv_cv_simd_cmple_h;
+    break;
+  case RISCV::BI__builtin_riscv_cv_simd_cmple_b:
+    ID = Intrinsic::riscv_cv_simd_cmple_b;
+    break;
+  case RISCV::BI__builtin_riscv_cv_simd_cmple_sc_h:
+    ID = Intrinsic::riscv_cv_simd_cmple_sc_h;
+    break;
+  case RISCV::BI__builtin_riscv_cv_simd_cmple_sc_b:
+    ID = Intrinsic::riscv_cv_simd_cmple_sc_b;
+    break;
+  case RISCV::BI__builtin_riscv_cv_simd_cmpgtu_h:
+    ID = Intrinsic::riscv_cv_simd_cmpgtu_h;
+    break;
+  case RISCV::BI__builtin_riscv_cv_simd_cmpgtu_b:
+    ID = Intrinsic::riscv_cv_simd_cmpgtu_b;
+    break;
+  case RISCV::BI__builtin_riscv_cv_simd_cmpgtu_sc_h:
+    ID = Intrinsic::riscv_cv_simd_cmpgtu_sc_h;
+    break;
+  case RISCV::BI__builtin_riscv_cv_simd_cmpgtu_sc_b:
+    ID = Intrinsic::riscv_cv_simd_cmpgtu_sc_b;
+    break;
+  case RISCV::BI__builtin_riscv_cv_simd_cmpgeu_h:
+    ID = Intrinsic::riscv_cv_simd_cmpgeu_h;
+    break;
+  case RISCV::BI__builtin_riscv_cv_simd_cmpgeu_b:
+    ID = Intrinsic::riscv_cv_simd_cmpgeu_b;
+    break;
+  case RISCV::BI__builtin_riscv_cv_simd_cmpgeu_sc_h:
+    ID = Intrinsic::riscv_cv_simd_cmpgeu_sc_h;
+    break;
+  case RISCV::BI__builtin_riscv_cv_simd_cmpgeu_sc_b:
+    ID = Intrinsic::riscv_cv_simd_cmpgeu_sc_b;
+    break;
+  case RISCV::BI__builtin_riscv_cv_simd_cmpltu_h:
+    ID = Intrinsic::riscv_cv_simd_cmpltu_h;
+    break;
+  case RISCV::BI__builtin_riscv_cv_simd_cmpltu_b:
+    ID = Intrinsic::riscv_cv_simd_cmpltu_b;
+    break;
+  case RISCV::BI__builtin_riscv_cv_simd_cmpltu_sc_h:
+    ID = Intrinsic::riscv_cv_simd_cmpltu_sc_h;
+    break;
+  case RISCV::BI__builtin_riscv_cv_simd_cmpltu_sc_b:
+    ID = Intrinsic::riscv_cv_simd_cmpltu_sc_b;
+    break;
+  case RISCV::BI__builtin_riscv_cv_simd_cmpleu_h:
+    ID = Intrinsic::riscv_cv_simd_cmpleu_h;
+    break;
+  case RISCV::BI__builtin_riscv_cv_simd_cmpleu_b:
+    ID = Intrinsic::riscv_cv_simd_cmpleu_b;
+    break;
+  case RISCV::BI__builtin_riscv_cv_simd_cmpleu_sc_h:
+    ID = Intrinsic::riscv_cv_simd_cmpleu_sc_h;
+    break;
+  case RISCV::BI__builtin_riscv_cv_simd_cmpleu_sc_b:
+    ID = Intrinsic::riscv_cv_simd_cmpleu_sc_b;
+    break;
+
+  // XCVsimd - COMPLEX
+  case RISCV::BI__builtin_riscv_cv_simd_cplxmul_r:
+    ID = Intrinsic::riscv_cv_simd_cplxmul_r;
+    break;
+  case RISCV::BI__builtin_riscv_cv_simd_cplxmul_i:
+    ID = Intrinsic::riscv_cv_simd_cplxmul_i;
+    break;
+  case RISCV::BI__builtin_riscv_cv_simd_cplxconj:
+    ID = Intrinsic::riscv_cv_simd_cplxconj;
+    break;
+  case RISCV::BI__builtin_riscv_cv_simd_subrotmj:
+    ID = Intrinsic::riscv_cv_simd_subrotmj;
+    break;
+
   // XAndesPerf
   case RISCV::BI__builtin_riscv_nds_ffb_32:
   case RISCV::BI__builtin_riscv_nds_ffb_64:
diff --git a/clang/lib/Headers/CMakeLists.txt b/clang/lib/Headers/CMakeLists.txt
index e1021a6020305..b314bfdffea45 100644
--- a/clang/lib/Headers/CMakeLists.txt
+++ b/clang/lib/Headers/CMakeLists.txt
@@ -140,6 +140,7 @@ set(riscv_files
   riscv_corev_alu.h
   riscv_corev_elw.h
   riscv_corev_mac.h
+  riscv_corev_simd.h
   riscv_mips.h
   riscv_nds.h
   riscv_packed_simd.h
diff --git a/clang/lib/Headers/riscv_corev_simd.h b/clang/lib/Headers/riscv_corev_simd.h
new file mode 100644
index 0000000000000..a1b7164b3977e
--- /dev/null
+++ b/clang/lib/Headers/riscv_corev_simd.h
@@ -0,0 +1,707 @@
+/*===---- riscv_corev_simd.h - CORE-V SIMD intrinsics ----------------------===
+ *
+ * Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+ * See https://llvm.org/LICENSE.txt for license information.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ *
+ *===-----------------------------------------------------------------------===
+ *
+ * This header provides C intrinsics for the CORE-V XCVsimd ISA extension.
+ * Include this header when compiling with -march=..._xcvsimd.
+ *
+ * All operations work on packed sub-word elements within a 32-bit GPR:
+ *   - .h variants operate on two packed int16 / uint16 (halfwords)
+ *   - .b variants operate on four packed int8  / uint8  (bytes)
+ *   - .sc variants use the lower halfword/byte of a GPR as a scalar operand
+ *   - .sci variants use a sign-extended 6-bit immediate as a scalar operand
+ *
+ * Spec: https://docs.openhwgroup.org/projects/cv32e40p-user-manual/en/latest/
+ *       instruction_set_extensions.html#simd
+ *
+ *===-----------------------------------------------------------------------===
+ */
+
+#ifndef __RISCV_COREV_SIMD_H
+#define __RISCV_COREV_SIMD_H
+
+#include <stdint.h>
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+#if defined(__riscv_xcvsimd)
+
+#define __DEFAULT_FN_ATTRS                                                      \
+  __attribute__((__always_inline__, __nodebug__, __artificial__))
+
+/* ===========================================================================
+ * ADD / SUB
+ *
+ * .h: cv.add.h  rd, rs1, rs2 (or .div2/.div4/.div8)
+ * .b: cv.add.b  rd, rs1, rs2
+ *
+ * The _h variant takes a div-shift code as third argument (0=no shift,
+ * 1=/2, 2=/4, 3=/8). This is an immediate, so it must be a compile-time
+ * constant — hence the macro form.
+ * =========================================================================== */
+
+/* add.h with div-by-N right shift (DIVCODE in [0,3]) */
+#define __riscv_cv_simd_add_h(__rs1, __rs2, __DIVCODE)                         \
+  ((uint32_t)__builtin_riscv_cv_simd_add_h((uint32_t)(__rs1),                  \
+                                            (uint32_t)(__rs2),                  \
+                                            (uint32_t)(__DIVCODE)))
+
+static __inline__ uint32_t __DEFAULT_FN_ATTRS
+__riscv_cv_simd_add_b(uint32_t a, uint32_t b) {
+  return __builtin_riscv_cv_simd_add_b(a, b);
+}
+static __inline__ uint32_t __DEFAULT_FN_ATTRS
+__riscv_cv_simd_add_sc_h(uint32_t a, uint32_t b) {
+  return __builtin_riscv_cv_simd_add_sc_h(a, b);
+}
+static __inline__ uint32_t __DEFAULT_FN_ATTRS
+__riscv_cv_simd_add_sc_b(uint32_t a, uint32_t b) {
+  return __builtin_riscv_cv_simd_add_sc_b(a, b);
+}
+
+/* sub.h with div-by-N right shift (DIVCODE in [0,3]) */
+#define __riscv_cv_simd_sub_h(__rs1, __rs2, __DIVCODE)                         \
+  ((uint32_t)__builtin_riscv_cv_simd_sub_h((uint32_t)(__rs1),                  \
+                                            (uint32_t)(__rs2),                  \
+                                            (uint32_t)(__DIVCODE)))
+
+static __inline__ uint32_t __DEFAULT_FN_ATTRS
+__riscv_cv_simd_sub_b(uint32_t a, uint32_t b) {
+  return __builtin_riscv_cv_simd_sub_b(a, b);
+}
+static __inline__ uint32_t __DEFAULT_FN_ATTRS
+__riscv_cv_simd_sub_sc_h(uint32_t a, uint32_t b) {
+  return __builtin_riscv_cv_simd_sub_sc_h(a, b);
+}
+static __inline__ uint32_t __DEFAULT_FN_ATTRS
+__riscv_cv_simd_sub_sc_b(uint32_t a, uint32_t b) {
+  return __builtin_riscv_cv_simd_sub_sc_b(a, b);
+}
+
+/* ===========================================================================
+ * AVG / AVGU  (signed and unsigned average)
+ * =========================================================================== */
+
+static __inline__ uint32_t __DEFAULT_FN_ATTRS
+__riscv_cv_simd_avg_h(uint32_t a, uint32_t b) {
+  return __builtin_riscv_cv_simd_avg_h(a, b);
+}
+static __inline__ uint32_t __DEFAULT_FN_ATTRS
+__riscv_cv_simd_avg_b(uint32_t a, uint32_t b) {
+  return __builtin_riscv_cv_simd_avg_b(a, b);
+}
+static __inline__ uint32_t __DEFAULT_FN_ATTRS
+__riscv_cv_simd_avg_sc_h(uint32_t a, uint32_t b) {
+  return __builtin_riscv_cv_simd_avg_sc_h(a, b);
+}
+static __inline__ uint32_t __DEFAULT_FN_ATTRS
+__riscv_cv_simd_avg_sc_b(uint32_t a, uint32_t b) {
+  return __builtin_riscv_cv_simd_avg_sc_b(a, b);
+}
+
+static __inline__ uint32_t __DEFAULT_FN_ATTRS
+__riscv_cv_simd_avgu_h(uint32_t a, uint32_t b) {
+  return __builtin_riscv_cv_simd_avgu_h(a, b);
+}
+static __inline__ uint32_t __DEFAULT_FN_ATTRS
+__riscv_cv_simd_avgu_b(uint32_t a, uint32_t b) {
+  return __builtin_riscv_cv_simd_avgu_b(a, b);
+}
+static __inline__ uint32_t __DEFAULT_FN_ATTRS
+__riscv_cv_simd_avgu_sc_h(uint32_t a, uint32_t b) {
+  return __builtin_riscv_cv_simd_avgu_sc_h(a, b);
+}
+static __inline__ uint32_t __DEFAULT_FN_ATTRS
+__riscv_cv_simd_avgu_sc_b(uint32_t a, uint32_t b) {
+  return __builtin_riscv_cv_simd_avgu_sc_b(a, b);
+}
+
+/* ===========================================================================
+ * MIN / MINU  (signed and unsigned per-element minimum)
+ * =========================================================================== */
+
+static __inline__ uint32_t __DEFAULT_FN_ATTRS
+__riscv_cv_simd_min_h(uint32_t a, uint32_t b) {
+  return __builtin_riscv_cv_simd_min_h(a, b);
+}
+static __inline__ uint32_t __DEFAULT_FN_ATTRS
+__riscv_cv_simd_min_b(uint32_t a, uint32_t b) {
+  return __builtin_riscv_cv_simd_min_b(a, b);
+}
+static __inline__ uint32_t __DEFAULT_FN_ATTRS
+__riscv_cv_simd_min_sc_h(uint32_t a, uint32_t b) {
+  return __builtin_riscv_cv_simd_min_sc_h(a, b);
+}
+static __inline__ uint32_t __DEFAULT_FN_ATTRS
+__riscv_cv_simd_min_sc_b(uint32_t a, uint32_t b) {
+  return __builtin_riscv_cv_simd_min_sc_b(a, b);
+}
+
+static __inline__ uint32_t __DEFAULT_FN_ATTRS
+__riscv_cv_simd_minu_h(uint32_t a, uint32_t b) {
+  return __builtin_riscv_cv_simd_minu_h(a, b);
+}
+static __inline__ uint32_t __DEFAULT_FN_ATTRS
+__riscv_cv_simd_minu_b(uint32_t a, uint32_t b) {
+  return __builtin_riscv_cv_simd_minu_b(a, b);
+}
+static __inline__ uint32_t __DEFAULT_FN_ATTRS
+__riscv_cv_simd_minu_sc_h(uint32_t a, uint32_t b) {
+  return __builtin_riscv_cv_simd_minu_sc_h(a, b);
+}
+static __inline__ uint32_t __DEFAULT_FN_ATTRS
+__riscv_cv_simd_minu_sc_b(uint32_t a, uint32_t b) {
+  return __builtin_riscv_cv_simd_minu_sc_b(a, b);
+}
+
+/* ===========================================================================
+ * MAX / MAXU  (signed and unsigned per-element maximum)
+ * =========================================================================== */
+
+static __inline__ uint32_t __DEFAULT_FN_ATTRS
+__riscv_cv_simd_max_h(uint32_t a, uint32_t b) {
+  return __builtin_riscv_cv_simd_max_h(a, b);
+}
+static __inline__ uint32_t __DEFAULT_FN_ATTRS
+__riscv_cv_simd_max_b(uint32_t a, uint32_t b) {
+  return __builtin_riscv_cv_simd_max_b(a, b);
+}
+static __inline__ uint32_t __DEFAULT_FN_ATTRS
+__riscv_cv_simd_max_sc_h(uint32_t a, uint32_t b) {
+  return __builtin_riscv_cv_simd_max_sc_h(a, b);
+}
+static __inline__ uint32_t __DEFAULT_FN_ATTRS
+__riscv_cv_simd_max_sc_b(uint32_t a, uint32_t b) {
+  return __builtin_riscv_cv_simd_max_sc_b(a, b);
+}
+
+static __inline__ uint32_t __DEFAULT_FN_ATTRS
+__riscv_cv_simd_maxu_h(uint32_t a, uint32_t b) {
+  return __builtin_riscv_cv_simd_maxu_h(a, b);
+}
+static __inline__ uint32_t __DEFAULT_FN_ATTRS
+__riscv_cv_simd_maxu_b(uint32_t a, uint32_t b) {
+  return __builtin_riscv_cv_simd_maxu_b(a, b);
+}
+static __inline__ uint32_t __DEFAULT_FN_ATTRS
+__riscv_cv_simd_maxu_sc_h(uint32_t a, uint32_t b) {
+  return __builtin_riscv_cv_simd_maxu_sc_h(a, b);
+}
+static __inline__ uint32_t __DEFAULT_FN_ATTRS
+__riscv_cv_simd_maxu_sc_b(uint32_t a, uint32_t b) {
+  return __builtin_riscv_cv_simd_maxu_sc_b(a, b);
+}
+
+/* ===========================================================================
+ * SHIFT: SRL / SRA / SLL
+ * .sc  variants take a GPR shift amount (lower bits used)
+ * No .sci variant for shifts (the instruction encodes a small immediate
+ * directly in the funct3 space; use the .sc_h/.sc_b with a constant GPR).
+ * =========================================================================== */
+
+static __inline__ uint32_t __DEFAULT_FN_ATTRS
+__riscv_cv_simd_srl_h(uint32_t a, uint32_t b) {
+  return __builtin_riscv_cv_simd_srl_h(a, b);
+}
+static __inline__ uint32_t __DEFAULT_FN_ATTRS
+__riscv_cv_simd_srl_b(uint32_t a, uint32_t b) {
+  return __builtin_riscv_cv_simd_srl_b(a, b);
+}
+static __inline__ uint32_t __DEFAULT_FN_ATTRS
+__riscv_cv_simd_srl_sc_h(uint32_t a, uint32_t b) {
+  return __builtin_riscv_cv_simd_srl_sc_h(a, b);
+}
+static __inline__ uint32_t __DEFAULT_FN_ATTRS
+__riscv_cv_simd_srl_sc_b(uint32_t a, uint32_t b) {
+  return __builtin_riscv_cv_simd_srl_sc_b(a, b);
+}
+
+static __inline__ uint32_t __DEFAULT_FN_ATTRS
+__riscv_cv_simd_sra_h(uint32_t a, uint32_t b) {
+  return __builtin_riscv_cv_simd_sra_h(a, b);
+}
+static __inline__ uint32_t __DEFAULT_FN_ATTRS
+__riscv_cv_simd_sra_b(uint32_t a, uint32_t b) {
+  return __builtin_riscv_cv_simd_sra_b(a, b);
+}
+static __inline__ uint32_t __DEFAULT_FN_ATTRS
+__riscv_cv_simd_sra_sc_h(uint32_t a, uint32_t b) {
+  return __builtin_riscv_cv_simd_sra_sc_h(a, b);
+}
+static __inline__ uint32_t __DEFAULT_FN_ATTRS
+__riscv_cv_simd_sra_sc_b(uint32_t a, uint32_t b) {
+  return __builtin_riscv_cv_simd_sra_sc_b(a, b);
+}
+
+static __inline__ uint32_t __DEFAULT_FN_ATTRS
+__riscv_cv_simd_sll_h(uint32_t a, uint32_t b) {
+  return __builtin_riscv_cv_simd_sll_h(a, b);
+}
+static __inline__ uint32_t __DEFAULT_FN_ATTRS
+__riscv_cv_simd_sll_b(uint32_t a, uint32_t b) {
+  return __builtin_riscv_cv_simd_sll_b(a, b);
+}
+static __inline__ uint32_t __DEFAULT_FN_ATTRS
+__riscv_cv_simd_sll_sc_h(uint32_t a, uint32_t b) {
+  return __builtin_riscv_cv_simd_sll_sc_h(a, b);
+}
+static __inline__ uint32_t __DEFAULT_FN_ATTRS
+__riscv_cv_simd_sll_sc_b(uint32_t a, uint32_t b) {
+  return __builtin_riscv_cv_simd_sll_sc_b(a, b);
+}
+
+/* ===========================================================================
+ * BITWISE: OR / XOR / AND
+ * =========================================================================== */
+
+static __inline__ uint32_t __DEFAULT_FN_ATTRS
+__riscv_cv_simd_or_h(uint32_t a, uint32_t b) {
+  return __builtin_riscv_cv_simd_or_h(a, b);
+}
+static __inline__ uint32_t __DEFAULT_FN_ATTRS
+__riscv_cv_simd_or_b(uint32_t a, uint32_t b) {
+  return __builtin_riscv_cv_simd_or_b(a, b);
+}
+static __inline__ uint32_t __DEFAULT_FN_ATTRS
+__riscv_cv_simd_or_sc_h(uint32_t a, uint32_t b) {
+  return __builtin_riscv_cv_simd_or_sc_h(a, b);
+}
+static __inline__ uint32_t __DEFAULT_FN_ATTRS
+__riscv_cv_simd_or_sc_b(uint32_t a, uint32_t b) {
+  return __builtin_riscv_cv_simd_or_sc_b(a, b);
+}
+
+static __inline__ uint32_t __DEFAULT_FN_ATTRS
+__riscv_cv_simd_xor_h(uint32_t a, uint32_t b) {
+  return __builtin_riscv_cv_simd_xor_h(a, b);
+}
+static __inline__ uint32_t __DEFAULT_FN_ATTRS
+__riscv_cv_simd_xor_b(uint32_t a, uint32_t b) {
+  return __builtin_riscv_cv_simd_xor_b(a, b);
+}
+static __inline__ uint32_t __DEFAULT_FN_ATTRS
+__riscv_cv_simd_xor_sc_h(uint32_t a, uint32_t b) {
+  return __builtin_riscv_cv_simd_xor_sc_h(a, b);
+}
+static __inline__ uint32_t __DEFAULT_FN_ATTRS
+__riscv_cv_simd_xor_sc_b(uint32_t a, uint32_t b) {
+  return __builtin_riscv_cv_simd_xor_sc_b(a, b);
+}
+
+static __inline__ uint32_t __DEFAULT_FN_ATTRS
+__riscv_cv_simd_and_h(uint32_t a, uint32_t b) {
+  return __builtin_riscv_cv_simd_and_h(a, b);
+}
+static __inline__ uint32_t __DEFAULT_FN_ATTRS
+__riscv_cv_simd_and_b(uint32_t a, uint32_t b) {
+  return __builtin_riscv_cv_simd_and_b(a, b);
+}
+static __inline__ uint32_t __DEFAULT_FN_ATTRS
+__riscv_cv_simd_and_sc_h(uint32_t a, uint32_t b) {
+  return __builtin_riscv_cv_simd_and_sc_h(a, b);
+}
+static __inline__ uint32_t __DEFAULT_FN_ATTRS
+__riscv_cv_simd_and_sc_b(uint32_t a, uint32_t b) {
+  return __builtin_riscv_cv_simd_and_sc_b(a, b);
+}
+
+/* ===========================================================================
+ * ABS  (per-element absolute value)
+ * =========================================================================== */
+
+static __inline__ uint32_t __DEFAULT_FN_ATTRS
+__riscv_cv_simd_abs_h(uint32_t a) {
+  return __builtin_riscv_cv_simd_abs_h(a);
+}
+static __inline__ uint32_t __DEFAULT_FN_ATTRS
+__riscv_cv_simd_abs_b(uint32_t a) {
+  return __builtin_riscv_cv_simd_abs_b(a);
+}
+
+/* ===========================================================================
+ * DOT PRODUCTS
+ *
+ * dotup  — unsigned × unsigned dot product  (result is uint32)
+ * dotusp — unsigned × signed  dot product  (result is int32)
+ * dotsp  — signed   × signed  dot product  (result is int32)
+ *
+ * sdot* — same but adds result to accumulator register rd (read-modify-write)
+ * =========================================================================== */
+
+/* dotup */
+static __inline__ uint32_t __DEFAULT_FN_ATTRS
+__riscv_cv_simd_dotup_h(uint32_t a, uint32_t b) {
+  return __builtin_riscv_cv_simd_dotup_h(a, b);
+}
+static __inline__ uint32_t __DEFAULT_FN_ATTRS
+__riscv_cv_simd_dotup_b(uint32_t a, uint32_t b) {
+  return __builtin_riscv_cv_simd_dotup_b(a, b);
+}
+static __inline__ uint32_t __DEFAULT_FN_ATTRS
+__riscv_cv_simd_dotup_sc_h(uint32_t a, uint32_t b) {
+  return __builtin_riscv_cv_simd_dotup_sc_h(a, b);
+}
+static __inline__ uint32_t __DEFAULT_FN_ATTRS
+__riscv_cv_simd_dotup_sc_b(uint32_t a, uint32_t b) {
+  return __builtin_riscv_cv_simd_dotup_sc_b(a, b);
+}
+
+/* dotusp */
+static __inline__ int32_t __DEFAULT_FN_ATTRS
+__riscv_cv_simd_dotusp_h(uint32_t a, uint32_t b) {
+  return __builtin_riscv_cv_simd_dotusp_h(a, b);
+}
+static __inline__ int32_t __DEFAULT_FN_ATTRS
+__riscv_cv_simd_dotusp_b(uint32_t a, uint32_t b) {
+  return __builtin_riscv_cv_simd_dotusp_b(a, b);
+}
+static __inline__ int32_t __DEFAULT_FN_ATTRS
+__riscv_cv_simd_dotusp_sc_h(uint32_t a, uint32_t b) {
+  return __builtin_riscv_cv_simd_dotusp_sc_h(a, b);
+}
+static __inline__ int32_t __DEFAULT_FN_ATTRS
+__riscv_cv_simd_dotusp_sc_b(uint32_t a, uint32_t b) {
+  return __builtin_riscv_cv_simd_dotusp_sc_b(a, b);
+}
+
+/* dotsp */
+static __inline__ int32_t __DEFAULT_FN_ATTRS
+__riscv_cv_simd_dotsp_h(uint32_t a, uint32_t b) {
+  return __builtin_riscv_cv_simd_dotsp_h(a, b);
+}
+static __inline__ int32_t __DEFAULT_FN_ATTRS
+__riscv_cv_simd_dotsp_b(uint32_t a, uint32_t b) {
+  return __builtin_riscv_cv_simd_dotsp_b(a, b);
+}
+static __inline__ int32_t __DEFAULT_FN_ATTRS
+__riscv_cv_simd_dotsp_sc_h(uint32_t a, uint32_t b) {
+  return __builtin_riscv_cv_simd_dotsp_sc_h(a, b);
+}
+static __inline__ int32_t __DEFAULT_FN_ATTRS
+__riscv_cv_simd_dotsp_sc_b(uint32_t a, uint32_t b) {
+  return __builtin_riscv_cv_simd_dotsp_sc_b(a, b);
+}
+
+/* sdotup (unsigned × unsigned, accumulating) */
+static __inline__ uint32_t __DEFAULT_FN_ATTRS
+__riscv_cv_simd_sdotup_h(uint32_t a, uint32_t b, uint32_t acc) {
+  return __builtin_riscv_cv_simd_sdotup_h(a, b, acc);
+}
+static __inline__ uint32_t __DEFAULT_FN_ATTRS
+__riscv_cv_simd_sdotup_b(uint32_t a, uint32_t b, uint32_t acc) {
+  return __builtin_riscv_cv_simd_sdotup_b(a, b, acc);
+}
+static __inline__ uint32_t __DEFAULT_FN_ATTRS
+__riscv_cv_simd_sdotup_sc_h(uint32_t a, uint32_t b, uint32_t acc) {
+  return __builtin_riscv_cv_simd_sdotup_sc_h(a, b, acc);
+}
+static __inline__ uint32_t __DEFAULT_FN_ATTRS
+__riscv_cv_simd_sdotup_sc_b(uint32_t a, uint32_t b, uint32_t acc) {
+  return __builtin_riscv_cv_simd_sdotup_sc_b(a, b, acc);
+}
+
+/* sdotusp (unsigned × signed, accumulating) */
+static __inline__ int32_t __DEFAULT_FN_ATTRS
+__riscv_cv_simd_sdotusp_h(uint32_t a, uint32_t b, int32_t acc) {
+  return __builtin_riscv_cv_simd_sdotusp_h(a, b, acc);
+}
+static __inline__ int32_t __DEFAULT_FN_ATTRS
+__riscv_cv_simd_sdotusp_b(uint32_t a, uint32_t b, int32_t acc) {
+  return __builtin_riscv_cv_simd_sdotusp_b(a, b, acc);
+}
+static __inline__ int32_t __DEFAULT_FN_ATTRS
+__riscv_cv_simd_sdotusp_sc_h(uint32_t a, uint32_t b, int32_t acc) {
+  return __builtin_riscv_cv_simd_sdotusp_sc_h(a, b, acc);
+}
+static __inline__ int32_t __DEFAULT_FN_ATTRS
+__riscv_cv_simd_sdotusp_sc_b(uint32_t a, uint32_t b, int32_t acc) {
+  return __builtin_riscv_cv_simd_sdotusp_sc_b(a, b, acc);
+}
+
+/* sdotsp (signed × signed, accumulating) */
+static __inline__ int32_t __DEFAULT_FN_ATTRS
+__riscv_cv_simd_sdotsp_h(uint32_t a, uint32_t b, int32_t acc) {
+  return __builtin_riscv_cv_simd_sdotsp_h(a, b, acc);
+}
+static __inline__ int32_t __DEFAULT_FN_ATTRS
+__riscv_cv_simd_sdotsp_b(uint32_t a, uint32_t b, int32_t acc) {
+  return __builtin_riscv_cv_simd_sdotsp_b(a, b, acc);
+}
+static __inline__ int32_t __DEFAULT_FN_ATTRS
+__riscv_cv_simd_sdotsp_sc_h(uint32_t a, uint32_t b, int32_t acc) {
+  return __builtin_riscv_cv_simd_sdotsp_sc_h(a, b, acc);
+}
+static __inline__ int32_t __DEFAULT_FN_ATTRS
+__riscv_cv_simd_sdotsp_sc_b(uint32_t a, uint32_t b, int32_t acc) {
+  return __builtin_riscv_cv_simd_sdotsp_sc_b(a, b, acc);
+}
+
+/* ===========================================================================
+ * EXTRACT / EXTRACTU / INSERT
+ *
+ * cv.extract.h  rd, rs1, IMM  — extract halfword IMM (0 or 1), sign-extended
+ * cv.extract.b  rd, rs1, IMM  — extract byte IMM (0..3), sign-extended
+ * cv.extractu.h rd, rs1, IMM  — extract halfword IMM, zero-extended
+ * cv.extractu.b rd, rs1, IMM  — extract byte IMM, zero-extended
+ * cv.insert.h   rd, rs1, IMM  — insert lower halfword of rs1 into rd at IMM
+ * cv.insert.b   rd, rs1, IMM  — insert lower byte of rs1 into rd at IMM
+ *
+ * IMM is an immediate (compile-time constant), so macros are used.
+ * =========================================================================== */
+
+#define __riscv_cv_simd_extract_h(__rs1, __IMM)                                \
+  ((int32_t)__builtin_riscv_cv_simd_extract_h((uint32_t)(__rs1),               \
+                                               (uint32_t)(__IMM)))
+
+#define __riscv_cv_simd_extract_b(__rs1, __IMM)                                \
+  ((int32_t)__builtin_riscv_cv_simd_extract_b((uint32_t)(__rs1),               \
+                                               (uint32_t)(__IMM)))
+
+#define __riscv_cv_simd_extractu_h(__rs1, __IMM)                               \
+  ((uint32_t)__builtin_riscv_cv_simd_extractu_h((uint32_t)(__rs1),             \
+                                                 (uint32_t)(__IMM)))
+
+#define __riscv_cv_simd_extractu_b(__rs1, __IMM)                               \
+  ((uint32_t)__builtin_riscv_cv_simd_extractu_b((uint32_t)(__rs1),             \
+                                                 (uint32_t)(__IMM)))
+
+/* insert: rd is both input and output (read-modify-write accumulator).
+   The intrinsic prototype is (rs1, rd_in, IMM) -> rd_out.               */
+#define __riscv_cv_simd_insert_h(__rD, __rs1, __IMM)                           \
+  ((uint32_t)__builtin_riscv_cv_simd_insert_h((uint32_t)(__rD),                \
+                                               (uint32_t)(__rs1),               \
+                                               (uint32_t)(__IMM)))
+
+#define __riscv_cv_simd_insert_b(__rD, __rs1, __IMM)                           \
+  ((uint32_t)__builtin_riscv_cv_simd_insert_b((uint32_t)(__rD),                \
+                                               (uint32_t)(__rs1),               \
+                                               (uint32_t)(__IMM)))
+
+/* ===========================================================================
+ * SHUFFLE / SHUFFLE2
+ *
+ * cv.shuffle.h     rd, rs1, rs2  — shuffle halfwords of rs1 using rs2 mask
+ * cv.shuffle.b     rd, rs1, rs2  — shuffle bytes of rs1 using rs2 mask
+ * cv.shuffle.sci.h rd, rs1, IMM  — shuffle halfwords using 2-bit imm
+ * cv.shuffle.sci.b rd, rs1, IMM  — shuffle bytes using 8-bit imm
+ *                                  (split internally into SHUFFLEIx.sci.b)
+ * cv.shuffle2.h    rd, rs1, rs2  — interleave shuffle using rs2 mask + rd input
+ * cv.shuffle2.b    rd, rs1, rs2  — interleave shuffle using rs2 mask + rd input
+ * =========================================================================== */
+
+static __inline__ uint32_t __DEFAULT_FN_ATTRS
+__riscv_cv_simd_shuffle_h(uint32_t a, uint32_t mask) {
+  return __builtin_riscv_cv_simd_shuffle_h(a, mask);
+}
+static __inline__ uint32_t __DEFAULT_FN_ATTRS
+__riscv_cv_simd_shuffle_b(uint32_t a, uint32_t mask) {
+  return __builtin_riscv_cv_simd_shuffle_b(a, mask);
+}
+
+/* shuffle.sci.h — IMM is a 2-bit immediate [0,3] */
+#define __riscv_cv_simd_shuffle_sci_h(__rs1, __IMM)                            \
+  ((uint32_t)__builtin_riscv_cv_simd_shuffle_sci_h((uint32_t)(__rs1),          \
+                                                    (uint32_t)(__IMM)))
+
+/* shuffle.sci.b — IMM is an 8-bit immediate [0,255].
+   The backend splits this into two bits (top 2 → SHUFFLEIx selector) + 6-bit
+   payload, emitting the correct CV_SHUFFLEIx_SCI_B instruction.           */
+#define __riscv_cv_simd_shuffle_sci_b(__rs1, __IMM)                            \
+  ((uint32_t)__builtin_riscv_cv_simd_shuffle_sci_b((uint32_t)(__rs1),          \
+                                                    (uint32_t)(__IMM)))
+
+/* shuffle2: rd is read-modify-write (used as additional input lane) */
+static __inline__ uint32_t __DEFAULT_FN_ATTRS
+__riscv_cv_simd_shuffle2_h(uint32_t rD, uint32_t rs1, uint32_t rs2) {
+  return __builtin_riscv_cv_simd_shuffle2_h(rs1, rs2, rD);
+}
+static __inline__ uint32_t __DEFAULT_FN_ATTRS
+__riscv_cv_simd_shuffle2_b(uint32_t rD, uint32_t rs1, uint32_t rs2) {
+  return __builtin_riscv_cv_simd_shuffle2_b(rs1, rs2, rD);
+}
+
+/* ===========================================================================
+ * PACK
+ *
+ * cv.pack    rd, rs1, rs2  — pack lower halfwords: rd = {rs1[15:0], rs2[15:0]}
+ * cv.pack.h  rd, rs1, rs2  — pack upper halfwords: rd = {rs1[31:16], rs2[31:16]}
+ * cv.packhi.b rd, rs1, rs2 — pack odd bytes:  rd = {rs1[31:24],rs1[15:8],
+ *                                                    rs2[31:24],rs2[15:8]}
+ * cv.packlo.b rd, rs1, rs2 — pack even bytes: rd = {rs1[23:16],rs1[7:0],
+ *                                                    rs2[23:16],rs2[7:0]}
+ *
+ * packhi/packlo: rd is read-modify-write.
+ * =========================================================================== */
+
+static __inline__ uint32_t __DEFAULT_FN_ATTRS
+__riscv_cv_simd_packlo_h(uint32_t rs1, uint32_t rs2) {
+  return __builtin_riscv_cv_simd_packlo_h(rs1, rs2);
+}
+static __inline__ uint32_t __DEFAULT_FN_ATTRS
+__riscv_cv_simd_packhi_h(uint32_t rs1, uint32_t rs2) {
+  return __builtin_riscv_cv_simd_packhi_h(rs1, rs2);
+}
+
+/* packhi/packlo.b: rD is the accumulator half that keeps unmodified bytes */
+static __inline__ uint32_t __DEFAULT_FN_ATTRS
+__riscv_cv_simd_packhi_b(uint32_t rD, uint32_t rs1, uint32_t rs2) {
+  return __builtin_riscv_cv_simd_packhi_b(rD, rs1, rs2);
+}
+static __inline__ uint32_t __DEFAULT_FN_ATTRS
+__riscv_cv_simd_packlo_b(uint32_t rD, uint32_t rs1, uint32_t rs2) {
+  return __builtin_riscv_cv_simd_packlo_b(rD, rs1, rs2);
+}
+
+/* ===========================================================================
+ * COMPARE  (per-element, result is all-1s or all-0s per lane)
+ * =========================================================================== */
+
+/* cmpeq */
+static __inline__ uint32_t __DEFAULT_FN_ATTRS
+__riscv_cv_simd_cmpeq_h(uint32_t a, uint32_t b) { return __builtin_riscv_cv_simd_cmpeq_h(a, b); }
+static __inline__ uint32_t __DEFAULT_FN_ATTRS
+__riscv_cv_simd_cmpeq_b(uint32_t a, uint32_t b) { return __builtin_riscv_cv_simd_cmpeq_b(a, b); }
+static __inline__ uint32_t __DEFAULT_FN_ATTRS
+__riscv_cv_simd_cmpeq_sc_h(uint32_t a, uint32_t b) { return __builtin_riscv_cv_simd_cmpeq_sc_h(a, b); }
+static __inline__ uint32_t __DEFAULT_FN_ATTRS
+__riscv_cv_simd_cmpeq_sc_b(uint32_t a, uint32_t b) { return __builtin_riscv_cv_simd_cmpeq_sc_b(a, b); }
+
+/* cmpne */
+static __inline__ uint32_t __DEFAULT_FN_ATTRS
+__riscv_cv_simd_cmpne_h(uint32_t a, uint32_t b) { return __builtin_riscv_cv_simd_cmpne_h(a, b); }
+static __inline__ uint32_t __DEFAULT_FN_ATTRS
+__riscv_cv_simd_cmpne_b(uint32_t a, uint32_t b) { return __builtin_riscv_cv_simd_cmpne_b(a, b); }
+static __inline__ uint32_t __DEFAULT_FN_ATTRS
+__riscv_cv_simd_cmpne_sc_h(uint32_t a, uint32_t b) { return __builtin_riscv_cv_simd_cmpne_sc_h(a, b); }
+static __inline__ uint32_t __DEFAULT_FN_ATTRS
+__riscv_cv_simd_cmpne_sc_b(uint32_t a, uint32_t b) { return __builtin_riscv_cv_simd_cmpne_sc_b(a, b); }
+
+/* cmpgt (signed greater-than) */
+static __inline__ uint32_t __DEFAULT_FN_ATTRS
+__riscv_cv_simd_cmpgt_h(uint32_t a, uint32_t b) { return __builtin_riscv_cv_simd_cmpgt_h(a, b); }
+static __inline__ uint32_t __DEFAULT_FN_ATTRS
+__riscv_cv_simd_cmpgt_b(uint32_t a, uint32_t b) { return __builtin_riscv_cv_simd_cmpgt_b(a, b); }
+static __inline__ uint32_t __DEFAULT_FN_ATTRS
+__riscv_cv_simd_cmpgt_sc_h(uint32_t a, uint32_t b) { return __builtin_riscv_cv_simd_cmpgt_sc_h(a, b); }
+static __inline__ uint32_t __DEFAULT_FN_ATTRS
+__riscv_cv_simd_cmpgt_sc_b(uint32_t a, uint32_t b) { return __builtin_riscv_cv_simd_cmpgt_sc_b(a, b); }
+
+/* cmpge (signed greater-or-equal) */
+static __inline__ uint32_t __DEFAULT_FN_ATTRS
+__riscv_cv_simd_cmpge_h(uint32_t a, uint32_t b) { return __builtin_riscv_cv_simd_cmpge_h(a, b); }
+static __inline__ uint32_t __DEFAULT_FN_ATTRS
+__riscv_cv_simd_cmpge_b(uint32_t a, uint32_t b) { return __builtin_riscv_cv_simd_cmpge_b(a, b); }
+static __inline__ uint32_t __DEFAULT_FN_ATTRS
+__riscv_cv_simd_cmpge_sc_h(uint32_t a, uint32_t b) { return __builtin_riscv_cv_simd_cmpge_sc_h(a, b); }
+static __inline__ uint32_t __DEFAULT_FN_ATTRS
+__riscv_cv_simd_cmpge_sc_b(uint32_t a, uint32_t b) { return __builtin_riscv_cv_simd_cmpge_sc_b(a, b); }
+
+/* cmplt (signed less-than) */
+static __inline__ uint32_t __DEFAULT_FN_ATTRS
+__riscv_cv_simd_cmplt_h(uint32_t a, uint32_t b) { return __builtin_riscv_cv_simd_cmplt_h(a, b); }
+static __inline__ uint32_t __DEFAULT_FN_ATTRS
+__riscv_cv_simd_cmplt_b(uint32_t a, uint32_t b) { return __builtin_riscv_cv_simd_cmplt_b(a, b); }
+static __inline__ uint32_t __DEFAULT_FN_ATTRS
+__riscv_cv_simd_cmplt_sc_h(uint32_t a, uint32_t b) { return __builtin_riscv_cv_simd_cmplt_sc_h(a, b); }
+static __inline__ uint32_t __DEFAULT_FN_ATTRS
+__riscv_cv_simd_cmplt_sc_b(uint32_t a, uint32_t b) { return __builtin_riscv_cv_simd_cmplt_sc_b(a, b); }
+
+/* cmple (signed less-or-equal) */
+static __inline__ uint32_t __DEFAULT_FN_ATTRS
+__riscv_cv_simd_cmple_h(uint32_t a, uint32_t b) { return __builtin_riscv_cv_simd_cmple_h(a, b); }
+static __inline__ uint32_t __DEFAULT_FN_ATTRS
+__riscv_cv_simd_cmple_b(uint32_t a, uint32_t b) { return __builtin_riscv_cv_simd_cmple_b(a, b); }
+static __inline__ uint32_t __DEFAULT_FN_ATTRS
+__riscv_cv_simd_cmple_sc_h(uint32_t a, uint32_t b) { return __builtin_riscv_cv_simd_cmple_sc_h(a, b); }
+static __inline__ uint32_t __DEFAULT_FN_ATTRS
+__riscv_cv_simd_cmple_sc_b(uint32_t a, uint32_t b) { return __builtin_riscv_cv_simd_cmple_sc_b(a, b); }
+
+/* cmpgtu (unsigned greater-than) */
+static __inline__ uint32_t __DEFAULT_FN_ATTRS
+__riscv_cv_simd_cmpgtu_h(uint32_t a, uint32_t b) { return __builtin_riscv_cv_simd_cmpgtu_h(a, b); }
+static __inline__ uint32_t __DEFAULT_FN_ATTRS
+__riscv_cv_simd_cmpgtu_b(uint32_t a, uint32_t b) { return __builtin_riscv_cv_simd_cmpgtu_b(a, b); }
+static __inline__ uint32_t __DEFAULT_FN_ATTRS
+__riscv_cv_simd_cmpgtu_sc_h(uint32_t a, uint32_t b) { return __builtin_riscv_cv_simd_cmpgtu_sc_h(a, b); }
+static __inline__ uint32_t __DEFAULT_FN_ATTRS
+__riscv_cv_simd_cmpgtu_sc_b(uint32_t a, uint32_t b) { return __builtin_riscv_cv_simd_cmpgtu_sc_b(a, b); }
+
+/* cmpgeu (unsigned greater-or-equal) */
+static __inline__ uint32_t __DEFAULT_FN_ATTRS
+__riscv_cv_simd_cmpgeu_h(uint32_t a, uint32_t b) { return __builtin_riscv_cv_simd_cmpgeu_h(a, b); }
+static __inline__ uint32_t __DEFAULT_FN_ATTRS
+__riscv_cv_simd_cmpgeu_b(uint32_t a, uint32_t b) { return __builtin_riscv_cv_simd_cmpgeu_b(a, b); }
+static __inline__ uint32_t __DEFAULT_FN_ATTRS
+__riscv_cv_simd_cmpgeu_sc_h(uint32_t a, uint32_t b) { return __builtin_riscv_cv_simd_cmpgeu_sc_h(a, b); }
+static __inline__ uint32_t __DEFAULT_FN_ATTRS
+__riscv_cv_simd_cmpgeu_sc_b(uint32_t a, uint32_t b) { return __builtin_riscv_cv_simd_cmpgeu_sc_b(a, b); }
+
+/* cmpltu (unsigned less-than) */
+static __inline__ uint32_t __DEFAULT_FN_ATTRS
+__riscv_cv_simd_cmpltu_h(uint32_t a, uint32_t b) { return __builtin_riscv_cv_simd_cmpltu_h(a, b); }
+static __inline__ uint32_t __DEFAULT_FN_ATTRS
+__riscv_cv_simd_cmpltu_b(uint32_t a, uint32_t b) { return __builtin_riscv_cv_simd_cmpltu_b(a, b); }
+static __inline__ uint32_t __DEFAULT_FN_ATTRS
+__riscv_cv_simd_cmpltu_sc_h(uint32_t a, uint32_t b) { return __builtin_riscv_cv_simd_cmpltu_sc_h(a, b); }
+static __inline__ uint32_t __DEFAULT_FN_ATTRS
+__riscv_cv_simd_cmpltu_sc_b(uint32_t a, uint32_t b) { return __builtin_riscv_cv_simd_cmpltu_sc_b(a, b); }
+
+/* cmpleu (unsigned less-or-equal) */
+static __inline__ uint32_t __DEFAULT_FN_ATTRS
+__riscv_cv_simd_cmpleu_h(uint32_t a, uint32_t b) { return __builtin_riscv_cv_simd_cmpleu_h(a, b); }
+static __inline__ uint32_t __DEFAULT_FN_ATTRS
+__riscv_cv_simd_cmpleu_b(uint32_t a, uint32_t b) { return __builtin_riscv_cv_simd_cmpleu_b(a, b); }
+static __inline__ uint32_t __DEFAULT_FN_ATTRS
+__riscv_cv_simd_cmpleu_sc_h(uint32_t a, uint32_t b) { return __builtin_riscv_cv_simd_cmpleu_sc_h(a, b); }
+static __inline__ uint32_t __DEFAULT_FN_ATTRS
+__riscv_cv_simd_cmpleu_sc_b(uint32_t a, uint32_t b) { return __builtin_riscv_cv_simd_cmpleu_sc_b(a, b); }
+
+/* ===========================================================================
+ * COMPLEX NUMBER OPERATIONS
+ *
+ * cv.cplxmul.r  rd, rs1, rs2 [, divcode]  — complex multiply, real part
+ * cv.cplxmul.i  rd, rs1, rs2 [, divcode]  — complex multiply, imaginary part
+ *   divcode: 0=no shift, 1=/2, 2=/4, 3=/8  (compile-time constant)
+ *   rd is read-modify-write (accumulator for the real or imag lane)
+ *
+ * cv.cplxconj   rd, rs1       — complex conjugate (negate imaginary part)
+ *
+ * cv.subrotmj   rd, rs1, rs2 [, divcode]  — subtract + rotate by -j
+ *   result = ((rs1 - rs2) >> div) rotated by -j  (swap re/im, negate new im)
+ * =========================================================================== */
+
+#define __riscv_cv_simd_cplxmul_r(__rD, __rs1, __rs2, __DIVCODE)               \
+  ((uint32_t)__builtin_riscv_cv_simd_cplxmul_r((uint32_t)(__rs1),              \
+                                                (uint32_t)(__rs2),              \
+                                                (uint32_t)(__rD),               \
+                                                (uint32_t)(__DIVCODE)))
+
+#define __riscv_cv_simd_cplxmul_i(__rD, __rs1, __rs2, __DIVCODE)               \
+  ((uint32_t)__builtin_riscv_cv_simd_cplxmul_i((uint32_t)(__rs1),              \
+                                                (uint32_t)(__rs2),              \
+                                                (uint32_t)(__rD),               \
+                                                (uint32_t)(__DIVCODE)))
+
+static __inline__ uint32_t __DEFAULT_FN_ATTRS
+__riscv_cv_simd_cplxconj(uint32_t a) {
+  return __builtin_riscv_cv_simd_cplxconj(a);
+}
+
+#define __riscv_cv_simd_subrotmj(__rs1, __rs2, __DIVCODE)                      \
+  ((uint32_t)__builtin_riscv_cv_simd_subrotmj((uint32_t)(__rs1),               \
+                                               (uint32_t)(__rs2),               \
+                                               (uint32_t)(__DIVCODE)))
+
+#endif /* __riscv_xcvsimd */
+
+#if defined(__cplusplus)
+}
+#endif
+
+#endif /* __RISCV_COREV_SIMD_H */
diff --git a/clang/lib/Sema/SemaRISCV.cpp b/clang/lib/Sema/SemaRISCV.cpp
index 5711d87300b05..480fbff686f7a 100644
--- a/clang/lib/Sema/SemaRISCV.cpp
+++ b/clang/lib/Sema/SemaRISCV.cpp
@@ -673,6 +673,37 @@ bool SemaRISCV::CheckBuiltinFunctionCall(const TargetInfo &TI,
   case RISCV::BI__builtin_riscv_cv_mac_machhsRN:
     return SemaRef.BuiltinConstantArgRange(TheCall, 3, 0, 31);
 
+  // XCVsimd — extract/insert index
+  case RISCV::BI__builtin_riscv_cv_simd_extract_h:
+  case RISCV::BI__builtin_riscv_cv_simd_extractu_h:
+  return SemaRef.BuiltinConstantArgRange(TheCall, 1, 0, 1); // [0,1] for 2 halfwords
+  case RISCV::BI__builtin_riscv_cv_simd_insert_h:
+    return SemaRef.BuiltinConstantArgRange(TheCall, 2, 0, 1); // [0,1] for 2 halfwords
+  case RISCV::BI__builtin_riscv_cv_simd_extract_b:
+  case RISCV::BI__builtin_riscv_cv_simd_extractu_b:
+  return SemaRef.BuiltinConstantArgRange(TheCall, 1, 0, 3); // [0,3] for 4 bytes
+  case RISCV::BI__builtin_riscv_cv_simd_insert_b:
+    return SemaRef.BuiltinConstantArgRange(TheCall, 2, 0, 3); // [0,3] for 4 bytes
+  // Note: insert has index at arg 2 not 1
+  // Shuffle SCI — 6-bit immediate [0, 63]
+  case RISCV::BI__builtin_riscv_cv_simd_shuffle_sci_h:
+    return SemaRef.BuiltinConstantArgRange(TheCall, 1, 0, 3);
+  case RISCV::BI__builtin_riscv_cv_simd_shuffle_sci_b:
+    return SemaRef.BuiltinConstantArgRange(TheCall, 1, 0, 255); // 8-bit, split by codegen
+
+  // add_h / sub_h div code [0,3] (0=no shift, 1=/2, 2=/4, 3=/8)
+  case RISCV::BI__builtin_riscv_cv_simd_add_h:
+  case RISCV::BI__builtin_riscv_cv_simd_sub_h:
+    return SemaRef.BuiltinConstantArgRange(TheCall, 2, 0, 3);
+
+  // complex mul div code [0,3]
+  case RISCV::BI__builtin_riscv_cv_simd_cplxmul_r:
+  case RISCV::BI__builtin_riscv_cv_simd_cplxmul_i:
+    return SemaRef.BuiltinConstantArgRange(TheCall, 3, 0, 3);
+  case RISCV::BI__builtin_riscv_cv_simd_subrotmj:
+    return SemaRef.BuiltinConstantArgRange(TheCall, 2, 0, 3);
+  }
+
   auto CheckVSetVL = [&](unsigned SEWOffset, unsigned LMULOffset) -> bool {
     const FunctionDecl *FD = SemaRef.getCurFunctionDecl();
     llvm::StringMap<bool> FunctionFeatureMap;

>From 04fa62659da05b239d443598afee0fc6143e353f Mon Sep 17 00:00:00 2001
From: vitbur <vittorioburani at gmail.com>
Date: Wed, 1 Apr 2026 11:02:44 +0200
Subject: [PATCH 05/10] [Clang][RISCV] Add Clang builtins for `XCVbitmanip`
 extension

- `BuiltinsRISCVXCV.td`: add all bitmanip attributes
- `SemaRISCV.cpp`: add range checks
- `RISCV.cpp`: add dispatch cases
- `CIRGenBuiltinRISCV.cpp`: add NYI cases
- add `riscv_corev_bitmanip.h` header + `CMakeLists.txt` addition
---
 clang/include/clang/Basic/BuiltinsRISCVXCV.td |  13 ++
 clang/lib/CIR/CodeGen/CIRGenBuiltinRISCV.cpp  |   8 ++
 clang/lib/CodeGen/TargetBuiltins/RISCV.cpp    |  23 ++++
 clang/lib/Headers/CMakeLists.txt              |   1 +
 clang/lib/Headers/riscv_corev_bitmanip.h      | 117 ++++++++++++++++++
 clang/lib/Sema/SemaRISCV.cpp                  |   5 +
 6 files changed, 167 insertions(+)
 create mode 100644 clang/lib/Headers/riscv_corev_bitmanip.h

diff --git a/clang/include/clang/Basic/BuiltinsRISCVXCV.td b/clang/include/clang/Basic/BuiltinsRISCVXCV.td
index eb0bb58e4814d..31b4788345096 100644
--- a/clang/include/clang/Basic/BuiltinsRISCVXCV.td
+++ b/clang/include/clang/Basic/BuiltinsRISCVXCV.td
@@ -40,6 +40,19 @@ def alu_subRN  : RISCVXCVBuiltin<"int(int, int, unsigned int)", "xcvalu">;
 def alu_subuRN : RISCVXCVBuiltin<"unsigned int(unsigned int, unsigned int, unsigned int)", "xcvalu">;
 } // Attributes = [NoThrow, Const]
 
+//===----------------------------------------------------------------------===//
+// XCVbitmanip extension.
+//===----------------------------------------------------------------------===//
+let Attributes = [NoThrow, Const] in {
+def bitmanip_extract  : RISCVXCVBuiltin<"int(unsigned int, unsigned int)", "xcvbitmanip">;
+def bitmanip_extractu : RISCVXCVBuiltin<"unsigned int(unsigned int, unsigned int)", "xcvbitmanip">;
+def bitmanip_bclr     : RISCVXCVBuiltin<"unsigned int(unsigned int, unsigned int)", "xcvbitmanip">;
+def bitmanip_bset     : RISCVXCVBuiltin<"unsigned int(unsigned int, unsigned int)", "xcvbitmanip">;
+def bitmanip_insert   : RISCVXCVBuiltin<"unsigned int(unsigned int, unsigned int, unsigned int)", "xcvbitmanip">;
+def bitmanip_clb      : RISCVXCVBuiltin<"unsigned int(unsigned int)", "xcvbitmanip">;
+def bitmanip_bitrev   : RISCVXCVBuiltin<"unsigned int(unsigned int, _Constant unsigned int, _Constant unsigned int)", "xcvbitmanip">;
+} // Attributes = [NoThrow, Const]
+
 //===----------------------------------------------------------------------===//
 // XCVelw extension.
 //===----------------------------------------------------------------------===//
diff --git a/clang/lib/CIR/CodeGen/CIRGenBuiltinRISCV.cpp b/clang/lib/CIR/CodeGen/CIRGenBuiltinRISCV.cpp
index 23c497acb2447..47ec19193b322 100644
--- a/clang/lib/CIR/CodeGen/CIRGenBuiltinRISCV.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenBuiltinRISCV.cpp
@@ -184,6 +184,14 @@ CIRGenFunction::emitRISCVBuiltinExpr(unsigned builtinID, const CallExpr *e) {
   case RISCV::BI__builtin_riscv_cv_alu_subRN:
   case RISCV::BI__builtin_riscv_cv_alu_subuN:
   case RISCV::BI__builtin_riscv_cv_alu_subuRN:
+  // XCVbitmanip
+  case RISCV::BI__builtin_riscv_cv_bitmanip_extract:
+  case RISCV::BI__builtin_riscv_cv_bitmanip_extractu:
+  case RISCV::BI__builtin_riscv_cv_bitmanip_bclr:
+  case RISCV::BI__builtin_riscv_cv_bitmanip_bset:
+  case RISCV::BI__builtin_riscv_cv_bitmanip_insert:
+  case RISCV::BI__builtin_riscv_cv_bitmanip_clb:
+  case RISCV::BI__builtin_riscv_cv_bitmanip_bitrev:
   // XCVelw
   case RISCV::BI__builtin_riscv_cv_elw_elw:
   // XCVmac
diff --git a/clang/lib/CodeGen/TargetBuiltins/RISCV.cpp b/clang/lib/CodeGen/TargetBuiltins/RISCV.cpp
index 1338eda9f876b..5fde76c4ce3d4 100644
--- a/clang/lib/CodeGen/TargetBuiltins/RISCV.cpp
+++ b/clang/lib/CodeGen/TargetBuiltins/RISCV.cpp
@@ -1433,6 +1433,29 @@ Value *CodeGenFunction::EmitRISCVBuiltinExpr(unsigned BuiltinID,
     ID = Intrinsic::riscv_cv_alu_subuRN;
     break;
 
+  // XCVbitmanip
+  case RISCV::BI__builtin_riscv_cv_bitmanip_extract:
+    ID = Intrinsic::riscv_cv_bitmanip_extract;
+    break;
+  case RISCV::BI__builtin_riscv_cv_bitmanip_extractu:
+    ID = Intrinsic::riscv_cv_bitmanip_extractu;
+    break;
+  case RISCV::BI__builtin_riscv_cv_bitmanip_bclr:
+    ID = Intrinsic::riscv_cv_bitmanip_bclr;
+    break;
+  case RISCV::BI__builtin_riscv_cv_bitmanip_bset:
+    ID = Intrinsic::riscv_cv_bitmanip_bset;
+    break;
+  case RISCV::BI__builtin_riscv_cv_bitmanip_insert:
+    ID = Intrinsic::riscv_cv_bitmanip_insert;
+    break;
+  case RISCV::BI__builtin_riscv_cv_bitmanip_clb:
+    ID = Intrinsic::riscv_cv_bitmanip_clb;
+    break;
+  case RISCV::BI__builtin_riscv_cv_bitmanip_bitrev:
+    ID = Intrinsic::riscv_cv_bitmanip_bitrev;
+    break;
+
   // XCVelw
   case RISCV::BI__builtin_riscv_cv_elw_elw: {
     // cv.elw rd, imm(rs1) — load word with event wait
diff --git a/clang/lib/Headers/CMakeLists.txt b/clang/lib/Headers/CMakeLists.txt
index b314bfdffea45..6216151fb060f 100644
--- a/clang/lib/Headers/CMakeLists.txt
+++ b/clang/lib/Headers/CMakeLists.txt
@@ -138,6 +138,7 @@ set(riscv_files
   # Vendor headers
   andes_vector.h
   riscv_corev_alu.h
+  riscv_corev_bitmanip.h
   riscv_corev_elw.h
   riscv_corev_mac.h
   riscv_corev_simd.h
diff --git a/clang/lib/Headers/riscv_corev_bitmanip.h b/clang/lib/Headers/riscv_corev_bitmanip.h
new file mode 100644
index 0000000000000..7676e44df87bd
--- /dev/null
+++ b/clang/lib/Headers/riscv_corev_bitmanip.h
@@ -0,0 +1,117 @@
+/*===---- riscv_corev_bitmanip.h - CORE-V bit-manipulation intrinsics ------===
+ *
+ * Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+ * See https://llvm.org/LICENSE.txt for license information.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ *
+ *===-----------------------------------------------------------------------===
+ *
+ * This header provides C intrinsics for the CORE-V XCVbitmanip ISA extension.
+ * Include this header when compiling with -march=..._xcvbitmanip.
+ *
+ * Spec: https://github.com/openhwgroup/cv32e40p/blob/master/docs/source/
+ *       instruction_set_extensions.rst  (Bit Manipulation section)
+ *
+ *===-----------------------------------------------------------------------===
+ */
+
+#ifndef __RISCV_COREV_BITMANIP_H
+#define __RISCV_COREV_BITMANIP_H
+
+#include <stdint.h>
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+#if defined(__riscv_xcvbitmanip)
+
+#define __DEFAULT_FN_ATTRS                                                      \
+  __attribute__((__always_inline__, __nodebug__, __artificial__))
+
+/* ---------------------------------------------------------------------------
+ * cv.extract rd, rs1, IS3, IS2
+ *   rd = SignExtend(rs1[IS3+IS2-1 : IS2], 32)
+ *   IS3 = bit-width (uimm5), IS2 = lower bit index (uimm5)
+ *   The two immediates are packed as a single uimm10: IS3<<5 | IS2
+ *   IMM must be a compile-time constant.
+ * --------------------------------------------------------------------------- */
+#define __riscv_cv_bitmanip_extract(__rs1, __IMM)                               \
+  ((int32_t)__builtin_riscv_cv_bitmanip_extract((uint32_t)(__rs1),             \
+                                                 (uint32_t)(__IMM)))
+
+/* ---------------------------------------------------------------------------
+ * cv.extractu rd, rs1, IS3, IS2
+ *   rd = ZeroExtend(rs1[IS3+IS2-1 : IS2], 32)
+ * --------------------------------------------------------------------------- */
+#define __riscv_cv_bitmanip_extractu(__rs1, __IMM)                             \
+  ((uint32_t)__builtin_riscv_cv_bitmanip_extractu((uint32_t)(__rs1),          \
+                                                   (uint32_t)(__IMM)))
+
+/* ---------------------------------------------------------------------------
+ * cv.bclr rd, rs1, IS3, IS2
+ *   rd = rs1 & ~(((1 << IS3) - 1) << IS2)   (clear IS3 bits starting at IS2)
+ * --------------------------------------------------------------------------- */
+#define __riscv_cv_bitmanip_bclr(__rs1, __IMM)                                 \
+  ((uint32_t)__builtin_riscv_cv_bitmanip_bclr((uint32_t)(__rs1),              \
+                                               (uint32_t)(__IMM)))
+
+/* ---------------------------------------------------------------------------
+ * cv.bset rd, rs1, IS3, IS2
+ *   rd = rs1 | (((1 << IS3) - 1) << IS2)    (set IS3 bits starting at IS2)
+ * --------------------------------------------------------------------------- */
+#define __riscv_cv_bitmanip_bset(__rs1, __IMM)                                 \
+  ((uint32_t)__builtin_riscv_cv_bitmanip_bset((uint32_t)(__rs1),              \
+                                               (uint32_t)(__IMM)))
+
+/* ---------------------------------------------------------------------------
+ * cv.insert rd, rs1, IS3, IS2
+ *   rd[IS3+IS2-1 : IS2] = rs1[IS3-1 : 0]
+ *   rd is read-modify-write (the bits outside the target range are preserved).
+ *   IS3 = bit-width (uimm5), IS2 = lower bit index (uimm5)
+ *   The two immediates are packed as a single uimm10: IS3<<5 | IS2
+ * --------------------------------------------------------------------------- */
+#define __riscv_cv_bitmanip_insert(__rD, __rs1, __IMM)                         \
+  ((uint32_t)__builtin_riscv_cv_bitmanip_insert((uint32_t)(__rs1),            \
+                                                 (uint32_t)(__IMM),            \
+                                                 (uint32_t)(__rD)))
+
+/* ---------------------------------------------------------------------------
+ * cv.clb rd, rs1
+ *   rd = number of consecutive leading bits equal to the sign bit (after the
+ *        sign bit itself), i.e. count leading bits equal to bit 31.
+ *   Equivalent to max(0, clz(rs1) + clz(~rs1) - 1).
+ *
+ * Note: ff1 (find-first-one from LSB), fl1 (find-last-one from LSB), cnt
+ * (popcount) and ror (rotate-right) are intentionally absent from this header.
+ * The compiler automatically selects cv.ff1 / cv.fl1 / cv.cnt / cv.ror from
+ * standard C expressions (__builtin_ctz, __builtin_clz, __builtin_popcount,
+ * rotate patterns) when -march includes xcvbitmanip. No explicit builtin call
+ * is required or provided for those four operations.
+ * --------------------------------------------------------------------------- */
+static __inline__ uint32_t __DEFAULT_FN_ATTRS
+__riscv_cv_bitmanip_clb(uint32_t a) {
+  return __builtin_riscv_cv_bitmanip_clb(a);
+}
+
+/* ---------------------------------------------------------------------------
+ * cv.bitrev rd, rs1, IS2, IS3
+ *   Reverses groups of (2^IS2) bits within each (IS3+1)-bit segment of rs1.
+ *   IS2 = radix (uimm2, 0..3), IS3 = number of significant bits minus 1 (uimm5)
+ *   Both IS2 and IS3 must be compile-time constants.
+ *
+ * Example: cv.bitrev t0, t0, 2, 23 reverses groups of 4 bits within each
+ * 24-bit window.
+ * --------------------------------------------------------------------------- */
+#define __riscv_cv_bitmanip_bitrev(__rs1, __IS2, __IS3)                        \
+  ((uint32_t)__builtin_riscv_cv_bitmanip_bitrev((uint32_t)(__rs1),            \
+                                                 (uint32_t)(__IS2),            \
+                                                 (uint32_t)(__IS3)))
+
+#endif /* __riscv_xcvbitmanip */
+
+#if defined(__cplusplus)
+}
+#endif
+
+#endif /* __RISCV_COREV_BITMANIP_H */
diff --git a/clang/lib/Sema/SemaRISCV.cpp b/clang/lib/Sema/SemaRISCV.cpp
index 480fbff686f7a..0af3053ff3db9 100644
--- a/clang/lib/Sema/SemaRISCV.cpp
+++ b/clang/lib/Sema/SemaRISCV.cpp
@@ -653,6 +653,11 @@ bool SemaRISCV::CheckBuiltinFunctionCall(const TargetInfo &TI,
     break;
   }
 
+  // XCVbitmanip — bitrev: IS2 (radix) in [0,3], IS3 (pts) in [0,31]
+  case RISCV::BI__builtin_riscv_cv_bitmanip_bitrev:
+    return SemaRef.BuiltinConstantArgRange(TheCall, 1, 0, 3) ||
+           SemaRef.BuiltinConstantArgRange(TheCall, 2, 0, 31);
+
   // XCVmac — shift amount in [0, 31]
   case RISCV::BI__builtin_riscv_cv_mac_muluN:
   case RISCV::BI__builtin_riscv_cv_mac_mulhhuN:

>From 3fad9ce51b4f100688b9c3403755374f0f7ffc6a Mon Sep 17 00:00:00 2001
From: vitbur <vittorioburani at gmail.com>
Date: Tue, 7 Apr 2026 18:45:18 +0200
Subject: [PATCH 06/10] [Clang][RISCV] Add tests for `XCVelw` builtins

- add `rvv-xcvelw-builtins.c`
---
 .../test/CodeGen/RISCV/rvv-xcvelw-builtins.c  | 20 +++++++++++++++++++
 1 file changed, 20 insertions(+)
 create mode 100644 clang/test/CodeGen/RISCV/rvv-xcvelw-builtins.c

diff --git a/clang/test/CodeGen/RISCV/rvv-xcvelw-builtins.c b/clang/test/CodeGen/RISCV/rvv-xcvelw-builtins.c
new file mode 100644
index 0000000000000..0eb41ec3261e4
--- /dev/null
+++ b/clang/test/CodeGen/RISCV/rvv-xcvelw-builtins.c
@@ -0,0 +1,20 @@
+// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py
+// RUN: %clang_cc1 -triple riscv32 -target-feature +xcvelw -emit-llvm %s -o - \
+// RUN:   | FileCheck %s
+
+// This file tests that the XCVelw Clang builtin is correctly lowered
+// to its corresponding LLVM IR intrinsic.
+
+#include <stdint.h>
+
+// CHECK-LABEL: @test_elw(
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:    [[ADDR_ADDR:%.*]] = alloca ptr, align 4
+// CHECK-NEXT:    store ptr [[ADDR:%.*]], ptr [[ADDR_ADDR]], align 4
+// CHECK-NEXT:    [[TMP0:%.*]] = load ptr, ptr [[ADDR_ADDR]], align 4
+// CHECK-NEXT:    [[TMP1:%.*]] = call i32 @llvm.riscv.cv.elw.elw(ptr [[TMP0]])
+// CHECK-NEXT:    ret i32 [[TMP1]]
+//
+int32_t test_elw(int32_t *addr) {
+  return __builtin_riscv_cv_elw_elw(addr);
+}

>From df4d6dba06f7b676c506ba0190dd145607fff0d5 Mon Sep 17 00:00:00 2001
From: vitbur <vittorioburani at gmail.com>
Date: Tue, 7 Apr 2026 18:46:56 +0200
Subject: [PATCH 07/10] [Clang][RISCV] Add tests for `XCVmac` builtins

- add `rvv-xcvmac-builtins.c`
- add Sema tests for XCVmac in `rvv-xcv-sema.c`
---
 .../test/CodeGen/RISCV/rvv-xcvmac-builtins.c  | 318 ++++++++++++++++++
 clang/test/Sema/rvv-xcv-sema.c                |  17 +
 2 files changed, 335 insertions(+)
 create mode 100644 clang/test/CodeGen/RISCV/rvv-xcvmac-builtins.c
 create mode 100644 clang/test/Sema/rvv-xcv-sema.c

diff --git a/clang/test/CodeGen/RISCV/rvv-xcvmac-builtins.c b/clang/test/CodeGen/RISCV/rvv-xcvmac-builtins.c
new file mode 100644
index 0000000000000..84d7d9c02c5a2
--- /dev/null
+++ b/clang/test/CodeGen/RISCV/rvv-xcvmac-builtins.c
@@ -0,0 +1,318 @@
+// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py
+// RUN: %clang_cc1 -triple riscv32 -target-feature +xcvmac -emit-llvm %s -o - \
+// RUN:   | FileCheck %s
+
+// This file tests that XCVmac Clang builtins are correctly lowered
+// to their corresponding LLVM IR intrinsics.
+
+#include <stdint.h>
+
+// ---- 32x32 MAC/MSU ----
+
+// CHECK-LABEL: @test_mac(
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:    [[A_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    [[B_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    [[ACC_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    store i32 [[A:%.*]], ptr [[A_ADDR]], align 4
+// CHECK-NEXT:    store i32 [[B:%.*]], ptr [[B_ADDR]], align 4
+// CHECK-NEXT:    store i32 [[ACC:%.*]], ptr [[ACC_ADDR]], align 4
+// CHECK-NEXT:    [[TMP0:%.*]] = load i32, ptr [[A_ADDR]], align 4
+// CHECK-NEXT:    [[TMP1:%.*]] = load i32, ptr [[B_ADDR]], align 4
+// CHECK-NEXT:    [[TMP2:%.*]] = load i32, ptr [[ACC_ADDR]], align 4
+// CHECK-NEXT:    [[TMP3:%.*]] = call i32 @llvm.riscv.cv.mac.mac(i32 [[TMP0]], i32 [[TMP1]], i32 [[TMP2]])
+// CHECK-NEXT:    ret i32 [[TMP3]]
+//
+int32_t test_mac(int32_t a, int32_t b, int32_t acc) {
+  return __builtin_riscv_cv_mac_mac(a, b, acc);
+}
+
+// CHECK-LABEL: @test_msu(
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:    [[A_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    [[B_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    [[ACC_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    store i32 [[A:%.*]], ptr [[A_ADDR]], align 4
+// CHECK-NEXT:    store i32 [[B:%.*]], ptr [[B_ADDR]], align 4
+// CHECK-NEXT:    store i32 [[ACC:%.*]], ptr [[ACC_ADDR]], align 4
+// CHECK-NEXT:    [[TMP0:%.*]] = load i32, ptr [[A_ADDR]], align 4
+// CHECK-NEXT:    [[TMP1:%.*]] = load i32, ptr [[B_ADDR]], align 4
+// CHECK-NEXT:    [[TMP2:%.*]] = load i32, ptr [[ACC_ADDR]], align 4
+// CHECK-NEXT:    [[TMP3:%.*]] = call i32 @llvm.riscv.cv.mac.msu(i32 [[TMP0]], i32 [[TMP1]], i32 [[TMP2]])
+// CHECK-NEXT:    ret i32 [[TMP3]]
+//
+int32_t test_msu(int32_t a, int32_t b, int32_t acc) {
+  return __builtin_riscv_cv_mac_msu(a, b, acc);
+}
+
+// ---- Unsigned 16x16 multiply with shift ----
+
+// CHECK-LABEL: @test_muluN(
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:    [[A_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    [[B_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    store i32 [[A:%.*]], ptr [[A_ADDR]], align 4
+// CHECK-NEXT:    store i32 [[B:%.*]], ptr [[B_ADDR]], align 4
+// CHECK-NEXT:    [[TMP0:%.*]] = load i32, ptr [[A_ADDR]], align 4
+// CHECK-NEXT:    [[TMP1:%.*]] = load i32, ptr [[B_ADDR]], align 4
+// CHECK-NEXT:    [[TMP2:%.*]] = call i32 @llvm.riscv.cv.mac.muluN(i32 [[TMP0]], i32 [[TMP1]], i32 5)
+// CHECK-NEXT:    ret i32 [[TMP2]]
+//
+uint32_t test_muluN(uint32_t a, uint32_t b) {
+  return __builtin_riscv_cv_mac_muluN(a, b, 5);
+}
+
+// CHECK-LABEL: @test_mulhhuN(
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:    [[A_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    [[B_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    store i32 [[A:%.*]], ptr [[A_ADDR]], align 4
+// CHECK-NEXT:    store i32 [[B:%.*]], ptr [[B_ADDR]], align 4
+// CHECK-NEXT:    [[TMP0:%.*]] = load i32, ptr [[A_ADDR]], align 4
+// CHECK-NEXT:    [[TMP1:%.*]] = load i32, ptr [[B_ADDR]], align 4
+// CHECK-NEXT:    [[TMP2:%.*]] = call i32 @llvm.riscv.cv.mac.mulhhuN(i32 [[TMP0]], i32 [[TMP1]], i32 5)
+// CHECK-NEXT:    ret i32 [[TMP2]]
+//
+uint32_t test_mulhhuN(uint32_t a, uint32_t b) {
+  return __builtin_riscv_cv_mac_mulhhuN(a, b, 5);
+}
+
+// CHECK-LABEL: @test_muluRN(
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:    [[A_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    [[B_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    store i32 [[A:%.*]], ptr [[A_ADDR]], align 4
+// CHECK-NEXT:    store i32 [[B:%.*]], ptr [[B_ADDR]], align 4
+// CHECK-NEXT:    [[TMP0:%.*]] = load i32, ptr [[A_ADDR]], align 4
+// CHECK-NEXT:    [[TMP1:%.*]] = load i32, ptr [[B_ADDR]], align 4
+// CHECK-NEXT:    [[TMP2:%.*]] = call i32 @llvm.riscv.cv.mac.muluRN(i32 [[TMP0]], i32 [[TMP1]], i32 5)
+// CHECK-NEXT:    ret i32 [[TMP2]]
+//
+uint32_t test_muluRN(uint32_t a, uint32_t b) {
+  return __builtin_riscv_cv_mac_muluRN(a, b, 5);
+}
+
+// CHECK-LABEL: @test_mulhhuRN(
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:    [[A_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    [[B_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    store i32 [[A:%.*]], ptr [[A_ADDR]], align 4
+// CHECK-NEXT:    store i32 [[B:%.*]], ptr [[B_ADDR]], align 4
+// CHECK-NEXT:    [[TMP0:%.*]] = load i32, ptr [[A_ADDR]], align 4
+// CHECK-NEXT:    [[TMP1:%.*]] = load i32, ptr [[B_ADDR]], align 4
+// CHECK-NEXT:    [[TMP2:%.*]] = call i32 @llvm.riscv.cv.mac.mulhhuRN(i32 [[TMP0]], i32 [[TMP1]], i32 5)
+// CHECK-NEXT:    ret i32 [[TMP2]]
+//
+uint32_t test_mulhhuRN(uint32_t a, uint32_t b) {
+  return __builtin_riscv_cv_mac_mulhhuRN(a, b, 5);
+}
+
+// ---- Signed 16x16 multiply with shift ----
+
+// CHECK-LABEL: @test_mulsN(
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:    [[A_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    [[B_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    store i32 [[A:%.*]], ptr [[A_ADDR]], align 4
+// CHECK-NEXT:    store i32 [[B:%.*]], ptr [[B_ADDR]], align 4
+// CHECK-NEXT:    [[TMP0:%.*]] = load i32, ptr [[A_ADDR]], align 4
+// CHECK-NEXT:    [[TMP1:%.*]] = load i32, ptr [[B_ADDR]], align 4
+// CHECK-NEXT:    [[TMP2:%.*]] = call i32 @llvm.riscv.cv.mac.mulsN(i32 [[TMP0]], i32 [[TMP1]], i32 5)
+// CHECK-NEXT:    ret i32 [[TMP2]]
+//
+int32_t test_mulsN(uint32_t a, uint32_t b) {
+  return __builtin_riscv_cv_mac_mulsN(a, b, 5);
+}
+
+// CHECK-LABEL: @test_mulhhsN(
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:    [[A_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    [[B_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    store i32 [[A:%.*]], ptr [[A_ADDR]], align 4
+// CHECK-NEXT:    store i32 [[B:%.*]], ptr [[B_ADDR]], align 4
+// CHECK-NEXT:    [[TMP0:%.*]] = load i32, ptr [[A_ADDR]], align 4
+// CHECK-NEXT:    [[TMP1:%.*]] = load i32, ptr [[B_ADDR]], align 4
+// CHECK-NEXT:    [[TMP2:%.*]] = call i32 @llvm.riscv.cv.mac.mulhhsN(i32 [[TMP0]], i32 [[TMP1]], i32 5)
+// CHECK-NEXT:    ret i32 [[TMP2]]
+//
+int32_t test_mulhhsN(uint32_t a, uint32_t b) {
+  return __builtin_riscv_cv_mac_mulhhsN(a, b, 5);
+}
+
+// CHECK-LABEL: @test_mulsRN(
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:    [[A_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    [[B_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    store i32 [[A:%.*]], ptr [[A_ADDR]], align 4
+// CHECK-NEXT:    store i32 [[B:%.*]], ptr [[B_ADDR]], align 4
+// CHECK-NEXT:    [[TMP0:%.*]] = load i32, ptr [[A_ADDR]], align 4
+// CHECK-NEXT:    [[TMP1:%.*]] = load i32, ptr [[B_ADDR]], align 4
+// CHECK-NEXT:    [[TMP2:%.*]] = call i32 @llvm.riscv.cv.mac.mulsRN(i32 [[TMP0]], i32 [[TMP1]], i32 5)
+// CHECK-NEXT:    ret i32 [[TMP2]]
+//
+int32_t test_mulsRN(uint32_t a, uint32_t b) {
+  return __builtin_riscv_cv_mac_mulsRN(a, b, 5);
+}
+
+// CHECK-LABEL: @test_mulhhsRN(
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:    [[A_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    [[B_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    store i32 [[A:%.*]], ptr [[A_ADDR]], align 4
+// CHECK-NEXT:    store i32 [[B:%.*]], ptr [[B_ADDR]], align 4
+// CHECK-NEXT:    [[TMP0:%.*]] = load i32, ptr [[A_ADDR]], align 4
+// CHECK-NEXT:    [[TMP1:%.*]] = load i32, ptr [[B_ADDR]], align 4
+// CHECK-NEXT:    [[TMP2:%.*]] = call i32 @llvm.riscv.cv.mac.mulhhsRN(i32 [[TMP0]], i32 [[TMP1]], i32 5)
+// CHECK-NEXT:    ret i32 [[TMP2]]
+//
+int32_t test_mulhhsRN(uint32_t a, uint32_t b) {
+  return __builtin_riscv_cv_mac_mulhhsRN(a, b, 5);
+}
+
+// ---- Unsigned 16x16 MAC with shift ----
+
+// CHECK-LABEL: @test_macuN(
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:    [[A_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    [[B_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    [[ACC_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    store i32 [[A:%.*]], ptr [[A_ADDR]], align 4
+// CHECK-NEXT:    store i32 [[B:%.*]], ptr [[B_ADDR]], align 4
+// CHECK-NEXT:    store i32 [[ACC:%.*]], ptr [[ACC_ADDR]], align 4
+// CHECK-NEXT:    [[TMP0:%.*]] = load i32, ptr [[A_ADDR]], align 4
+// CHECK-NEXT:    [[TMP1:%.*]] = load i32, ptr [[B_ADDR]], align 4
+// CHECK-NEXT:    [[TMP2:%.*]] = load i32, ptr [[ACC_ADDR]], align 4
+// CHECK-NEXT:    [[TMP3:%.*]] = call i32 @llvm.riscv.cv.mac.macuN(i32 [[TMP0]], i32 [[TMP1]], i32 [[TMP2]], i32 5)
+// CHECK-NEXT:    ret i32 [[TMP3]]
+//
+uint32_t test_macuN(uint32_t a, uint32_t b, uint32_t acc) {
+  return __builtin_riscv_cv_mac_macuN(a, b, acc, 5);
+}
+
+// CHECK-LABEL: @test_machhuN(
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:    [[A_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    [[B_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    [[ACC_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    store i32 [[A:%.*]], ptr [[A_ADDR]], align 4
+// CHECK-NEXT:    store i32 [[B:%.*]], ptr [[B_ADDR]], align 4
+// CHECK-NEXT:    store i32 [[ACC:%.*]], ptr [[ACC_ADDR]], align 4
+// CHECK-NEXT:    [[TMP0:%.*]] = load i32, ptr [[A_ADDR]], align 4
+// CHECK-NEXT:    [[TMP1:%.*]] = load i32, ptr [[B_ADDR]], align 4
+// CHECK-NEXT:    [[TMP2:%.*]] = load i32, ptr [[ACC_ADDR]], align 4
+// CHECK-NEXT:    [[TMP3:%.*]] = call i32 @llvm.riscv.cv.mac.machhuN(i32 [[TMP0]], i32 [[TMP1]], i32 [[TMP2]], i32 5)
+// CHECK-NEXT:    ret i32 [[TMP3]]
+//
+uint32_t test_machhuN(uint32_t a, uint32_t b, uint32_t acc) {
+  return __builtin_riscv_cv_mac_machhuN(a, b, acc, 5);
+}
+
+// CHECK-LABEL: @test_macuRN(
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:    [[A_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    [[B_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    [[ACC_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    store i32 [[A:%.*]], ptr [[A_ADDR]], align 4
+// CHECK-NEXT:    store i32 [[B:%.*]], ptr [[B_ADDR]], align 4
+// CHECK-NEXT:    store i32 [[ACC:%.*]], ptr [[ACC_ADDR]], align 4
+// CHECK-NEXT:    [[TMP0:%.*]] = load i32, ptr [[A_ADDR]], align 4
+// CHECK-NEXT:    [[TMP1:%.*]] = load i32, ptr [[B_ADDR]], align 4
+// CHECK-NEXT:    [[TMP2:%.*]] = load i32, ptr [[ACC_ADDR]], align 4
+// CHECK-NEXT:    [[TMP3:%.*]] = call i32 @llvm.riscv.cv.mac.macuRN(i32 [[TMP0]], i32 [[TMP1]], i32 [[TMP2]], i32 5)
+// CHECK-NEXT:    ret i32 [[TMP3]]
+//
+uint32_t test_macuRN(uint32_t a, uint32_t b, uint32_t acc) {
+  return __builtin_riscv_cv_mac_macuRN(a, b, acc, 5);
+}
+
+// CHECK-LABEL: @test_machhuRN(
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:    [[A_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    [[B_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    [[ACC_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    store i32 [[A:%.*]], ptr [[A_ADDR]], align 4
+// CHECK-NEXT:    store i32 [[B:%.*]], ptr [[B_ADDR]], align 4
+// CHECK-NEXT:    store i32 [[ACC:%.*]], ptr [[ACC_ADDR]], align 4
+// CHECK-NEXT:    [[TMP0:%.*]] = load i32, ptr [[A_ADDR]], align 4
+// CHECK-NEXT:    [[TMP1:%.*]] = load i32, ptr [[B_ADDR]], align 4
+// CHECK-NEXT:    [[TMP2:%.*]] = load i32, ptr [[ACC_ADDR]], align 4
+// CHECK-NEXT:    [[TMP3:%.*]] = call i32 @llvm.riscv.cv.mac.machhuRN(i32 [[TMP0]], i32 [[TMP1]], i32 [[TMP2]], i32 5)
+// CHECK-NEXT:    ret i32 [[TMP3]]
+//
+uint32_t test_machhuRN(uint32_t a, uint32_t b, uint32_t acc) {
+  return __builtin_riscv_cv_mac_machhuRN(a, b, acc, 5);
+}
+
+// ---- Signed 16x16 MAC with shift ----
+
+// CHECK-LABEL: @test_macsN(
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:    [[A_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    [[B_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    [[ACC_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    store i32 [[A:%.*]], ptr [[A_ADDR]], align 4
+// CHECK-NEXT:    store i32 [[B:%.*]], ptr [[B_ADDR]], align 4
+// CHECK-NEXT:    store i32 [[ACC:%.*]], ptr [[ACC_ADDR]], align 4
+// CHECK-NEXT:    [[TMP0:%.*]] = load i32, ptr [[A_ADDR]], align 4
+// CHECK-NEXT:    [[TMP1:%.*]] = load i32, ptr [[B_ADDR]], align 4
+// CHECK-NEXT:    [[TMP2:%.*]] = load i32, ptr [[ACC_ADDR]], align 4
+// CHECK-NEXT:    [[TMP3:%.*]] = call i32 @llvm.riscv.cv.mac.macsN(i32 [[TMP0]], i32 [[TMP1]], i32 [[TMP2]], i32 5)
+// CHECK-NEXT:    ret i32 [[TMP3]]
+//
+int32_t test_macsN(uint32_t a, uint32_t b, uint32_t acc) {
+  return __builtin_riscv_cv_mac_macsN(a, b, acc, 5);
+}
+
+// CHECK-LABEL: @test_machhsN(
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:    [[A_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    [[B_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    [[ACC_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    store i32 [[A:%.*]], ptr [[A_ADDR]], align 4
+// CHECK-NEXT:    store i32 [[B:%.*]], ptr [[B_ADDR]], align 4
+// CHECK-NEXT:    store i32 [[ACC:%.*]], ptr [[ACC_ADDR]], align 4
+// CHECK-NEXT:    [[TMP0:%.*]] = load i32, ptr [[A_ADDR]], align 4
+// CHECK-NEXT:    [[TMP1:%.*]] = load i32, ptr [[B_ADDR]], align 4
+// CHECK-NEXT:    [[TMP2:%.*]] = load i32, ptr [[ACC_ADDR]], align 4
+// CHECK-NEXT:    [[TMP3:%.*]] = call i32 @llvm.riscv.cv.mac.machhsN(i32 [[TMP0]], i32 [[TMP1]], i32 [[TMP2]], i32 5)
+// CHECK-NEXT:    ret i32 [[TMP3]]
+//
+int32_t test_machhsN(uint32_t a, uint32_t b, uint32_t acc) {
+  return __builtin_riscv_cv_mac_machhsN(a, b, acc, 5);
+}
+
+// CHECK-LABEL: @test_macsRN(
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:    [[A_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    [[B_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    [[ACC_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    store i32 [[A:%.*]], ptr [[A_ADDR]], align 4
+// CHECK-NEXT:    store i32 [[B:%.*]], ptr [[B_ADDR]], align 4
+// CHECK-NEXT:    store i32 [[ACC:%.*]], ptr [[ACC_ADDR]], align 4
+// CHECK-NEXT:    [[TMP0:%.*]] = load i32, ptr [[A_ADDR]], align 4
+// CHECK-NEXT:    [[TMP1:%.*]] = load i32, ptr [[B_ADDR]], align 4
+// CHECK-NEXT:    [[TMP2:%.*]] = load i32, ptr [[ACC_ADDR]], align 4
+// CHECK-NEXT:    [[TMP3:%.*]] = call i32 @llvm.riscv.cv.mac.macsRN(i32 [[TMP0]], i32 [[TMP1]], i32 [[TMP2]], i32 5)
+// CHECK-NEXT:    ret i32 [[TMP3]]
+//
+int32_t test_macsRN(uint32_t a, uint32_t b, uint32_t acc) {
+  return __builtin_riscv_cv_mac_macsRN(a, b, acc, 5);
+}
+
+// CHECK-LABEL: @test_machhsRN(
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:    [[A_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    [[B_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    [[ACC_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    store i32 [[A:%.*]], ptr [[A_ADDR]], align 4
+// CHECK-NEXT:    store i32 [[B:%.*]], ptr [[B_ADDR]], align 4
+// CHECK-NEXT:    store i32 [[ACC:%.*]], ptr [[ACC_ADDR]], align 4
+// CHECK-NEXT:    [[TMP0:%.*]] = load i32, ptr [[A_ADDR]], align 4
+// CHECK-NEXT:    [[TMP1:%.*]] = load i32, ptr [[B_ADDR]], align 4
+// CHECK-NEXT:    [[TMP2:%.*]] = load i32, ptr [[ACC_ADDR]], align 4
+// CHECK-NEXT:    [[TMP3:%.*]] = call i32 @llvm.riscv.cv.mac.machhsRN(i32 [[TMP0]], i32 [[TMP1]], i32 [[TMP2]], i32 5)
+// CHECK-NEXT:    ret i32 [[TMP3]]
+//
+int32_t test_machhsRN(uint32_t a, uint32_t b, uint32_t acc) {
+  return __builtin_riscv_cv_mac_machhsRN(a, b, acc, 5);
+}
diff --git a/clang/test/Sema/rvv-xcv-sema.c b/clang/test/Sema/rvv-xcv-sema.c
new file mode 100644
index 0000000000000..681e6c7c385dd
--- /dev/null
+++ b/clang/test/Sema/rvv-xcv-sema.c
@@ -0,0 +1,17 @@
+// RUN: %clang_cc1 -triple riscv32 -target-feature +xcvmac -target-feature +xcvsimd \
+// RUN:   -target-feature +xcvbitmanip -fsyntax-only -verify %s
+
+// This file tests that Sema range checks correctly reject out-of-range
+// immediate arguments for XCV builtins.
+
+#include <stdint.h>
+
+// ===== XCVmac — shift must be in [0, 31] =====
+
+void test_mac_range(uint32_t a, uint32_t b, uint32_t c) {
+  (void)__builtin_riscv_cv_mac_muluN(a, b, 31);  // OK: max value
+  (void)__builtin_riscv_cv_mac_muluN(a, b, 32);  // expected-error {{argument value 32 is outside the valid range [0, 31]}}
+  (void)__builtin_riscv_cv_mac_mulsN(a, b, 0);   // OK: min value
+  (void)__builtin_riscv_cv_mac_macuN(a, b, c, 31);  // OK
+  (void)__builtin_riscv_cv_mac_macuN(a, b, c, 32);  // expected-error {{argument value 32 is outside the valid range [0, 31]}}
+}

>From 410e6b40654daf9ae29aec131a072e373c723323 Mon Sep 17 00:00:00 2001
From: vitbur <vittorioburani at gmail.com>
Date: Tue, 7 Apr 2026 18:48:34 +0200
Subject: [PATCH 08/10] [Clang][RISCV] Add tests for `XCVsimd` builtins

- add `rvv-xcvsimd-builtins.c`
- add Sema tests for XCVsimd in `rvv-xcv-sema.c`
---
 .../test/CodeGen/RISCV/rvv-xcvsimd-builtins.c | 1219 +++++++++++++++++
 clang/test/Sema/rvv-xcv-sema.c                |   40 +
 2 files changed, 1259 insertions(+)
 create mode 100644 clang/test/CodeGen/RISCV/rvv-xcvsimd-builtins.c

diff --git a/clang/test/CodeGen/RISCV/rvv-xcvsimd-builtins.c b/clang/test/CodeGen/RISCV/rvv-xcvsimd-builtins.c
new file mode 100644
index 0000000000000..5e163c81d36d4
--- /dev/null
+++ b/clang/test/CodeGen/RISCV/rvv-xcvsimd-builtins.c
@@ -0,0 +1,1219 @@
+// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py
+// RUN: %clang_cc1 -triple riscv32 -target-feature +xcvsimd -emit-llvm %s -o - \
+// RUN:   | FileCheck %s
+
+// This file tests that XCVsimd Clang builtins are correctly lowered
+// to their corresponding LLVM IR intrinsics.
+
+#include <stdint.h>
+
+// ===== ADD / SUB =====
+
+// CHECK-LABEL: @test_add_h(
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:    [[A_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    [[B_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    store i32 [[A:%.*]], ptr [[A_ADDR]], align 4
+// CHECK-NEXT:    store i32 [[B:%.*]], ptr [[B_ADDR]], align 4
+// CHECK-NEXT:    [[TMP0:%.*]] = load i32, ptr [[A_ADDR]], align 4
+// CHECK-NEXT:    [[TMP1:%.*]] = load i32, ptr [[B_ADDR]], align 4
+// CHECK-NEXT:    [[TMP2:%.*]] = call i32 @llvm.riscv.cv.simd.add.h(i32 [[TMP0]], i32 [[TMP1]], i32 0)
+// CHECK-NEXT:    ret i32 [[TMP2]]
+//
+uint32_t test_add_h(uint32_t a, uint32_t b) {
+  return __builtin_riscv_cv_simd_add_h(a, b, 0);
+}
+
+// CHECK-LABEL: @test_add_h_div2(
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:    [[A_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    [[B_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    store i32 [[A:%.*]], ptr [[A_ADDR]], align 4
+// CHECK-NEXT:    store i32 [[B:%.*]], ptr [[B_ADDR]], align 4
+// CHECK-NEXT:    [[TMP0:%.*]] = load i32, ptr [[A_ADDR]], align 4
+// CHECK-NEXT:    [[TMP1:%.*]] = load i32, ptr [[B_ADDR]], align 4
+// CHECK-NEXT:    [[TMP2:%.*]] = call i32 @llvm.riscv.cv.simd.add.h(i32 [[TMP0]], i32 [[TMP1]], i32 1)
+// CHECK-NEXT:    ret i32 [[TMP2]]
+//
+uint32_t test_add_h_div2(uint32_t a, uint32_t b) {
+  return __builtin_riscv_cv_simd_add_h(a, b, 1);
+}
+
+// CHECK-LABEL: @test_add_b(
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:    [[A_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    [[B_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    store i32 [[A:%.*]], ptr [[A_ADDR]], align 4
+// CHECK-NEXT:    store i32 [[B:%.*]], ptr [[B_ADDR]], align 4
+// CHECK-NEXT:    [[TMP0:%.*]] = load i32, ptr [[A_ADDR]], align 4
+// CHECK-NEXT:    [[TMP1:%.*]] = load i32, ptr [[B_ADDR]], align 4
+// CHECK-NEXT:    [[TMP2:%.*]] = call i32 @llvm.riscv.cv.simd.add.b(i32 [[TMP0]], i32 [[TMP1]])
+// CHECK-NEXT:    ret i32 [[TMP2]]
+//
+uint32_t test_add_b(uint32_t a, uint32_t b) {
+  return __builtin_riscv_cv_simd_add_b(a, b);
+}
+
+// CHECK-LABEL: @test_add_sc_h(
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:    [[A_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    [[B_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    store i32 [[A:%.*]], ptr [[A_ADDR]], align 4
+// CHECK-NEXT:    store i32 [[B:%.*]], ptr [[B_ADDR]], align 4
+// CHECK-NEXT:    [[TMP0:%.*]] = load i32, ptr [[A_ADDR]], align 4
+// CHECK-NEXT:    [[TMP1:%.*]] = load i32, ptr [[B_ADDR]], align 4
+// CHECK-NEXT:    [[TMP2:%.*]] = call i32 @llvm.riscv.cv.simd.add.sc.h(i32 [[TMP0]], i32 [[TMP1]])
+// CHECK-NEXT:    ret i32 [[TMP2]]
+//
+uint32_t test_add_sc_h(uint32_t a, uint32_t b) {
+  return __builtin_riscv_cv_simd_add_sc_h(a, b);
+}
+
+// CHECK-LABEL: @test_add_sc_b(
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:    [[A_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    [[B_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    store i32 [[A:%.*]], ptr [[A_ADDR]], align 4
+// CHECK-NEXT:    store i32 [[B:%.*]], ptr [[B_ADDR]], align 4
+// CHECK-NEXT:    [[TMP0:%.*]] = load i32, ptr [[A_ADDR]], align 4
+// CHECK-NEXT:    [[TMP1:%.*]] = load i32, ptr [[B_ADDR]], align 4
+// CHECK-NEXT:    [[TMP2:%.*]] = call i32 @llvm.riscv.cv.simd.add.sc.b(i32 [[TMP0]], i32 [[TMP1]])
+// CHECK-NEXT:    ret i32 [[TMP2]]
+//
+uint32_t test_add_sc_b(uint32_t a, uint32_t b) {
+  return __builtin_riscv_cv_simd_add_sc_b(a, b);
+}
+
+// CHECK-LABEL: @test_sub_h(
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:    [[A_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    [[B_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    store i32 [[A:%.*]], ptr [[A_ADDR]], align 4
+// CHECK-NEXT:    store i32 [[B:%.*]], ptr [[B_ADDR]], align 4
+// CHECK-NEXT:    [[TMP0:%.*]] = load i32, ptr [[A_ADDR]], align 4
+// CHECK-NEXT:    [[TMP1:%.*]] = load i32, ptr [[B_ADDR]], align 4
+// CHECK-NEXT:    [[TMP2:%.*]] = call i32 @llvm.riscv.cv.simd.sub.h(i32 [[TMP0]], i32 [[TMP1]], i32 0)
+// CHECK-NEXT:    ret i32 [[TMP2]]
+//
+uint32_t test_sub_h(uint32_t a, uint32_t b) {
+  return __builtin_riscv_cv_simd_sub_h(a, b, 0);
+}
+
+// CHECK-LABEL: @test_sub_b(
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:    [[A_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    [[B_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    store i32 [[A:%.*]], ptr [[A_ADDR]], align 4
+// CHECK-NEXT:    store i32 [[B:%.*]], ptr [[B_ADDR]], align 4
+// CHECK-NEXT:    [[TMP0:%.*]] = load i32, ptr [[A_ADDR]], align 4
+// CHECK-NEXT:    [[TMP1:%.*]] = load i32, ptr [[B_ADDR]], align 4
+// CHECK-NEXT:    [[TMP2:%.*]] = call i32 @llvm.riscv.cv.simd.sub.b(i32 [[TMP0]], i32 [[TMP1]])
+// CHECK-NEXT:    ret i32 [[TMP2]]
+//
+uint32_t test_sub_b(uint32_t a, uint32_t b) {
+  return __builtin_riscv_cv_simd_sub_b(a, b);
+}
+
+// CHECK-LABEL: @test_sub_sc_h(
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:    [[A_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    [[B_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    store i32 [[A:%.*]], ptr [[A_ADDR]], align 4
+// CHECK-NEXT:    store i32 [[B:%.*]], ptr [[B_ADDR]], align 4
+// CHECK-NEXT:    [[TMP0:%.*]] = load i32, ptr [[A_ADDR]], align 4
+// CHECK-NEXT:    [[TMP1:%.*]] = load i32, ptr [[B_ADDR]], align 4
+// CHECK-NEXT:    [[TMP2:%.*]] = call i32 @llvm.riscv.cv.simd.sub.sc.h(i32 [[TMP0]], i32 [[TMP1]])
+// CHECK-NEXT:    ret i32 [[TMP2]]
+//
+uint32_t test_sub_sc_h(uint32_t a, uint32_t b) {
+  return __builtin_riscv_cv_simd_sub_sc_h(a, b);
+}
+
+// CHECK-LABEL: @test_sub_sc_b(
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:    [[A_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    [[B_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    store i32 [[A:%.*]], ptr [[A_ADDR]], align 4
+// CHECK-NEXT:    store i32 [[B:%.*]], ptr [[B_ADDR]], align 4
+// CHECK-NEXT:    [[TMP0:%.*]] = load i32, ptr [[A_ADDR]], align 4
+// CHECK-NEXT:    [[TMP1:%.*]] = load i32, ptr [[B_ADDR]], align 4
+// CHECK-NEXT:    [[TMP2:%.*]] = call i32 @llvm.riscv.cv.simd.sub.sc.b(i32 [[TMP0]], i32 [[TMP1]])
+// CHECK-NEXT:    ret i32 [[TMP2]]
+//
+uint32_t test_sub_sc_b(uint32_t a, uint32_t b) {
+  return __builtin_riscv_cv_simd_sub_sc_b(a, b);
+}
+
+// ===== AVG / AVGU =====
+
+// CHECK-LABEL: @test_avg_h(
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:    [[A_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    [[B_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    store i32 [[A:%.*]], ptr [[A_ADDR]], align 4
+// CHECK-NEXT:    store i32 [[B:%.*]], ptr [[B_ADDR]], align 4
+// CHECK-NEXT:    [[TMP0:%.*]] = load i32, ptr [[A_ADDR]], align 4
+// CHECK-NEXT:    [[TMP1:%.*]] = load i32, ptr [[B_ADDR]], align 4
+// CHECK-NEXT:    [[TMP2:%.*]] = call i32 @llvm.riscv.cv.simd.avg.h(i32 [[TMP0]], i32 [[TMP1]])
+// CHECK-NEXT:    ret i32 [[TMP2]]
+//
+uint32_t test_avg_h(uint32_t a, uint32_t b) {
+  return __builtin_riscv_cv_simd_avg_h(a, b);
+}
+
+// CHECK-LABEL: @test_avg_b(
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:    [[A_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    [[B_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    store i32 [[A:%.*]], ptr [[A_ADDR]], align 4
+// CHECK-NEXT:    store i32 [[B:%.*]], ptr [[B_ADDR]], align 4
+// CHECK-NEXT:    [[TMP0:%.*]] = load i32, ptr [[A_ADDR]], align 4
+// CHECK-NEXT:    [[TMP1:%.*]] = load i32, ptr [[B_ADDR]], align 4
+// CHECK-NEXT:    [[TMP2:%.*]] = call i32 @llvm.riscv.cv.simd.avg.b(i32 [[TMP0]], i32 [[TMP1]])
+// CHECK-NEXT:    ret i32 [[TMP2]]
+//
+uint32_t test_avg_b(uint32_t a, uint32_t b) {
+  return __builtin_riscv_cv_simd_avg_b(a, b);
+}
+
+// CHECK-LABEL: @test_avg_sc_h(
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:    [[A_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    [[B_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    store i32 [[A:%.*]], ptr [[A_ADDR]], align 4
+// CHECK-NEXT:    store i32 [[B:%.*]], ptr [[B_ADDR]], align 4
+// CHECK-NEXT:    [[TMP0:%.*]] = load i32, ptr [[A_ADDR]], align 4
+// CHECK-NEXT:    [[TMP1:%.*]] = load i32, ptr [[B_ADDR]], align 4
+// CHECK-NEXT:    [[TMP2:%.*]] = call i32 @llvm.riscv.cv.simd.avg.sc.h(i32 [[TMP0]], i32 [[TMP1]])
+// CHECK-NEXT:    ret i32 [[TMP2]]
+//
+uint32_t test_avg_sc_h(uint32_t a, uint32_t b) {
+  return __builtin_riscv_cv_simd_avg_sc_h(a, b);
+}
+
+// CHECK-LABEL: @test_avg_sc_b(
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:    [[A_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    [[B_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    store i32 [[A:%.*]], ptr [[A_ADDR]], align 4
+// CHECK-NEXT:    store i32 [[B:%.*]], ptr [[B_ADDR]], align 4
+// CHECK-NEXT:    [[TMP0:%.*]] = load i32, ptr [[A_ADDR]], align 4
+// CHECK-NEXT:    [[TMP1:%.*]] = load i32, ptr [[B_ADDR]], align 4
+// CHECK-NEXT:    [[TMP2:%.*]] = call i32 @llvm.riscv.cv.simd.avg.sc.b(i32 [[TMP0]], i32 [[TMP1]])
+// CHECK-NEXT:    ret i32 [[TMP2]]
+//
+uint32_t test_avg_sc_b(uint32_t a, uint32_t b) {
+  return __builtin_riscv_cv_simd_avg_sc_b(a, b);
+}
+
+// CHECK-LABEL: @test_avgu_h(
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:    [[A_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    [[B_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    store i32 [[A:%.*]], ptr [[A_ADDR]], align 4
+// CHECK-NEXT:    store i32 [[B:%.*]], ptr [[B_ADDR]], align 4
+// CHECK-NEXT:    [[TMP0:%.*]] = load i32, ptr [[A_ADDR]], align 4
+// CHECK-NEXT:    [[TMP1:%.*]] = load i32, ptr [[B_ADDR]], align 4
+// CHECK-NEXT:    [[TMP2:%.*]] = call i32 @llvm.riscv.cv.simd.avgu.h(i32 [[TMP0]], i32 [[TMP1]])
+// CHECK-NEXT:    ret i32 [[TMP2]]
+//
+uint32_t test_avgu_h(uint32_t a, uint32_t b) {
+  return __builtin_riscv_cv_simd_avgu_h(a, b);
+}
+
+// CHECK-LABEL: @test_avgu_b(
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:    [[A_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    [[B_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    store i32 [[A:%.*]], ptr [[A_ADDR]], align 4
+// CHECK-NEXT:    store i32 [[B:%.*]], ptr [[B_ADDR]], align 4
+// CHECK-NEXT:    [[TMP0:%.*]] = load i32, ptr [[A_ADDR]], align 4
+// CHECK-NEXT:    [[TMP1:%.*]] = load i32, ptr [[B_ADDR]], align 4
+// CHECK-NEXT:    [[TMP2:%.*]] = call i32 @llvm.riscv.cv.simd.avgu.b(i32 [[TMP0]], i32 [[TMP1]])
+// CHECK-NEXT:    ret i32 [[TMP2]]
+//
+uint32_t test_avgu_b(uint32_t a, uint32_t b) {
+  return __builtin_riscv_cv_simd_avgu_b(a, b);
+}
+
+// CHECK-LABEL: @test_avgu_sc_h(
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:    [[A_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    [[B_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    store i32 [[A:%.*]], ptr [[A_ADDR]], align 4
+// CHECK-NEXT:    store i32 [[B:%.*]], ptr [[B_ADDR]], align 4
+// CHECK-NEXT:    [[TMP0:%.*]] = load i32, ptr [[A_ADDR]], align 4
+// CHECK-NEXT:    [[TMP1:%.*]] = load i32, ptr [[B_ADDR]], align 4
+// CHECK-NEXT:    [[TMP2:%.*]] = call i32 @llvm.riscv.cv.simd.avgu.sc.h(i32 [[TMP0]], i32 [[TMP1]])
+// CHECK-NEXT:    ret i32 [[TMP2]]
+//
+uint32_t test_avgu_sc_h(uint32_t a, uint32_t b) {
+  return __builtin_riscv_cv_simd_avgu_sc_h(a, b);
+}
+
+// CHECK-LABEL: @test_avgu_sc_b(
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:    [[A_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    [[B_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    store i32 [[A:%.*]], ptr [[A_ADDR]], align 4
+// CHECK-NEXT:    store i32 [[B:%.*]], ptr [[B_ADDR]], align 4
+// CHECK-NEXT:    [[TMP0:%.*]] = load i32, ptr [[A_ADDR]], align 4
+// CHECK-NEXT:    [[TMP1:%.*]] = load i32, ptr [[B_ADDR]], align 4
+// CHECK-NEXT:    [[TMP2:%.*]] = call i32 @llvm.riscv.cv.simd.avgu.sc.b(i32 [[TMP0]], i32 [[TMP1]])
+// CHECK-NEXT:    ret i32 [[TMP2]]
+//
+uint32_t test_avgu_sc_b(uint32_t a, uint32_t b) {
+  return __builtin_riscv_cv_simd_avgu_sc_b(a, b);
+}
+
+// ===== MIN / MINU / MAX / MAXU (representative) =====
+
+// CHECK-LABEL: @test_min_h(
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:    [[A_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    [[B_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    store i32 [[A:%.*]], ptr [[A_ADDR]], align 4
+// CHECK-NEXT:    store i32 [[B:%.*]], ptr [[B_ADDR]], align 4
+// CHECK-NEXT:    [[TMP0:%.*]] = load i32, ptr [[A_ADDR]], align 4
+// CHECK-NEXT:    [[TMP1:%.*]] = load i32, ptr [[B_ADDR]], align 4
+// CHECK-NEXT:    [[TMP2:%.*]] = call i32 @llvm.riscv.cv.simd.min.h(i32 [[TMP0]], i32 [[TMP1]])
+// CHECK-NEXT:    ret i32 [[TMP2]]
+//
+uint32_t test_min_h(uint32_t a, uint32_t b) {
+  return __builtin_riscv_cv_simd_min_h(a, b);
+}
+
+// CHECK-LABEL: @test_min_b(
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:    [[A_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    [[B_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    store i32 [[A:%.*]], ptr [[A_ADDR]], align 4
+// CHECK-NEXT:    store i32 [[B:%.*]], ptr [[B_ADDR]], align 4
+// CHECK-NEXT:    [[TMP0:%.*]] = load i32, ptr [[A_ADDR]], align 4
+// CHECK-NEXT:    [[TMP1:%.*]] = load i32, ptr [[B_ADDR]], align 4
+// CHECK-NEXT:    [[TMP2:%.*]] = call i32 @llvm.riscv.cv.simd.min.b(i32 [[TMP0]], i32 [[TMP1]])
+// CHECK-NEXT:    ret i32 [[TMP2]]
+//
+uint32_t test_min_b(uint32_t a, uint32_t b) {
+  return __builtin_riscv_cv_simd_min_b(a, b);
+}
+
+// CHECK-LABEL: @test_min_sc_h(
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:    [[A_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    [[B_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    store i32 [[A:%.*]], ptr [[A_ADDR]], align 4
+// CHECK-NEXT:    store i32 [[B:%.*]], ptr [[B_ADDR]], align 4
+// CHECK-NEXT:    [[TMP0:%.*]] = load i32, ptr [[A_ADDR]], align 4
+// CHECK-NEXT:    [[TMP1:%.*]] = load i32, ptr [[B_ADDR]], align 4
+// CHECK-NEXT:    [[TMP2:%.*]] = call i32 @llvm.riscv.cv.simd.min.sc.h(i32 [[TMP0]], i32 [[TMP1]])
+// CHECK-NEXT:    ret i32 [[TMP2]]
+//
+uint32_t test_min_sc_h(uint32_t a, uint32_t b) {
+  return __builtin_riscv_cv_simd_min_sc_h(a, b);
+}
+
+// CHECK-LABEL: @test_min_sc_b(
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:    [[A_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    [[B_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    store i32 [[A:%.*]], ptr [[A_ADDR]], align 4
+// CHECK-NEXT:    store i32 [[B:%.*]], ptr [[B_ADDR]], align 4
+// CHECK-NEXT:    [[TMP0:%.*]] = load i32, ptr [[A_ADDR]], align 4
+// CHECK-NEXT:    [[TMP1:%.*]] = load i32, ptr [[B_ADDR]], align 4
+// CHECK-NEXT:    [[TMP2:%.*]] = call i32 @llvm.riscv.cv.simd.min.sc.b(i32 [[TMP0]], i32 [[TMP1]])
+// CHECK-NEXT:    ret i32 [[TMP2]]
+//
+uint32_t test_min_sc_b(uint32_t a, uint32_t b) {
+  return __builtin_riscv_cv_simd_min_sc_b(a, b);
+}
+
+// CHECK-LABEL: @test_minu_h(
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:    [[A_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    [[B_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    store i32 [[A:%.*]], ptr [[A_ADDR]], align 4
+// CHECK-NEXT:    store i32 [[B:%.*]], ptr [[B_ADDR]], align 4
+// CHECK-NEXT:    [[TMP0:%.*]] = load i32, ptr [[A_ADDR]], align 4
+// CHECK-NEXT:    [[TMP1:%.*]] = load i32, ptr [[B_ADDR]], align 4
+// CHECK-NEXT:    [[TMP2:%.*]] = call i32 @llvm.riscv.cv.simd.minu.h(i32 [[TMP0]], i32 [[TMP1]])
+// CHECK-NEXT:    ret i32 [[TMP2]]
+//
+uint32_t test_minu_h(uint32_t a, uint32_t b) {
+  return __builtin_riscv_cv_simd_minu_h(a, b);
+}
+
+// CHECK-LABEL: @test_max_h(
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:    [[A_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    [[B_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    store i32 [[A:%.*]], ptr [[A_ADDR]], align 4
+// CHECK-NEXT:    store i32 [[B:%.*]], ptr [[B_ADDR]], align 4
+// CHECK-NEXT:    [[TMP0:%.*]] = load i32, ptr [[A_ADDR]], align 4
+// CHECK-NEXT:    [[TMP1:%.*]] = load i32, ptr [[B_ADDR]], align 4
+// CHECK-NEXT:    [[TMP2:%.*]] = call i32 @llvm.riscv.cv.simd.max.h(i32 [[TMP0]], i32 [[TMP1]])
+// CHECK-NEXT:    ret i32 [[TMP2]]
+//
+uint32_t test_max_h(uint32_t a, uint32_t b) {
+  return __builtin_riscv_cv_simd_max_h(a, b);
+}
+
+// CHECK-LABEL: @test_maxu_h(
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:    [[A_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    [[B_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    store i32 [[A:%.*]], ptr [[A_ADDR]], align 4
+// CHECK-NEXT:    store i32 [[B:%.*]], ptr [[B_ADDR]], align 4
+// CHECK-NEXT:    [[TMP0:%.*]] = load i32, ptr [[A_ADDR]], align 4
+// CHECK-NEXT:    [[TMP1:%.*]] = load i32, ptr [[B_ADDR]], align 4
+// CHECK-NEXT:    [[TMP2:%.*]] = call i32 @llvm.riscv.cv.simd.maxu.h(i32 [[TMP0]], i32 [[TMP1]])
+// CHECK-NEXT:    ret i32 [[TMP2]]
+//
+uint32_t test_maxu_h(uint32_t a, uint32_t b) {
+  return __builtin_riscv_cv_simd_maxu_h(a, b);
+}
+
+// ===== SRL / SRA / SLL (representative) =====
+
+// CHECK-LABEL: @test_srl_h(
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:    [[A_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    [[B_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    store i32 [[A:%.*]], ptr [[A_ADDR]], align 4
+// CHECK-NEXT:    store i32 [[B:%.*]], ptr [[B_ADDR]], align 4
+// CHECK-NEXT:    [[TMP0:%.*]] = load i32, ptr [[A_ADDR]], align 4
+// CHECK-NEXT:    [[TMP1:%.*]] = load i32, ptr [[B_ADDR]], align 4
+// CHECK-NEXT:    [[TMP2:%.*]] = call i32 @llvm.riscv.cv.simd.srl.h(i32 [[TMP0]], i32 [[TMP1]])
+// CHECK-NEXT:    ret i32 [[TMP2]]
+//
+uint32_t test_srl_h(uint32_t a, uint32_t b) {
+  return __builtin_riscv_cv_simd_srl_h(a, b);
+}
+
+// CHECK-LABEL: @test_sra_h(
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:    [[A_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    [[B_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    store i32 [[A:%.*]], ptr [[A_ADDR]], align 4
+// CHECK-NEXT:    store i32 [[B:%.*]], ptr [[B_ADDR]], align 4
+// CHECK-NEXT:    [[TMP0:%.*]] = load i32, ptr [[A_ADDR]], align 4
+// CHECK-NEXT:    [[TMP1:%.*]] = load i32, ptr [[B_ADDR]], align 4
+// CHECK-NEXT:    [[TMP2:%.*]] = call i32 @llvm.riscv.cv.simd.sra.h(i32 [[TMP0]], i32 [[TMP1]])
+// CHECK-NEXT:    ret i32 [[TMP2]]
+//
+uint32_t test_sra_h(uint32_t a, uint32_t b) {
+  return __builtin_riscv_cv_simd_sra_h(a, b);
+}
+
+// CHECK-LABEL: @test_sll_h(
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:    [[A_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    [[B_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    store i32 [[A:%.*]], ptr [[A_ADDR]], align 4
+// CHECK-NEXT:    store i32 [[B:%.*]], ptr [[B_ADDR]], align 4
+// CHECK-NEXT:    [[TMP0:%.*]] = load i32, ptr [[A_ADDR]], align 4
+// CHECK-NEXT:    [[TMP1:%.*]] = load i32, ptr [[B_ADDR]], align 4
+// CHECK-NEXT:    [[TMP2:%.*]] = call i32 @llvm.riscv.cv.simd.sll.h(i32 [[TMP0]], i32 [[TMP1]])
+// CHECK-NEXT:    ret i32 [[TMP2]]
+//
+uint32_t test_sll_h(uint32_t a, uint32_t b) {
+  return __builtin_riscv_cv_simd_sll_h(a, b);
+}
+
+// CHECK-LABEL: @test_srl_sc_b(
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:    [[A_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    [[B_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    store i32 [[A:%.*]], ptr [[A_ADDR]], align 4
+// CHECK-NEXT:    store i32 [[B:%.*]], ptr [[B_ADDR]], align 4
+// CHECK-NEXT:    [[TMP0:%.*]] = load i32, ptr [[A_ADDR]], align 4
+// CHECK-NEXT:    [[TMP1:%.*]] = load i32, ptr [[B_ADDR]], align 4
+// CHECK-NEXT:    [[TMP2:%.*]] = call i32 @llvm.riscv.cv.simd.srl.sc.b(i32 [[TMP0]], i32 [[TMP1]])
+// CHECK-NEXT:    ret i32 [[TMP2]]
+//
+uint32_t test_srl_sc_b(uint32_t a, uint32_t b) {
+  return __builtin_riscv_cv_simd_srl_sc_b(a, b);
+}
+
+// ===== OR / XOR / AND (representative) =====
+
+// CHECK-LABEL: @test_or_h(
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:    [[A_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    [[B_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    store i32 [[A:%.*]], ptr [[A_ADDR]], align 4
+// CHECK-NEXT:    store i32 [[B:%.*]], ptr [[B_ADDR]], align 4
+// CHECK-NEXT:    [[TMP0:%.*]] = load i32, ptr [[A_ADDR]], align 4
+// CHECK-NEXT:    [[TMP1:%.*]] = load i32, ptr [[B_ADDR]], align 4
+// CHECK-NEXT:    [[TMP2:%.*]] = call i32 @llvm.riscv.cv.simd.or.h(i32 [[TMP0]], i32 [[TMP1]])
+// CHECK-NEXT:    ret i32 [[TMP2]]
+//
+uint32_t test_or_h(uint32_t a, uint32_t b) {
+  return __builtin_riscv_cv_simd_or_h(a, b);
+}
+
+// CHECK-LABEL: @test_xor_h(
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:    [[A_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    [[B_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    store i32 [[A:%.*]], ptr [[A_ADDR]], align 4
+// CHECK-NEXT:    store i32 [[B:%.*]], ptr [[B_ADDR]], align 4
+// CHECK-NEXT:    [[TMP0:%.*]] = load i32, ptr [[A_ADDR]], align 4
+// CHECK-NEXT:    [[TMP1:%.*]] = load i32, ptr [[B_ADDR]], align 4
+// CHECK-NEXT:    [[TMP2:%.*]] = call i32 @llvm.riscv.cv.simd.xor.h(i32 [[TMP0]], i32 [[TMP1]])
+// CHECK-NEXT:    ret i32 [[TMP2]]
+//
+uint32_t test_xor_h(uint32_t a, uint32_t b) {
+  return __builtin_riscv_cv_simd_xor_h(a, b);
+}
+
+// CHECK-LABEL: @test_and_h(
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:    [[A_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    [[B_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    store i32 [[A:%.*]], ptr [[A_ADDR]], align 4
+// CHECK-NEXT:    store i32 [[B:%.*]], ptr [[B_ADDR]], align 4
+// CHECK-NEXT:    [[TMP0:%.*]] = load i32, ptr [[A_ADDR]], align 4
+// CHECK-NEXT:    [[TMP1:%.*]] = load i32, ptr [[B_ADDR]], align 4
+// CHECK-NEXT:    [[TMP2:%.*]] = call i32 @llvm.riscv.cv.simd.and.h(i32 [[TMP0]], i32 [[TMP1]])
+// CHECK-NEXT:    ret i32 [[TMP2]]
+//
+uint32_t test_and_h(uint32_t a, uint32_t b) {
+  return __builtin_riscv_cv_simd_and_h(a, b);
+}
+
+// ===== ABS =====
+
+// CHECK-LABEL: @test_abs_h(
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:    [[A_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    store i32 [[A:%.*]], ptr [[A_ADDR]], align 4
+// CHECK-NEXT:    [[TMP0:%.*]] = load i32, ptr [[A_ADDR]], align 4
+// CHECK-NEXT:    [[TMP1:%.*]] = call i32 @llvm.riscv.cv.simd.abs.h(i32 [[TMP0]])
+// CHECK-NEXT:    ret i32 [[TMP1]]
+//
+uint32_t test_abs_h(uint32_t a) {
+  return __builtin_riscv_cv_simd_abs_h(a);
+}
+
+// CHECK-LABEL: @test_abs_b(
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:    [[A_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    store i32 [[A:%.*]], ptr [[A_ADDR]], align 4
+// CHECK-NEXT:    [[TMP0:%.*]] = load i32, ptr [[A_ADDR]], align 4
+// CHECK-NEXT:    [[TMP1:%.*]] = call i32 @llvm.riscv.cv.simd.abs.b(i32 [[TMP0]])
+// CHECK-NEXT:    ret i32 [[TMP1]]
+//
+uint32_t test_abs_b(uint32_t a) {
+  return __builtin_riscv_cv_simd_abs_b(a);
+}
+
+// ===== DOT PRODUCTS =====
+
+// CHECK-LABEL: @test_dotup_h(
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:    [[A_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    [[B_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    store i32 [[A:%.*]], ptr [[A_ADDR]], align 4
+// CHECK-NEXT:    store i32 [[B:%.*]], ptr [[B_ADDR]], align 4
+// CHECK-NEXT:    [[TMP0:%.*]] = load i32, ptr [[A_ADDR]], align 4
+// CHECK-NEXT:    [[TMP1:%.*]] = load i32, ptr [[B_ADDR]], align 4
+// CHECK-NEXT:    [[TMP2:%.*]] = call i32 @llvm.riscv.cv.simd.dotup.h(i32 [[TMP0]], i32 [[TMP1]])
+// CHECK-NEXT:    ret i32 [[TMP2]]
+//
+uint32_t test_dotup_h(uint32_t a, uint32_t b) {
+  return __builtin_riscv_cv_simd_dotup_h(a, b);
+}
+
+// CHECK-LABEL: @test_dotup_b(
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:    [[A_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    [[B_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    store i32 [[A:%.*]], ptr [[A_ADDR]], align 4
+// CHECK-NEXT:    store i32 [[B:%.*]], ptr [[B_ADDR]], align 4
+// CHECK-NEXT:    [[TMP0:%.*]] = load i32, ptr [[A_ADDR]], align 4
+// CHECK-NEXT:    [[TMP1:%.*]] = load i32, ptr [[B_ADDR]], align 4
+// CHECK-NEXT:    [[TMP2:%.*]] = call i32 @llvm.riscv.cv.simd.dotup.b(i32 [[TMP0]], i32 [[TMP1]])
+// CHECK-NEXT:    ret i32 [[TMP2]]
+//
+uint32_t test_dotup_b(uint32_t a, uint32_t b) {
+  return __builtin_riscv_cv_simd_dotup_b(a, b);
+}
+
+// CHECK-LABEL: @test_dotup_sc_h(
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:    [[A_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    [[B_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    store i32 [[A:%.*]], ptr [[A_ADDR]], align 4
+// CHECK-NEXT:    store i32 [[B:%.*]], ptr [[B_ADDR]], align 4
+// CHECK-NEXT:    [[TMP0:%.*]] = load i32, ptr [[A_ADDR]], align 4
+// CHECK-NEXT:    [[TMP1:%.*]] = load i32, ptr [[B_ADDR]], align 4
+// CHECK-NEXT:    [[TMP2:%.*]] = call i32 @llvm.riscv.cv.simd.dotup.sc.h(i32 [[TMP0]], i32 [[TMP1]])
+// CHECK-NEXT:    ret i32 [[TMP2]]
+//
+uint32_t test_dotup_sc_h(uint32_t a, uint32_t b) {
+  return __builtin_riscv_cv_simd_dotup_sc_h(a, b);
+}
+
+// CHECK-LABEL: @test_dotusp_h(
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:    [[A_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    [[B_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    store i32 [[A:%.*]], ptr [[A_ADDR]], align 4
+// CHECK-NEXT:    store i32 [[B:%.*]], ptr [[B_ADDR]], align 4
+// CHECK-NEXT:    [[TMP0:%.*]] = load i32, ptr [[A_ADDR]], align 4
+// CHECK-NEXT:    [[TMP1:%.*]] = load i32, ptr [[B_ADDR]], align 4
+// CHECK-NEXT:    [[TMP2:%.*]] = call i32 @llvm.riscv.cv.simd.dotusp.h(i32 [[TMP0]], i32 [[TMP1]])
+// CHECK-NEXT:    ret i32 [[TMP2]]
+//
+int32_t test_dotusp_h(uint32_t a, uint32_t b) {
+  return __builtin_riscv_cv_simd_dotusp_h(a, b);
+}
+
+// CHECK-LABEL: @test_dotsp_h(
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:    [[A_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    [[B_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    store i32 [[A:%.*]], ptr [[A_ADDR]], align 4
+// CHECK-NEXT:    store i32 [[B:%.*]], ptr [[B_ADDR]], align 4
+// CHECK-NEXT:    [[TMP0:%.*]] = load i32, ptr [[A_ADDR]], align 4
+// CHECK-NEXT:    [[TMP1:%.*]] = load i32, ptr [[B_ADDR]], align 4
+// CHECK-NEXT:    [[TMP2:%.*]] = call i32 @llvm.riscv.cv.simd.dotsp.h(i32 [[TMP0]], i32 [[TMP1]])
+// CHECK-NEXT:    ret i32 [[TMP2]]
+//
+int32_t test_dotsp_h(uint32_t a, uint32_t b) {
+  return __builtin_riscv_cv_simd_dotsp_h(a, b);
+}
+
+// ===== SDOT (accumulating) =====
+
+// CHECK-LABEL: @test_sdotup_h(
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:    [[A_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    [[B_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    [[ACC_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    store i32 [[A:%.*]], ptr [[A_ADDR]], align 4
+// CHECK-NEXT:    store i32 [[B:%.*]], ptr [[B_ADDR]], align 4
+// CHECK-NEXT:    store i32 [[ACC:%.*]], ptr [[ACC_ADDR]], align 4
+// CHECK-NEXT:    [[TMP0:%.*]] = load i32, ptr [[A_ADDR]], align 4
+// CHECK-NEXT:    [[TMP1:%.*]] = load i32, ptr [[B_ADDR]], align 4
+// CHECK-NEXT:    [[TMP2:%.*]] = load i32, ptr [[ACC_ADDR]], align 4
+// CHECK-NEXT:    [[TMP3:%.*]] = call i32 @llvm.riscv.cv.simd.sdotup.h(i32 [[TMP0]], i32 [[TMP1]], i32 [[TMP2]])
+// CHECK-NEXT:    ret i32 [[TMP3]]
+//
+uint32_t test_sdotup_h(uint32_t a, uint32_t b, uint32_t acc) {
+  return __builtin_riscv_cv_simd_sdotup_h(a, b, acc);
+}
+
+// CHECK-LABEL: @test_sdotup_b(
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:    [[A_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    [[B_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    [[ACC_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    store i32 [[A:%.*]], ptr [[A_ADDR]], align 4
+// CHECK-NEXT:    store i32 [[B:%.*]], ptr [[B_ADDR]], align 4
+// CHECK-NEXT:    store i32 [[ACC:%.*]], ptr [[ACC_ADDR]], align 4
+// CHECK-NEXT:    [[TMP0:%.*]] = load i32, ptr [[A_ADDR]], align 4
+// CHECK-NEXT:    [[TMP1:%.*]] = load i32, ptr [[B_ADDR]], align 4
+// CHECK-NEXT:    [[TMP2:%.*]] = load i32, ptr [[ACC_ADDR]], align 4
+// CHECK-NEXT:    [[TMP3:%.*]] = call i32 @llvm.riscv.cv.simd.sdotup.b(i32 [[TMP0]], i32 [[TMP1]], i32 [[TMP2]])
+// CHECK-NEXT:    ret i32 [[TMP3]]
+//
+uint32_t test_sdotup_b(uint32_t a, uint32_t b, uint32_t acc) {
+  return __builtin_riscv_cv_simd_sdotup_b(a, b, acc);
+}
+
+// CHECK-LABEL: @test_sdotusp_h(
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:    [[A_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    [[B_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    [[ACC_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    store i32 [[A:%.*]], ptr [[A_ADDR]], align 4
+// CHECK-NEXT:    store i32 [[B:%.*]], ptr [[B_ADDR]], align 4
+// CHECK-NEXT:    store i32 [[ACC:%.*]], ptr [[ACC_ADDR]], align 4
+// CHECK-NEXT:    [[TMP0:%.*]] = load i32, ptr [[A_ADDR]], align 4
+// CHECK-NEXT:    [[TMP1:%.*]] = load i32, ptr [[B_ADDR]], align 4
+// CHECK-NEXT:    [[TMP2:%.*]] = load i32, ptr [[ACC_ADDR]], align 4
+// CHECK-NEXT:    [[TMP3:%.*]] = call i32 @llvm.riscv.cv.simd.sdotusp.h(i32 [[TMP0]], i32 [[TMP1]], i32 [[TMP2]])
+// CHECK-NEXT:    ret i32 [[TMP3]]
+//
+int32_t test_sdotusp_h(uint32_t a, uint32_t b, int32_t acc) {
+  return __builtin_riscv_cv_simd_sdotusp_h(a, b, acc);
+}
+
+// CHECK-LABEL: @test_sdotsp_h(
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:    [[A_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    [[B_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    [[ACC_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    store i32 [[A:%.*]], ptr [[A_ADDR]], align 4
+// CHECK-NEXT:    store i32 [[B:%.*]], ptr [[B_ADDR]], align 4
+// CHECK-NEXT:    store i32 [[ACC:%.*]], ptr [[ACC_ADDR]], align 4
+// CHECK-NEXT:    [[TMP0:%.*]] = load i32, ptr [[A_ADDR]], align 4
+// CHECK-NEXT:    [[TMP1:%.*]] = load i32, ptr [[B_ADDR]], align 4
+// CHECK-NEXT:    [[TMP2:%.*]] = load i32, ptr [[ACC_ADDR]], align 4
+// CHECK-NEXT:    [[TMP3:%.*]] = call i32 @llvm.riscv.cv.simd.sdotsp.h(i32 [[TMP0]], i32 [[TMP1]], i32 [[TMP2]])
+// CHECK-NEXT:    ret i32 [[TMP3]]
+//
+int32_t test_sdotsp_h(uint32_t a, uint32_t b, int32_t acc) {
+  return __builtin_riscv_cv_simd_sdotsp_h(a, b, acc);
+}
+
+// CHECK-LABEL: @test_sdotsp_sc_h(
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:    [[A_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    [[B_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    [[ACC_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    store i32 [[A:%.*]], ptr [[A_ADDR]], align 4
+// CHECK-NEXT:    store i32 [[B:%.*]], ptr [[B_ADDR]], align 4
+// CHECK-NEXT:    store i32 [[ACC:%.*]], ptr [[ACC_ADDR]], align 4
+// CHECK-NEXT:    [[TMP0:%.*]] = load i32, ptr [[A_ADDR]], align 4
+// CHECK-NEXT:    [[TMP1:%.*]] = load i32, ptr [[B_ADDR]], align 4
+// CHECK-NEXT:    [[TMP2:%.*]] = load i32, ptr [[ACC_ADDR]], align 4
+// CHECK-NEXT:    [[TMP3:%.*]] = call i32 @llvm.riscv.cv.simd.sdotsp.sc.h(i32 [[TMP0]], i32 [[TMP1]], i32 [[TMP2]])
+// CHECK-NEXT:    ret i32 [[TMP3]]
+//
+int32_t test_sdotsp_sc_h(uint32_t a, uint32_t b, int32_t acc) {
+  return __builtin_riscv_cv_simd_sdotsp_sc_h(a, b, acc);
+}
+
+// CHECK-LABEL: @test_sdotsp_sc_b(
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:    [[A_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    [[B_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    [[ACC_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    store i32 [[A:%.*]], ptr [[A_ADDR]], align 4
+// CHECK-NEXT:    store i32 [[B:%.*]], ptr [[B_ADDR]], align 4
+// CHECK-NEXT:    store i32 [[ACC:%.*]], ptr [[ACC_ADDR]], align 4
+// CHECK-NEXT:    [[TMP0:%.*]] = load i32, ptr [[A_ADDR]], align 4
+// CHECK-NEXT:    [[TMP1:%.*]] = load i32, ptr [[B_ADDR]], align 4
+// CHECK-NEXT:    [[TMP2:%.*]] = load i32, ptr [[ACC_ADDR]], align 4
+// CHECK-NEXT:    [[TMP3:%.*]] = call i32 @llvm.riscv.cv.simd.sdotsp.sc.b(i32 [[TMP0]], i32 [[TMP1]], i32 [[TMP2]])
+// CHECK-NEXT:    ret i32 [[TMP3]]
+//
+int32_t test_sdotsp_sc_b(uint32_t a, uint32_t b, int32_t acc) {
+  return __builtin_riscv_cv_simd_sdotsp_sc_b(a, b, acc);
+}
+
+// ===== EXTRACT / EXTRACTU / INSERT =====
+
+// CHECK-LABEL: @test_extract_h(
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:    [[A_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    store i32 [[A:%.*]], ptr [[A_ADDR]], align 4
+// CHECK-NEXT:    [[TMP0:%.*]] = load i32, ptr [[A_ADDR]], align 4
+// CHECK-NEXT:    [[TMP1:%.*]] = call i32 @llvm.riscv.cv.simd.extract.h(i32 [[TMP0]], i32 1)
+// CHECK-NEXT:    ret i32 [[TMP1]]
+//
+int32_t test_extract_h(uint32_t a) {
+  return __builtin_riscv_cv_simd_extract_h(a, 1);
+}
+
+// CHECK-LABEL: @test_extract_b(
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:    [[A_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    store i32 [[A:%.*]], ptr [[A_ADDR]], align 4
+// CHECK-NEXT:    [[TMP0:%.*]] = load i32, ptr [[A_ADDR]], align 4
+// CHECK-NEXT:    [[TMP1:%.*]] = call i32 @llvm.riscv.cv.simd.extract.b(i32 [[TMP0]], i32 3)
+// CHECK-NEXT:    ret i32 [[TMP1]]
+//
+int32_t test_extract_b(uint32_t a) {
+  return __builtin_riscv_cv_simd_extract_b(a, 3);
+}
+
+// CHECK-LABEL: @test_extractu_h(
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:    [[A_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    store i32 [[A:%.*]], ptr [[A_ADDR]], align 4
+// CHECK-NEXT:    [[TMP0:%.*]] = load i32, ptr [[A_ADDR]], align 4
+// CHECK-NEXT:    [[TMP1:%.*]] = call i32 @llvm.riscv.cv.simd.extractu.h(i32 [[TMP0]], i32 0)
+// CHECK-NEXT:    ret i32 [[TMP1]]
+//
+uint32_t test_extractu_h(uint32_t a) {
+  return __builtin_riscv_cv_simd_extractu_h(a, 0);
+}
+
+// CHECK-LABEL: @test_extractu_b(
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:    [[A_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    store i32 [[A:%.*]], ptr [[A_ADDR]], align 4
+// CHECK-NEXT:    [[TMP0:%.*]] = load i32, ptr [[A_ADDR]], align 4
+// CHECK-NEXT:    [[TMP1:%.*]] = call i32 @llvm.riscv.cv.simd.extractu.b(i32 [[TMP0]], i32 2)
+// CHECK-NEXT:    ret i32 [[TMP1]]
+//
+uint32_t test_extractu_b(uint32_t a) {
+  return __builtin_riscv_cv_simd_extractu_b(a, 2);
+}
+
+// CHECK-LABEL: @test_insert_h(
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:    [[RD_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    [[RS1_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    store i32 [[RD:%.*]], ptr [[RD_ADDR]], align 4
+// CHECK-NEXT:    store i32 [[RS1:%.*]], ptr [[RS1_ADDR]], align 4
+// CHECK-NEXT:    [[TMP0:%.*]] = load i32, ptr [[RD_ADDR]], align 4
+// CHECK-NEXT:    [[TMP1:%.*]] = load i32, ptr [[RS1_ADDR]], align 4
+// CHECK-NEXT:    [[TMP2:%.*]] = call i32 @llvm.riscv.cv.simd.insert.h(i32 [[TMP0]], i32 [[TMP1]], i32 1)
+// CHECK-NEXT:    ret i32 [[TMP2]]
+//
+uint32_t test_insert_h(uint32_t rd, uint32_t rs1) {
+  return __builtin_riscv_cv_simd_insert_h(rd, rs1, 1);
+}
+
+// CHECK-LABEL: @test_insert_b(
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:    [[RD_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    [[RS1_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    store i32 [[RD:%.*]], ptr [[RD_ADDR]], align 4
+// CHECK-NEXT:    store i32 [[RS1:%.*]], ptr [[RS1_ADDR]], align 4
+// CHECK-NEXT:    [[TMP0:%.*]] = load i32, ptr [[RD_ADDR]], align 4
+// CHECK-NEXT:    [[TMP1:%.*]] = load i32, ptr [[RS1_ADDR]], align 4
+// CHECK-NEXT:    [[TMP2:%.*]] = call i32 @llvm.riscv.cv.simd.insert.b(i32 [[TMP0]], i32 [[TMP1]], i32 2)
+// CHECK-NEXT:    ret i32 [[TMP2]]
+//
+uint32_t test_insert_b(uint32_t rd, uint32_t rs1) {
+  return __builtin_riscv_cv_simd_insert_b(rd, rs1, 2);
+}
+
+// ===== SHUFFLE / SHUFFLE2 =====
+
+// CHECK-LABEL: @test_shuffle_h(
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:    [[A_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    [[MASK_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    store i32 [[A:%.*]], ptr [[A_ADDR]], align 4
+// CHECK-NEXT:    store i32 [[MASK:%.*]], ptr [[MASK_ADDR]], align 4
+// CHECK-NEXT:    [[TMP0:%.*]] = load i32, ptr [[A_ADDR]], align 4
+// CHECK-NEXT:    [[TMP1:%.*]] = load i32, ptr [[MASK_ADDR]], align 4
+// CHECK-NEXT:    [[TMP2:%.*]] = call i32 @llvm.riscv.cv.simd.shuffle.h(i32 [[TMP0]], i32 [[TMP1]])
+// CHECK-NEXT:    ret i32 [[TMP2]]
+//
+uint32_t test_shuffle_h(uint32_t a, uint32_t mask) {
+  return __builtin_riscv_cv_simd_shuffle_h(a, mask);
+}
+
+// CHECK-LABEL: @test_shuffle_b(
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:    [[A_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    [[MASK_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    store i32 [[A:%.*]], ptr [[A_ADDR]], align 4
+// CHECK-NEXT:    store i32 [[MASK:%.*]], ptr [[MASK_ADDR]], align 4
+// CHECK-NEXT:    [[TMP0:%.*]] = load i32, ptr [[A_ADDR]], align 4
+// CHECK-NEXT:    [[TMP1:%.*]] = load i32, ptr [[MASK_ADDR]], align 4
+// CHECK-NEXT:    [[TMP2:%.*]] = call i32 @llvm.riscv.cv.simd.shuffle.b(i32 [[TMP0]], i32 [[TMP1]])
+// CHECK-NEXT:    ret i32 [[TMP2]]
+//
+uint32_t test_shuffle_b(uint32_t a, uint32_t mask) {
+  return __builtin_riscv_cv_simd_shuffle_b(a, mask);
+}
+
+// CHECK-LABEL: @test_shuffle_sci_h(
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:    [[A_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    store i32 [[A:%.*]], ptr [[A_ADDR]], align 4
+// CHECK-NEXT:    [[TMP0:%.*]] = load i32, ptr [[A_ADDR]], align 4
+// CHECK-NEXT:    [[TMP1:%.*]] = call i32 @llvm.riscv.cv.simd.shuffle.sci.h(i32 [[TMP0]], i32 2)
+// CHECK-NEXT:    ret i32 [[TMP1]]
+//
+uint32_t test_shuffle_sci_h(uint32_t a) {
+  return __builtin_riscv_cv_simd_shuffle_sci_h(a, 2);
+}
+
+// CHECK-LABEL: @test_shuffle_sci_b(
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:    [[A_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    store i32 [[A:%.*]], ptr [[A_ADDR]], align 4
+// CHECK-NEXT:    [[TMP0:%.*]] = load i32, ptr [[A_ADDR]], align 4
+// CHECK-NEXT:    [[TMP1:%.*]] = call i32 @llvm.riscv.cv.simd.shuffle.sci.b(i32 [[TMP0]], i32 69)
+// CHECK-NEXT:    ret i32 [[TMP1]]
+//
+uint32_t test_shuffle_sci_b(uint32_t a) {
+  return __builtin_riscv_cv_simd_shuffle_sci_b(a, 69);
+}
+
+// CHECK-LABEL: @test_shuffle2_h(
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:    [[RS1_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    [[RS2_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    [[RD_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    store i32 [[RS1:%.*]], ptr [[RS1_ADDR]], align 4
+// CHECK-NEXT:    store i32 [[RS2:%.*]], ptr [[RS2_ADDR]], align 4
+// CHECK-NEXT:    store i32 [[RD:%.*]], ptr [[RD_ADDR]], align 4
+// CHECK-NEXT:    [[TMP0:%.*]] = load i32, ptr [[RS1_ADDR]], align 4
+// CHECK-NEXT:    [[TMP1:%.*]] = load i32, ptr [[RS2_ADDR]], align 4
+// CHECK-NEXT:    [[TMP2:%.*]] = load i32, ptr [[RD_ADDR]], align 4
+// CHECK-NEXT:    [[TMP3:%.*]] = call i32 @llvm.riscv.cv.simd.shuffle2.h(i32 [[TMP0]], i32 [[TMP1]], i32 [[TMP2]])
+// CHECK-NEXT:    ret i32 [[TMP3]]
+//
+uint32_t test_shuffle2_h(uint32_t rs1, uint32_t rs2, uint32_t rd) {
+  return __builtin_riscv_cv_simd_shuffle2_h(rs1, rs2, rd);
+}
+
+// CHECK-LABEL: @test_shuffle2_b(
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:    [[RS1_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    [[RS2_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    [[RD_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    store i32 [[RS1:%.*]], ptr [[RS1_ADDR]], align 4
+// CHECK-NEXT:    store i32 [[RS2:%.*]], ptr [[RS2_ADDR]], align 4
+// CHECK-NEXT:    store i32 [[RD:%.*]], ptr [[RD_ADDR]], align 4
+// CHECK-NEXT:    [[TMP0:%.*]] = load i32, ptr [[RS1_ADDR]], align 4
+// CHECK-NEXT:    [[TMP1:%.*]] = load i32, ptr [[RS2_ADDR]], align 4
+// CHECK-NEXT:    [[TMP2:%.*]] = load i32, ptr [[RD_ADDR]], align 4
+// CHECK-NEXT:    [[TMP3:%.*]] = call i32 @llvm.riscv.cv.simd.shuffle2.b(i32 [[TMP0]], i32 [[TMP1]], i32 [[TMP2]])
+// CHECK-NEXT:    ret i32 [[TMP3]]
+//
+uint32_t test_shuffle2_b(uint32_t rs1, uint32_t rs2, uint32_t rd) {
+  return __builtin_riscv_cv_simd_shuffle2_b(rs1, rs2, rd);
+}
+
+// ===== PACK =====
+
+// CHECK-LABEL: @test_packhi_h(
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:    [[A_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    [[B_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    store i32 [[A:%.*]], ptr [[A_ADDR]], align 4
+// CHECK-NEXT:    store i32 [[B:%.*]], ptr [[B_ADDR]], align 4
+// CHECK-NEXT:    [[TMP0:%.*]] = load i32, ptr [[A_ADDR]], align 4
+// CHECK-NEXT:    [[TMP1:%.*]] = load i32, ptr [[B_ADDR]], align 4
+// CHECK-NEXT:    [[TMP2:%.*]] = call i32 @llvm.riscv.cv.simd.packhi.h(i32 [[TMP0]], i32 [[TMP1]])
+// CHECK-NEXT:    ret i32 [[TMP2]]
+//
+uint32_t test_packhi_h(uint32_t a, uint32_t b) {
+  return __builtin_riscv_cv_simd_packhi_h(a, b);
+}
+
+// CHECK-LABEL: @test_packlo_h(
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:    [[A_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    [[B_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    store i32 [[A:%.*]], ptr [[A_ADDR]], align 4
+// CHECK-NEXT:    store i32 [[B:%.*]], ptr [[B_ADDR]], align 4
+// CHECK-NEXT:    [[TMP0:%.*]] = load i32, ptr [[A_ADDR]], align 4
+// CHECK-NEXT:    [[TMP1:%.*]] = load i32, ptr [[B_ADDR]], align 4
+// CHECK-NEXT:    [[TMP2:%.*]] = call i32 @llvm.riscv.cv.simd.packlo.h(i32 [[TMP0]], i32 [[TMP1]])
+// CHECK-NEXT:    ret i32 [[TMP2]]
+//
+uint32_t test_packlo_h(uint32_t a, uint32_t b) {
+  return __builtin_riscv_cv_simd_packlo_h(a, b);
+}
+
+// CHECK-LABEL: @test_packhi_b(
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:    [[RD_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    [[RS1_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    [[RS2_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    store i32 [[RD:%.*]], ptr [[RD_ADDR]], align 4
+// CHECK-NEXT:    store i32 [[RS1:%.*]], ptr [[RS1_ADDR]], align 4
+// CHECK-NEXT:    store i32 [[RS2:%.*]], ptr [[RS2_ADDR]], align 4
+// CHECK-NEXT:    [[TMP0:%.*]] = load i32, ptr [[RD_ADDR]], align 4
+// CHECK-NEXT:    [[TMP1:%.*]] = load i32, ptr [[RS1_ADDR]], align 4
+// CHECK-NEXT:    [[TMP2:%.*]] = load i32, ptr [[RS2_ADDR]], align 4
+// CHECK-NEXT:    [[TMP3:%.*]] = call i32 @llvm.riscv.cv.simd.packhi.b(i32 [[TMP0]], i32 [[TMP1]], i32 [[TMP2]])
+// CHECK-NEXT:    ret i32 [[TMP3]]
+//
+uint32_t test_packhi_b(uint32_t rd, uint32_t rs1, uint32_t rs2) {
+  return __builtin_riscv_cv_simd_packhi_b(rd, rs1, rs2);
+}
+
+// CHECK-LABEL: @test_packlo_b(
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:    [[RD_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    [[RS1_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    [[RS2_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    store i32 [[RD:%.*]], ptr [[RD_ADDR]], align 4
+// CHECK-NEXT:    store i32 [[RS1:%.*]], ptr [[RS1_ADDR]], align 4
+// CHECK-NEXT:    store i32 [[RS2:%.*]], ptr [[RS2_ADDR]], align 4
+// CHECK-NEXT:    [[TMP0:%.*]] = load i32, ptr [[RD_ADDR]], align 4
+// CHECK-NEXT:    [[TMP1:%.*]] = load i32, ptr [[RS1_ADDR]], align 4
+// CHECK-NEXT:    [[TMP2:%.*]] = load i32, ptr [[RS2_ADDR]], align 4
+// CHECK-NEXT:    [[TMP3:%.*]] = call i32 @llvm.riscv.cv.simd.packlo.b(i32 [[TMP0]], i32 [[TMP1]], i32 [[TMP2]])
+// CHECK-NEXT:    ret i32 [[TMP3]]
+//
+uint32_t test_packlo_b(uint32_t rd, uint32_t rs1, uint32_t rs2) {
+  return __builtin_riscv_cv_simd_packlo_b(rd, rs1, rs2);
+}
+
+// ===== COMPARE (representative) =====
+
+// CHECK-LABEL: @test_cmpeq_h(
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:    [[A_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    [[B_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    store i32 [[A:%.*]], ptr [[A_ADDR]], align 4
+// CHECK-NEXT:    store i32 [[B:%.*]], ptr [[B_ADDR]], align 4
+// CHECK-NEXT:    [[TMP0:%.*]] = load i32, ptr [[A_ADDR]], align 4
+// CHECK-NEXT:    [[TMP1:%.*]] = load i32, ptr [[B_ADDR]], align 4
+// CHECK-NEXT:    [[TMP2:%.*]] = call i32 @llvm.riscv.cv.simd.cmpeq.h(i32 [[TMP0]], i32 [[TMP1]])
+// CHECK-NEXT:    ret i32 [[TMP2]]
+//
+uint32_t test_cmpeq_h(uint32_t a, uint32_t b) {
+  return __builtin_riscv_cv_simd_cmpeq_h(a, b);
+}
+
+// CHECK-LABEL: @test_cmpeq_b(
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:    [[A_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    [[B_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    store i32 [[A:%.*]], ptr [[A_ADDR]], align 4
+// CHECK-NEXT:    store i32 [[B:%.*]], ptr [[B_ADDR]], align 4
+// CHECK-NEXT:    [[TMP0:%.*]] = load i32, ptr [[A_ADDR]], align 4
+// CHECK-NEXT:    [[TMP1:%.*]] = load i32, ptr [[B_ADDR]], align 4
+// CHECK-NEXT:    [[TMP2:%.*]] = call i32 @llvm.riscv.cv.simd.cmpeq.b(i32 [[TMP0]], i32 [[TMP1]])
+// CHECK-NEXT:    ret i32 [[TMP2]]
+//
+uint32_t test_cmpeq_b(uint32_t a, uint32_t b) {
+  return __builtin_riscv_cv_simd_cmpeq_b(a, b);
+}
+
+// CHECK-LABEL: @test_cmpne_h(
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:    [[A_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    [[B_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    store i32 [[A:%.*]], ptr [[A_ADDR]], align 4
+// CHECK-NEXT:    store i32 [[B:%.*]], ptr [[B_ADDR]], align 4
+// CHECK-NEXT:    [[TMP0:%.*]] = load i32, ptr [[A_ADDR]], align 4
+// CHECK-NEXT:    [[TMP1:%.*]] = load i32, ptr [[B_ADDR]], align 4
+// CHECK-NEXT:    [[TMP2:%.*]] = call i32 @llvm.riscv.cv.simd.cmpne.h(i32 [[TMP0]], i32 [[TMP1]])
+// CHECK-NEXT:    ret i32 [[TMP2]]
+//
+uint32_t test_cmpne_h(uint32_t a, uint32_t b) {
+  return __builtin_riscv_cv_simd_cmpne_h(a, b);
+}
+
+// CHECK-LABEL: @test_cmpgt_h(
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:    [[A_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    [[B_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    store i32 [[A:%.*]], ptr [[A_ADDR]], align 4
+// CHECK-NEXT:    store i32 [[B:%.*]], ptr [[B_ADDR]], align 4
+// CHECK-NEXT:    [[TMP0:%.*]] = load i32, ptr [[A_ADDR]], align 4
+// CHECK-NEXT:    [[TMP1:%.*]] = load i32, ptr [[B_ADDR]], align 4
+// CHECK-NEXT:    [[TMP2:%.*]] = call i32 @llvm.riscv.cv.simd.cmpgt.h(i32 [[TMP0]], i32 [[TMP1]])
+// CHECK-NEXT:    ret i32 [[TMP2]]
+//
+uint32_t test_cmpgt_h(uint32_t a, uint32_t b) {
+  return __builtin_riscv_cv_simd_cmpgt_h(a, b);
+}
+
+// CHECK-LABEL: @test_cmpge_sc_h(
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:    [[A_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    [[B_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    store i32 [[A:%.*]], ptr [[A_ADDR]], align 4
+// CHECK-NEXT:    store i32 [[B:%.*]], ptr [[B_ADDR]], align 4
+// CHECK-NEXT:    [[TMP0:%.*]] = load i32, ptr [[A_ADDR]], align 4
+// CHECK-NEXT:    [[TMP1:%.*]] = load i32, ptr [[B_ADDR]], align 4
+// CHECK-NEXT:    [[TMP2:%.*]] = call i32 @llvm.riscv.cv.simd.cmpge.sc.h(i32 [[TMP0]], i32 [[TMP1]])
+// CHECK-NEXT:    ret i32 [[TMP2]]
+//
+uint32_t test_cmpge_sc_h(uint32_t a, uint32_t b) {
+  return __builtin_riscv_cv_simd_cmpge_sc_h(a, b);
+}
+
+// CHECK-LABEL: @test_cmplt_b(
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:    [[A_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    [[B_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    store i32 [[A:%.*]], ptr [[A_ADDR]], align 4
+// CHECK-NEXT:    store i32 [[B:%.*]], ptr [[B_ADDR]], align 4
+// CHECK-NEXT:    [[TMP0:%.*]] = load i32, ptr [[A_ADDR]], align 4
+// CHECK-NEXT:    [[TMP1:%.*]] = load i32, ptr [[B_ADDR]], align 4
+// CHECK-NEXT:    [[TMP2:%.*]] = call i32 @llvm.riscv.cv.simd.cmplt.b(i32 [[TMP0]], i32 [[TMP1]])
+// CHECK-NEXT:    ret i32 [[TMP2]]
+//
+uint32_t test_cmplt_b(uint32_t a, uint32_t b) {
+  return __builtin_riscv_cv_simd_cmplt_b(a, b);
+}
+
+// CHECK-LABEL: @test_cmple_sc_b(
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:    [[A_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    [[B_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    store i32 [[A:%.*]], ptr [[A_ADDR]], align 4
+// CHECK-NEXT:    store i32 [[B:%.*]], ptr [[B_ADDR]], align 4
+// CHECK-NEXT:    [[TMP0:%.*]] = load i32, ptr [[A_ADDR]], align 4
+// CHECK-NEXT:    [[TMP1:%.*]] = load i32, ptr [[B_ADDR]], align 4
+// CHECK-NEXT:    [[TMP2:%.*]] = call i32 @llvm.riscv.cv.simd.cmple.sc.b(i32 [[TMP0]], i32 [[TMP1]])
+// CHECK-NEXT:    ret i32 [[TMP2]]
+//
+uint32_t test_cmple_sc_b(uint32_t a, uint32_t b) {
+  return __builtin_riscv_cv_simd_cmple_sc_b(a, b);
+}
+
+// CHECK-LABEL: @test_cmpgtu_h(
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:    [[A_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    [[B_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    store i32 [[A:%.*]], ptr [[A_ADDR]], align 4
+// CHECK-NEXT:    store i32 [[B:%.*]], ptr [[B_ADDR]], align 4
+// CHECK-NEXT:    [[TMP0:%.*]] = load i32, ptr [[A_ADDR]], align 4
+// CHECK-NEXT:    [[TMP1:%.*]] = load i32, ptr [[B_ADDR]], align 4
+// CHECK-NEXT:    [[TMP2:%.*]] = call i32 @llvm.riscv.cv.simd.cmpgtu.h(i32 [[TMP0]], i32 [[TMP1]])
+// CHECK-NEXT:    ret i32 [[TMP2]]
+//
+uint32_t test_cmpgtu_h(uint32_t a, uint32_t b) {
+  return __builtin_riscv_cv_simd_cmpgtu_h(a, b);
+}
+
+// CHECK-LABEL: @test_cmpgeu_b(
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:    [[A_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    [[B_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    store i32 [[A:%.*]], ptr [[A_ADDR]], align 4
+// CHECK-NEXT:    store i32 [[B:%.*]], ptr [[B_ADDR]], align 4
+// CHECK-NEXT:    [[TMP0:%.*]] = load i32, ptr [[A_ADDR]], align 4
+// CHECK-NEXT:    [[TMP1:%.*]] = load i32, ptr [[B_ADDR]], align 4
+// CHECK-NEXT:    [[TMP2:%.*]] = call i32 @llvm.riscv.cv.simd.cmpgeu.b(i32 [[TMP0]], i32 [[TMP1]])
+// CHECK-NEXT:    ret i32 [[TMP2]]
+//
+uint32_t test_cmpgeu_b(uint32_t a, uint32_t b) {
+  return __builtin_riscv_cv_simd_cmpgeu_b(a, b);
+}
+
+// CHECK-LABEL: @test_cmpltu_sc_h(
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:    [[A_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    [[B_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    store i32 [[A:%.*]], ptr [[A_ADDR]], align 4
+// CHECK-NEXT:    store i32 [[B:%.*]], ptr [[B_ADDR]], align 4
+// CHECK-NEXT:    [[TMP0:%.*]] = load i32, ptr [[A_ADDR]], align 4
+// CHECK-NEXT:    [[TMP1:%.*]] = load i32, ptr [[B_ADDR]], align 4
+// CHECK-NEXT:    [[TMP2:%.*]] = call i32 @llvm.riscv.cv.simd.cmpltu.sc.h(i32 [[TMP0]], i32 [[TMP1]])
+// CHECK-NEXT:    ret i32 [[TMP2]]
+//
+uint32_t test_cmpltu_sc_h(uint32_t a, uint32_t b) {
+  return __builtin_riscv_cv_simd_cmpltu_sc_h(a, b);
+}
+
+// CHECK-LABEL: @test_cmpleu_b(
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:    [[A_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    [[B_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    store i32 [[A:%.*]], ptr [[A_ADDR]], align 4
+// CHECK-NEXT:    store i32 [[B:%.*]], ptr [[B_ADDR]], align 4
+// CHECK-NEXT:    [[TMP0:%.*]] = load i32, ptr [[A_ADDR]], align 4
+// CHECK-NEXT:    [[TMP1:%.*]] = load i32, ptr [[B_ADDR]], align 4
+// CHECK-NEXT:    [[TMP2:%.*]] = call i32 @llvm.riscv.cv.simd.cmpleu.b(i32 [[TMP0]], i32 [[TMP1]])
+// CHECK-NEXT:    ret i32 [[TMP2]]
+//
+uint32_t test_cmpleu_b(uint32_t a, uint32_t b) {
+  return __builtin_riscv_cv_simd_cmpleu_b(a, b);
+}
+
+// ===== COMPLEX =====
+
+// CHECK-LABEL: @test_cplxmul_r(
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:    [[RS1_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    [[RS2_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    [[RD_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    store i32 [[RS1:%.*]], ptr [[RS1_ADDR]], align 4
+// CHECK-NEXT:    store i32 [[RS2:%.*]], ptr [[RS2_ADDR]], align 4
+// CHECK-NEXT:    store i32 [[RD:%.*]], ptr [[RD_ADDR]], align 4
+// CHECK-NEXT:    [[TMP0:%.*]] = load i32, ptr [[RS1_ADDR]], align 4
+// CHECK-NEXT:    [[TMP1:%.*]] = load i32, ptr [[RS2_ADDR]], align 4
+// CHECK-NEXT:    [[TMP2:%.*]] = load i32, ptr [[RD_ADDR]], align 4
+// CHECK-NEXT:    [[TMP3:%.*]] = call i32 @llvm.riscv.cv.simd.cplxmul.r(i32 [[TMP0]], i32 [[TMP1]], i32 [[TMP2]], i32 0)
+// CHECK-NEXT:    ret i32 [[TMP3]]
+//
+uint32_t test_cplxmul_r(uint32_t rs1, uint32_t rs2, uint32_t rd) {
+  return __builtin_riscv_cv_simd_cplxmul_r(rs1, rs2, rd, 0);
+}
+
+// CHECK-LABEL: @test_cplxmul_r_div2(
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:    [[RS1_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    [[RS2_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    [[RD_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    store i32 [[RS1:%.*]], ptr [[RS1_ADDR]], align 4
+// CHECK-NEXT:    store i32 [[RS2:%.*]], ptr [[RS2_ADDR]], align 4
+// CHECK-NEXT:    store i32 [[RD:%.*]], ptr [[RD_ADDR]], align 4
+// CHECK-NEXT:    [[TMP0:%.*]] = load i32, ptr [[RS1_ADDR]], align 4
+// CHECK-NEXT:    [[TMP1:%.*]] = load i32, ptr [[RS2_ADDR]], align 4
+// CHECK-NEXT:    [[TMP2:%.*]] = load i32, ptr [[RD_ADDR]], align 4
+// CHECK-NEXT:    [[TMP3:%.*]] = call i32 @llvm.riscv.cv.simd.cplxmul.r(i32 [[TMP0]], i32 [[TMP1]], i32 [[TMP2]], i32 1)
+// CHECK-NEXT:    ret i32 [[TMP3]]
+//
+uint32_t test_cplxmul_r_div2(uint32_t rs1, uint32_t rs2, uint32_t rd) {
+  return __builtin_riscv_cv_simd_cplxmul_r(rs1, rs2, rd, 1);
+}
+
+// CHECK-LABEL: @test_cplxmul_i(
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:    [[RS1_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    [[RS2_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    [[RD_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    store i32 [[RS1:%.*]], ptr [[RS1_ADDR]], align 4
+// CHECK-NEXT:    store i32 [[RS2:%.*]], ptr [[RS2_ADDR]], align 4
+// CHECK-NEXT:    store i32 [[RD:%.*]], ptr [[RD_ADDR]], align 4
+// CHECK-NEXT:    [[TMP0:%.*]] = load i32, ptr [[RS1_ADDR]], align 4
+// CHECK-NEXT:    [[TMP1:%.*]] = load i32, ptr [[RS2_ADDR]], align 4
+// CHECK-NEXT:    [[TMP2:%.*]] = load i32, ptr [[RD_ADDR]], align 4
+// CHECK-NEXT:    [[TMP3:%.*]] = call i32 @llvm.riscv.cv.simd.cplxmul.i(i32 [[TMP0]], i32 [[TMP1]], i32 [[TMP2]], i32 0)
+// CHECK-NEXT:    ret i32 [[TMP3]]
+//
+uint32_t test_cplxmul_i(uint32_t rs1, uint32_t rs2, uint32_t rd) {
+  return __builtin_riscv_cv_simd_cplxmul_i(rs1, rs2, rd, 0);
+}
+
+// CHECK-LABEL: @test_cplxmul_i_div4(
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:    [[RS1_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    [[RS2_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    [[RD_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    store i32 [[RS1:%.*]], ptr [[RS1_ADDR]], align 4
+// CHECK-NEXT:    store i32 [[RS2:%.*]], ptr [[RS2_ADDR]], align 4
+// CHECK-NEXT:    store i32 [[RD:%.*]], ptr [[RD_ADDR]], align 4
+// CHECK-NEXT:    [[TMP0:%.*]] = load i32, ptr [[RS1_ADDR]], align 4
+// CHECK-NEXT:    [[TMP1:%.*]] = load i32, ptr [[RS2_ADDR]], align 4
+// CHECK-NEXT:    [[TMP2:%.*]] = load i32, ptr [[RD_ADDR]], align 4
+// CHECK-NEXT:    [[TMP3:%.*]] = call i32 @llvm.riscv.cv.simd.cplxmul.i(i32 [[TMP0]], i32 [[TMP1]], i32 [[TMP2]], i32 2)
+// CHECK-NEXT:    ret i32 [[TMP3]]
+//
+uint32_t test_cplxmul_i_div4(uint32_t rs1, uint32_t rs2, uint32_t rd) {
+  return __builtin_riscv_cv_simd_cplxmul_i(rs1, rs2, rd, 2);
+}
+
+// CHECK-LABEL: @test_cplxconj(
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:    [[A_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    store i32 [[A:%.*]], ptr [[A_ADDR]], align 4
+// CHECK-NEXT:    [[TMP0:%.*]] = load i32, ptr [[A_ADDR]], align 4
+// CHECK-NEXT:    [[TMP1:%.*]] = call i32 @llvm.riscv.cv.simd.cplxconj(i32 [[TMP0]])
+// CHECK-NEXT:    ret i32 [[TMP1]]
+//
+uint32_t test_cplxconj(uint32_t a) {
+  return __builtin_riscv_cv_simd_cplxconj(a);
+}
+
+// CHECK-LABEL: @test_subrotmj(
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:    [[A_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    [[B_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    store i32 [[A:%.*]], ptr [[A_ADDR]], align 4
+// CHECK-NEXT:    store i32 [[B:%.*]], ptr [[B_ADDR]], align 4
+// CHECK-NEXT:    [[TMP0:%.*]] = load i32, ptr [[A_ADDR]], align 4
+// CHECK-NEXT:    [[TMP1:%.*]] = load i32, ptr [[B_ADDR]], align 4
+// CHECK-NEXT:    [[TMP2:%.*]] = call i32 @llvm.riscv.cv.simd.subrotmj(i32 [[TMP0]], i32 [[TMP1]], i32 0)
+// CHECK-NEXT:    ret i32 [[TMP2]]
+//
+uint32_t test_subrotmj(uint32_t a, uint32_t b) {
+  return __builtin_riscv_cv_simd_subrotmj(a, b, 0);
+}
+
+// CHECK-LABEL: @test_subrotmj_div8(
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:    [[A_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    [[B_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    store i32 [[A:%.*]], ptr [[A_ADDR]], align 4
+// CHECK-NEXT:    store i32 [[B:%.*]], ptr [[B_ADDR]], align 4
+// CHECK-NEXT:    [[TMP0:%.*]] = load i32, ptr [[A_ADDR]], align 4
+// CHECK-NEXT:    [[TMP1:%.*]] = load i32, ptr [[B_ADDR]], align 4
+// CHECK-NEXT:    [[TMP2:%.*]] = call i32 @llvm.riscv.cv.simd.subrotmj(i32 [[TMP0]], i32 [[TMP1]], i32 3)
+// CHECK-NEXT:    ret i32 [[TMP2]]
+//
+uint32_t test_subrotmj_div8(uint32_t a, uint32_t b) {
+  return __builtin_riscv_cv_simd_subrotmj(a, b, 3);
+}
diff --git a/clang/test/Sema/rvv-xcv-sema.c b/clang/test/Sema/rvv-xcv-sema.c
index 681e6c7c385dd..7f873ecc02c14 100644
--- a/clang/test/Sema/rvv-xcv-sema.c
+++ b/clang/test/Sema/rvv-xcv-sema.c
@@ -15,3 +15,43 @@ void test_mac_range(uint32_t a, uint32_t b, uint32_t c) {
   (void)__builtin_riscv_cv_mac_macuN(a, b, c, 31);  // OK
   (void)__builtin_riscv_cv_mac_macuN(a, b, c, 32);  // expected-error {{argument value 32 is outside the valid range [0, 31]}}
 }
+
+// ===== XCVsimd — various immediate ranges =====
+
+void test_simd_extract_range(uint32_t a) {
+  (void)__builtin_riscv_cv_simd_extract_h(a, 0);   // OK
+  (void)__builtin_riscv_cv_simd_extract_h(a, 1);   // OK: max for halfword
+  (void)__builtin_riscv_cv_simd_extract_h(a, 2);   // expected-error {{argument value 2 is outside the valid range [0, 1]}}
+  (void)__builtin_riscv_cv_simd_extract_b(a, 3);   // OK: max for byte
+  (void)__builtin_riscv_cv_simd_extract_b(a, 4);   // expected-error {{argument value 4 is outside the valid range [0, 3]}}
+}
+
+void test_simd_insert_range(uint32_t a, uint32_t b) {
+  (void)__builtin_riscv_cv_simd_insert_h(a, b, 1);   // OK
+  (void)__builtin_riscv_cv_simd_insert_h(a, b, 2);   // expected-error {{argument value 2 is outside the valid range [0, 1]}}
+  (void)__builtin_riscv_cv_simd_insert_b(a, b, 3);   // OK
+  (void)__builtin_riscv_cv_simd_insert_b(a, b, 4);   // expected-error {{argument value 4 is outside the valid range [0, 3]}}
+}
+
+void test_simd_shuffle_sci_range(uint32_t a) {
+  (void)__builtin_riscv_cv_simd_shuffle_sci_h(a, 3);    // OK: max for 2-bit
+  (void)__builtin_riscv_cv_simd_shuffle_sci_h(a, 4);    // expected-error {{argument value 4 is outside the valid range [0, 3]}}
+  (void)__builtin_riscv_cv_simd_shuffle_sci_b(a, 255);  // OK: max for 8-bit
+  (void)__builtin_riscv_cv_simd_shuffle_sci_b(a, 256);  // expected-error {{argument value 256 is outside the valid range [0, 255]}}
+}
+
+void test_simd_add_h_range(uint32_t a, uint32_t b) {
+  (void)__builtin_riscv_cv_simd_add_h(a, b, 0);  // OK
+  (void)__builtin_riscv_cv_simd_add_h(a, b, 3);  // OK: max divcode
+  (void)__builtin_riscv_cv_simd_add_h(a, b, 4);  // expected-error {{argument value 4 is outside the valid range [0, 3]}}
+}
+
+void test_simd_cplxmul_range(uint32_t a, uint32_t b, uint32_t c) {
+  (void)__builtin_riscv_cv_simd_cplxmul_r(a, b, c, 3);  // OK
+  (void)__builtin_riscv_cv_simd_cplxmul_r(a, b, c, 4);  // expected-error {{argument value 4 is outside the valid range [0, 3]}}
+}
+
+void test_simd_subrotmj_range(uint32_t a, uint32_t b) {
+  (void)__builtin_riscv_cv_simd_subrotmj(a, b, 3);  // OK
+  (void)__builtin_riscv_cv_simd_subrotmj(a, b, 4);  // expected-error {{argument value 4 is outside the valid range [0, 3]}}
+}

>From 7dda09142d0f914f46b6dfe22803ec0e22f3ee1b Mon Sep 17 00:00:00 2001
From: vitbur <vittorioburani at gmail.com>
Date: Tue, 7 Apr 2026 18:48:54 +0200
Subject: [PATCH 09/10] [Clang][RISCV] Add tests for `XCVbitmanip` builtins

- add `rvv-xcvbitmanip-builtins.c`
- add Sema tests for XCVbitmanip in `rvv-xcv-sema.c`
---
 .../CodeGen/RISCV/rvv-xcvbitmanip-builtins.c  | 95 +++++++++++++++++++
 clang/test/Sema/rvv-xcv-sema.c                |  8 ++
 2 files changed, 103 insertions(+)
 create mode 100644 clang/test/CodeGen/RISCV/rvv-xcvbitmanip-builtins.c

diff --git a/clang/test/CodeGen/RISCV/rvv-xcvbitmanip-builtins.c b/clang/test/CodeGen/RISCV/rvv-xcvbitmanip-builtins.c
new file mode 100644
index 0000000000000..98e976bc4122b
--- /dev/null
+++ b/clang/test/CodeGen/RISCV/rvv-xcvbitmanip-builtins.c
@@ -0,0 +1,95 @@
+// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py
+// RUN: %clang_cc1 -triple riscv32 -target-feature +xcvbitmanip -emit-llvm %s -o - \
+// RUN:   | FileCheck %s
+
+// This file tests that XCVbitmanip Clang builtins are correctly lowered
+// to their corresponding LLVM IR intrinsics.
+
+#include <stdint.h>
+
+// CHECK-LABEL: @test_extract(
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:    [[A_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    store i32 [[A:%.*]], ptr [[A_ADDR]], align 4
+// CHECK-NEXT:    [[TMP0:%.*]] = load i32, ptr [[A_ADDR]], align 4
+// CHECK-NEXT:    [[TMP1:%.*]] = call i32 @llvm.riscv.cv.bitmanip.extract(i32 [[TMP0]], i32 164)
+// CHECK-NEXT:    ret i32 [[TMP1]]
+//
+uint32_t test_extract(uint32_t a) {
+  return __builtin_riscv_cv_bitmanip_extract(a, 164);
+}
+
+// CHECK-LABEL: @test_extractu(
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:    [[A_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    store i32 [[A:%.*]], ptr [[A_ADDR]], align 4
+// CHECK-NEXT:    [[TMP0:%.*]] = load i32, ptr [[A_ADDR]], align 4
+// CHECK-NEXT:    [[TMP1:%.*]] = call i32 @llvm.riscv.cv.bitmanip.extractu(i32 [[TMP0]], i32 164)
+// CHECK-NEXT:    ret i32 [[TMP1]]
+//
+uint32_t test_extractu(uint32_t a) {
+  return __builtin_riscv_cv_bitmanip_extractu(a, 164);
+}
+
+// CHECK-LABEL: @test_bclr(
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:    [[A_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    store i32 [[A:%.*]], ptr [[A_ADDR]], align 4
+// CHECK-NEXT:    [[TMP0:%.*]] = load i32, ptr [[A_ADDR]], align 4
+// CHECK-NEXT:    [[TMP1:%.*]] = call i32 @llvm.riscv.cv.bitmanip.bclr(i32 [[TMP0]], i32 164)
+// CHECK-NEXT:    ret i32 [[TMP1]]
+//
+uint32_t test_bclr(uint32_t a) {
+  return __builtin_riscv_cv_bitmanip_bclr(a, 164);
+}
+
+// CHECK-LABEL: @test_bset(
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:    [[A_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    store i32 [[A:%.*]], ptr [[A_ADDR]], align 4
+// CHECK-NEXT:    [[TMP0:%.*]] = load i32, ptr [[A_ADDR]], align 4
+// CHECK-NEXT:    [[TMP1:%.*]] = call i32 @llvm.riscv.cv.bitmanip.bset(i32 [[TMP0]], i32 164)
+// CHECK-NEXT:    ret i32 [[TMP1]]
+//
+uint32_t test_bset(uint32_t a) {
+  return __builtin_riscv_cv_bitmanip_bset(a, 164);
+}
+
+// CHECK-LABEL: @test_insert(
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:    [[A_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    [[RD_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    store i32 [[A:%.*]], ptr [[A_ADDR]], align 4
+// CHECK-NEXT:    store i32 [[RD:%.*]], ptr [[RD_ADDR]], align 4
+// CHECK-NEXT:    [[TMP0:%.*]] = load i32, ptr [[A_ADDR]], align 4
+// CHECK-NEXT:    [[TMP1:%.*]] = load i32, ptr [[RD_ADDR]], align 4
+// CHECK-NEXT:    [[TMP2:%.*]] = call i32 @llvm.riscv.cv.bitmanip.insert(i32 [[TMP0]], i32 164, i32 [[TMP1]])
+// CHECK-NEXT:    ret i32 [[TMP2]]
+//
+uint32_t test_insert(uint32_t a, uint32_t rd) {
+  return __builtin_riscv_cv_bitmanip_insert(a, 164, rd);
+}
+
+// CHECK-LABEL: @test_clb(
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:    [[A_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    store i32 [[A:%.*]], ptr [[A_ADDR]], align 4
+// CHECK-NEXT:    [[TMP0:%.*]] = load i32, ptr [[A_ADDR]], align 4
+// CHECK-NEXT:    [[TMP1:%.*]] = call i32 @llvm.riscv.cv.bitmanip.clb(i32 [[TMP0]])
+// CHECK-NEXT:    ret i32 [[TMP1]]
+//
+uint32_t test_clb(uint32_t a) {
+  return __builtin_riscv_cv_bitmanip_clb(a);
+}
+
+// CHECK-LABEL: @test_bitrev(
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:    [[A_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    store i32 [[A:%.*]], ptr [[A_ADDR]], align 4
+// CHECK-NEXT:    [[TMP0:%.*]] = load i32, ptr [[A_ADDR]], align 4
+// CHECK-NEXT:    [[TMP1:%.*]] = call i32 @llvm.riscv.cv.bitmanip.bitrev(i32 [[TMP0]], i32 2, i32 23)
+// CHECK-NEXT:    ret i32 [[TMP1]]
+//
+uint32_t test_bitrev(uint32_t a) {
+  return __builtin_riscv_cv_bitmanip_bitrev(a, 2, 23);
+}
diff --git a/clang/test/Sema/rvv-xcv-sema.c b/clang/test/Sema/rvv-xcv-sema.c
index 7f873ecc02c14..b7e28fe28791c 100644
--- a/clang/test/Sema/rvv-xcv-sema.c
+++ b/clang/test/Sema/rvv-xcv-sema.c
@@ -55,3 +55,11 @@ void test_simd_subrotmj_range(uint32_t a, uint32_t b) {
   (void)__builtin_riscv_cv_simd_subrotmj(a, b, 3);  // OK
   (void)__builtin_riscv_cv_simd_subrotmj(a, b, 4);  // expected-error {{argument value 4 is outside the valid range [0, 3]}}
 }
+
+// ===== XCVbitmanip — bitrev ranges =====
+
+void test_bitmanip_bitrev_range(uint32_t a) {
+  (void)__builtin_riscv_cv_bitmanip_bitrev(a, 3, 31);  // OK: max values
+  (void)__builtin_riscv_cv_bitmanip_bitrev(a, 4, 0);   // expected-error {{argument value 4 is outside the valid range [0, 3]}}
+  (void)__builtin_riscv_cv_bitmanip_bitrev(a, 0, 32);  // expected-error {{argument value 32 is outside the valid range [0, 31]}}
+}

>From 8cc8f0f3ca6c7c15bf174c3f8e9ae2ffe8a44d1e Mon Sep 17 00:00:00 2001
From: vitbur <vittorioburani at gmail.com>
Date: Fri, 19 Jun 2026 18:51:40 +0200
Subject: [PATCH 10/10] [Clang][RISCV] Apply clang-format to XCV builtin
 sources

---
 clang/lib/Headers/riscv_corev_bitmanip.h |  49 ++--
 clang/lib/Headers/riscv_corev_elw.h      |   5 +-
 clang/lib/Headers/riscv_corev_mac.h      | 145 ++++++------
 clang/lib/Headers/riscv_corev_simd.h     | 289 +++++++++++++++--------
 clang/lib/Sema/SemaRISCV.cpp             |  15 +-
 5 files changed, 296 insertions(+), 207 deletions(-)

diff --git a/clang/lib/Headers/riscv_corev_bitmanip.h b/clang/lib/Headers/riscv_corev_bitmanip.h
index 7676e44df87bd..d48c53f6c8a26 100644
--- a/clang/lib/Headers/riscv_corev_bitmanip.h
+++ b/clang/lib/Headers/riscv_corev_bitmanip.h
@@ -26,7 +26,7 @@ extern "C" {
 
 #if defined(__riscv_xcvbitmanip)
 
-#define __DEFAULT_FN_ATTRS                                                      \
+#define __DEFAULT_FN_ATTRS                                                     \
   __attribute__((__always_inline__, __nodebug__, __artificial__))
 
 /* ---------------------------------------------------------------------------
@@ -35,34 +35,38 @@ extern "C" {
  *   IS3 = bit-width (uimm5), IS2 = lower bit index (uimm5)
  *   The two immediates are packed as a single uimm10: IS3<<5 | IS2
  *   IMM must be a compile-time constant.
- * --------------------------------------------------------------------------- */
-#define __riscv_cv_bitmanip_extract(__rs1, __IMM)                               \
+ * ---------------------------------------------------------------------------
+ */
+#define __riscv_cv_bitmanip_extract(__rs1, __IMM)                              \
   ((int32_t)__builtin_riscv_cv_bitmanip_extract((uint32_t)(__rs1),             \
-                                                 (uint32_t)(__IMM)))
+                                                (uint32_t)(__IMM)))
 
 /* ---------------------------------------------------------------------------
  * cv.extractu rd, rs1, IS3, IS2
  *   rd = ZeroExtend(rs1[IS3+IS2-1 : IS2], 32)
- * --------------------------------------------------------------------------- */
+ * ---------------------------------------------------------------------------
+ */
 #define __riscv_cv_bitmanip_extractu(__rs1, __IMM)                             \
-  ((uint32_t)__builtin_riscv_cv_bitmanip_extractu((uint32_t)(__rs1),          \
-                                                   (uint32_t)(__IMM)))
+  ((uint32_t)__builtin_riscv_cv_bitmanip_extractu((uint32_t)(__rs1),           \
+                                                  (uint32_t)(__IMM)))
 
 /* ---------------------------------------------------------------------------
  * cv.bclr rd, rs1, IS3, IS2
  *   rd = rs1 & ~(((1 << IS3) - 1) << IS2)   (clear IS3 bits starting at IS2)
- * --------------------------------------------------------------------------- */
+ * ---------------------------------------------------------------------------
+ */
 #define __riscv_cv_bitmanip_bclr(__rs1, __IMM)                                 \
-  ((uint32_t)__builtin_riscv_cv_bitmanip_bclr((uint32_t)(__rs1),              \
-                                               (uint32_t)(__IMM)))
+  ((uint32_t)__builtin_riscv_cv_bitmanip_bclr((uint32_t)(__rs1),               \
+                                              (uint32_t)(__IMM)))
 
 /* ---------------------------------------------------------------------------
  * cv.bset rd, rs1, IS3, IS2
  *   rd = rs1 | (((1 << IS3) - 1) << IS2)    (set IS3 bits starting at IS2)
- * --------------------------------------------------------------------------- */
+ * ---------------------------------------------------------------------------
+ */
 #define __riscv_cv_bitmanip_bset(__rs1, __IMM)                                 \
-  ((uint32_t)__builtin_riscv_cv_bitmanip_bset((uint32_t)(__rs1),              \
-                                               (uint32_t)(__IMM)))
+  ((uint32_t)__builtin_riscv_cv_bitmanip_bset((uint32_t)(__rs1),               \
+                                              (uint32_t)(__IMM)))
 
 /* ---------------------------------------------------------------------------
  * cv.insert rd, rs1, IS3, IS2
@@ -70,11 +74,11 @@ extern "C" {
  *   rd is read-modify-write (the bits outside the target range are preserved).
  *   IS3 = bit-width (uimm5), IS2 = lower bit index (uimm5)
  *   The two immediates are packed as a single uimm10: IS3<<5 | IS2
- * --------------------------------------------------------------------------- */
+ * ---------------------------------------------------------------------------
+ */
 #define __riscv_cv_bitmanip_insert(__rD, __rs1, __IMM)                         \
-  ((uint32_t)__builtin_riscv_cv_bitmanip_insert((uint32_t)(__rs1),            \
-                                                 (uint32_t)(__IMM),            \
-                                                 (uint32_t)(__rD)))
+  ((uint32_t)__builtin_riscv_cv_bitmanip_insert(                               \
+      (uint32_t)(__rs1), (uint32_t)(__IMM), (uint32_t)(__rD)))
 
 /* ---------------------------------------------------------------------------
  * cv.clb rd, rs1
@@ -88,7 +92,8 @@ extern "C" {
  * standard C expressions (__builtin_ctz, __builtin_clz, __builtin_popcount,
  * rotate patterns) when -march includes xcvbitmanip. No explicit builtin call
  * is required or provided for those four operations.
- * --------------------------------------------------------------------------- */
+ * ---------------------------------------------------------------------------
+ */
 static __inline__ uint32_t __DEFAULT_FN_ATTRS
 __riscv_cv_bitmanip_clb(uint32_t a) {
   return __builtin_riscv_cv_bitmanip_clb(a);
@@ -102,11 +107,11 @@ __riscv_cv_bitmanip_clb(uint32_t a) {
  *
  * Example: cv.bitrev t0, t0, 2, 23 reverses groups of 4 bits within each
  * 24-bit window.
- * --------------------------------------------------------------------------- */
+ * ---------------------------------------------------------------------------
+ */
 #define __riscv_cv_bitmanip_bitrev(__rs1, __IS2, __IS3)                        \
-  ((uint32_t)__builtin_riscv_cv_bitmanip_bitrev((uint32_t)(__rs1),            \
-                                                 (uint32_t)(__IS2),            \
-                                                 (uint32_t)(__IS3)))
+  ((uint32_t)__builtin_riscv_cv_bitmanip_bitrev(                               \
+      (uint32_t)(__rs1), (uint32_t)(__IS2), (uint32_t)(__IS3)))
 
 #endif /* __riscv_xcvbitmanip */
 
diff --git a/clang/lib/Headers/riscv_corev_elw.h b/clang/lib/Headers/riscv_corev_elw.h
index 9676799b5b2e0..f0583ad35c543 100644
--- a/clang/lib/Headers/riscv_corev_elw.h
+++ b/clang/lib/Headers/riscv_corev_elw.h
@@ -5,12 +5,11 @@
 extern "C" {
 #endif
 #if defined(__riscv_xcvelw)
-#define __DEFAULT_FN_ATTRS \
+#define __DEFAULT_FN_ATTRS                                                     \
   __attribute__((__always_inline__, __nodebug__, __artificial__))
 
 // cv.elw rd, imm(rs1): event load word
-static __inline__ int32_t __DEFAULT_FN_ATTRS
-__riscv_cv_elw_elw(int32_t *ptr) {
+static __inline__ int32_t __DEFAULT_FN_ATTRS __riscv_cv_elw_elw(int32_t *ptr) {
   return __builtin_riscv_cv_elw_elw(ptr);
 }
 #endif
diff --git a/clang/lib/Headers/riscv_corev_mac.h b/clang/lib/Headers/riscv_corev_mac.h
index 531c9b01f862f..dccb8ae9dbf81 100644
--- a/clang/lib/Headers/riscv_corev_mac.h
+++ b/clang/lib/Headers/riscv_corev_mac.h
@@ -26,18 +26,19 @@ extern "C" {
 
 #if defined(__riscv_xcvmac)
 
-#define __DEFAULT_FN_ATTRS                                                      \
+#define __DEFAULT_FN_ATTRS                                                     \
   __attribute__((__always_inline__, __nodebug__, __artificial__))
 
 /* ---------------------------------------------------------------------------
  * 32x32-bit MAC / MSU
  *
- *   cv.mac  rd, rs1, rs2  ->  rd += rs1 * rs2
- *   cv.msu  rd, rs1, rs2  ->  rd -= rs1 * rs2
+ * cv.mac  rd, rs1, rs2 -> rd += rs1 * rs2
+ * cv.msu  rd, rs1, rs2 -> rd -= rs1 * rs2
  *
  * These are the only two operations that take a plain GPR accumulator
  * (no shift/round), so they can be static inline functions.
- * --------------------------------------------------------------------------- */
+ * ---------------------------------------------------------------------------
+ */
 
 static __inline__ int32_t __DEFAULT_FN_ATTRS
 __riscv_cv_mac_mac(int32_t a, int32_t b, int32_t accumulator) {
@@ -52,136 +53,124 @@ __riscv_cv_mac_msu(int32_t a, int32_t b, int32_t accumulator) {
 /* ---------------------------------------------------------------------------
  * 16x16-bit multiply (lower halfwords), unsigned, with normalisation shift
  *
- *   cv.mulun   rd, rs1, rs2, imm5  ->  rd = (u16(rs1) * u16(rs2)) >> imm5
- *   cv.mulhhun rd, rs1, rs2, imm5  ->  rd = (u16hi(rs1) * u16hi(rs2)) >> imm5
- *   cv.mulurn  rd, rs1, rs2, imm5  ->  rd = (u16(rs1) * u16(rs2) + rnd) >> imm5
- *   cv.mulhhurn rd, rs1, rs2, imm5 ->  rd = (u16hi(rs1)*u16hi(rs2) + rnd) >> imm5
+ * cv.mulun   rd, rs1, rs2, imm5  -> rd = (u16(rs1) * u16(rs2)) >> imm5
+ * cv.mulhhun rd, rs1, rs2, imm5  -> rd = (u16hi(rs1) * u16hi(rs2)) >> imm5
+ * cv.mulurn  rd, rs1, rs2, imm5  -> rd = (u16(rs1) * u16(rs2) + rnd) >> imm5
+ * cv.mulhhurn rd, rs1, rs2, imm5 -> rd = (u16hi(rs1)*u16hi(rs2) + rnd) >> imm5
  *
  * SHIFT must be a compile-time constant in [0, 31].
  * These are macros so the SHIFT argument is passed as an immediate.
- * --------------------------------------------------------------------------- */
+ * ---------------------------------------------------------------------------
+ */
 
 #define __riscv_cv_mac_muluN(__rs1, __rs2, __SHIFT)                            \
-  ((uint32_t)__builtin_riscv_cv_mac_muluN((uint32_t)(__rs1),                   \
-                                           (uint32_t)(__rs2),                   \
-                                           (uint32_t)(__SHIFT)))
+  ((uint32_t)__builtin_riscv_cv_mac_muluN(                                     \
+      (uint32_t)(__rs1), (uint32_t)(__rs2), (uint32_t)(__SHIFT)))
 
 #define __riscv_cv_mac_mulhhuN(__rs1, __rs2, __SHIFT)                          \
-  ((uint32_t)__builtin_riscv_cv_mac_mulhhuN((uint32_t)(__rs1),                 \
-                                             (uint32_t)(__rs2),                 \
-                                             (uint32_t)(__SHIFT)))
+  ((uint32_t)__builtin_riscv_cv_mac_mulhhuN(                                   \
+      (uint32_t)(__rs1), (uint32_t)(__rs2), (uint32_t)(__SHIFT)))
 
 #define __riscv_cv_mac_muluRN(__rs1, __rs2, __SHIFT)                           \
-  ((uint32_t)__builtin_riscv_cv_mac_muluRN((uint32_t)(__rs1),                  \
-                                            (uint32_t)(__rs2),                  \
-                                            (uint32_t)(__SHIFT)))
+  ((uint32_t)__builtin_riscv_cv_mac_muluRN(                                    \
+      (uint32_t)(__rs1), (uint32_t)(__rs2), (uint32_t)(__SHIFT)))
 
 #define __riscv_cv_mac_mulhhuRN(__rs1, __rs2, __SHIFT)                         \
-  ((uint32_t)__builtin_riscv_cv_mac_mulhhuRN((uint32_t)(__rs1),                \
-                                              (uint32_t)(__rs2),                \
-                                              (uint32_t)(__SHIFT)))
+  ((uint32_t)__builtin_riscv_cv_mac_mulhhuRN(                                  \
+      (uint32_t)(__rs1), (uint32_t)(__rs2), (uint32_t)(__SHIFT)))
 
 /* ---------------------------------------------------------------------------
  * 16x16-bit multiply (lower halfwords), signed, with normalisation shift
  *
- *   cv.mulsn    rd, rs1, rs2, imm5  ->  rd = (s16(rs1) * s16(rs2)) >> imm5
- *   cv.mulhhsn  rd, rs1, rs2, imm5  ->  rd = (s16hi(rs1)*s16hi(rs2)) >> imm5
- *   cv.mulsrn   rd, rs1, rs2, imm5  ->  rd = (s16(rs1) * s16(rs2) + rnd) >> imm5
- *   cv.mulhhsrn rd, rs1, rs2, imm5  ->  rd = (s16hi(rs1)*s16hi(rs2)+rnd) >> imm5
+ * cv.mulsn    rd, rs1, rs2, imm5 -> rd = (s16(rs1) * s16(rs2)) >> imm5
+ * cv.mulhhsn  rd, rs1, rs2, imm5 -> rd = (s16hi(rs1)*s16hi(rs2)) >> imm5
+ * cv.mulsrn   rd, rs1, rs2, imm5 -> rd = (s16(rs1) * s16(rs2) + rnd) >> imm5
+ * cv.mulhhsrn rd, rs1, rs2, imm5 -> rd = (s16hi(rs1)*s16hi(rs2)+rnd) >> imm5
  *
  * SHIFT must be a compile-time constant in [0, 31].
- * --------------------------------------------------------------------------- */
+ * ---------------------------------------------------------------------------
+ */
 
 #define __riscv_cv_mac_mulsN(__rs1, __rs2, __SHIFT)                            \
-  ((int32_t)__builtin_riscv_cv_mac_mulsN((uint32_t)(__rs1),                    \
-                                          (uint32_t)(__rs2),                    \
-                                          (uint32_t)(__SHIFT)))
+  ((int32_t)__builtin_riscv_cv_mac_mulsN((uint32_t)(__rs1), (uint32_t)(__rs2), \
+                                         (uint32_t)(__SHIFT)))
 
 #define __riscv_cv_mac_mulhhsN(__rs1, __rs2, __SHIFT)                          \
-  ((int32_t)__builtin_riscv_cv_mac_mulhhsN((uint32_t)(__rs1),                  \
-                                            (uint32_t)(__rs2),                  \
-                                            (uint32_t)(__SHIFT)))
+  ((int32_t)__builtin_riscv_cv_mac_mulhhsN(                                    \
+      (uint32_t)(__rs1), (uint32_t)(__rs2), (uint32_t)(__SHIFT)))
 
 #define __riscv_cv_mac_mulsRN(__rs1, __rs2, __SHIFT)                           \
-  ((int32_t)__builtin_riscv_cv_mac_mulsRN((uint32_t)(__rs1),                   \
-                                           (uint32_t)(__rs2),                   \
-                                           (uint32_t)(__SHIFT)))
+  ((int32_t)__builtin_riscv_cv_mac_mulsRN(                                     \
+      (uint32_t)(__rs1), (uint32_t)(__rs2), (uint32_t)(__SHIFT)))
 
 #define __riscv_cv_mac_mulhhsRN(__rs1, __rs2, __SHIFT)                         \
-  ((int32_t)__builtin_riscv_cv_mac_mulhhsRN((uint32_t)(__rs1),                 \
-                                             (uint32_t)(__rs2),                 \
-                                             (uint32_t)(__SHIFT)))
+  ((int32_t)__builtin_riscv_cv_mac_mulhhsRN(                                   \
+      (uint32_t)(__rs1), (uint32_t)(__rs2), (uint32_t)(__SHIFT)))
 
 /* ---------------------------------------------------------------------------
  * 16x16-bit multiply-accumulate (lower halfwords), unsigned
  *
- *   cv.macun    rd, rs1, rs2, imm5  ->  rd = (rd + u16(rs1) * u16(rs2)) >> imm5
- *   cv.machhun  rd, rs1, rs2, imm5  ->  rd = (rd + u16hi(rs1)*u16hi(rs2)) >> imm5
- *   cv.macurn   rd, rs1, rs2, imm5  ->  rd = (rd + u16(rs1)*u16(rs2)+rnd) >> imm5
- *   cv.machhurn rd, rs1, rs2, imm5  ->  rd = (rd+u16hi(rs1)*u16hi(rs2)+rnd)>>imm5
+ * cv.macun    rd, rs1, rs2, imm5 -> rd = (rd + u16(rs1) * u16(rs2)) >> imm5
+ * cv.machhun  rd, rs1, rs2, imm5 -> rd = (rd + u16hi(rs1)*u16hi(rs2)) >> imm5
+ * cv.macurn   rd, rs1, rs2, imm5 -> rd = (rd + u16(rs1)*u16(rs2)+rnd) >> imm5
+ * cv.machhurn rd, rs1, rs2, imm5 -> rd = (rd+u16hi(rs1)*u16hi(rs2)+rnd)>>imm5
  *
  * SHIFT must be a compile-time constant in [0, 31].
  * rD is the accumulator register (read-modify-write).
- * --------------------------------------------------------------------------- */
+ * ---------------------------------------------------------------------------
+ */
 
 #define __riscv_cv_mac_macuN(__rD, __rs1, __rs2, __SHIFT)                      \
   ((uint32_t)__builtin_riscv_cv_mac_macuN((uint32_t)(__rs1),                   \
-                                           (uint32_t)(__rs2),                   \
-                                           (uint32_t)(__rD),                    \
-                                           (uint32_t)(__SHIFT)))
+                                          (uint32_t)(__rs2), (uint32_t)(__rD), \
+                                          (uint32_t)(__SHIFT)))
 
 #define __riscv_cv_mac_machhuN(__rD, __rs1, __rs2, __SHIFT)                    \
-  ((uint32_t)__builtin_riscv_cv_mac_machhuN((uint32_t)(__rs1),                 \
-                                             (uint32_t)(__rs2),                 \
-                                             (uint32_t)(__rD),                  \
-                                             (uint32_t)(__SHIFT)))
+  ((uint32_t)__builtin_riscv_cv_mac_machhuN(                                   \
+      (uint32_t)(__rs1), (uint32_t)(__rs2), (uint32_t)(__rD),                  \
+      (uint32_t)(__SHIFT)))
 
 #define __riscv_cv_mac_macuRN(__rD, __rs1, __rs2, __SHIFT)                     \
-  ((uint32_t)__builtin_riscv_cv_mac_macuRN((uint32_t)(__rs1),                  \
-                                            (uint32_t)(__rs2),                  \
-                                            (uint32_t)(__rD),                   \
-                                            (uint32_t)(__SHIFT)))
+  ((uint32_t)__builtin_riscv_cv_mac_macuRN(                                    \
+      (uint32_t)(__rs1), (uint32_t)(__rs2), (uint32_t)(__rD),                  \
+      (uint32_t)(__SHIFT)))
 
 #define __riscv_cv_mac_machhuRN(__rD, __rs1, __rs2, __SHIFT)                   \
-  ((uint32_t)__builtin_riscv_cv_mac_machhuRN((uint32_t)(__rs1),                \
-                                              (uint32_t)(__rs2),                \
-                                              (uint32_t)(__rD),                 \
-                                              (uint32_t)(__SHIFT)))
+  ((uint32_t)__builtin_riscv_cv_mac_machhuRN(                                  \
+      (uint32_t)(__rs1), (uint32_t)(__rs2), (uint32_t)(__rD),                  \
+      (uint32_t)(__SHIFT)))
 
 /* ---------------------------------------------------------------------------
  * 16x16-bit multiply-accumulate (lower halfwords), signed
  *
- *   cv.macsn    rd, rs1, rs2, imm5  ->  rd = (rd + s16(rs1) * s16(rs2)) >> imm5
- *   cv.machhsn  rd, rs1, rs2, imm5  ->  rd = (rd+s16hi(rs1)*s16hi(rs2)) >> imm5
- *   cv.macsrn   rd, rs1, rs2, imm5  ->  rd = (rd+s16(rs1)*s16(rs2)+rnd) >> imm5
- *   cv.machhsrn rd, rs1, rs2, imm5  ->  rd = (rd+s16hi*s16hi+rnd) >> imm5
+ * cv.macsn    rd, rs1, rs2, imm5 -> rd = (rd + s16(rs1) * s16(rs2)) >> imm5
+ * cv.machhsn  rd, rs1, rs2, imm5 -> rd = (rd+s16hi(rs1)*s16hi(rs2)) >> imm5
+ * cv.macsrn   rd, rs1, rs2, imm5 -> rd = (rd+s16(rs1)*s16(rs2)+rnd) >> imm5
+ * cv.machhsrn rd, rs1, rs2, imm5 -> rd = (rd+s16hi*s16hi+rnd) >> imm5
  *
  * SHIFT must be a compile-time constant in [0, 31].
- * --------------------------------------------------------------------------- */
+ * ---------------------------------------------------------------------------
+ */
 
 #define __riscv_cv_mac_macsN(__rD, __rs1, __rs2, __SHIFT)                      \
-  ((int32_t)__builtin_riscv_cv_mac_macsN((uint32_t)(__rs1),                    \
-                                          (uint32_t)(__rs2),                    \
-                                          (uint32_t)(__rD),                     \
-                                          (uint32_t)(__SHIFT)))
+  ((int32_t)__builtin_riscv_cv_mac_macsN((uint32_t)(__rs1), (uint32_t)(__rs2), \
+                                         (uint32_t)(__rD),                     \
+                                         (uint32_t)(__SHIFT)))
 
 #define __riscv_cv_mac_machhsN(__rD, __rs1, __rs2, __SHIFT)                    \
-  ((int32_t)__builtin_riscv_cv_mac_machhsN((uint32_t)(__rs1),                  \
-                                            (uint32_t)(__rs2),                  \
-                                            (uint32_t)(__rD),                   \
-                                            (uint32_t)(__SHIFT)))
+  ((int32_t)__builtin_riscv_cv_mac_machhsN(                                    \
+      (uint32_t)(__rs1), (uint32_t)(__rs2), (uint32_t)(__rD),                  \
+      (uint32_t)(__SHIFT)))
 
 #define __riscv_cv_mac_macsRN(__rD, __rs1, __rs2, __SHIFT)                     \
   ((int32_t)__builtin_riscv_cv_mac_macsRN((uint32_t)(__rs1),                   \
-                                           (uint32_t)(__rs2),                   \
-                                           (uint32_t)(__rD),                    \
-                                           (uint32_t)(__SHIFT)))
+                                          (uint32_t)(__rs2), (uint32_t)(__rD), \
+                                          (uint32_t)(__SHIFT)))
 
 #define __riscv_cv_mac_machhsRN(__rD, __rs1, __rs2, __SHIFT)                   \
-  ((int32_t)__builtin_riscv_cv_mac_machhsRN((uint32_t)(__rs1),                 \
-                                             (uint32_t)(__rs2),                 \
-                                             (uint32_t)(__rD),                  \
-                                             (uint32_t)(__SHIFT)))
+  ((int32_t)__builtin_riscv_cv_mac_machhsRN(                                   \
+      (uint32_t)(__rs1), (uint32_t)(__rs2), (uint32_t)(__rD),                  \
+      (uint32_t)(__SHIFT)))
 
 #endif /* __riscv_xcvmac */
 
diff --git a/clang/lib/Headers/riscv_corev_simd.h b/clang/lib/Headers/riscv_corev_simd.h
index a1b7164b3977e..3127d0eebfe92 100644
--- a/clang/lib/Headers/riscv_corev_simd.h
+++ b/clang/lib/Headers/riscv_corev_simd.h
@@ -32,7 +32,7 @@ extern "C" {
 
 #if defined(__riscv_xcvsimd)
 
-#define __DEFAULT_FN_ATTRS                                                      \
+#define __DEFAULT_FN_ATTRS                                                     \
   __attribute__((__always_inline__, __nodebug__, __artificial__))
 
 /* ===========================================================================
@@ -44,16 +44,16 @@ extern "C" {
  * The _h variant takes a div-shift code as third argument (0=no shift,
  * 1=/2, 2=/4, 3=/8). This is an immediate, so it must be a compile-time
  * constant — hence the macro form.
- * =========================================================================== */
+ * ===========================================================================
+ */
 
 /* add.h with div-by-N right shift (DIVCODE in [0,3]) */
 #define __riscv_cv_simd_add_h(__rs1, __rs2, __DIVCODE)                         \
-  ((uint32_t)__builtin_riscv_cv_simd_add_h((uint32_t)(__rs1),                  \
-                                            (uint32_t)(__rs2),                  \
-                                            (uint32_t)(__DIVCODE)))
+  ((uint32_t)__builtin_riscv_cv_simd_add_h(                                    \
+      (uint32_t)(__rs1), (uint32_t)(__rs2), (uint32_t)(__DIVCODE)))
 
-static __inline__ uint32_t __DEFAULT_FN_ATTRS
-__riscv_cv_simd_add_b(uint32_t a, uint32_t b) {
+static __inline__ uint32_t
+    __DEFAULT_FN_ATTRS __riscv_cv_simd_add_b(uint32_t a, uint32_t b) {
   return __builtin_riscv_cv_simd_add_b(a, b);
 }
 static __inline__ uint32_t __DEFAULT_FN_ATTRS
@@ -67,12 +67,11 @@ __riscv_cv_simd_add_sc_b(uint32_t a, uint32_t b) {
 
 /* sub.h with div-by-N right shift (DIVCODE in [0,3]) */
 #define __riscv_cv_simd_sub_h(__rs1, __rs2, __DIVCODE)                         \
-  ((uint32_t)__builtin_riscv_cv_simd_sub_h((uint32_t)(__rs1),                  \
-                                            (uint32_t)(__rs2),                  \
-                                            (uint32_t)(__DIVCODE)))
+  ((uint32_t)__builtin_riscv_cv_simd_sub_h(                                    \
+      (uint32_t)(__rs1), (uint32_t)(__rs2), (uint32_t)(__DIVCODE)))
 
-static __inline__ uint32_t __DEFAULT_FN_ATTRS
-__riscv_cv_simd_sub_b(uint32_t a, uint32_t b) {
+static __inline__ uint32_t
+    __DEFAULT_FN_ATTRS __riscv_cv_simd_sub_b(uint32_t a, uint32_t b) {
   return __builtin_riscv_cv_simd_sub_b(a, b);
 }
 static __inline__ uint32_t __DEFAULT_FN_ATTRS
@@ -86,7 +85,8 @@ __riscv_cv_simd_sub_sc_b(uint32_t a, uint32_t b) {
 
 /* ===========================================================================
  * AVG / AVGU  (signed and unsigned average)
- * =========================================================================== */
+ * ===========================================================================
+ */
 
 static __inline__ uint32_t __DEFAULT_FN_ATTRS
 __riscv_cv_simd_avg_h(uint32_t a, uint32_t b) {
@@ -124,7 +124,8 @@ __riscv_cv_simd_avgu_sc_b(uint32_t a, uint32_t b) {
 
 /* ===========================================================================
  * MIN / MINU  (signed and unsigned per-element minimum)
- * =========================================================================== */
+ * ===========================================================================
+ */
 
 static __inline__ uint32_t __DEFAULT_FN_ATTRS
 __riscv_cv_simd_min_h(uint32_t a, uint32_t b) {
@@ -162,7 +163,8 @@ __riscv_cv_simd_minu_sc_b(uint32_t a, uint32_t b) {
 
 /* ===========================================================================
  * MAX / MAXU  (signed and unsigned per-element maximum)
- * =========================================================================== */
+ * ===========================================================================
+ */
 
 static __inline__ uint32_t __DEFAULT_FN_ATTRS
 __riscv_cv_simd_max_h(uint32_t a, uint32_t b) {
@@ -203,7 +205,8 @@ __riscv_cv_simd_maxu_sc_b(uint32_t a, uint32_t b) {
  * .sc  variants take a GPR shift amount (lower bits used)
  * No .sci variant for shifts (the instruction encodes a small immediate
  * directly in the funct3 space; use the .sc_h/.sc_b with a constant GPR).
- * =========================================================================== */
+ * ===========================================================================
+ */
 
 static __inline__ uint32_t __DEFAULT_FN_ATTRS
 __riscv_cv_simd_srl_h(uint32_t a, uint32_t b) {
@@ -258,14 +261,15 @@ __riscv_cv_simd_sll_sc_b(uint32_t a, uint32_t b) {
 
 /* ===========================================================================
  * BITWISE: OR / XOR / AND
- * =========================================================================== */
+ * ===========================================================================
+ */
 
-static __inline__ uint32_t __DEFAULT_FN_ATTRS
-__riscv_cv_simd_or_h(uint32_t a, uint32_t b) {
+static __inline__ uint32_t __DEFAULT_FN_ATTRS __riscv_cv_simd_or_h(uint32_t a,
+                                                                   uint32_t b) {
   return __builtin_riscv_cv_simd_or_h(a, b);
 }
-static __inline__ uint32_t __DEFAULT_FN_ATTRS
-__riscv_cv_simd_or_b(uint32_t a, uint32_t b) {
+static __inline__ uint32_t __DEFAULT_FN_ATTRS __riscv_cv_simd_or_b(uint32_t a,
+                                                                   uint32_t b) {
   return __builtin_riscv_cv_simd_or_b(a, b);
 }
 static __inline__ uint32_t __DEFAULT_FN_ATTRS
@@ -313,7 +317,8 @@ __riscv_cv_simd_and_sc_b(uint32_t a, uint32_t b) {
 
 /* ===========================================================================
  * ABS  (per-element absolute value)
- * =========================================================================== */
+ * ===========================================================================
+ */
 
 static __inline__ uint32_t __DEFAULT_FN_ATTRS
 __riscv_cv_simd_abs_h(uint32_t a) {
@@ -332,7 +337,8 @@ __riscv_cv_simd_abs_b(uint32_t a) {
  * dotsp  — signed   × signed  dot product  (result is int32)
  *
  * sdot* — same but adds result to accumulator register rd (read-modify-write)
- * =========================================================================== */
+ * ===========================================================================
+ */
 
 /* dotup */
 static __inline__ uint32_t __DEFAULT_FN_ATTRS
@@ -453,35 +459,34 @@ __riscv_cv_simd_sdotsp_sc_b(uint32_t a, uint32_t b, int32_t acc) {
  * cv.insert.b   rd, rs1, IMM  — insert lower byte of rs1 into rd at IMM
  *
  * IMM is an immediate (compile-time constant), so macros are used.
- * =========================================================================== */
+ * ===========================================================================
+ */
 
 #define __riscv_cv_simd_extract_h(__rs1, __IMM)                                \
   ((int32_t)__builtin_riscv_cv_simd_extract_h((uint32_t)(__rs1),               \
-                                               (uint32_t)(__IMM)))
+                                              (uint32_t)(__IMM)))
 
 #define __riscv_cv_simd_extract_b(__rs1, __IMM)                                \
   ((int32_t)__builtin_riscv_cv_simd_extract_b((uint32_t)(__rs1),               \
-                                               (uint32_t)(__IMM)))
+                                              (uint32_t)(__IMM)))
 
 #define __riscv_cv_simd_extractu_h(__rs1, __IMM)                               \
   ((uint32_t)__builtin_riscv_cv_simd_extractu_h((uint32_t)(__rs1),             \
-                                                 (uint32_t)(__IMM)))
+                                                (uint32_t)(__IMM)))
 
 #define __riscv_cv_simd_extractu_b(__rs1, __IMM)                               \
   ((uint32_t)__builtin_riscv_cv_simd_extractu_b((uint32_t)(__rs1),             \
-                                                 (uint32_t)(__IMM)))
+                                                (uint32_t)(__IMM)))
 
 /* insert: rd is both input and output (read-modify-write accumulator).
    The intrinsic prototype is (rs1, rd_in, IMM) -> rd_out.               */
 #define __riscv_cv_simd_insert_h(__rD, __rs1, __IMM)                           \
-  ((uint32_t)__builtin_riscv_cv_simd_insert_h((uint32_t)(__rD),                \
-                                               (uint32_t)(__rs1),               \
-                                               (uint32_t)(__IMM)))
+  ((uint32_t)__builtin_riscv_cv_simd_insert_h(                                 \
+      (uint32_t)(__rD), (uint32_t)(__rs1), (uint32_t)(__IMM)))
 
 #define __riscv_cv_simd_insert_b(__rD, __rs1, __IMM)                           \
-  ((uint32_t)__builtin_riscv_cv_simd_insert_b((uint32_t)(__rD),                \
-                                               (uint32_t)(__rs1),               \
-                                               (uint32_t)(__IMM)))
+  ((uint32_t)__builtin_riscv_cv_simd_insert_b(                                 \
+      (uint32_t)(__rD), (uint32_t)(__rs1), (uint32_t)(__IMM)))
 
 /* ===========================================================================
  * SHUFFLE / SHUFFLE2
@@ -493,7 +498,8 @@ __riscv_cv_simd_sdotsp_sc_b(uint32_t a, uint32_t b, int32_t acc) {
  *                                  (split internally into SHUFFLEIx.sci.b)
  * cv.shuffle2.h    rd, rs1, rs2  — interleave shuffle using rs2 mask + rd input
  * cv.shuffle2.b    rd, rs1, rs2  — interleave shuffle using rs2 mask + rd input
- * =========================================================================== */
+ * ===========================================================================
+ */
 
 static __inline__ uint32_t __DEFAULT_FN_ATTRS
 __riscv_cv_simd_shuffle_h(uint32_t a, uint32_t mask) {
@@ -507,14 +513,14 @@ __riscv_cv_simd_shuffle_b(uint32_t a, uint32_t mask) {
 /* shuffle.sci.h — IMM is a 2-bit immediate [0,3] */
 #define __riscv_cv_simd_shuffle_sci_h(__rs1, __IMM)                            \
   ((uint32_t)__builtin_riscv_cv_simd_shuffle_sci_h((uint32_t)(__rs1),          \
-                                                    (uint32_t)(__IMM)))
+                                                   (uint32_t)(__IMM)))
 
 /* shuffle.sci.b — IMM is an 8-bit immediate [0,255].
    The backend splits this into two bits (top 2 → SHUFFLEIx selector) + 6-bit
    payload, emitting the correct CV_SHUFFLEIx_SCI_B instruction.           */
 #define __riscv_cv_simd_shuffle_sci_b(__rs1, __IMM)                            \
   ((uint32_t)__builtin_riscv_cv_simd_shuffle_sci_b((uint32_t)(__rs1),          \
-                                                    (uint32_t)(__IMM)))
+                                                   (uint32_t)(__IMM)))
 
 /* shuffle2: rd is read-modify-write (used as additional input lane) */
 static __inline__ uint32_t __DEFAULT_FN_ATTRS
@@ -529,15 +535,21 @@ __riscv_cv_simd_shuffle2_b(uint32_t rD, uint32_t rs1, uint32_t rs2) {
 /* ===========================================================================
  * PACK
  *
- * cv.pack    rd, rs1, rs2  — pack lower halfwords: rd = {rs1[15:0], rs2[15:0]}
- * cv.pack.h  rd, rs1, rs2  — pack upper halfwords: rd = {rs1[31:16], rs2[31:16]}
- * cv.packhi.b rd, rs1, rs2 — pack odd bytes:  rd = {rs1[31:24],rs1[15:8],
- *                                                    rs2[31:24],rs2[15:8]}
- * cv.packlo.b rd, rs1, rs2 — pack even bytes: rd = {rs1[23:16],rs1[7:0],
- *                                                    rs2[23:16],rs2[7:0]}
+ * cv.pack    rd, rs1, rs2  — pack lower halfwords:
+ * rd = {rs1[15:0], rs2[15:0]}
+ *
+ * cv.pack.h  rd, rs1, rs2  — pack upper halfwords:
+ * rd = {rs1[31:16], rs2[31:16]}
+ *
+ * cv.packhi.b rd, rs1, rs2 — pack odd bytes:
+ * rd = {rs1[31:24],rs1[15:8], rs2[31:24],rs2[15:8]}
+ *
+ * cv.packlo.b rd, rs1, rs2 — pack even bytes:
+ * rd = {rs1[23:16],rs1[7:0], rs2[23:16],rs2[7:0]}
  *
  * packhi/packlo: rd is read-modify-write.
- * =========================================================================== */
+ * ===========================================================================
+ */
 
 static __inline__ uint32_t __DEFAULT_FN_ATTRS
 __riscv_cv_simd_packlo_h(uint32_t rs1, uint32_t rs2) {
@@ -560,107 +572,188 @@ __riscv_cv_simd_packlo_b(uint32_t rD, uint32_t rs1, uint32_t rs2) {
 
 /* ===========================================================================
  * COMPARE  (per-element, result is all-1s or all-0s per lane)
- * =========================================================================== */
+ * ===========================================================================
+ */
 
 /* cmpeq */
 static __inline__ uint32_t __DEFAULT_FN_ATTRS
-__riscv_cv_simd_cmpeq_h(uint32_t a, uint32_t b) { return __builtin_riscv_cv_simd_cmpeq_h(a, b); }
+__riscv_cv_simd_cmpeq_h(uint32_t a, uint32_t b) {
+  return __builtin_riscv_cv_simd_cmpeq_h(a, b);
+}
 static __inline__ uint32_t __DEFAULT_FN_ATTRS
-__riscv_cv_simd_cmpeq_b(uint32_t a, uint32_t b) { return __builtin_riscv_cv_simd_cmpeq_b(a, b); }
+__riscv_cv_simd_cmpeq_b(uint32_t a, uint32_t b) {
+  return __builtin_riscv_cv_simd_cmpeq_b(a, b);
+}
 static __inline__ uint32_t __DEFAULT_FN_ATTRS
-__riscv_cv_simd_cmpeq_sc_h(uint32_t a, uint32_t b) { return __builtin_riscv_cv_simd_cmpeq_sc_h(a, b); }
+__riscv_cv_simd_cmpeq_sc_h(uint32_t a, uint32_t b) {
+  return __builtin_riscv_cv_simd_cmpeq_sc_h(a, b);
+}
 static __inline__ uint32_t __DEFAULT_FN_ATTRS
-__riscv_cv_simd_cmpeq_sc_b(uint32_t a, uint32_t b) { return __builtin_riscv_cv_simd_cmpeq_sc_b(a, b); }
+__riscv_cv_simd_cmpeq_sc_b(uint32_t a, uint32_t b) {
+  return __builtin_riscv_cv_simd_cmpeq_sc_b(a, b);
+}
 
 /* cmpne */
 static __inline__ uint32_t __DEFAULT_FN_ATTRS
-__riscv_cv_simd_cmpne_h(uint32_t a, uint32_t b) { return __builtin_riscv_cv_simd_cmpne_h(a, b); }
+__riscv_cv_simd_cmpne_h(uint32_t a, uint32_t b) {
+  return __builtin_riscv_cv_simd_cmpne_h(a, b);
+}
 static __inline__ uint32_t __DEFAULT_FN_ATTRS
-__riscv_cv_simd_cmpne_b(uint32_t a, uint32_t b) { return __builtin_riscv_cv_simd_cmpne_b(a, b); }
+__riscv_cv_simd_cmpne_b(uint32_t a, uint32_t b) {
+  return __builtin_riscv_cv_simd_cmpne_b(a, b);
+}
 static __inline__ uint32_t __DEFAULT_FN_ATTRS
-__riscv_cv_simd_cmpne_sc_h(uint32_t a, uint32_t b) { return __builtin_riscv_cv_simd_cmpne_sc_h(a, b); }
+__riscv_cv_simd_cmpne_sc_h(uint32_t a, uint32_t b) {
+  return __builtin_riscv_cv_simd_cmpne_sc_h(a, b);
+}
 static __inline__ uint32_t __DEFAULT_FN_ATTRS
-__riscv_cv_simd_cmpne_sc_b(uint32_t a, uint32_t b) { return __builtin_riscv_cv_simd_cmpne_sc_b(a, b); }
+__riscv_cv_simd_cmpne_sc_b(uint32_t a, uint32_t b) {
+  return __builtin_riscv_cv_simd_cmpne_sc_b(a, b);
+}
 
 /* cmpgt (signed greater-than) */
 static __inline__ uint32_t __DEFAULT_FN_ATTRS
-__riscv_cv_simd_cmpgt_h(uint32_t a, uint32_t b) { return __builtin_riscv_cv_simd_cmpgt_h(a, b); }
+__riscv_cv_simd_cmpgt_h(uint32_t a, uint32_t b) {
+  return __builtin_riscv_cv_simd_cmpgt_h(a, b);
+}
 static __inline__ uint32_t __DEFAULT_FN_ATTRS
-__riscv_cv_simd_cmpgt_b(uint32_t a, uint32_t b) { return __builtin_riscv_cv_simd_cmpgt_b(a, b); }
+__riscv_cv_simd_cmpgt_b(uint32_t a, uint32_t b) {
+  return __builtin_riscv_cv_simd_cmpgt_b(a, b);
+}
 static __inline__ uint32_t __DEFAULT_FN_ATTRS
-__riscv_cv_simd_cmpgt_sc_h(uint32_t a, uint32_t b) { return __builtin_riscv_cv_simd_cmpgt_sc_h(a, b); }
+__riscv_cv_simd_cmpgt_sc_h(uint32_t a, uint32_t b) {
+  return __builtin_riscv_cv_simd_cmpgt_sc_h(a, b);
+}
 static __inline__ uint32_t __DEFAULT_FN_ATTRS
-__riscv_cv_simd_cmpgt_sc_b(uint32_t a, uint32_t b) { return __builtin_riscv_cv_simd_cmpgt_sc_b(a, b); }
+__riscv_cv_simd_cmpgt_sc_b(uint32_t a, uint32_t b) {
+  return __builtin_riscv_cv_simd_cmpgt_sc_b(a, b);
+}
 
 /* cmpge (signed greater-or-equal) */
 static __inline__ uint32_t __DEFAULT_FN_ATTRS
-__riscv_cv_simd_cmpge_h(uint32_t a, uint32_t b) { return __builtin_riscv_cv_simd_cmpge_h(a, b); }
+__riscv_cv_simd_cmpge_h(uint32_t a, uint32_t b) {
+  return __builtin_riscv_cv_simd_cmpge_h(a, b);
+}
 static __inline__ uint32_t __DEFAULT_FN_ATTRS
-__riscv_cv_simd_cmpge_b(uint32_t a, uint32_t b) { return __builtin_riscv_cv_simd_cmpge_b(a, b); }
+__riscv_cv_simd_cmpge_b(uint32_t a, uint32_t b) {
+  return __builtin_riscv_cv_simd_cmpge_b(a, b);
+}
 static __inline__ uint32_t __DEFAULT_FN_ATTRS
-__riscv_cv_simd_cmpge_sc_h(uint32_t a, uint32_t b) { return __builtin_riscv_cv_simd_cmpge_sc_h(a, b); }
+__riscv_cv_simd_cmpge_sc_h(uint32_t a, uint32_t b) {
+  return __builtin_riscv_cv_simd_cmpge_sc_h(a, b);
+}
 static __inline__ uint32_t __DEFAULT_FN_ATTRS
-__riscv_cv_simd_cmpge_sc_b(uint32_t a, uint32_t b) { return __builtin_riscv_cv_simd_cmpge_sc_b(a, b); }
+__riscv_cv_simd_cmpge_sc_b(uint32_t a, uint32_t b) {
+  return __builtin_riscv_cv_simd_cmpge_sc_b(a, b);
+}
 
 /* cmplt (signed less-than) */
 static __inline__ uint32_t __DEFAULT_FN_ATTRS
-__riscv_cv_simd_cmplt_h(uint32_t a, uint32_t b) { return __builtin_riscv_cv_simd_cmplt_h(a, b); }
+__riscv_cv_simd_cmplt_h(uint32_t a, uint32_t b) {
+  return __builtin_riscv_cv_simd_cmplt_h(a, b);
+}
 static __inline__ uint32_t __DEFAULT_FN_ATTRS
-__riscv_cv_simd_cmplt_b(uint32_t a, uint32_t b) { return __builtin_riscv_cv_simd_cmplt_b(a, b); }
+__riscv_cv_simd_cmplt_b(uint32_t a, uint32_t b) {
+  return __builtin_riscv_cv_simd_cmplt_b(a, b);
+}
 static __inline__ uint32_t __DEFAULT_FN_ATTRS
-__riscv_cv_simd_cmplt_sc_h(uint32_t a, uint32_t b) { return __builtin_riscv_cv_simd_cmplt_sc_h(a, b); }
+__riscv_cv_simd_cmplt_sc_h(uint32_t a, uint32_t b) {
+  return __builtin_riscv_cv_simd_cmplt_sc_h(a, b);
+}
 static __inline__ uint32_t __DEFAULT_FN_ATTRS
-__riscv_cv_simd_cmplt_sc_b(uint32_t a, uint32_t b) { return __builtin_riscv_cv_simd_cmplt_sc_b(a, b); }
+__riscv_cv_simd_cmplt_sc_b(uint32_t a, uint32_t b) {
+  return __builtin_riscv_cv_simd_cmplt_sc_b(a, b);
+}
 
 /* cmple (signed less-or-equal) */
 static __inline__ uint32_t __DEFAULT_FN_ATTRS
-__riscv_cv_simd_cmple_h(uint32_t a, uint32_t b) { return __builtin_riscv_cv_simd_cmple_h(a, b); }
+__riscv_cv_simd_cmple_h(uint32_t a, uint32_t b) {
+  return __builtin_riscv_cv_simd_cmple_h(a, b);
+}
 static __inline__ uint32_t __DEFAULT_FN_ATTRS
-__riscv_cv_simd_cmple_b(uint32_t a, uint32_t b) { return __builtin_riscv_cv_simd_cmple_b(a, b); }
+__riscv_cv_simd_cmple_b(uint32_t a, uint32_t b) {
+  return __builtin_riscv_cv_simd_cmple_b(a, b);
+}
 static __inline__ uint32_t __DEFAULT_FN_ATTRS
-__riscv_cv_simd_cmple_sc_h(uint32_t a, uint32_t b) { return __builtin_riscv_cv_simd_cmple_sc_h(a, b); }
+__riscv_cv_simd_cmple_sc_h(uint32_t a, uint32_t b) {
+  return __builtin_riscv_cv_simd_cmple_sc_h(a, b);
+}
 static __inline__ uint32_t __DEFAULT_FN_ATTRS
-__riscv_cv_simd_cmple_sc_b(uint32_t a, uint32_t b) { return __builtin_riscv_cv_simd_cmple_sc_b(a, b); }
+__riscv_cv_simd_cmple_sc_b(uint32_t a, uint32_t b) {
+  return __builtin_riscv_cv_simd_cmple_sc_b(a, b);
+}
 
 /* cmpgtu (unsigned greater-than) */
 static __inline__ uint32_t __DEFAULT_FN_ATTRS
-__riscv_cv_simd_cmpgtu_h(uint32_t a, uint32_t b) { return __builtin_riscv_cv_simd_cmpgtu_h(a, b); }
+__riscv_cv_simd_cmpgtu_h(uint32_t a, uint32_t b) {
+  return __builtin_riscv_cv_simd_cmpgtu_h(a, b);
+}
 static __inline__ uint32_t __DEFAULT_FN_ATTRS
-__riscv_cv_simd_cmpgtu_b(uint32_t a, uint32_t b) { return __builtin_riscv_cv_simd_cmpgtu_b(a, b); }
+__riscv_cv_simd_cmpgtu_b(uint32_t a, uint32_t b) {
+  return __builtin_riscv_cv_simd_cmpgtu_b(a, b);
+}
 static __inline__ uint32_t __DEFAULT_FN_ATTRS
-__riscv_cv_simd_cmpgtu_sc_h(uint32_t a, uint32_t b) { return __builtin_riscv_cv_simd_cmpgtu_sc_h(a, b); }
+__riscv_cv_simd_cmpgtu_sc_h(uint32_t a, uint32_t b) {
+  return __builtin_riscv_cv_simd_cmpgtu_sc_h(a, b);
+}
 static __inline__ uint32_t __DEFAULT_FN_ATTRS
-__riscv_cv_simd_cmpgtu_sc_b(uint32_t a, uint32_t b) { return __builtin_riscv_cv_simd_cmpgtu_sc_b(a, b); }
+__riscv_cv_simd_cmpgtu_sc_b(uint32_t a, uint32_t b) {
+  return __builtin_riscv_cv_simd_cmpgtu_sc_b(a, b);
+}
 
 /* cmpgeu (unsigned greater-or-equal) */
 static __inline__ uint32_t __DEFAULT_FN_ATTRS
-__riscv_cv_simd_cmpgeu_h(uint32_t a, uint32_t b) { return __builtin_riscv_cv_simd_cmpgeu_h(a, b); }
+__riscv_cv_simd_cmpgeu_h(uint32_t a, uint32_t b) {
+  return __builtin_riscv_cv_simd_cmpgeu_h(a, b);
+}
 static __inline__ uint32_t __DEFAULT_FN_ATTRS
-__riscv_cv_simd_cmpgeu_b(uint32_t a, uint32_t b) { return __builtin_riscv_cv_simd_cmpgeu_b(a, b); }
+__riscv_cv_simd_cmpgeu_b(uint32_t a, uint32_t b) {
+  return __builtin_riscv_cv_simd_cmpgeu_b(a, b);
+}
 static __inline__ uint32_t __DEFAULT_FN_ATTRS
-__riscv_cv_simd_cmpgeu_sc_h(uint32_t a, uint32_t b) { return __builtin_riscv_cv_simd_cmpgeu_sc_h(a, b); }
+__riscv_cv_simd_cmpgeu_sc_h(uint32_t a, uint32_t b) {
+  return __builtin_riscv_cv_simd_cmpgeu_sc_h(a, b);
+}
 static __inline__ uint32_t __DEFAULT_FN_ATTRS
-__riscv_cv_simd_cmpgeu_sc_b(uint32_t a, uint32_t b) { return __builtin_riscv_cv_simd_cmpgeu_sc_b(a, b); }
+__riscv_cv_simd_cmpgeu_sc_b(uint32_t a, uint32_t b) {
+  return __builtin_riscv_cv_simd_cmpgeu_sc_b(a, b);
+}
 
 /* cmpltu (unsigned less-than) */
 static __inline__ uint32_t __DEFAULT_FN_ATTRS
-__riscv_cv_simd_cmpltu_h(uint32_t a, uint32_t b) { return __builtin_riscv_cv_simd_cmpltu_h(a, b); }
+__riscv_cv_simd_cmpltu_h(uint32_t a, uint32_t b) {
+  return __builtin_riscv_cv_simd_cmpltu_h(a, b);
+}
 static __inline__ uint32_t __DEFAULT_FN_ATTRS
-__riscv_cv_simd_cmpltu_b(uint32_t a, uint32_t b) { return __builtin_riscv_cv_simd_cmpltu_b(a, b); }
+__riscv_cv_simd_cmpltu_b(uint32_t a, uint32_t b) {
+  return __builtin_riscv_cv_simd_cmpltu_b(a, b);
+}
 static __inline__ uint32_t __DEFAULT_FN_ATTRS
-__riscv_cv_simd_cmpltu_sc_h(uint32_t a, uint32_t b) { return __builtin_riscv_cv_simd_cmpltu_sc_h(a, b); }
+__riscv_cv_simd_cmpltu_sc_h(uint32_t a, uint32_t b) {
+  return __builtin_riscv_cv_simd_cmpltu_sc_h(a, b);
+}
 static __inline__ uint32_t __DEFAULT_FN_ATTRS
-__riscv_cv_simd_cmpltu_sc_b(uint32_t a, uint32_t b) { return __builtin_riscv_cv_simd_cmpltu_sc_b(a, b); }
+__riscv_cv_simd_cmpltu_sc_b(uint32_t a, uint32_t b) {
+  return __builtin_riscv_cv_simd_cmpltu_sc_b(a, b);
+}
 
 /* cmpleu (unsigned less-or-equal) */
 static __inline__ uint32_t __DEFAULT_FN_ATTRS
-__riscv_cv_simd_cmpleu_h(uint32_t a, uint32_t b) { return __builtin_riscv_cv_simd_cmpleu_h(a, b); }
+__riscv_cv_simd_cmpleu_h(uint32_t a, uint32_t b) {
+  return __builtin_riscv_cv_simd_cmpleu_h(a, b);
+}
 static __inline__ uint32_t __DEFAULT_FN_ATTRS
-__riscv_cv_simd_cmpleu_b(uint32_t a, uint32_t b) { return __builtin_riscv_cv_simd_cmpleu_b(a, b); }
+__riscv_cv_simd_cmpleu_b(uint32_t a, uint32_t b) {
+  return __builtin_riscv_cv_simd_cmpleu_b(a, b);
+}
 static __inline__ uint32_t __DEFAULT_FN_ATTRS
-__riscv_cv_simd_cmpleu_sc_h(uint32_t a, uint32_t b) { return __builtin_riscv_cv_simd_cmpleu_sc_h(a, b); }
+__riscv_cv_simd_cmpleu_sc_h(uint32_t a, uint32_t b) {
+  return __builtin_riscv_cv_simd_cmpleu_sc_h(a, b);
+}
 static __inline__ uint32_t __DEFAULT_FN_ATTRS
-__riscv_cv_simd_cmpleu_sc_b(uint32_t a, uint32_t b) { return __builtin_riscv_cv_simd_cmpleu_sc_b(a, b); }
+__riscv_cv_simd_cmpleu_sc_b(uint32_t a, uint32_t b) {
+  return __builtin_riscv_cv_simd_cmpleu_sc_b(a, b);
+}
 
 /* ===========================================================================
  * COMPLEX NUMBER OPERATIONS
@@ -674,29 +767,27 @@ __riscv_cv_simd_cmpleu_sc_b(uint32_t a, uint32_t b) { return __builtin_riscv_cv_
  *
  * cv.subrotmj   rd, rs1, rs2 [, divcode]  — subtract + rotate by -j
  *   result = ((rs1 - rs2) >> div) rotated by -j  (swap re/im, negate new im)
- * =========================================================================== */
+ * ===========================================================================
+ */
 
 #define __riscv_cv_simd_cplxmul_r(__rD, __rs1, __rs2, __DIVCODE)               \
-  ((uint32_t)__builtin_riscv_cv_simd_cplxmul_r((uint32_t)(__rs1),              \
-                                                (uint32_t)(__rs2),              \
-                                                (uint32_t)(__rD),               \
-                                                (uint32_t)(__DIVCODE)))
+  ((uint32_t)__builtin_riscv_cv_simd_cplxmul_r(                                \
+      (uint32_t)(__rs1), (uint32_t)(__rs2), (uint32_t)(__rD),                  \
+      (uint32_t)(__DIVCODE)))
 
 #define __riscv_cv_simd_cplxmul_i(__rD, __rs1, __rs2, __DIVCODE)               \
-  ((uint32_t)__builtin_riscv_cv_simd_cplxmul_i((uint32_t)(__rs1),              \
-                                                (uint32_t)(__rs2),              \
-                                                (uint32_t)(__rD),               \
-                                                (uint32_t)(__DIVCODE)))
+  ((uint32_t)__builtin_riscv_cv_simd_cplxmul_i(                                \
+      (uint32_t)(__rs1), (uint32_t)(__rs2), (uint32_t)(__rD),                  \
+      (uint32_t)(__DIVCODE)))
 
-static __inline__ uint32_t __DEFAULT_FN_ATTRS
-__riscv_cv_simd_cplxconj(uint32_t a) {
+static __inline__ uint32_t
+    __DEFAULT_FN_ATTRS __riscv_cv_simd_cplxconj(uint32_t a) {
   return __builtin_riscv_cv_simd_cplxconj(a);
 }
 
 #define __riscv_cv_simd_subrotmj(__rs1, __rs2, __DIVCODE)                      \
-  ((uint32_t)__builtin_riscv_cv_simd_subrotmj((uint32_t)(__rs1),               \
-                                               (uint32_t)(__rs2),               \
-                                               (uint32_t)(__DIVCODE)))
+  ((uint32_t)__builtin_riscv_cv_simd_subrotmj(                                 \
+      (uint32_t)(__rs1), (uint32_t)(__rs2), (uint32_t)(__DIVCODE)))
 
 #endif /* __riscv_xcvsimd */
 
diff --git a/clang/lib/Sema/SemaRISCV.cpp b/clang/lib/Sema/SemaRISCV.cpp
index 0af3053ff3db9..40e89529d4656 100644
--- a/clang/lib/Sema/SemaRISCV.cpp
+++ b/clang/lib/Sema/SemaRISCV.cpp
@@ -679,22 +679,27 @@ bool SemaRISCV::CheckBuiltinFunctionCall(const TargetInfo &TI,
     return SemaRef.BuiltinConstantArgRange(TheCall, 3, 0, 31);
 
   // XCVsimd — extract/insert index
+  // [0,1] for 2 halfwords
   case RISCV::BI__builtin_riscv_cv_simd_extract_h:
   case RISCV::BI__builtin_riscv_cv_simd_extractu_h:
-  return SemaRef.BuiltinConstantArgRange(TheCall, 1, 0, 1); // [0,1] for 2 halfwords
+    return SemaRef.BuiltinConstantArgRange(TheCall, 1, 0, 1);
+  // [0,1] for 2 halfwords
   case RISCV::BI__builtin_riscv_cv_simd_insert_h:
-    return SemaRef.BuiltinConstantArgRange(TheCall, 2, 0, 1); // [0,1] for 2 halfwords
+    return SemaRef.BuiltinConstantArgRange(TheCall, 2, 0, 1);
+  // [0,3] for 4 bytes
   case RISCV::BI__builtin_riscv_cv_simd_extract_b:
   case RISCV::BI__builtin_riscv_cv_simd_extractu_b:
-  return SemaRef.BuiltinConstantArgRange(TheCall, 1, 0, 3); // [0,3] for 4 bytes
+    return SemaRef.BuiltinConstantArgRange(TheCall, 1, 0, 3);
+  // [0,3] for 4 bytes
   case RISCV::BI__builtin_riscv_cv_simd_insert_b:
-    return SemaRef.BuiltinConstantArgRange(TheCall, 2, 0, 3); // [0,3] for 4 bytes
+    return SemaRef.BuiltinConstantArgRange(TheCall, 2, 0, 3);
   // Note: insert has index at arg 2 not 1
   // Shuffle SCI — 6-bit immediate [0, 63]
   case RISCV::BI__builtin_riscv_cv_simd_shuffle_sci_h:
     return SemaRef.BuiltinConstantArgRange(TheCall, 1, 0, 3);
+  // 8-bit, split by codegen
   case RISCV::BI__builtin_riscv_cv_simd_shuffle_sci_b:
-    return SemaRef.BuiltinConstantArgRange(TheCall, 1, 0, 255); // 8-bit, split by codegen
+    return SemaRef.BuiltinConstantArgRange(TheCall, 1, 0, 255);
 
   // add_h / sub_h div code [0,3] (0=no shift, 1=/2, 2=/4, 3=/8)
   case RISCV::BI__builtin_riscv_cv_simd_add_h:



More information about the cfe-commits mailing list