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

via cfe-commits cfe-commits at lists.llvm.org
Tue Jun 23 02:57:14 PDT 2026


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

>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/14] [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 1bf134e58ee8d7f324ca48de37d6489269104c39 Mon Sep 17 00:00:00 2001
From: vitbur <vittorioburani at gmail.com>
Date: Mon, 22 Jun 2026 18:00:55 +0200
Subject: [PATCH 02/14] [RISCV][XCV] Select element-wise XCVsimd ops from
 packed-vector IR

Make 2 x i16 / 4 x i8 legal GPR-resident types under XCVsimd (RV32) and
add patterns so element-wise vector IR selects the SIMD instructions:
add/sub to cv.add/sub, smin/umin/smax/umax to cv.min/minu/max/maxu, abs
to cv.abs, and bitwise and/or/xor reuse the scalar AND/OR/XOR since they
are lane-agnostic. Drop the now-redundant full-vector intrinsics; the
scalar-broadcast (sc/sci) forms keep their intrinsics.

Shifts, avg and the comparisons stay as intrinsics for now: their exact
lane semantics need confirming against the CV32E40P spec before mapping
them to generic IR.

First step toward expressing the element-wise XCVsimd operations as
native IR vector ops rather than dedicated intrinsics, per review.
---
 llvm/include/llvm/IR/IntrinsicsRISCVXCV.td  |  25 +--
 llvm/lib/Target/RISCV/RISCVISelLowering.cpp |  16 ++
 llvm/lib/Target/RISCV/RISCVInstrInfoXCV.td  |  91 +++++++--
 llvm/test/CodeGen/RISCV/xcvsimd-vector.ll   | 198 ++++++++++++++++++++
 llvm/test/CodeGen/RISCV/xcvsimd.ll          | 180 ------------------
 5 files changed, 301 insertions(+), 209 deletions(-)
 create mode 100644 llvm/test/CodeGen/RISCV/xcvsimd-vector.ll

diff --git a/llvm/include/llvm/IR/IntrinsicsRISCVXCV.td b/llvm/include/llvm/IR/IntrinsicsRISCVXCV.td
index 3dcc2b49f5f2c..14b21115145ad 100644
--- a/llvm/include/llvm/IR/IntrinsicsRISCVXCV.td
+++ b/llvm/include/llvm/IR/IntrinsicsRISCVXCV.td
@@ -146,11 +146,11 @@ let TargetPrefix = "riscv" in {
   // ==== 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;
+  // add_b: expressed as a plain `add <4 x i8>` in IR; no intrinsic needed.
   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;
+  // sub_b: expressed as a plain `sub <4 x i8>` in IR; no intrinsic needed.
   def int_riscv_cv_simd_sub_sc_h  : ScalarCoreVSimdGprGprIntrinsic;
   def int_riscv_cv_simd_sub_sc_b  : ScalarCoreVSimdGprGprIntrinsic;
 
@@ -165,20 +165,14 @@ let TargetPrefix = "riscv" in {
   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;
+  // Full-vector forms are expressed as llvm.smin/umin/smax/umax on a packed
+  // vector type; only the scalar-broadcast (sc) forms keep an intrinsic.
   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;
 
@@ -197,22 +191,17 @@ let TargetPrefix = "riscv" in {
   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;
+  // Full-vector bitwise forms are plain and/or/xor on a packed vector type;
+  // only the scalar-broadcast (sc) forms keep an intrinsic.
   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;
+  // abs_h/abs_b are expressed as llvm.abs on a packed vector type.
 
   // ==== XCVsimd — DOT PRODUCTS (non-accumulating) ====
   def int_riscv_cv_simd_dotup_h    : ScalarCoreVSimdGprGprIntrinsic;
diff --git a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
index c9c807cfa78aa..021883cff66d3 100644
--- a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
+++ b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
@@ -304,9 +304,25 @@ RISCVTargetLowering::RISCVTargetLowering(const TargetMachine &TM,
     }
   }
 
+  // XCVsimd packs 2 x i16 / 4 x i8 into a GPR (RV32 only); make those types
+  // legal so element-wise IR ops select the cv.*.h / cv.*.b SIMD instructions.
+  if (Subtarget.hasVendorXCVsimd() && !Subtarget.hasStdExtP()) {
+    addRegisterClass(MVT::v2i16, &RISCV::GPRRegClass);
+    addRegisterClass(MVT::v4i8, &RISCV::GPRRegClass);
+  }
+
   // Compute derived properties from the register classes.
   computeRegisterProperties(STI.getRegisterInfo());
 
+  if (Subtarget.hasVendorXCVsimd() && !Subtarget.hasStdExtP()) {
+    for (MVT VT : {MVT::v2i16, MVT::v4i8}) {
+      setOperationAction({ISD::ADD, ISD::SUB, ISD::AND, ISD::OR, ISD::XOR,
+                          ISD::SMIN, ISD::SMAX, ISD::UMIN, ISD::UMAX, ISD::ABS},
+                         VT, Legal);
+      setOperationAction({ISD::LOAD, ISD::STORE}, VT, Legal);
+    }
+  }
+
   setStackPointerRegisterToSaveRestore(RISCV::X2);
 
   setLoadExtAction({ISD::EXTLOAD, ISD::SEXTLOAD, ISD::ZEXTLOAD}, XLenVT,
diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfoXCV.td b/llvm/lib/Target/RISCV/RISCVInstrInfoXCV.td
index 281a9f1edff39..bc6cbaa95e77e 100644
--- a/llvm/lib/Target/RISCV/RISCVInstrInfoXCV.td
+++ b/llvm/lib/Target/RISCV/RISCVInstrInfoXCV.td
@@ -907,6 +907,35 @@ multiclass PatCoreVSimdUnsigned<string iname> {
             (!cast<RVInst>("CV_" # NAME # "_SCI_B") GPR:$rs1, uimm6:$imm)>;
 }
 
+// Scalar-broadcast-only variants: the full-vector _h/_b forms are expressed as
+// native packed-vector IR ops (2 x i16 / 4 x i8), so only the scalar-operand
+// (sc / sci) forms keep an intrinsic.
+multiclass PatCoreVSimdSignedScOnly<string iname> {
+  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, 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)>;
+}
+
+multiclass PatCoreVSimdUnsignedScOnly<string iname> {
+  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"),
@@ -988,7 +1017,6 @@ let Predicates = [HasVendorXCVsimd, IsRV32], AddedComplexity = 1 in {
   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),
@@ -1005,7 +1033,6 @@ let Predicates = [HasVendorXCVsimd, IsRV32], AddedComplexity = 1 in {
   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),
@@ -1016,10 +1043,10 @@ let Predicates = [HasVendorXCVsimd, IsRV32], AddedComplexity = 1 in {
   // ---- 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">;
+  defm MIN  : PatCoreVSimdSignedScOnly<"min">;
+  defm MINU : PatCoreVSimdUnsignedScOnly<"minu">;
+  defm MAX  : PatCoreVSimdSignedScOnly<"max">;
+  defm MAXU : PatCoreVSimdUnsignedScOnly<"maxu">;
 
   // ---- SRL / SRA / SLL ----
   defm SRL : PatCoreVSimdShift<"srl">;
@@ -1027,13 +1054,12 @@ let Predicates = [HasVendorXCVsimd, IsRV32], AddedComplexity = 1 in {
   defm SLL : PatCoreVSimdShift<"sll">;
 
   // ---- OR / XOR / AND ----
-  defm OR  : PatCoreVSimdSigned<"or">;
-  defm XOR : PatCoreVSimdSigned<"xor">;
-  defm AND : PatCoreVSimdSigned<"and">;
+  defm OR  : PatCoreVSimdSignedScOnly<"or">;
+  defm XOR : PatCoreVSimdSignedScOnly<"xor">;
+  defm AND : PatCoreVSimdSignedScOnly<"and">;
 
   // ---- ABS ----
-  def : PatGpr<int_riscv_cv_simd_abs_h, CV_ABS_H>;
-  def : PatGpr<int_riscv_cv_simd_abs_b, CV_ABS_B>;
+  // abs_h/abs_b: expressed as `llvm.abs` on a packed-vector type (see below).
 
   // ---- DOT PRODUCTS (non-accumulating) ----
   defm DOTUP  : PatCoreVSimdUnsigned<"dotup">;
@@ -1137,3 +1163,46 @@ let Predicates = [HasVendorXCVsimd, IsRV32], AddedComplexity = 1 in {
             (CV_SUBROTMJ_DIV8 GPR:$rs1, GPR:$rs2)>;
 
 } // Predicates = [HasVendorXCVsimd, IsRV32], AddedComplexity = 1
+
+//===----------------------------------------------------------------------===//
+// XCVsimd: select the element-wise SIMD instructions from generic
+// packed-vector IR.
+//
+// 2 x i16 / 4 x i8 are legal GPR-resident types for XCVsimd (RV32), so the
+// element-wise vector operations map directly to the SIMD instructions without
+// needing dedicated intrinsics. Bitwise ops are lane-agnostic and reuse the
+// base scalar AND/OR/XOR.
+//===----------------------------------------------------------------------===//
+
+let Predicates = [HasVendorXCVsimd, IsRV32] in {
+  def : Pat<(v2i16 (add GPR:$rs1, GPR:$rs2)), (CV_ADD_H GPR:$rs1, GPR:$rs2)>;
+  def : Pat<(v4i8  (add GPR:$rs1, GPR:$rs2)), (CV_ADD_B GPR:$rs1, GPR:$rs2)>;
+  def : Pat<(v2i16 (sub GPR:$rs1, GPR:$rs2)), (CV_SUB_H GPR:$rs1, GPR:$rs2)>;
+  def : Pat<(v4i8  (sub GPR:$rs1, GPR:$rs2)), (CV_SUB_B GPR:$rs1, GPR:$rs2)>;
+
+  def : Pat<(v2i16 (smin GPR:$rs1, GPR:$rs2)), (CV_MIN_H GPR:$rs1, GPR:$rs2)>;
+  def : Pat<(v4i8  (smin GPR:$rs1, GPR:$rs2)), (CV_MIN_B GPR:$rs1, GPR:$rs2)>;
+  def : Pat<(v2i16 (umin GPR:$rs1, GPR:$rs2)), (CV_MINU_H GPR:$rs1, GPR:$rs2)>;
+  def : Pat<(v4i8  (umin GPR:$rs1, GPR:$rs2)), (CV_MINU_B GPR:$rs1, GPR:$rs2)>;
+  def : Pat<(v2i16 (smax GPR:$rs1, GPR:$rs2)), (CV_MAX_H GPR:$rs1, GPR:$rs2)>;
+  def : Pat<(v4i8  (smax GPR:$rs1, GPR:$rs2)), (CV_MAX_B GPR:$rs1, GPR:$rs2)>;
+  def : Pat<(v2i16 (umax GPR:$rs1, GPR:$rs2)), (CV_MAXU_H GPR:$rs1, GPR:$rs2)>;
+  def : Pat<(v4i8  (umax GPR:$rs1, GPR:$rs2)), (CV_MAXU_B GPR:$rs1, GPR:$rs2)>;
+
+  // Bitwise ops do not depend on lane boundaries: reuse the scalar insns.
+  def : Pat<(v2i16 (and GPR:$rs1, GPR:$rs2)), (AND GPR:$rs1, GPR:$rs2)>;
+  def : Pat<(v4i8  (and GPR:$rs1, GPR:$rs2)), (AND GPR:$rs1, GPR:$rs2)>;
+  def : Pat<(v2i16 (or  GPR:$rs1, GPR:$rs2)), (OR  GPR:$rs1, GPR:$rs2)>;
+  def : Pat<(v4i8  (or  GPR:$rs1, GPR:$rs2)), (OR  GPR:$rs1, GPR:$rs2)>;
+  def : Pat<(v2i16 (xor GPR:$rs1, GPR:$rs2)), (XOR GPR:$rs1, GPR:$rs2)>;
+  def : Pat<(v4i8  (xor GPR:$rs1, GPR:$rs2)), (XOR GPR:$rs1, GPR:$rs2)>;
+
+  // abs: per-lane absolute value.
+  def : Pat<(v2i16 (abs GPR:$rs1)), (CV_ABS_H GPR:$rs1)>;
+  def : Pat<(v4i8  (abs GPR:$rs1)), (CV_ABS_B GPR:$rs1)>;
+
+  def : LdPat<load, LW, v2i16>;
+  def : LdPat<load, LW, v4i8>;
+  def : StPat<store, SW, GPR, v2i16>;
+  def : StPat<store, SW, GPR, v4i8>;
+}
diff --git a/llvm/test/CodeGen/RISCV/xcvsimd-vector.ll b/llvm/test/CodeGen/RISCV/xcvsimd-vector.ll
new file mode 100644
index 0000000000000..67de774ecf7d8
--- /dev/null
+++ b/llvm/test/CodeGen/RISCV/xcvsimd-vector.ll
@@ -0,0 +1,198 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 6
+; RUN: llc -mtriple=riscv32 -mattr=+xcvsimd -verify-machineinstrs < %s \
+; RUN:   | FileCheck %s
+
+; XCVsimd element-wise ops are expressed as plain packed-vector IR
+; (2 x i16 / 4 x i8) and select the cv.*.h / cv.*.b SIMD instructions,
+; without dedicated intrinsics.
+
+define void @add_v2i16(ptr %p, ptr %q, ptr %r) {
+; CHECK-LABEL: add_v2i16:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    lw a1, 0(a1)
+; CHECK-NEXT:    lw a0, 0(a0)
+; CHECK-NEXT:    cv.add.h a0, a0, a1
+; CHECK-NEXT:    sw a0, 0(a2)
+; CHECK-NEXT:    ret
+  %a = load <2 x i16>, ptr %p
+  %b = load <2 x i16>, ptr %q
+  %c = add <2 x i16> %a, %b
+  store <2 x i16> %c, ptr %r
+  ret void
+}
+
+define void @add_v4i8(ptr %p, ptr %q, ptr %r) {
+; CHECK-LABEL: add_v4i8:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    lw a1, 0(a1)
+; CHECK-NEXT:    lw a0, 0(a0)
+; CHECK-NEXT:    cv.add.b a0, a0, a1
+; CHECK-NEXT:    sw a0, 0(a2)
+; CHECK-NEXT:    ret
+  %a = load <4 x i8>, ptr %p
+  %b = load <4 x i8>, ptr %q
+  %c = add <4 x i8> %a, %b
+  store <4 x i8> %c, ptr %r
+  ret void
+}
+
+define void @sub_v2i16(ptr %p, ptr %q, ptr %r) {
+; CHECK-LABEL: sub_v2i16:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    lw a1, 0(a1)
+; CHECK-NEXT:    lw a0, 0(a0)
+; CHECK-NEXT:    cv.sub.h a0, a0, a1
+; CHECK-NEXT:    sw a0, 0(a2)
+; CHECK-NEXT:    ret
+  %a = load <2 x i16>, ptr %p
+  %b = load <2 x i16>, ptr %q
+  %c = sub <2 x i16> %a, %b
+  store <2 x i16> %c, ptr %r
+  ret void
+}
+
+define void @sub_v4i8(ptr %p, ptr %q, ptr %r) {
+; CHECK-LABEL: sub_v4i8:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    lw a1, 0(a1)
+; CHECK-NEXT:    lw a0, 0(a0)
+; CHECK-NEXT:    cv.sub.b a0, a0, a1
+; CHECK-NEXT:    sw a0, 0(a2)
+; CHECK-NEXT:    ret
+  %a = load <4 x i8>, ptr %p
+  %b = load <4 x i8>, ptr %q
+  %c = sub <4 x i8> %a, %b
+  store <4 x i8> %c, ptr %r
+  ret void
+}
+
+define void @and_v2i16(ptr %p, ptr %q, ptr %r) {
+; CHECK-LABEL: and_v2i16:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    lw a1, 0(a1)
+; CHECK-NEXT:    lw a0, 0(a0)
+; CHECK-NEXT:    and a0, a0, a1
+; CHECK-NEXT:    sw a0, 0(a2)
+; CHECK-NEXT:    ret
+  %a = load <2 x i16>, ptr %p
+  %b = load <2 x i16>, ptr %q
+  %c = and <2 x i16> %a, %b
+  store <2 x i16> %c, ptr %r
+  ret void
+}
+
+define void @or_v4i8(ptr %p, ptr %q, ptr %r) {
+; CHECK-LABEL: or_v4i8:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    lw a1, 0(a1)
+; CHECK-NEXT:    lw a0, 0(a0)
+; CHECK-NEXT:    or a0, a0, a1
+; CHECK-NEXT:    sw a0, 0(a2)
+; CHECK-NEXT:    ret
+  %a = load <4 x i8>, ptr %p
+  %b = load <4 x i8>, ptr %q
+  %c = or <4 x i8> %a, %b
+  store <4 x i8> %c, ptr %r
+  ret void
+}
+
+define void @xor_v2i16(ptr %p, ptr %q, ptr %r) {
+; CHECK-LABEL: xor_v2i16:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    lw a1, 0(a1)
+; CHECK-NEXT:    lw a0, 0(a0)
+; CHECK-NEXT:    xor a0, a0, a1
+; CHECK-NEXT:    sw a0, 0(a2)
+; CHECK-NEXT:    ret
+  %a = load <2 x i16>, ptr %p
+  %b = load <2 x i16>, ptr %q
+  %c = xor <2 x i16> %a, %b
+  store <2 x i16> %c, ptr %r
+  ret void
+}
+
+define void @smin_v2i16(ptr %p, ptr %q, ptr %r) {
+; CHECK-LABEL: smin_v2i16:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    lw a1, 0(a1)
+; CHECK-NEXT:    lw a0, 0(a0)
+; CHECK-NEXT:    cv.min.h a0, a0, a1
+; CHECK-NEXT:    sw a0, 0(a2)
+; CHECK-NEXT:    ret
+  %a = load <2 x i16>, ptr %p
+  %b = load <2 x i16>, ptr %q
+  %c = call <2 x i16> @llvm.smin.v2i16(<2 x i16> %a, <2 x i16> %b)
+  store <2 x i16> %c, ptr %r
+  ret void
+}
+
+define void @umin_v4i8(ptr %p, ptr %q, ptr %r) {
+; CHECK-LABEL: umin_v4i8:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    lw a1, 0(a1)
+; CHECK-NEXT:    lw a0, 0(a0)
+; CHECK-NEXT:    cv.minu.b a0, a0, a1
+; CHECK-NEXT:    sw a0, 0(a2)
+; CHECK-NEXT:    ret
+  %a = load <4 x i8>, ptr %p
+  %b = load <4 x i8>, ptr %q
+  %c = call <4 x i8> @llvm.umin.v4i8(<4 x i8> %a, <4 x i8> %b)
+  store <4 x i8> %c, ptr %r
+  ret void
+}
+
+define void @smax_v4i8(ptr %p, ptr %q, ptr %r) {
+; CHECK-LABEL: smax_v4i8:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    lw a1, 0(a1)
+; CHECK-NEXT:    lw a0, 0(a0)
+; CHECK-NEXT:    cv.max.b a0, a0, a1
+; CHECK-NEXT:    sw a0, 0(a2)
+; CHECK-NEXT:    ret
+  %a = load <4 x i8>, ptr %p
+  %b = load <4 x i8>, ptr %q
+  %c = call <4 x i8> @llvm.smax.v4i8(<4 x i8> %a, <4 x i8> %b)
+  store <4 x i8> %c, ptr %r
+  ret void
+}
+
+define void @umax_v2i16(ptr %p, ptr %q, ptr %r) {
+; CHECK-LABEL: umax_v2i16:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    lw a1, 0(a1)
+; CHECK-NEXT:    lw a0, 0(a0)
+; CHECK-NEXT:    cv.maxu.h a0, a0, a1
+; CHECK-NEXT:    sw a0, 0(a2)
+; CHECK-NEXT:    ret
+  %a = load <2 x i16>, ptr %p
+  %b = load <2 x i16>, ptr %q
+  %c = call <2 x i16> @llvm.umax.v2i16(<2 x i16> %a, <2 x i16> %b)
+  store <2 x i16> %c, ptr %r
+  ret void
+}
+
+define void @abs_v2i16(ptr %p, ptr %r) {
+; CHECK-LABEL: abs_v2i16:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    lw a0, 0(a0)
+; CHECK-NEXT:    cv.abs.h a0, a0
+; CHECK-NEXT:    sw a0, 0(a1)
+; CHECK-NEXT:    ret
+  %a = load <2 x i16>, ptr %p
+  %c = call <2 x i16> @llvm.abs.v2i16(<2 x i16> %a, i1 false)
+  store <2 x i16> %c, ptr %r
+  ret void
+}
+
+define void @abs_v4i8(ptr %p, ptr %r) {
+; CHECK-LABEL: abs_v4i8:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    lw a0, 0(a0)
+; CHECK-NEXT:    cv.abs.b a0, a0
+; CHECK-NEXT:    sw a0, 0(a1)
+; CHECK-NEXT:    ret
+  %a = load <4 x i8>, ptr %p
+  %c = call <4 x i8> @llvm.abs.v4i8(<4 x i8> %a, i1 false)
+  store <4 x i8> %c, ptr %r
+  ret void
+}
diff --git a/llvm/test/CodeGen/RISCV/xcvsimd.ll b/llvm/test/CodeGen/RISCV/xcvsimd.ll
index 20cb4f787797d..f72c6b2ee0ad4 100644
--- a/llvm/test/CodeGen/RISCV/xcvsimd.ll
+++ b/llvm/test/CodeGen/RISCV/xcvsimd.ll
@@ -45,15 +45,6 @@ define i32 @test_cv_simd_add_h_div8(i32 %a, i32 %b) {
   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:
@@ -108,15 +99,6 @@ define i32 @test_cv_simd_sub_h_div8(i32 %a, i32 %b) {
   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:
@@ -215,24 +197,6 @@ define i32 @test_cv_simd_avgu_sc_b(i32 %a, i32 %b) {
 ; 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:
@@ -251,60 +215,6 @@ define i32 @test_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
 ;===----------------------------------------------------------------------===;
@@ -385,82 +295,10 @@ define i32 @test_cv_simd_sll_b(i32 %a, i32 %b) {
 ; 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)
 ;===----------------------------------------------------------------------===;
@@ -948,11 +786,9 @@ define i32 @test_cv_simd_subrotmj_div8(i32 %a, i32 %b) {
 
 ; 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)
 
@@ -967,20 +803,12 @@ 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)
 
@@ -999,22 +827,14 @@ 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)

>From 8a41000a0a432cf691014997d545f27df2d470aa Mon Sep 17 00:00:00 2001
From: vitbur <vittorioburani at gmail.com>
Date: Tue, 31 Mar 2026 18:37:47 +0200
Subject: [PATCH 03/14] [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 460631e8c074df0b19bd85030e75e1b2a2f89218 Mon Sep 17 00:00:00 2001
From: vitbur <vittorioburani at gmail.com>
Date: Tue, 31 Mar 2026 18:43:53 +0200
Subject: [PATCH 04/14] [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 8aa6d0097c3327b866253dda29c7084ea05615e2 Mon Sep 17 00:00:00 2001
From: vitbur <vittorioburani at gmail.com>
Date: Tue, 31 Mar 2026 18:49:29 +0200
Subject: [PATCH 05/14] [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 1332e87be25f5afcec94a5d177b9abb72f4a329c Mon Sep 17 00:00:00 2001
From: vitbur <vittorioburani at gmail.com>
Date: Wed, 1 Apr 2026 11:02:44 +0200
Subject: [PATCH 06/14] [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 9f4f7d58ac111f333f7d3e4561e18af7324bd7b5 Mon Sep 17 00:00:00 2001
From: vitbur <vittorioburani at gmail.com>
Date: Tue, 7 Apr 2026 18:45:18 +0200
Subject: [PATCH 07/14] [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 2ba7ef1ab9628bbc03be57efe642e4c96990d112 Mon Sep 17 00:00:00 2001
From: vitbur <vittorioburani at gmail.com>
Date: Tue, 7 Apr 2026 18:46:56 +0200
Subject: [PATCH 08/14] [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 c8bd4829156fa6a06b8270a6be1b3a33e49e7d0d Mon Sep 17 00:00:00 2001
From: vitbur <vittorioburani at gmail.com>
Date: Tue, 7 Apr 2026 18:48:34 +0200
Subject: [PATCH 09/14] [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 a7856aa78285e19bd094bfaa9675da01f1a359e2 Mon Sep 17 00:00:00 2001
From: vitbur <vittorioburani at gmail.com>
Date: Tue, 7 Apr 2026 18:48:54 +0200
Subject: [PATCH 10/14] [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 cb8b36631b7f960c172c883050039c883554b531 Mon Sep 17 00:00:00 2001
From: vitbur <vittorioburani at gmail.com>
Date: Fri, 19 Jun 2026 18:51:40 +0200
Subject: [PATCH 11/14] [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:

>From 4d222fa28b634ff87f8bec668bfff677913a4019 Mon Sep 17 00:00:00 2001
From: vitbur <vittorioburani at gmail.com>
Date: Mon, 22 Jun 2026 13:57:20 +0200
Subject: [PATCH 12/14] [Clang][RISCV] Reference CV32E40P manual in CORE-V
 headers

Point the XCVmac and XCVbitmanip header spec comments at the CV32E40P
user manual instead of the raw docs .rst, matching the XCVsimd header,
and add the missing file header (license + description + spec link) to
the XCVelw header.
---
 clang/lib/Headers/riscv_corev_bitmanip.h |  5 +++--
 clang/lib/Headers/riscv_corev_elw.h      | 18 ++++++++++++++++++
 clang/lib/Headers/riscv_corev_mac.h      |  5 +++--
 3 files changed, 24 insertions(+), 4 deletions(-)

diff --git a/clang/lib/Headers/riscv_corev_bitmanip.h b/clang/lib/Headers/riscv_corev_bitmanip.h
index d48c53f6c8a26..55a2ca94eb31f 100644
--- a/clang/lib/Headers/riscv_corev_bitmanip.h
+++ b/clang/lib/Headers/riscv_corev_bitmanip.h
@@ -9,8 +9,9 @@
  * 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)
+ * Spec: CV32E40P user manual, Instruction Set Extensions (XCVbitmanip):
+ *       https://docs.openhwgroup.org/projects/cv32e40p-user-manual/en/latest/
+ *       instruction_set_extensions.html
  *
  *===-----------------------------------------------------------------------===
  */
diff --git a/clang/lib/Headers/riscv_corev_elw.h b/clang/lib/Headers/riscv_corev_elw.h
index f0583ad35c543..5ff9efa1c9aca 100644
--- a/clang/lib/Headers/riscv_corev_elw.h
+++ b/clang/lib/Headers/riscv_corev_elw.h
@@ -1,3 +1,21 @@
+/*===---- riscv_corev_elw.h - CORE-V event-load-word 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 XCVelw ISA extension.
+ * Include this header when compiling with -march=..._xcvelw.
+ *
+ * Spec: CV32E40P user manual, Instruction Set Extensions (XCVelw):
+ *       https://docs.openhwgroup.org/projects/cv32e40p-user-manual/en/latest/
+ *       instruction_set_extensions.html
+ *
+ *===-----------------------------------------------------------------------===
+ */
+
 #ifndef __RISCV_COREV_ELW_H
 #define __RISCV_COREV_ELW_H
 #include <stdint.h>
diff --git a/clang/lib/Headers/riscv_corev_mac.h b/clang/lib/Headers/riscv_corev_mac.h
index dccb8ae9dbf81..4b7f5df8f622a 100644
--- a/clang/lib/Headers/riscv_corev_mac.h
+++ b/clang/lib/Headers/riscv_corev_mac.h
@@ -9,8 +9,9 @@
  * 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)
+ * Spec: CV32E40P user manual, Instruction Set Extensions (XCVmac):
+ *       https://docs.openhwgroup.org/projects/cv32e40p-user-manual/en/latest/
+ *       instruction_set_extensions.html
  *
  *===-----------------------------------------------------------------------===
  */

>From 1c5d789ecafd0fc2307472f6d8400fbd85605c67 Mon Sep 17 00:00:00 2001
From: vitbur <vittorioburani at gmail.com>
Date: Mon, 22 Jun 2026 18:09:19 +0200
Subject: [PATCH 13/14] [Clang][RISCV] Drop XCVsimd add_b/sub_b builtins

These map to a plain add/sub on a 4 x i8 vector and are now expressed in
IR (the backend selects cv.add.b/cv.sub.b from the vector op), so the
dedicated builtins and header wrappers are no longer needed.
---
 clang/include/clang/Basic/BuiltinsRISCVXCV.td |  4 +--
 clang/lib/CodeGen/TargetBuiltins/RISCV.cpp    |  6 ----
 clang/lib/Headers/riscv_corev_simd.h          | 10 ++-----
 .../test/CodeGen/RISCV/rvv-xcvsimd-builtins.c | 29 -------------------
 4 files changed, 4 insertions(+), 45 deletions(-)

diff --git a/clang/include/clang/Basic/BuiltinsRISCVXCV.td b/clang/include/clang/Basic/BuiltinsRISCVXCV.td
index 31b4788345096..10b0c29efb3e7 100644
--- a/clang/include/clang/Basic/BuiltinsRISCVXCV.td
+++ b/clang/include/clang/Basic/BuiltinsRISCVXCV.td
@@ -91,11 +91,11 @@ 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">;
+// add_b: use a plain `add` on a 4 x i8 vector type; no builtin needed.
 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">;
+// sub_b: use a plain `sub` on a 4 x i8 vector type; no builtin needed.
 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">;
 
diff --git a/clang/lib/CodeGen/TargetBuiltins/RISCV.cpp b/clang/lib/CodeGen/TargetBuiltins/RISCV.cpp
index 5fde76c4ce3d4..3a6d707bf3fc5 100644
--- a/clang/lib/CodeGen/TargetBuiltins/RISCV.cpp
+++ b/clang/lib/CodeGen/TargetBuiltins/RISCV.cpp
@@ -1525,9 +1525,6 @@ Value *CodeGenFunction::EmitRISCVBuiltinExpr(unsigned BuiltinID,
   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;
@@ -1537,9 +1534,6 @@ Value *CodeGenFunction::EmitRISCVBuiltinExpr(unsigned BuiltinID,
   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;
diff --git a/clang/lib/Headers/riscv_corev_simd.h b/clang/lib/Headers/riscv_corev_simd.h
index 3127d0eebfe92..8e6fbee7f3ee9 100644
--- a/clang/lib/Headers/riscv_corev_simd.h
+++ b/clang/lib/Headers/riscv_corev_simd.h
@@ -52,10 +52,7 @@ extern "C" {
   ((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);
-}
+/* add.b: use a plain `+` on a 4 x i8 vector type; no builtin needed. */
 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);
@@ -70,10 +67,7 @@ __riscv_cv_simd_add_sc_b(uint32_t a, uint32_t b) {
   ((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);
-}
+/* sub.b: use a plain `-` on a 4 x i8 vector type; no builtin needed. */
 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);
diff --git a/clang/test/CodeGen/RISCV/rvv-xcvsimd-builtins.c b/clang/test/CodeGen/RISCV/rvv-xcvsimd-builtins.c
index 5e163c81d36d4..904ffcec8d569 100644
--- a/clang/test/CodeGen/RISCV/rvv-xcvsimd-builtins.c
+++ b/clang/test/CodeGen/RISCV/rvv-xcvsimd-builtins.c
@@ -39,21 +39,6 @@ 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
@@ -99,20 +84,6 @@ 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:

>From 9d75bb3f5fd9b6137d5d82b1dc43be100ddd7b60 Mon Sep 17 00:00:00 2001
From: vitbur <vittorioburani at gmail.com>
Date: Mon, 22 Jun 2026 18:56:24 +0200
Subject: [PATCH 14/14] [Clang][RISCV] Drop element-wise XCVsimd builtins
 expressed in IR

Remove the full-vector min/minu/max/maxu/and/or/xor/abs builtins and
their header wrappers: these now map to plain min/max/bitwise/abs on a
4 x i8 / 2 x i16 vector type, which the backend lowers to the SIMD
instructions. The scalar-broadcast (sc) builtins are kept.
---
 clang/include/clang/Basic/BuiltinsRISCVXCV.td |  16 --
 clang/lib/CodeGen/TargetBuiltins/RISCV.cpp    |  48 ------
 clang/lib/Headers/riscv_corev_simd.h          |  65 --------
 .../test/CodeGen/RISCV/rvv-xcvsimd-builtins.c | 144 ------------------
 4 files changed, 273 deletions(-)

diff --git a/clang/include/clang/Basic/BuiltinsRISCVXCV.td b/clang/include/clang/Basic/BuiltinsRISCVXCV.td
index 10b0c29efb3e7..890314b8dc758 100644
--- a/clang/include/clang/Basic/BuiltinsRISCVXCV.td
+++ b/clang/include/clang/Basic/BuiltinsRISCVXCV.td
@@ -112,20 +112,12 @@ def simd_avgu_sc_h : RISCVXCVBuiltin<"unsigned int(unsigned int, unsigned int)",
 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">;
 
@@ -144,22 +136,14 @@ def simd_sll_sc_h : RISCVXCVBuiltin<"unsigned int(unsigned int, unsigned int)",
 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">;
diff --git a/clang/lib/CodeGen/TargetBuiltins/RISCV.cpp b/clang/lib/CodeGen/TargetBuiltins/RISCV.cpp
index 3a6d707bf3fc5..ca87ec8356dd5 100644
--- a/clang/lib/CodeGen/TargetBuiltins/RISCV.cpp
+++ b/clang/lib/CodeGen/TargetBuiltins/RISCV.cpp
@@ -1570,48 +1570,24 @@ Value *CodeGenFunction::EmitRISCVBuiltinExpr(unsigned BuiltinID,
     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;
@@ -1658,36 +1634,18 @@ Value *CodeGenFunction::EmitRISCVBuiltinExpr(unsigned BuiltinID,
     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;
@@ -1696,12 +1654,6 @@ Value *CodeGenFunction::EmitRISCVBuiltinExpr(unsigned BuiltinID,
     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:
diff --git a/clang/lib/Headers/riscv_corev_simd.h b/clang/lib/Headers/riscv_corev_simd.h
index 8e6fbee7f3ee9..7923bdcdd2158 100644
--- a/clang/lib/Headers/riscv_corev_simd.h
+++ b/clang/lib/Headers/riscv_corev_simd.h
@@ -121,14 +121,6 @@ __riscv_cv_simd_avgu_sc_b(uint32_t a, uint32_t b) {
  * ===========================================================================
  */
 
-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);
@@ -138,14 +130,6 @@ __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);
@@ -160,14 +144,6 @@ __riscv_cv_simd_minu_sc_b(uint32_t a, uint32_t b) {
  * ===========================================================================
  */
 
-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);
@@ -177,14 +153,6 @@ __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);
@@ -258,14 +226,6 @@ __riscv_cv_simd_sll_sc_b(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) {
-  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);
@@ -275,14 +235,6 @@ __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);
@@ -292,14 +244,6 @@ __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);
@@ -314,15 +258,6 @@ __riscv_cv_simd_and_sc_b(uint32_t a, uint32_t b) {
  * ===========================================================================
  */
 
-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
  *
diff --git a/clang/test/CodeGen/RISCV/rvv-xcvsimd-builtins.c b/clang/test/CodeGen/RISCV/rvv-xcvsimd-builtins.c
index 904ffcec8d569..1e37e1d9e7d2f 100644
--- a/clang/test/CodeGen/RISCV/rvv-xcvsimd-builtins.c
+++ b/clang/test/CodeGen/RISCV/rvv-xcvsimd-builtins.c
@@ -239,36 +239,6 @@ uint32_t test_avgu_sc_b(uint32_t a, uint32_t 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
@@ -299,51 +269,6 @@ 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(
@@ -408,77 +333,8 @@ uint32_t test_srl_sc_b(uint32_t a, uint32_t 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(



More information about the cfe-commits mailing list