[clang] [llvm] [Clang][RISCV] Add CORE-V (XCV) builtins for CV32E40P (PR #204881)
via cfe-commits
cfe-commits at lists.llvm.org
Fri Jun 19 11:38:07 PDT 2026
https://github.com/VittorioBurani created https://github.com/llvm/llvm-project/pull/204881
Add Clang builtins and user-facing headers for the CORE-V extensions `XCVmac`, `XCVelw`, `XCVsimd` and `XCVbitmanip`:
- builtin definitions in `BuiltinsRISCVXCV.td`, CodeGen dispatch in `TargetBuiltins/RISCV.cpp`, argument range checks in `SemaRISCV.cpp`, and ClangIR NYI stubs in `CIRGenBuiltinRISCV.cpp`;
- headers `riscv_corev_{mac,elw,simd,bitmanip}.h` (wired into `clang/lib/Headers/CMakeLists.txt`).
The XCVsimd builtins lower to the `llvm.riscv.cv.simd.*` intrinsics; the mac/elw/bitmanip builtins lower to intrinsics already present upstream.
**Tests:** `clang/test/CodeGen/RISCV/rvv-xcv*-builtins.c`, `clang/test/Sema/rvv-xcv-sema.c`.
**Depends on #204880** — the XCVsimd intrinsics must exist for the XCVsimd builtins to resolve (without them Clang's dispatch table will not compile). This PR will show that PR's commit until it merges; it will be rebased afterward. Marked Draft until then.
Part of a CORE-V (XCV) series; see RFC: https://discourse.llvm.org/t/rfc-core-v-xcv-support-for-cv32e40p-clang-builtins-xcvsimd-intrinsics-and-generic-auto-selection/91111
>From 593f42d47f03bc7dc76d0c59c44a1a7707ea4016 Mon Sep 17 00:00:00 2001
From: vitbur <vittorioburani at gmail.com>
Date: Wed, 1 Apr 2026 18:45:22 +0200
Subject: [PATCH 01/10] [RISCV][LLVM] Add LLVM intrinsics and patterns for
XCVsimd
- add 150+ LLVM IR intrinsic declarations for all XCVsimd
operations (add, sub, avg, min, max, shift, logic, dot product,
extract, insert, shuffle, pack, compare, complex multiply,
conjugate, subrotmj).
- add SelectionDAG patterns mapping each intrinsic to its
corresponding CV32E40P machine instruction, including:
- SCI immediate fallback patterns for scalar-constant operands
- Divcode-based instruction selection for
add_h/sub_h/subrotmj/cplxmul
- CV_SHUFFLE_SCI_B_PSEUDO with RISCVExpandPseudoInsts expansion
- this enables the Clang builtins (__builtin_riscv_cv_simd_*)
- add xcvsimd.ll file to test XCVsimid intrinsics
---
llvm/include/llvm/IR/IntrinsicsRISCVXCV.td | 225 ++++
.../Target/RISCV/RISCVExpandPseudoInsts.cpp | 31 +
llvm/lib/Target/RISCV/RISCVInstrInfoXCV.td | 287 +++++
llvm/test/CodeGen/RISCV/xcvsimd.ll | 1115 +++++++++++++++++
4 files changed, 1658 insertions(+)
create mode 100644 llvm/test/CodeGen/RISCV/xcvsimd.ll
diff --git a/llvm/include/llvm/IR/IntrinsicsRISCVXCV.td b/llvm/include/llvm/IR/IntrinsicsRISCVXCV.td
index 465665c838bae..3dcc2b49f5f2c 100644
--- a/llvm/include/llvm/IR/IntrinsicsRISCVXCV.td
+++ b/llvm/include/llvm/IR/IntrinsicsRISCVXCV.td
@@ -42,6 +42,54 @@ class ScalarCoreVMacGprGprGprImmIntrinsic
: Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty],
[IntrNoMem, IntrWillReturn, IntrSpeculatable, ImmArg<ArgIndex<3>>]>;
+// Binary: (i32, i32) -> i32, pure
+class ScalarCoreVSimdGprGprIntrinsic
+ : DefaultAttrsIntrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty],
+ [IntrNoMem, IntrSpeculatable]>;
+
+// Unary: (i32) -> i32, pure
+class ScalarCoreVSimdGprIntrinsic
+ : DefaultAttrsIntrinsic<[llvm_i32_ty], [llvm_i32_ty],
+ [IntrNoMem, IntrSpeculatable]>;
+
+// Ternary: (i32, i32, i32) -> i32, pure (for accumulating ops like sdot)
+class ScalarCoreVSimdGprGprGprIntrinsic
+ : DefaultAttrsIntrinsic<[llvm_i32_ty],
+ [llvm_i32_ty, llvm_i32_ty, llvm_i32_ty],
+ [IntrNoMem, IntrSpeculatable]>;
+
+// Binary with immediate at arg2: (i32, i32, IMM) -> i32
+// Used for: add_h/sub_h (divcode), subrotmj (divcode)
+class ScalarCoreVSimdGprGprImmIntrinsic
+ : DefaultAttrsIntrinsic<[llvm_i32_ty],
+ [llvm_i32_ty, llvm_i32_ty, llvm_i32_ty],
+ [IntrNoMem, IntrSpeculatable,
+ ImmArg<ArgIndex<2>>]>;
+
+// Unary with immediate at arg1: (i32, IMM) -> i32
+// Used for: extract, extractu, shuffle_sci_h, shuffle_sci_b
+class ScalarCoreVSimdGprImmIntrinsic
+ : DefaultAttrsIntrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty],
+ [IntrNoMem, IntrSpeculatable,
+ ImmArg<ArgIndex<1>>]>;
+
+// Ternary with immediate at arg2, where arg0 is rd (accumulator):
+// (rd_in, rs1, IMM) -> rd_out
+// Used for: insert_h, insert_b
+class ScalarCoreVSimdGprGprImm2WbIntrinsic
+ : DefaultAttrsIntrinsic<[llvm_i32_ty],
+ [llvm_i32_ty, llvm_i32_ty, llvm_i32_ty],
+ [IntrNoMem, IntrSpeculatable,
+ ImmArg<ArgIndex<2>>]>;
+
+// Quaternary with immediate at arg3: (rs1, rs2, rd_in, IMM) -> rd_out
+// Used for: cplxmul_r, cplxmul_i
+class ScalarCoreVSimdGprGprGprImmIntrinsic
+ : DefaultAttrsIntrinsic<[llvm_i32_ty],
+ [llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty],
+ [IntrNoMem, IntrSpeculatable,
+ ImmArg<ArgIndex<3>>]>;
+
let TargetPrefix = "riscv" in {
def int_riscv_cv_bitmanip_extract : ScalarCoreVBitManipGprGprIntrinsic;
def int_riscv_cv_bitmanip_extractu : ScalarCoreVBitManipGprGprIntrinsic;
@@ -94,4 +142,181 @@ let TargetPrefix = "riscv" in {
def int_riscv_cv_elw_elw
: Intrinsic<[llvm_i32_ty], [llvm_ptr_ty],
[IntrReadMem, IntrArgMemOnly, IntrHasSideEffects]>;
+
+ // ==== XCVsimd — ADD/SUB ====
+ // add_h takes a divcode immediate (0=none, 1=/2, 2=/4, 3=/8)
+ def int_riscv_cv_simd_add_h : ScalarCoreVSimdGprGprImmIntrinsic;
+ def int_riscv_cv_simd_add_b : ScalarCoreVSimdGprGprIntrinsic;
+ def int_riscv_cv_simd_add_sc_h : ScalarCoreVSimdGprGprIntrinsic;
+ def int_riscv_cv_simd_add_sc_b : ScalarCoreVSimdGprGprIntrinsic;
+ def int_riscv_cv_simd_sub_h : ScalarCoreVSimdGprGprImmIntrinsic;
+ def int_riscv_cv_simd_sub_b : ScalarCoreVSimdGprGprIntrinsic;
+ def int_riscv_cv_simd_sub_sc_h : ScalarCoreVSimdGprGprIntrinsic;
+ def int_riscv_cv_simd_sub_sc_b : ScalarCoreVSimdGprGprIntrinsic;
+
+ // ==== XCVsimd — AVG / AVGU ====
+ def int_riscv_cv_simd_avg_h : ScalarCoreVSimdGprGprIntrinsic;
+ def int_riscv_cv_simd_avg_b : ScalarCoreVSimdGprGprIntrinsic;
+ def int_riscv_cv_simd_avg_sc_h : ScalarCoreVSimdGprGprIntrinsic;
+ def int_riscv_cv_simd_avg_sc_b : ScalarCoreVSimdGprGprIntrinsic;
+ def int_riscv_cv_simd_avgu_h : ScalarCoreVSimdGprGprIntrinsic;
+ def int_riscv_cv_simd_avgu_b : ScalarCoreVSimdGprGprIntrinsic;
+ def int_riscv_cv_simd_avgu_sc_h : ScalarCoreVSimdGprGprIntrinsic;
+ def int_riscv_cv_simd_avgu_sc_b : ScalarCoreVSimdGprGprIntrinsic;
+
+ // ==== XCVsimd — MIN / MINU / MAX / MAXU ====
+ def int_riscv_cv_simd_min_h : ScalarCoreVSimdGprGprIntrinsic;
+ def int_riscv_cv_simd_min_b : ScalarCoreVSimdGprGprIntrinsic;
+ def int_riscv_cv_simd_min_sc_h : ScalarCoreVSimdGprGprIntrinsic;
+ def int_riscv_cv_simd_min_sc_b : ScalarCoreVSimdGprGprIntrinsic;
+ def int_riscv_cv_simd_minu_h : ScalarCoreVSimdGprGprIntrinsic;
+ def int_riscv_cv_simd_minu_b : ScalarCoreVSimdGprGprIntrinsic;
+ def int_riscv_cv_simd_minu_sc_h : ScalarCoreVSimdGprGprIntrinsic;
+ def int_riscv_cv_simd_minu_sc_b : ScalarCoreVSimdGprGprIntrinsic;
+ def int_riscv_cv_simd_max_h : ScalarCoreVSimdGprGprIntrinsic;
+ def int_riscv_cv_simd_max_b : ScalarCoreVSimdGprGprIntrinsic;
+ def int_riscv_cv_simd_max_sc_h : ScalarCoreVSimdGprGprIntrinsic;
+ def int_riscv_cv_simd_max_sc_b : ScalarCoreVSimdGprGprIntrinsic;
+ def int_riscv_cv_simd_maxu_h : ScalarCoreVSimdGprGprIntrinsic;
+ def int_riscv_cv_simd_maxu_b : ScalarCoreVSimdGprGprIntrinsic;
+ def int_riscv_cv_simd_maxu_sc_h : ScalarCoreVSimdGprGprIntrinsic;
+ def int_riscv_cv_simd_maxu_sc_b : ScalarCoreVSimdGprGprIntrinsic;
+
+ // ==== XCVsimd — SRL / SRA / SLL ====
+ def int_riscv_cv_simd_srl_h : ScalarCoreVSimdGprGprIntrinsic;
+ def int_riscv_cv_simd_srl_b : ScalarCoreVSimdGprGprIntrinsic;
+ def int_riscv_cv_simd_srl_sc_h : ScalarCoreVSimdGprGprIntrinsic;
+ def int_riscv_cv_simd_srl_sc_b : ScalarCoreVSimdGprGprIntrinsic;
+ def int_riscv_cv_simd_sra_h : ScalarCoreVSimdGprGprIntrinsic;
+ def int_riscv_cv_simd_sra_b : ScalarCoreVSimdGprGprIntrinsic;
+ def int_riscv_cv_simd_sra_sc_h : ScalarCoreVSimdGprGprIntrinsic;
+ def int_riscv_cv_simd_sra_sc_b : ScalarCoreVSimdGprGprIntrinsic;
+ def int_riscv_cv_simd_sll_h : ScalarCoreVSimdGprGprIntrinsic;
+ def int_riscv_cv_simd_sll_b : ScalarCoreVSimdGprGprIntrinsic;
+ def int_riscv_cv_simd_sll_sc_h : ScalarCoreVSimdGprGprIntrinsic;
+ def int_riscv_cv_simd_sll_sc_b : ScalarCoreVSimdGprGprIntrinsic;
+
+ // ==== XCVsimd — OR / XOR / AND ====
+ def int_riscv_cv_simd_or_h : ScalarCoreVSimdGprGprIntrinsic;
+ def int_riscv_cv_simd_or_b : ScalarCoreVSimdGprGprIntrinsic;
+ def int_riscv_cv_simd_or_sc_h : ScalarCoreVSimdGprGprIntrinsic;
+ def int_riscv_cv_simd_or_sc_b : ScalarCoreVSimdGprGprIntrinsic;
+ def int_riscv_cv_simd_xor_h : ScalarCoreVSimdGprGprIntrinsic;
+ def int_riscv_cv_simd_xor_b : ScalarCoreVSimdGprGprIntrinsic;
+ def int_riscv_cv_simd_xor_sc_h : ScalarCoreVSimdGprGprIntrinsic;
+ def int_riscv_cv_simd_xor_sc_b : ScalarCoreVSimdGprGprIntrinsic;
+ def int_riscv_cv_simd_and_h : ScalarCoreVSimdGprGprIntrinsic;
+ def int_riscv_cv_simd_and_b : ScalarCoreVSimdGprGprIntrinsic;
+ def int_riscv_cv_simd_and_sc_h : ScalarCoreVSimdGprGprIntrinsic;
+ def int_riscv_cv_simd_and_sc_b : ScalarCoreVSimdGprGprIntrinsic;
+
+ // ==== XCVsimd — ABS ====
+ def int_riscv_cv_simd_abs_h : ScalarCoreVSimdGprIntrinsic;
+ def int_riscv_cv_simd_abs_b : ScalarCoreVSimdGprIntrinsic;
+
+ // ==== XCVsimd — DOT PRODUCTS (non-accumulating) ====
+ def int_riscv_cv_simd_dotup_h : ScalarCoreVSimdGprGprIntrinsic;
+ def int_riscv_cv_simd_dotup_b : ScalarCoreVSimdGprGprIntrinsic;
+ def int_riscv_cv_simd_dotup_sc_h : ScalarCoreVSimdGprGprIntrinsic;
+ def int_riscv_cv_simd_dotup_sc_b : ScalarCoreVSimdGprGprIntrinsic;
+ def int_riscv_cv_simd_dotusp_h : ScalarCoreVSimdGprGprIntrinsic;
+ def int_riscv_cv_simd_dotusp_b : ScalarCoreVSimdGprGprIntrinsic;
+ def int_riscv_cv_simd_dotusp_sc_h : ScalarCoreVSimdGprGprIntrinsic;
+ def int_riscv_cv_simd_dotusp_sc_b : ScalarCoreVSimdGprGprIntrinsic;
+ def int_riscv_cv_simd_dotsp_h : ScalarCoreVSimdGprGprIntrinsic;
+ def int_riscv_cv_simd_dotsp_b : ScalarCoreVSimdGprGprIntrinsic;
+ def int_riscv_cv_simd_dotsp_sc_h : ScalarCoreVSimdGprGprIntrinsic;
+ def int_riscv_cv_simd_dotsp_sc_b : ScalarCoreVSimdGprGprIntrinsic;
+
+ // ==== XCVsimd — SDOT (accumulating dot products): (rs1, rs2, acc) -> acc ====
+ def int_riscv_cv_simd_sdotup_h : ScalarCoreVSimdGprGprGprIntrinsic;
+ def int_riscv_cv_simd_sdotup_b : ScalarCoreVSimdGprGprGprIntrinsic;
+ def int_riscv_cv_simd_sdotup_sc_h : ScalarCoreVSimdGprGprGprIntrinsic;
+ def int_riscv_cv_simd_sdotup_sc_b : ScalarCoreVSimdGprGprGprIntrinsic;
+ def int_riscv_cv_simd_sdotusp_h : ScalarCoreVSimdGprGprGprIntrinsic;
+ def int_riscv_cv_simd_sdotusp_b : ScalarCoreVSimdGprGprGprIntrinsic;
+ def int_riscv_cv_simd_sdotusp_sc_h : ScalarCoreVSimdGprGprGprIntrinsic;
+ def int_riscv_cv_simd_sdotusp_sc_b : ScalarCoreVSimdGprGprGprIntrinsic;
+ def int_riscv_cv_simd_sdotsp_h : ScalarCoreVSimdGprGprGprIntrinsic;
+ def int_riscv_cv_simd_sdotsp_b : ScalarCoreVSimdGprGprGprIntrinsic;
+ def int_riscv_cv_simd_sdotsp_sc_h : ScalarCoreVSimdGprGprGprIntrinsic;
+ def int_riscv_cv_simd_sdotsp_sc_b : ScalarCoreVSimdGprGprGprIntrinsic;
+
+ // ==== XCVsimd — EXTRACT / EXTRACTU: (rs1, IMM) -> rd ====
+ def int_riscv_cv_simd_extract_h : ScalarCoreVSimdGprImmIntrinsic;
+ def int_riscv_cv_simd_extract_b : ScalarCoreVSimdGprImmIntrinsic;
+ def int_riscv_cv_simd_extractu_h : ScalarCoreVSimdGprImmIntrinsic;
+ def int_riscv_cv_simd_extractu_b : ScalarCoreVSimdGprImmIntrinsic;
+
+ // ==== XCVsimd — INSERT: (rd_in, rs1, IMM) -> rd_out ====
+ def int_riscv_cv_simd_insert_h : ScalarCoreVSimdGprGprImm2WbIntrinsic;
+ def int_riscv_cv_simd_insert_b : ScalarCoreVSimdGprGprImm2WbIntrinsic;
+
+ // ==== XCVsimd — SHUFFLE ====
+ def int_riscv_cv_simd_shuffle_h : ScalarCoreVSimdGprGprIntrinsic;
+ def int_riscv_cv_simd_shuffle_b : ScalarCoreVSimdGprGprIntrinsic;
+ def int_riscv_cv_simd_shuffle_sci_h : ScalarCoreVSimdGprImmIntrinsic;
+ def int_riscv_cv_simd_shuffle_sci_b : ScalarCoreVSimdGprImmIntrinsic;
+
+ // ==== XCVsimd — SHUFFLE2: (rs1, rs2, rd_in) -> rd_out ====
+ def int_riscv_cv_simd_shuffle2_h : ScalarCoreVSimdGprGprGprIntrinsic;
+ def int_riscv_cv_simd_shuffle2_b : ScalarCoreVSimdGprGprGprIntrinsic;
+
+ // ==== XCVsimd — PACK ====
+ // pack / pack.h: (rs1, rs2) -> rd
+ def int_riscv_cv_simd_packlo_h : ScalarCoreVSimdGprGprIntrinsic;
+ def int_riscv_cv_simd_packhi_h : ScalarCoreVSimdGprGprIntrinsic;
+ // packhi.b / packlo.b: (rd_in, rs1, rs2) -> rd_out (read-modify-write)
+ def int_riscv_cv_simd_packhi_b : ScalarCoreVSimdGprGprGprIntrinsic;
+ def int_riscv_cv_simd_packlo_b : ScalarCoreVSimdGprGprGprIntrinsic;
+
+ // ==== XCVsimd — COMPARE ====
+ def int_riscv_cv_simd_cmpeq_h : ScalarCoreVSimdGprGprIntrinsic;
+ def int_riscv_cv_simd_cmpeq_b : ScalarCoreVSimdGprGprIntrinsic;
+ def int_riscv_cv_simd_cmpeq_sc_h : ScalarCoreVSimdGprGprIntrinsic;
+ def int_riscv_cv_simd_cmpeq_sc_b : ScalarCoreVSimdGprGprIntrinsic;
+ def int_riscv_cv_simd_cmpne_h : ScalarCoreVSimdGprGprIntrinsic;
+ def int_riscv_cv_simd_cmpne_b : ScalarCoreVSimdGprGprIntrinsic;
+ def int_riscv_cv_simd_cmpne_sc_h : ScalarCoreVSimdGprGprIntrinsic;
+ def int_riscv_cv_simd_cmpne_sc_b : ScalarCoreVSimdGprGprIntrinsic;
+ def int_riscv_cv_simd_cmpgt_h : ScalarCoreVSimdGprGprIntrinsic;
+ def int_riscv_cv_simd_cmpgt_b : ScalarCoreVSimdGprGprIntrinsic;
+ def int_riscv_cv_simd_cmpgt_sc_h : ScalarCoreVSimdGprGprIntrinsic;
+ def int_riscv_cv_simd_cmpgt_sc_b : ScalarCoreVSimdGprGprIntrinsic;
+ def int_riscv_cv_simd_cmpge_h : ScalarCoreVSimdGprGprIntrinsic;
+ def int_riscv_cv_simd_cmpge_b : ScalarCoreVSimdGprGprIntrinsic;
+ def int_riscv_cv_simd_cmpge_sc_h : ScalarCoreVSimdGprGprIntrinsic;
+ def int_riscv_cv_simd_cmpge_sc_b : ScalarCoreVSimdGprGprIntrinsic;
+ def int_riscv_cv_simd_cmplt_h : ScalarCoreVSimdGprGprIntrinsic;
+ def int_riscv_cv_simd_cmplt_b : ScalarCoreVSimdGprGprIntrinsic;
+ def int_riscv_cv_simd_cmplt_sc_h : ScalarCoreVSimdGprGprIntrinsic;
+ def int_riscv_cv_simd_cmplt_sc_b : ScalarCoreVSimdGprGprIntrinsic;
+ def int_riscv_cv_simd_cmple_h : ScalarCoreVSimdGprGprIntrinsic;
+ def int_riscv_cv_simd_cmple_b : ScalarCoreVSimdGprGprIntrinsic;
+ def int_riscv_cv_simd_cmple_sc_h : ScalarCoreVSimdGprGprIntrinsic;
+ def int_riscv_cv_simd_cmple_sc_b : ScalarCoreVSimdGprGprIntrinsic;
+ def int_riscv_cv_simd_cmpgtu_h : ScalarCoreVSimdGprGprIntrinsic;
+ def int_riscv_cv_simd_cmpgtu_b : ScalarCoreVSimdGprGprIntrinsic;
+ def int_riscv_cv_simd_cmpgtu_sc_h : ScalarCoreVSimdGprGprIntrinsic;
+ def int_riscv_cv_simd_cmpgtu_sc_b : ScalarCoreVSimdGprGprIntrinsic;
+ def int_riscv_cv_simd_cmpgeu_h : ScalarCoreVSimdGprGprIntrinsic;
+ def int_riscv_cv_simd_cmpgeu_b : ScalarCoreVSimdGprGprIntrinsic;
+ def int_riscv_cv_simd_cmpgeu_sc_h : ScalarCoreVSimdGprGprIntrinsic;
+ def int_riscv_cv_simd_cmpgeu_sc_b : ScalarCoreVSimdGprGprIntrinsic;
+ def int_riscv_cv_simd_cmpltu_h : ScalarCoreVSimdGprGprIntrinsic;
+ def int_riscv_cv_simd_cmpltu_b : ScalarCoreVSimdGprGprIntrinsic;
+ def int_riscv_cv_simd_cmpltu_sc_h : ScalarCoreVSimdGprGprIntrinsic;
+ def int_riscv_cv_simd_cmpltu_sc_b : ScalarCoreVSimdGprGprIntrinsic;
+ def int_riscv_cv_simd_cmpleu_h : ScalarCoreVSimdGprGprIntrinsic;
+ def int_riscv_cv_simd_cmpleu_b : ScalarCoreVSimdGprGprIntrinsic;
+ def int_riscv_cv_simd_cmpleu_sc_h : ScalarCoreVSimdGprGprIntrinsic;
+ def int_riscv_cv_simd_cmpleu_sc_b : ScalarCoreVSimdGprGprIntrinsic;
+
+ // ==== XCVsimd — COMPLEX ====
+ // cplxmul: (rs1, rs2, rd_in, divcode_IMM) -> rd_out
+ def int_riscv_cv_simd_cplxmul_r : ScalarCoreVSimdGprGprGprImmIntrinsic;
+ def int_riscv_cv_simd_cplxmul_i : ScalarCoreVSimdGprGprGprImmIntrinsic;
+ def int_riscv_cv_simd_cplxconj : ScalarCoreVSimdGprIntrinsic;
+ // subrotmj: (rs1, rs2, divcode_IMM) -> rd
+ def int_riscv_cv_simd_subrotmj : ScalarCoreVSimdGprGprImmIntrinsic;
} // TargetPrefix = "riscv"
diff --git a/llvm/lib/Target/RISCV/RISCVExpandPseudoInsts.cpp b/llvm/lib/Target/RISCV/RISCVExpandPseudoInsts.cpp
index fdd98d03a77f1..d5a13a7e639fe 100644
--- a/llvm/lib/Target/RISCV/RISCVExpandPseudoInsts.cpp
+++ b/llvm/lib/Target/RISCV/RISCVExpandPseudoInsts.cpp
@@ -60,6 +60,8 @@ class RISCVExpandPseudo : public MachineFunctionPass {
MachineBasicBlock::iterator MBBI);
bool expandPseudoReadVLENBViaVSETVLIX0(MachineBasicBlock &MBB,
MachineBasicBlock::iterator MBBI);
+ bool expandVendorXcvsimdShuffle(MachineBasicBlock &MBB,
+ MachineBasicBlock::iterator MBBI);
#ifndef NDEBUG
unsigned getInstSizeInBytes(const MachineFunction &MF) const {
unsigned Size = 0;
@@ -192,6 +194,8 @@ bool RISCVExpandPseudo::expandMI(MachineBasicBlock &MBB,
return expandVMSET_VMCLR(MBB, MBBI, RISCV::VMXNOR_MM);
case RISCV::PseudoReadVLENBViaVSETVLIX0:
return expandPseudoReadVLENBViaVSETVLIX0(MBB, MBBI);
+ case RISCV::CV_SHUFFLE_SCI_B_PSEUDO:
+ return expandVendorXcvsimdShuffle(MBB, MBBI);
}
return false;
@@ -834,6 +838,33 @@ bool RISCVPreRAExpandPseudo::expandLoadTLSDescAddress(
return true;
}
+bool RISCVExpandPseudo::expandVendorXcvsimdShuffle(
+ MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI) {
+ // CV_SHUFFLE_SCI_B_PSEUDO takes an 8-bit immediate.
+ // Bits [7:6] select one of four cv.shuffleIx.sci.b instructions.
+ // Bits [5:0] become the 6-bit signed immediate payload.
+ DebugLoc DL = MBBI->getDebugLoc();
+ Register DstReg = MBBI->getOperand(0).getReg();
+ Register SrcReg = MBBI->getOperand(1).getReg();
+ unsigned Imm = MBBI->getOperand(2).getImm();
+
+ // Select the correct real instruction based on bits [7:6]
+ static const unsigned Opcodes[] = {
+ RISCV::CV_SHUFFLEI0_SCI_B,
+ RISCV::CV_SHUFFLEI1_SCI_B,
+ RISCV::CV_SHUFFLEI2_SCI_B,
+ RISCV::CV_SHUFFLEI3_SCI_B,
+ };
+ unsigned OpcIdx = (Imm >> 6) & 0x3;
+ unsigned Imm6 = Imm & 0x3F;
+
+ const MCInstrDesc &Desc = TII->get(Opcodes[OpcIdx]);
+ BuildMI(MBB, MBBI, DL, Desc, DstReg).addReg(SrcReg).addImm(Imm6);
+
+ MBBI->eraseFromParent();
+ return true;
+}
+
} // end of anonymous namespace
INITIALIZE_PASS(RISCVExpandPseudo, "riscv-expand-pseudo",
diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfoXCV.td b/llvm/lib/Target/RISCV/RISCVInstrInfoXCV.td
index ec93f60366e1e..281a9f1edff39 100644
--- a/llvm/lib/Target/RISCV/RISCVInstrInfoXCV.td
+++ b/llvm/lib/Target/RISCV/RISCVInstrInfoXCV.td
@@ -850,3 +850,290 @@ let Predicates = [HasVendorXCVmac] in {
def : PatCoreVMacGprGprGprUimm5<"macsRN", "MACSRN">;
def : PatCoreVMacGprGprGprUimm5<"machhsRN", "MACHHSRN">;
}
+
+//===----------------------------------------------------------------------===//
+// XCVsimd pseudo-instruction for cv.shuffle.sci.b
+//===----------------------------------------------------------------------===//
+// The hardware encodes the 8-bit shuffle immediate by splitting it across
+// four different opcodes: cv.shufflei0/1/2/3.sci.b, where bits [7:6] select
+// the opcode and bits [5:0] are the payload. This pseudo absorbs the full
+// 8-bit immediate; RISCVExpandPseudoInsts splits it into the correct real
+// instruction.
+
+let Predicates = [HasVendorXCVsimd, IsRV32] in {
+ let hasSideEffects = 0, mayLoad = 0, mayStore = 0, isCodeGenOnly = 1 in
+ def CV_SHUFFLE_SCI_B_PSEUDO
+ : Pseudo<(outs GPR:$rd), (ins GPR:$rs1, i32imm:$imm), []>;
+}
+
+//===----------------------------------------------------------------------===//
+// Pattern helper multiclasses for XCVsimd
+//===----------------------------------------------------------------------===//
+
+// Binary signed: RR variants + SCI with simm6
+multiclass PatCoreVSimdSigned<string iname> {
+ def : PatGprGpr<!cast<Intrinsic>("int_riscv_cv_simd_" # iname # "_h"),
+ !cast<RVInst>("CV_" # NAME # "_H")>;
+ def : PatGprGpr<!cast<Intrinsic>("int_riscv_cv_simd_" # iname # "_b"),
+ !cast<RVInst>("CV_" # NAME # "_B")>;
+ def : PatGprGpr<!cast<Intrinsic>("int_riscv_cv_simd_" # iname # "_sc_h"),
+ !cast<RVInst>("CV_" # NAME # "_SC_H")>;
+ def : PatGprGpr<!cast<Intrinsic>("int_riscv_cv_simd_" # iname # "_sc_b"),
+ !cast<RVInst>("CV_" # NAME # "_SC_B")>;
+ // SCI: when the scalar fits in simm6, prefer the immediate instruction
+ def : Pat<(!cast<Intrinsic>("int_riscv_cv_simd_" # iname # "_sc_h")
+ GPR:$rs1, simm6:$imm),
+ (!cast<RVInst>("CV_" # NAME # "_SCI_H") GPR:$rs1, simm6:$imm)>;
+ def : Pat<(!cast<Intrinsic>("int_riscv_cv_simd_" # iname # "_sc_b")
+ GPR:$rs1, simm6:$imm),
+ (!cast<RVInst>("CV_" # NAME # "_SCI_B") GPR:$rs1, simm6:$imm)>;
+}
+
+// Binary unsigned: RR variants + SCI with uimm6
+multiclass PatCoreVSimdUnsigned<string iname> {
+ def : PatGprGpr<!cast<Intrinsic>("int_riscv_cv_simd_" # iname # "_h"),
+ !cast<RVInst>("CV_" # NAME # "_H")>;
+ def : PatGprGpr<!cast<Intrinsic>("int_riscv_cv_simd_" # iname # "_b"),
+ !cast<RVInst>("CV_" # NAME # "_B")>;
+ def : PatGprGpr<!cast<Intrinsic>("int_riscv_cv_simd_" # iname # "_sc_h"),
+ !cast<RVInst>("CV_" # NAME # "_SC_H")>;
+ def : PatGprGpr<!cast<Intrinsic>("int_riscv_cv_simd_" # iname # "_sc_b"),
+ !cast<RVInst>("CV_" # NAME # "_SC_B")>;
+ def : Pat<(!cast<Intrinsic>("int_riscv_cv_simd_" # iname # "_sc_h")
+ GPR:$rs1, uimm6:$imm),
+ (!cast<RVInst>("CV_" # NAME # "_SCI_H") GPR:$rs1, uimm6:$imm)>;
+ def : Pat<(!cast<Intrinsic>("int_riscv_cv_simd_" # iname # "_sc_b")
+ GPR:$rs1, uimm6:$imm),
+ (!cast<RVInst>("CV_" # NAME # "_SCI_B") GPR:$rs1, uimm6:$imm)>;
+}
+
+// Shift: RR variants + SCI with uimm4 for .h, uimm3 for .b
+multiclass PatCoreVSimdShift<string iname> {
+ def : PatGprGpr<!cast<Intrinsic>("int_riscv_cv_simd_" # iname # "_h"),
+ !cast<RVInst>("CV_" # NAME # "_H")>;
+ def : PatGprGpr<!cast<Intrinsic>("int_riscv_cv_simd_" # iname # "_b"),
+ !cast<RVInst>("CV_" # NAME # "_B")>;
+ def : PatGprGpr<!cast<Intrinsic>("int_riscv_cv_simd_" # iname # "_sc_h"),
+ !cast<RVInst>("CV_" # NAME # "_SC_H")>;
+ def : PatGprGpr<!cast<Intrinsic>("int_riscv_cv_simd_" # iname # "_sc_b"),
+ !cast<RVInst>("CV_" # NAME # "_SC_B")>;
+ def : Pat<(!cast<Intrinsic>("int_riscv_cv_simd_" # iname # "_sc_h")
+ GPR:$rs1, uimm4:$imm),
+ (!cast<RVInst>("CV_" # NAME # "_SCI_H") GPR:$rs1, uimm4:$imm)>;
+ def : Pat<(!cast<Intrinsic>("int_riscv_cv_simd_" # iname # "_sc_b")
+ GPR:$rs1, uimm3:$imm),
+ (!cast<RVInst>("CV_" # NAME # "_SCI_B") GPR:$rs1, uimm3:$imm)>;
+}
+
+// Accumulating signed (Wb): intrinsic(rs1, rs2, acc) → instr(acc, rs1, rs2)
+// + SCI variant where rs2 (arg1) is simm6
+multiclass PatCoreVSimdSignedWb<string iname> {
+ def : Pat<(!cast<Intrinsic>("int_riscv_cv_simd_" # iname # "_h")
+ GPR:$rs1, GPR:$rs2, GPR:$rd),
+ (!cast<RVInst>("CV_" # NAME # "_H") GPR:$rd, GPR:$rs1, GPR:$rs2)>;
+ def : Pat<(!cast<Intrinsic>("int_riscv_cv_simd_" # iname # "_b")
+ GPR:$rs1, GPR:$rs2, GPR:$rd),
+ (!cast<RVInst>("CV_" # NAME # "_B") GPR:$rd, GPR:$rs1, GPR:$rs2)>;
+ def : Pat<(!cast<Intrinsic>("int_riscv_cv_simd_" # iname # "_sc_h")
+ GPR:$rs1, GPR:$rs2, GPR:$rd),
+ (!cast<RVInst>("CV_" # NAME # "_SC_H") GPR:$rd, GPR:$rs1, GPR:$rs2)>;
+ def : Pat<(!cast<Intrinsic>("int_riscv_cv_simd_" # iname # "_sc_b")
+ GPR:$rs1, GPR:$rs2, GPR:$rd),
+ (!cast<RVInst>("CV_" # NAME # "_SC_B") GPR:$rd, GPR:$rs1, GPR:$rs2)>;
+ def : Pat<(!cast<Intrinsic>("int_riscv_cv_simd_" # iname # "_sc_h")
+ GPR:$rs1, simm6:$imm, GPR:$rd),
+ (!cast<RVInst>("CV_" # NAME # "_SCI_H") GPR:$rd, GPR:$rs1, simm6:$imm)>;
+ def : Pat<(!cast<Intrinsic>("int_riscv_cv_simd_" # iname # "_sc_b")
+ GPR:$rs1, simm6:$imm, GPR:$rd),
+ (!cast<RVInst>("CV_" # NAME # "_SCI_B") GPR:$rd, GPR:$rs1, simm6:$imm)>;
+}
+
+// Accumulating unsigned (Wb): same but SCI uses uimm6
+multiclass PatCoreVSimdUnsignedWb<string iname> {
+ def : Pat<(!cast<Intrinsic>("int_riscv_cv_simd_" # iname # "_h")
+ GPR:$rs1, GPR:$rs2, GPR:$rd),
+ (!cast<RVInst>("CV_" # NAME # "_H") GPR:$rd, GPR:$rs1, GPR:$rs2)>;
+ def : Pat<(!cast<Intrinsic>("int_riscv_cv_simd_" # iname # "_b")
+ GPR:$rs1, GPR:$rs2, GPR:$rd),
+ (!cast<RVInst>("CV_" # NAME # "_B") GPR:$rd, GPR:$rs1, GPR:$rs2)>;
+ def : Pat<(!cast<Intrinsic>("int_riscv_cv_simd_" # iname # "_sc_h")
+ GPR:$rs1, GPR:$rs2, GPR:$rd),
+ (!cast<RVInst>("CV_" # NAME # "_SC_H") GPR:$rd, GPR:$rs1, GPR:$rs2)>;
+ def : Pat<(!cast<Intrinsic>("int_riscv_cv_simd_" # iname # "_sc_b")
+ GPR:$rs1, GPR:$rs2, GPR:$rd),
+ (!cast<RVInst>("CV_" # NAME # "_SC_B") GPR:$rd, GPR:$rs1, GPR:$rs2)>;
+ def : Pat<(!cast<Intrinsic>("int_riscv_cv_simd_" # iname # "_sc_h")
+ GPR:$rs1, uimm6:$imm, GPR:$rd),
+ (!cast<RVInst>("CV_" # NAME # "_SCI_H") GPR:$rd, GPR:$rs1, uimm6:$imm)>;
+ def : Pat<(!cast<Intrinsic>("int_riscv_cv_simd_" # iname # "_sc_b")
+ GPR:$rs1, uimm6:$imm, GPR:$rd),
+ (!cast<RVInst>("CV_" # NAME # "_SCI_B") GPR:$rd, GPR:$rs1, uimm6:$imm)>;
+}
+
+//===----------------------------------------------------------------------===//
+// XCVsimd intrinsic-to-instruction patterns
+//===----------------------------------------------------------------------===//
+
+let Predicates = [HasVendorXCVsimd, IsRV32], AddedComplexity = 1 in {
+
+ // ---- ADD / SUB ----
+ // add_h / sub_h use a divcode immediate to select between 4 instructions
+ // intrinsic: (rs1, rs2, divcode_IMM) -> rd
+ def : Pat<(int_riscv_cv_simd_add_h GPR:$rs1, GPR:$rs2, 0),
+ (CV_ADD_H GPR:$rs1, GPR:$rs2)>;
+ def : Pat<(int_riscv_cv_simd_add_h GPR:$rs1, GPR:$rs2, 1),
+ (CV_ADD_DIV2 GPR:$rs1, GPR:$rs2)>;
+ def : Pat<(int_riscv_cv_simd_add_h GPR:$rs1, GPR:$rs2, 2),
+ (CV_ADD_DIV4 GPR:$rs1, GPR:$rs2)>;
+ def : Pat<(int_riscv_cv_simd_add_h GPR:$rs1, GPR:$rs2, 3),
+ (CV_ADD_DIV8 GPR:$rs1, GPR:$rs2)>;
+
+ def : PatGprGpr<int_riscv_cv_simd_add_b, CV_ADD_B>;
+ def : PatGprGpr<int_riscv_cv_simd_add_sc_h, CV_ADD_SC_H>;
+ def : PatGprGpr<int_riscv_cv_simd_add_sc_b, CV_ADD_SC_B>;
+ def : Pat<(int_riscv_cv_simd_add_sc_h GPR:$rs1, simm6:$imm),
+ (CV_ADD_SCI_H GPR:$rs1, simm6:$imm)>;
+ def : Pat<(int_riscv_cv_simd_add_sc_b GPR:$rs1, simm6:$imm),
+ (CV_ADD_SCI_B GPR:$rs1, simm6:$imm)>;
+
+ def : Pat<(int_riscv_cv_simd_sub_h GPR:$rs1, GPR:$rs2, 0),
+ (CV_SUB_H GPR:$rs1, GPR:$rs2)>;
+ def : Pat<(int_riscv_cv_simd_sub_h GPR:$rs1, GPR:$rs2, 1),
+ (CV_SUB_DIV2 GPR:$rs1, GPR:$rs2)>;
+ def : Pat<(int_riscv_cv_simd_sub_h GPR:$rs1, GPR:$rs2, 2),
+ (CV_SUB_DIV4 GPR:$rs1, GPR:$rs2)>;
+ def : Pat<(int_riscv_cv_simd_sub_h GPR:$rs1, GPR:$rs2, 3),
+ (CV_SUB_DIV8 GPR:$rs1, GPR:$rs2)>;
+
+ def : PatGprGpr<int_riscv_cv_simd_sub_b, CV_SUB_B>;
+ def : PatGprGpr<int_riscv_cv_simd_sub_sc_h, CV_SUB_SC_H>;
+ def : PatGprGpr<int_riscv_cv_simd_sub_sc_b, CV_SUB_SC_B>;
+ def : Pat<(int_riscv_cv_simd_sub_sc_h GPR:$rs1, simm6:$imm),
+ (CV_SUB_SCI_H GPR:$rs1, simm6:$imm)>;
+ def : Pat<(int_riscv_cv_simd_sub_sc_b GPR:$rs1, simm6:$imm),
+ (CV_SUB_SCI_B GPR:$rs1, simm6:$imm)>;
+
+ // ---- AVG / AVGU / MIN / MINU / MAX / MAXU ----
+ defm AVG : PatCoreVSimdSigned<"avg">;
+ defm AVGU : PatCoreVSimdUnsigned<"avgu">;
+ defm MIN : PatCoreVSimdSigned<"min">;
+ defm MINU : PatCoreVSimdUnsigned<"minu">;
+ defm MAX : PatCoreVSimdSigned<"max">;
+ defm MAXU : PatCoreVSimdUnsigned<"maxu">;
+
+ // ---- SRL / SRA / SLL ----
+ defm SRL : PatCoreVSimdShift<"srl">;
+ defm SRA : PatCoreVSimdShift<"sra">;
+ defm SLL : PatCoreVSimdShift<"sll">;
+
+ // ---- OR / XOR / AND ----
+ defm OR : PatCoreVSimdSigned<"or">;
+ defm XOR : PatCoreVSimdSigned<"xor">;
+ defm AND : PatCoreVSimdSigned<"and">;
+
+ // ---- ABS ----
+ def : PatGpr<int_riscv_cv_simd_abs_h, CV_ABS_H>;
+ def : PatGpr<int_riscv_cv_simd_abs_b, CV_ABS_B>;
+
+ // ---- DOT PRODUCTS (non-accumulating) ----
+ defm DOTUP : PatCoreVSimdUnsigned<"dotup">;
+ defm DOTUSP : PatCoreVSimdSigned<"dotusp">;
+ defm DOTSP : PatCoreVSimdSigned<"dotsp">;
+
+ // ---- SDOT (accumulating) ----
+ defm SDOTUP : PatCoreVSimdUnsignedWb<"sdotup">;
+ defm SDOTUSP : PatCoreVSimdSignedWb<"sdotusp">;
+ defm SDOTSP : PatCoreVSimdSignedWb<"sdotsp">;
+
+ // ---- EXTRACT / EXTRACTU ----
+ // intrinsic: (rs1, IMM) -> rd
+ def : Pat<(int_riscv_cv_simd_extract_h GPR:$rs1, timm:$imm),
+ (CV_EXTRACT_H GPR:$rs1, timm:$imm)>;
+ def : Pat<(int_riscv_cv_simd_extract_b GPR:$rs1, timm:$imm),
+ (CV_EXTRACT_B GPR:$rs1, timm:$imm)>;
+ def : Pat<(int_riscv_cv_simd_extractu_h GPR:$rs1, timm:$imm),
+ (CV_EXTRACTU_H GPR:$rs1, timm:$imm)>;
+ def : Pat<(int_riscv_cv_simd_extractu_b GPR:$rs1, timm:$imm),
+ (CV_EXTRACTU_B GPR:$rs1, timm:$imm)>;
+
+ // ---- INSERT ----
+ // intrinsic: (rd_in, rs1, IMM) -> rd_out
+ def : Pat<(int_riscv_cv_simd_insert_h GPR:$rd, GPR:$rs1, timm:$imm),
+ (CV_INSERT_H GPR:$rd, GPR:$rs1, timm:$imm)>;
+ def : Pat<(int_riscv_cv_simd_insert_b GPR:$rd, GPR:$rs1, timm:$imm),
+ (CV_INSERT_B GPR:$rd, GPR:$rs1, timm:$imm)>;
+
+ // ---- SHUFFLE ----
+ def : PatGprGpr<int_riscv_cv_simd_shuffle_h, CV_SHUFFLE_H>;
+ def : PatGprGpr<int_riscv_cv_simd_shuffle_b, CV_SHUFFLE_B>;
+ def : Pat<(int_riscv_cv_simd_shuffle_sci_h GPR:$rs1, timm:$imm),
+ (CV_SHUFFLE_SCI_H GPR:$rs1, timm:$imm)>;
+ // shuffle_sci_b goes through the pseudo (8-bit imm split by expander)
+ def : Pat<(int_riscv_cv_simd_shuffle_sci_b GPR:$rs1, timm:$imm),
+ (CV_SHUFFLE_SCI_B_PSEUDO GPR:$rs1, timm:$imm)>;
+
+ // ---- SHUFFLE2: (rs1, rs2, rd_in) -> rd_out ----
+ def : Pat<(int_riscv_cv_simd_shuffle2_h GPR:$rs1, GPR:$rs2, GPR:$rd),
+ (CV_SHUFFLE2_H GPR:$rd, GPR:$rs1, GPR:$rs2)>;
+ def : Pat<(int_riscv_cv_simd_shuffle2_b GPR:$rs1, GPR:$rs2, GPR:$rd),
+ (CV_SHUFFLE2_B GPR:$rd, GPR:$rs1, GPR:$rs2)>;
+
+ // ---- PACK ----
+ // pack (packlo_h) and pack.h (packhi_h) are plain binary: (rs1, rs2) -> rd
+ def : PatGprGpr<int_riscv_cv_simd_packlo_h, CV_PACK>;
+ def : PatGprGpr<int_riscv_cv_simd_packhi_h, CV_PACK_H>;
+ // packhi.b / packlo.b are accumulating: (rd_in, rs1, rs2) -> rd_out
+ def : Pat<(int_riscv_cv_simd_packhi_b GPR:$rd, GPR:$rs1, GPR:$rs2),
+ (CV_PACKHI_B GPR:$rd, GPR:$rs1, GPR:$rs2)>;
+ def : Pat<(int_riscv_cv_simd_packlo_b GPR:$rd, GPR:$rs1, GPR:$rs2),
+ (CV_PACKLO_B GPR:$rd, GPR:$rs1, GPR:$rs2)>;
+
+ // ---- COMPARE (signed) ----
+ defm CMPEQ : PatCoreVSimdSigned<"cmpeq">;
+ defm CMPNE : PatCoreVSimdSigned<"cmpne">;
+ defm CMPGT : PatCoreVSimdSigned<"cmpgt">;
+ defm CMPGE : PatCoreVSimdSigned<"cmpge">;
+ defm CMPLT : PatCoreVSimdSigned<"cmplt">;
+ defm CMPLE : PatCoreVSimdSigned<"cmple">;
+
+ // ---- COMPARE (unsigned) ----
+ defm CMPGTU : PatCoreVSimdUnsigned<"cmpgtu">;
+ defm CMPGEU : PatCoreVSimdUnsigned<"cmpgeu">;
+ defm CMPLTU : PatCoreVSimdUnsigned<"cmpltu">;
+ defm CMPLEU : PatCoreVSimdUnsigned<"cmpleu">;
+
+ // ---- COMPLEX: cplxmul ----
+ // intrinsic: (rs1, rs2, rd_in, divcode_IMM) -> rd_out
+ def : Pat<(int_riscv_cv_simd_cplxmul_r GPR:$rs1, GPR:$rs2, GPR:$rd, 0),
+ (CV_CPLXMUL_R GPR:$rd, GPR:$rs1, GPR:$rs2)>;
+ def : Pat<(int_riscv_cv_simd_cplxmul_r GPR:$rs1, GPR:$rs2, GPR:$rd, 1),
+ (CV_CPLXMUL_R_DIV2 GPR:$rd, GPR:$rs1, GPR:$rs2)>;
+ def : Pat<(int_riscv_cv_simd_cplxmul_r GPR:$rs1, GPR:$rs2, GPR:$rd, 2),
+ (CV_CPLXMUL_R_DIV4 GPR:$rd, GPR:$rs1, GPR:$rs2)>;
+ def : Pat<(int_riscv_cv_simd_cplxmul_r GPR:$rs1, GPR:$rs2, GPR:$rd, 3),
+ (CV_CPLXMUL_R_DIV8 GPR:$rd, GPR:$rs1, GPR:$rs2)>;
+
+ def : Pat<(int_riscv_cv_simd_cplxmul_i GPR:$rs1, GPR:$rs2, GPR:$rd, 0),
+ (CV_CPLXMUL_I GPR:$rd, GPR:$rs1, GPR:$rs2)>;
+ def : Pat<(int_riscv_cv_simd_cplxmul_i GPR:$rs1, GPR:$rs2, GPR:$rd, 1),
+ (CV_CPLXMUL_I_DIV2 GPR:$rd, GPR:$rs1, GPR:$rs2)>;
+ def : Pat<(int_riscv_cv_simd_cplxmul_i GPR:$rs1, GPR:$rs2, GPR:$rd, 2),
+ (CV_CPLXMUL_I_DIV4 GPR:$rd, GPR:$rs1, GPR:$rs2)>;
+ def : Pat<(int_riscv_cv_simd_cplxmul_i GPR:$rs1, GPR:$rs2, GPR:$rd, 3),
+ (CV_CPLXMUL_I_DIV8 GPR:$rd, GPR:$rs1, GPR:$rs2)>;
+
+ // ---- COMPLEX: cplxconj ----
+ def : PatGpr<int_riscv_cv_simd_cplxconj, CV_CPLXCONJ>;
+
+ // ---- COMPLEX: subrotmj ----
+ // intrinsic: (rs1, rs2, divcode_IMM) -> rd
+ def : Pat<(int_riscv_cv_simd_subrotmj GPR:$rs1, GPR:$rs2, 0),
+ (CV_SUBROTMJ GPR:$rs1, GPR:$rs2)>;
+ def : Pat<(int_riscv_cv_simd_subrotmj GPR:$rs1, GPR:$rs2, 1),
+ (CV_SUBROTMJ_DIV2 GPR:$rs1, GPR:$rs2)>;
+ def : Pat<(int_riscv_cv_simd_subrotmj GPR:$rs1, GPR:$rs2, 2),
+ (CV_SUBROTMJ_DIV4 GPR:$rs1, GPR:$rs2)>;
+ def : Pat<(int_riscv_cv_simd_subrotmj GPR:$rs1, GPR:$rs2, 3),
+ (CV_SUBROTMJ_DIV8 GPR:$rs1, GPR:$rs2)>;
+
+} // Predicates = [HasVendorXCVsimd, IsRV32], AddedComplexity = 1
diff --git a/llvm/test/CodeGen/RISCV/xcvsimd.ll b/llvm/test/CodeGen/RISCV/xcvsimd.ll
new file mode 100644
index 0000000000000..20cb4f787797d
--- /dev/null
+++ b/llvm/test/CodeGen/RISCV/xcvsimd.ll
@@ -0,0 +1,1115 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
+; RUN: llc -mtriple=riscv32 -mattr=+m,+xcvsimd -verify-machineinstrs < %s \
+; RUN: | FileCheck %s
+
+; This file tests that all XCVsimd LLVM IR intrinsics are correctly lowered
+; to their corresponding CV32E40P machine instructions.
+
+;===----------------------------------------------------------------------===;
+; ADD / SUB
+;===----------------------------------------------------------------------===;
+
+define i32 @test_cv_simd_add_h(i32 %a, i32 %b) {
+; CHECK-LABEL: test_cv_simd_add_h:
+; CHECK: # %bb.0:
+; CHECK-NEXT: cv.add.h a0, a0, a1
+; CHECK-NEXT: ret
+ %res = call i32 @llvm.riscv.cv.simd.add.h(i32 %a, i32 %b, i32 0)
+ ret i32 %res
+}
+
+define i32 @test_cv_simd_add_h_div2(i32 %a, i32 %b) {
+; CHECK-LABEL: test_cv_simd_add_h_div2:
+; CHECK: # %bb.0:
+; CHECK-NEXT: cv.add.div2 a0, a0, a1
+; CHECK-NEXT: ret
+ %res = call i32 @llvm.riscv.cv.simd.add.h(i32 %a, i32 %b, i32 1)
+ ret i32 %res
+}
+
+define i32 @test_cv_simd_add_h_div4(i32 %a, i32 %b) {
+; CHECK-LABEL: test_cv_simd_add_h_div4:
+; CHECK: # %bb.0:
+; CHECK-NEXT: cv.add.div4 a0, a0, a1
+; CHECK-NEXT: ret
+ %res = call i32 @llvm.riscv.cv.simd.add.h(i32 %a, i32 %b, i32 2)
+ ret i32 %res
+}
+
+define i32 @test_cv_simd_add_h_div8(i32 %a, i32 %b) {
+; CHECK-LABEL: test_cv_simd_add_h_div8:
+; CHECK: # %bb.0:
+; CHECK-NEXT: cv.add.div8 a0, a0, a1
+; CHECK-NEXT: ret
+ %res = call i32 @llvm.riscv.cv.simd.add.h(i32 %a, i32 %b, i32 3)
+ ret i32 %res
+}
+
+define i32 @test_cv_simd_add_b(i32 %a, i32 %b) {
+; CHECK-LABEL: test_cv_simd_add_b:
+; CHECK: # %bb.0:
+; CHECK-NEXT: cv.add.b a0, a0, a1
+; CHECK-NEXT: ret
+ %res = call i32 @llvm.riscv.cv.simd.add.b(i32 %a, i32 %b)
+ ret i32 %res
+}
+
+define i32 @test_cv_simd_add_sc_h(i32 %a, i32 %b) {
+; CHECK-LABEL: test_cv_simd_add_sc_h:
+; CHECK: # %bb.0:
+; CHECK-NEXT: cv.add.sc.h a0, a0, a1
+; CHECK-NEXT: ret
+ %res = call i32 @llvm.riscv.cv.simd.add.sc.h(i32 %a, i32 %b)
+ ret i32 %res
+}
+
+define i32 @test_cv_simd_add_sc_b(i32 %a, i32 %b) {
+; CHECK-LABEL: test_cv_simd_add_sc_b:
+; CHECK: # %bb.0:
+; CHECK-NEXT: cv.add.sc.b a0, a0, a1
+; CHECK-NEXT: ret
+ %res = call i32 @llvm.riscv.cv.simd.add.sc.b(i32 %a, i32 %b)
+ ret i32 %res
+}
+
+define i32 @test_cv_simd_sub_h(i32 %a, i32 %b) {
+; CHECK-LABEL: test_cv_simd_sub_h:
+; CHECK: # %bb.0:
+; CHECK-NEXT: cv.sub.h a0, a0, a1
+; CHECK-NEXT: ret
+ %res = call i32 @llvm.riscv.cv.simd.sub.h(i32 %a, i32 %b, i32 0)
+ ret i32 %res
+}
+
+define i32 @test_cv_simd_sub_h_div2(i32 %a, i32 %b) {
+; CHECK-LABEL: test_cv_simd_sub_h_div2:
+; CHECK: # %bb.0:
+; CHECK-NEXT: cv.sub.div2 a0, a0, a1
+; CHECK-NEXT: ret
+ %res = call i32 @llvm.riscv.cv.simd.sub.h(i32 %a, i32 %b, i32 1)
+ ret i32 %res
+}
+
+define i32 @test_cv_simd_sub_h_div4(i32 %a, i32 %b) {
+; CHECK-LABEL: test_cv_simd_sub_h_div4:
+; CHECK: # %bb.0:
+; CHECK-NEXT: cv.sub.div4 a0, a0, a1
+; CHECK-NEXT: ret
+ %res = call i32 @llvm.riscv.cv.simd.sub.h(i32 %a, i32 %b, i32 2)
+ ret i32 %res
+}
+
+define i32 @test_cv_simd_sub_h_div8(i32 %a, i32 %b) {
+; CHECK-LABEL: test_cv_simd_sub_h_div8:
+; CHECK: # %bb.0:
+; CHECK-NEXT: cv.sub.div8 a0, a0, a1
+; CHECK-NEXT: ret
+ %res = call i32 @llvm.riscv.cv.simd.sub.h(i32 %a, i32 %b, i32 3)
+ ret i32 %res
+}
+
+define i32 @test_cv_simd_sub_b(i32 %a, i32 %b) {
+; CHECK-LABEL: test_cv_simd_sub_b:
+; CHECK: # %bb.0:
+; CHECK-NEXT: cv.sub.b a0, a0, a1
+; CHECK-NEXT: ret
+ %res = call i32 @llvm.riscv.cv.simd.sub.b(i32 %a, i32 %b)
+ ret i32 %res
+}
+
+define i32 @test_cv_simd_sub_sc_h(i32 %a, i32 %b) {
+; CHECK-LABEL: test_cv_simd_sub_sc_h:
+; CHECK: # %bb.0:
+; CHECK-NEXT: cv.sub.sc.h a0, a0, a1
+; CHECK-NEXT: ret
+ %res = call i32 @llvm.riscv.cv.simd.sub.sc.h(i32 %a, i32 %b)
+ ret i32 %res
+}
+
+define i32 @test_cv_simd_sub_sc_b(i32 %a, i32 %b) {
+; CHECK-LABEL: test_cv_simd_sub_sc_b:
+; CHECK: # %bb.0:
+; CHECK-NEXT: cv.sub.sc.b a0, a0, a1
+; CHECK-NEXT: ret
+ %res = call i32 @llvm.riscv.cv.simd.sub.sc.b(i32 %a, i32 %b)
+ ret i32 %res
+}
+
+;===----------------------------------------------------------------------===;
+; AVG / AVGU
+;===----------------------------------------------------------------------===;
+
+define i32 @test_cv_simd_avg_h(i32 %a, i32 %b) {
+; CHECK-LABEL: test_cv_simd_avg_h:
+; CHECK: # %bb.0:
+; CHECK-NEXT: cv.avg.h a0, a0, a1
+; CHECK-NEXT: ret
+ %res = call i32 @llvm.riscv.cv.simd.avg.h(i32 %a, i32 %b)
+ ret i32 %res
+}
+
+define i32 @test_cv_simd_avg_b(i32 %a, i32 %b) {
+; CHECK-LABEL: test_cv_simd_avg_b:
+; CHECK: # %bb.0:
+; CHECK-NEXT: cv.avg.b a0, a0, a1
+; CHECK-NEXT: ret
+ %res = call i32 @llvm.riscv.cv.simd.avg.b(i32 %a, i32 %b)
+ ret i32 %res
+}
+
+define i32 @test_cv_simd_avg_sc_h(i32 %a, i32 %b) {
+; CHECK-LABEL: test_cv_simd_avg_sc_h:
+; CHECK: # %bb.0:
+; CHECK-NEXT: cv.avg.sc.h a0, a0, a1
+; CHECK-NEXT: ret
+ %res = call i32 @llvm.riscv.cv.simd.avg.sc.h(i32 %a, i32 %b)
+ ret i32 %res
+}
+
+define i32 @test_cv_simd_avg_sc_b(i32 %a, i32 %b) {
+; CHECK-LABEL: test_cv_simd_avg_sc_b:
+; CHECK: # %bb.0:
+; CHECK-NEXT: cv.avg.sc.b a0, a0, a1
+; CHECK-NEXT: ret
+ %res = call i32 @llvm.riscv.cv.simd.avg.sc.b(i32 %a, i32 %b)
+ ret i32 %res
+}
+
+define i32 @test_cv_simd_avgu_h(i32 %a, i32 %b) {
+; CHECK-LABEL: test_cv_simd_avgu_h:
+; CHECK: # %bb.0:
+; CHECK-NEXT: cv.avgu.h a0, a0, a1
+; CHECK-NEXT: ret
+ %res = call i32 @llvm.riscv.cv.simd.avgu.h(i32 %a, i32 %b)
+ ret i32 %res
+}
+
+define i32 @test_cv_simd_avgu_b(i32 %a, i32 %b) {
+; CHECK-LABEL: test_cv_simd_avgu_b:
+; CHECK: # %bb.0:
+; CHECK-NEXT: cv.avgu.b a0, a0, a1
+; CHECK-NEXT: ret
+ %res = call i32 @llvm.riscv.cv.simd.avgu.b(i32 %a, i32 %b)
+ ret i32 %res
+}
+
+define i32 @test_cv_simd_avgu_sc_h(i32 %a, i32 %b) {
+; CHECK-LABEL: test_cv_simd_avgu_sc_h:
+; CHECK: # %bb.0:
+; CHECK-NEXT: cv.avgu.sc.h a0, a0, a1
+; CHECK-NEXT: ret
+ %res = call i32 @llvm.riscv.cv.simd.avgu.sc.h(i32 %a, i32 %b)
+ ret i32 %res
+}
+
+define i32 @test_cv_simd_avgu_sc_b(i32 %a, i32 %b) {
+; CHECK-LABEL: test_cv_simd_avgu_sc_b:
+; CHECK: # %bb.0:
+; CHECK-NEXT: cv.avgu.sc.b a0, a0, a1
+; CHECK-NEXT: ret
+ %res = call i32 @llvm.riscv.cv.simd.avgu.sc.b(i32 %a, i32 %b)
+ ret i32 %res
+}
+
+;===----------------------------------------------------------------------===;
+; MIN / MINU / MAX / MAXU (representative: _h and _sc_b for each)
+;===----------------------------------------------------------------------===;
+
+define i32 @test_cv_simd_min_h(i32 %a, i32 %b) {
+; CHECK-LABEL: test_cv_simd_min_h:
+; CHECK: # %bb.0:
+; CHECK-NEXT: cv.min.h a0, a0, a1
+; CHECK-NEXT: ret
+ %res = call i32 @llvm.riscv.cv.simd.min.h(i32 %a, i32 %b)
+ ret i32 %res
+}
+
+define i32 @test_cv_simd_min_b(i32 %a, i32 %b) {
+; CHECK-LABEL: test_cv_simd_min_b:
+; CHECK: # %bb.0:
+; CHECK-NEXT: cv.min.b a0, a0, a1
+; CHECK-NEXT: ret
+ %res = call i32 @llvm.riscv.cv.simd.min.b(i32 %a, i32 %b)
+ ret i32 %res
+}
+
+define i32 @test_cv_simd_min_sc_h(i32 %a, i32 %b) {
+; CHECK-LABEL: test_cv_simd_min_sc_h:
+; CHECK: # %bb.0:
+; CHECK-NEXT: cv.min.sc.h a0, a0, a1
+; CHECK-NEXT: ret
+ %res = call i32 @llvm.riscv.cv.simd.min.sc.h(i32 %a, i32 %b)
+ ret i32 %res
+}
+
+define i32 @test_cv_simd_min_sc_b(i32 %a, i32 %b) {
+; CHECK-LABEL: test_cv_simd_min_sc_b:
+; CHECK: # %bb.0:
+; CHECK-NEXT: cv.min.sc.b a0, a0, a1
+; CHECK-NEXT: ret
+ %res = call i32 @llvm.riscv.cv.simd.min.sc.b(i32 %a, i32 %b)
+ ret i32 %res
+}
+
+define i32 @test_cv_simd_minu_h(i32 %a, i32 %b) {
+; CHECK-LABEL: test_cv_simd_minu_h:
+; CHECK: # %bb.0:
+; CHECK-NEXT: cv.minu.h a0, a0, a1
+; CHECK-NEXT: ret
+ %res = call i32 @llvm.riscv.cv.simd.minu.h(i32 %a, i32 %b)
+ ret i32 %res
+}
+
+define i32 @test_cv_simd_minu_b(i32 %a, i32 %b) {
+; CHECK-LABEL: test_cv_simd_minu_b:
+; CHECK: # %bb.0:
+; CHECK-NEXT: cv.minu.b a0, a0, a1
+; CHECK-NEXT: ret
+ %res = call i32 @llvm.riscv.cv.simd.minu.b(i32 %a, i32 %b)
+ ret i32 %res
+}
+
+define i32 @test_cv_simd_max_h(i32 %a, i32 %b) {
+; CHECK-LABEL: test_cv_simd_max_h:
+; CHECK: # %bb.0:
+; CHECK-NEXT: cv.max.h a0, a0, a1
+; CHECK-NEXT: ret
+ %res = call i32 @llvm.riscv.cv.simd.max.h(i32 %a, i32 %b)
+ ret i32 %res
+}
+
+define i32 @test_cv_simd_max_b(i32 %a, i32 %b) {
+; CHECK-LABEL: test_cv_simd_max_b:
+; CHECK: # %bb.0:
+; CHECK-NEXT: cv.max.b a0, a0, a1
+; CHECK-NEXT: ret
+ %res = call i32 @llvm.riscv.cv.simd.max.b(i32 %a, i32 %b)
+ ret i32 %res
+}
+
+define i32 @test_cv_simd_maxu_h(i32 %a, i32 %b) {
+; CHECK-LABEL: test_cv_simd_maxu_h:
+; CHECK: # %bb.0:
+; CHECK-NEXT: cv.maxu.h a0, a0, a1
+; CHECK-NEXT: ret
+ %res = call i32 @llvm.riscv.cv.simd.maxu.h(i32 %a, i32 %b)
+ ret i32 %res
+}
+
+define i32 @test_cv_simd_maxu_b(i32 %a, i32 %b) {
+; CHECK-LABEL: test_cv_simd_maxu_b:
+; CHECK: # %bb.0:
+; CHECK-NEXT: cv.maxu.b a0, a0, a1
+; CHECK-NEXT: ret
+ %res = call i32 @llvm.riscv.cv.simd.maxu.b(i32 %a, i32 %b)
+ ret i32 %res
+}
+
+;===----------------------------------------------------------------------===;
+; SRL / SRA / SLL
+;===----------------------------------------------------------------------===;
+
+define i32 @test_cv_simd_srl_h(i32 %a, i32 %b) {
+; CHECK-LABEL: test_cv_simd_srl_h:
+; CHECK: # %bb.0:
+; CHECK-NEXT: cv.srl.h a0, a0, a1
+; CHECK-NEXT: ret
+ %res = call i32 @llvm.riscv.cv.simd.srl.h(i32 %a, i32 %b)
+ ret i32 %res
+}
+
+define i32 @test_cv_simd_srl_b(i32 %a, i32 %b) {
+; CHECK-LABEL: test_cv_simd_srl_b:
+; CHECK: # %bb.0:
+; CHECK-NEXT: cv.srl.b a0, a0, a1
+; CHECK-NEXT: ret
+ %res = call i32 @llvm.riscv.cv.simd.srl.b(i32 %a, i32 %b)
+ ret i32 %res
+}
+
+define i32 @test_cv_simd_srl_sc_h(i32 %a, i32 %b) {
+; CHECK-LABEL: test_cv_simd_srl_sc_h:
+; CHECK: # %bb.0:
+; CHECK-NEXT: cv.srl.sc.h a0, a0, a1
+; CHECK-NEXT: ret
+ %res = call i32 @llvm.riscv.cv.simd.srl.sc.h(i32 %a, i32 %b)
+ ret i32 %res
+}
+
+define i32 @test_cv_simd_srl_sc_b(i32 %a, i32 %b) {
+; CHECK-LABEL: test_cv_simd_srl_sc_b:
+; CHECK: # %bb.0:
+; CHECK-NEXT: cv.srl.sc.b a0, a0, a1
+; CHECK-NEXT: ret
+ %res = call i32 @llvm.riscv.cv.simd.srl.sc.b(i32 %a, i32 %b)
+ ret i32 %res
+}
+
+define i32 @test_cv_simd_sra_h(i32 %a, i32 %b) {
+; CHECK-LABEL: test_cv_simd_sra_h:
+; CHECK: # %bb.0:
+; CHECK-NEXT: cv.sra.h a0, a0, a1
+; CHECK-NEXT: ret
+ %res = call i32 @llvm.riscv.cv.simd.sra.h(i32 %a, i32 %b)
+ ret i32 %res
+}
+
+define i32 @test_cv_simd_sra_b(i32 %a, i32 %b) {
+; CHECK-LABEL: test_cv_simd_sra_b:
+; CHECK: # %bb.0:
+; CHECK-NEXT: cv.sra.b a0, a0, a1
+; CHECK-NEXT: ret
+ %res = call i32 @llvm.riscv.cv.simd.sra.b(i32 %a, i32 %b)
+ ret i32 %res
+}
+
+define i32 @test_cv_simd_sll_h(i32 %a, i32 %b) {
+; CHECK-LABEL: test_cv_simd_sll_h:
+; CHECK: # %bb.0:
+; CHECK-NEXT: cv.sll.h a0, a0, a1
+; CHECK-NEXT: ret
+ %res = call i32 @llvm.riscv.cv.simd.sll.h(i32 %a, i32 %b)
+ ret i32 %res
+}
+
+define i32 @test_cv_simd_sll_b(i32 %a, i32 %b) {
+; CHECK-LABEL: test_cv_simd_sll_b:
+; CHECK: # %bb.0:
+; CHECK-NEXT: cv.sll.b a0, a0, a1
+; CHECK-NEXT: ret
+ %res = call i32 @llvm.riscv.cv.simd.sll.b(i32 %a, i32 %b)
+ ret i32 %res
+}
+
+;===----------------------------------------------------------------------===;
+; OR / XOR / AND
+;===----------------------------------------------------------------------===;
+
+define i32 @test_cv_simd_or_h(i32 %a, i32 %b) {
+; CHECK-LABEL: test_cv_simd_or_h:
+; CHECK: # %bb.0:
+; CHECK-NEXT: cv.or.h a0, a0, a1
+; CHECK-NEXT: ret
+ %res = call i32 @llvm.riscv.cv.simd.or.h(i32 %a, i32 %b)
+ ret i32 %res
+}
+
+define i32 @test_cv_simd_or_b(i32 %a, i32 %b) {
+; CHECK-LABEL: test_cv_simd_or_b:
+; CHECK: # %bb.0:
+; CHECK-NEXT: cv.or.b a0, a0, a1
+; CHECK-NEXT: ret
+ %res = call i32 @llvm.riscv.cv.simd.or.b(i32 %a, i32 %b)
+ ret i32 %res
+}
+
+define i32 @test_cv_simd_xor_h(i32 %a, i32 %b) {
+; CHECK-LABEL: test_cv_simd_xor_h:
+; CHECK: # %bb.0:
+; CHECK-NEXT: cv.xor.h a0, a0, a1
+; CHECK-NEXT: ret
+ %res = call i32 @llvm.riscv.cv.simd.xor.h(i32 %a, i32 %b)
+ ret i32 %res
+}
+
+define i32 @test_cv_simd_xor_b(i32 %a, i32 %b) {
+; CHECK-LABEL: test_cv_simd_xor_b:
+; CHECK: # %bb.0:
+; CHECK-NEXT: cv.xor.b a0, a0, a1
+; CHECK-NEXT: ret
+ %res = call i32 @llvm.riscv.cv.simd.xor.b(i32 %a, i32 %b)
+ ret i32 %res
+}
+
+define i32 @test_cv_simd_and_h(i32 %a, i32 %b) {
+; CHECK-LABEL: test_cv_simd_and_h:
+; CHECK: # %bb.0:
+; CHECK-NEXT: cv.and.h a0, a0, a1
+; CHECK-NEXT: ret
+ %res = call i32 @llvm.riscv.cv.simd.and.h(i32 %a, i32 %b)
+ ret i32 %res
+}
+
+define i32 @test_cv_simd_and_b(i32 %a, i32 %b) {
+; CHECK-LABEL: test_cv_simd_and_b:
+; CHECK: # %bb.0:
+; CHECK-NEXT: cv.and.b a0, a0, a1
+; CHECK-NEXT: ret
+ %res = call i32 @llvm.riscv.cv.simd.and.b(i32 %a, i32 %b)
+ ret i32 %res
+}
+
+;===----------------------------------------------------------------------===;
+; ABS
+;===----------------------------------------------------------------------===;
+
+define i32 @test_cv_simd_abs_h(i32 %a) {
+; CHECK-LABEL: test_cv_simd_abs_h:
+; CHECK: # %bb.0:
+; CHECK-NEXT: cv.abs.h a0, a0
+; CHECK-NEXT: ret
+ %res = call i32 @llvm.riscv.cv.simd.abs.h(i32 %a)
+ ret i32 %res
+}
+
+define i32 @test_cv_simd_abs_b(i32 %a) {
+; CHECK-LABEL: test_cv_simd_abs_b:
+; CHECK: # %bb.0:
+; CHECK-NEXT: cv.abs.b a0, a0
+; CHECK-NEXT: ret
+ %res = call i32 @llvm.riscv.cv.simd.abs.b(i32 %a)
+ ret i32 %res
+}
+
+;===----------------------------------------------------------------------===;
+; DOT PRODUCTS (non-accumulating)
+;===----------------------------------------------------------------------===;
+
+define i32 @test_cv_simd_dotup_h(i32 %a, i32 %b) {
+; CHECK-LABEL: test_cv_simd_dotup_h:
+; CHECK: # %bb.0:
+; CHECK-NEXT: cv.dotup.h a0, a0, a1
+; CHECK-NEXT: ret
+ %res = call i32 @llvm.riscv.cv.simd.dotup.h(i32 %a, i32 %b)
+ ret i32 %res
+}
+
+define i32 @test_cv_simd_dotup_b(i32 %a, i32 %b) {
+; CHECK-LABEL: test_cv_simd_dotup_b:
+; CHECK: # %bb.0:
+; CHECK-NEXT: cv.dotup.b a0, a0, a1
+; CHECK-NEXT: ret
+ %res = call i32 @llvm.riscv.cv.simd.dotup.b(i32 %a, i32 %b)
+ ret i32 %res
+}
+
+define i32 @test_cv_simd_dotup_sc_h(i32 %a, i32 %b) {
+; CHECK-LABEL: test_cv_simd_dotup_sc_h:
+; CHECK: # %bb.0:
+; CHECK-NEXT: cv.dotup.sc.h a0, a0, a1
+; CHECK-NEXT: ret
+ %res = call i32 @llvm.riscv.cv.simd.dotup.sc.h(i32 %a, i32 %b)
+ ret i32 %res
+}
+
+define i32 @test_cv_simd_dotup_sc_b(i32 %a, i32 %b) {
+; CHECK-LABEL: test_cv_simd_dotup_sc_b:
+; CHECK: # %bb.0:
+; CHECK-NEXT: cv.dotup.sc.b a0, a0, a1
+; CHECK-NEXT: ret
+ %res = call i32 @llvm.riscv.cv.simd.dotup.sc.b(i32 %a, i32 %b)
+ ret i32 %res
+}
+
+define i32 @test_cv_simd_dotusp_h(i32 %a, i32 %b) {
+; CHECK-LABEL: test_cv_simd_dotusp_h:
+; CHECK: # %bb.0:
+; CHECK-NEXT: cv.dotusp.h a0, a0, a1
+; CHECK-NEXT: ret
+ %res = call i32 @llvm.riscv.cv.simd.dotusp.h(i32 %a, i32 %b)
+ ret i32 %res
+}
+
+define i32 @test_cv_simd_dotsp_h(i32 %a, i32 %b) {
+; CHECK-LABEL: test_cv_simd_dotsp_h:
+; CHECK: # %bb.0:
+; CHECK-NEXT: cv.dotsp.h a0, a0, a1
+; CHECK-NEXT: ret
+ %res = call i32 @llvm.riscv.cv.simd.dotsp.h(i32 %a, i32 %b)
+ ret i32 %res
+}
+
+;===----------------------------------------------------------------------===;
+; SDOT (accumulating dot products)
+;===----------------------------------------------------------------------===;
+
+define i32 @test_cv_simd_sdotup_h(i32 %a, i32 %b, i32 %acc) {
+; CHECK-LABEL: test_cv_simd_sdotup_h:
+; CHECK: # %bb.0:
+; CHECK-NEXT: cv.sdotup.h a2, a0, a1
+; CHECK-NEXT: mv a0, a2
+; CHECK-NEXT: ret
+ %res = call i32 @llvm.riscv.cv.simd.sdotup.h(i32 %a, i32 %b, i32 %acc)
+ ret i32 %res
+}
+
+define i32 @test_cv_simd_sdotup_b(i32 %a, i32 %b, i32 %acc) {
+; CHECK-LABEL: test_cv_simd_sdotup_b:
+; CHECK: # %bb.0:
+; CHECK-NEXT: cv.sdotup.b a2, a0, a1
+; CHECK-NEXT: mv a0, a2
+; CHECK-NEXT: ret
+ %res = call i32 @llvm.riscv.cv.simd.sdotup.b(i32 %a, i32 %b, i32 %acc)
+ ret i32 %res
+}
+
+define i32 @test_cv_simd_sdotusp_h(i32 %a, i32 %b, i32 %acc) {
+; CHECK-LABEL: test_cv_simd_sdotusp_h:
+; CHECK: # %bb.0:
+; CHECK-NEXT: cv.sdotusp.h a2, a0, a1
+; CHECK-NEXT: mv a0, a2
+; CHECK-NEXT: ret
+ %res = call i32 @llvm.riscv.cv.simd.sdotusp.h(i32 %a, i32 %b, i32 %acc)
+ ret i32 %res
+}
+
+define i32 @test_cv_simd_sdotsp_h(i32 %a, i32 %b, i32 %acc) {
+; CHECK-LABEL: test_cv_simd_sdotsp_h:
+; CHECK: # %bb.0:
+; CHECK-NEXT: cv.sdotsp.h a2, a0, a1
+; CHECK-NEXT: mv a0, a2
+; CHECK-NEXT: ret
+ %res = call i32 @llvm.riscv.cv.simd.sdotsp.h(i32 %a, i32 %b, i32 %acc)
+ ret i32 %res
+}
+
+;===----------------------------------------------------------------------===;
+; EXTRACT / EXTRACTU / INSERT
+;===----------------------------------------------------------------------===;
+
+define i32 @test_cv_simd_extract_h(i32 %a) {
+; CHECK-LABEL: test_cv_simd_extract_h:
+; CHECK: # %bb.0:
+; CHECK-NEXT: cv.extract.h a0, a0, 1
+; CHECK-NEXT: ret
+ %res = call i32 @llvm.riscv.cv.simd.extract.h(i32 %a, i32 1)
+ ret i32 %res
+}
+
+define i32 @test_cv_simd_extract_b(i32 %a) {
+; CHECK-LABEL: test_cv_simd_extract_b:
+; CHECK: # %bb.0:
+; CHECK-NEXT: cv.extract.b a0, a0, 3
+; CHECK-NEXT: ret
+ %res = call i32 @llvm.riscv.cv.simd.extract.b(i32 %a, i32 3)
+ ret i32 %res
+}
+
+define i32 @test_cv_simd_extractu_h(i32 %a) {
+; CHECK-LABEL: test_cv_simd_extractu_h:
+; CHECK: # %bb.0:
+; CHECK-NEXT: cv.extractu.h a0, a0, 0
+; CHECK-NEXT: ret
+ %res = call i32 @llvm.riscv.cv.simd.extractu.h(i32 %a, i32 0)
+ ret i32 %res
+}
+
+define i32 @test_cv_simd_extractu_b(i32 %a) {
+; CHECK-LABEL: test_cv_simd_extractu_b:
+; CHECK: # %bb.0:
+; CHECK-NEXT: cv.extractu.b a0, a0, 2
+; CHECK-NEXT: ret
+ %res = call i32 @llvm.riscv.cv.simd.extractu.b(i32 %a, i32 2)
+ ret i32 %res
+}
+
+define i32 @test_cv_simd_insert_h(i32 %rd, i32 %rs1) {
+; CHECK-LABEL: test_cv_simd_insert_h:
+; CHECK: # %bb.0:
+; CHECK-NEXT: cv.insert.h a0, a1, 1
+; CHECK-NEXT: ret
+ %res = call i32 @llvm.riscv.cv.simd.insert.h(i32 %rd, i32 %rs1, i32 1)
+ ret i32 %res
+}
+
+define i32 @test_cv_simd_insert_b(i32 %rd, i32 %rs1) {
+; CHECK-LABEL: test_cv_simd_insert_b:
+; CHECK: # %bb.0:
+; CHECK-NEXT: cv.insert.b a0, a1, 2
+; CHECK-NEXT: ret
+ %res = call i32 @llvm.riscv.cv.simd.insert.b(i32 %rd, i32 %rs1, i32 2)
+ ret i32 %res
+}
+
+;===----------------------------------------------------------------------===;
+; SHUFFLE / SHUFFLE2
+;===----------------------------------------------------------------------===;
+
+define i32 @test_cv_simd_shuffle_h(i32 %a, i32 %b) {
+; CHECK-LABEL: test_cv_simd_shuffle_h:
+; CHECK: # %bb.0:
+; CHECK-NEXT: cv.shuffle.h a0, a0, a1
+; CHECK-NEXT: ret
+ %res = call i32 @llvm.riscv.cv.simd.shuffle.h(i32 %a, i32 %b)
+ ret i32 %res
+}
+
+define i32 @test_cv_simd_shuffle_b(i32 %a, i32 %b) {
+; CHECK-LABEL: test_cv_simd_shuffle_b:
+; CHECK: # %bb.0:
+; CHECK-NEXT: cv.shuffle.b a0, a0, a1
+; CHECK-NEXT: ret
+ %res = call i32 @llvm.riscv.cv.simd.shuffle.b(i32 %a, i32 %b)
+ ret i32 %res
+}
+
+define i32 @test_cv_simd_shuffle_sci_h(i32 %a) {
+; CHECK-LABEL: test_cv_simd_shuffle_sci_h:
+; CHECK: # %bb.0:
+; CHECK-NEXT: cv.shuffle.sci.h a0, a0, 2
+; CHECK-NEXT: ret
+ %res = call i32 @llvm.riscv.cv.simd.shuffle.sci.h(i32 %a, i32 2)
+ ret i32 %res
+}
+
+; Test shuffle_sci_b pseudo expansion: imm=0x45 → bits[7:6]=1 → shufflei1
+define i32 @test_cv_simd_shuffle_sci_b_i1(i32 %a) {
+; CHECK-LABEL: test_cv_simd_shuffle_sci_b_i1:
+; CHECK: # %bb.0:
+; CHECK-NEXT: cv.shufflei1.sci.b a0, a0, 5
+; CHECK-NEXT: ret
+ %res = call i32 @llvm.riscv.cv.simd.shuffle.sci.b(i32 %a, i32 69)
+ ret i32 %res
+}
+
+; Test shuffle_sci_b pseudo expansion: imm=0x03 → bits[7:6]=0 → shufflei0
+define i32 @test_cv_simd_shuffle_sci_b_i0(i32 %a) {
+; CHECK-LABEL: test_cv_simd_shuffle_sci_b_i0:
+; CHECK: # %bb.0:
+; CHECK-NEXT: cv.shufflei0.sci.b a0, a0, 3
+; CHECK-NEXT: ret
+ %res = call i32 @llvm.riscv.cv.simd.shuffle.sci.b(i32 %a, i32 3)
+ ret i32 %res
+}
+
+; Test shuffle_sci_b pseudo expansion: imm=0x83 → bits[7:6]=2 → shufflei2
+define i32 @test_cv_simd_shuffle_sci_b_i2(i32 %a) {
+; CHECK-LABEL: test_cv_simd_shuffle_sci_b_i2:
+; CHECK: # %bb.0:
+; CHECK-NEXT: cv.shufflei2.sci.b a0, a0, 3
+; CHECK-NEXT: ret
+ %res = call i32 @llvm.riscv.cv.simd.shuffle.sci.b(i32 %a, i32 131)
+ ret i32 %res
+}
+
+; Test shuffle_sci_b pseudo expansion: imm=0xC0 → bits[7:6]=3 → shufflei3
+define i32 @test_cv_simd_shuffle_sci_b_i3(i32 %a) {
+; CHECK-LABEL: test_cv_simd_shuffle_sci_b_i3:
+; CHECK: # %bb.0:
+; CHECK-NEXT: cv.shufflei3.sci.b a0, a0, 0
+; CHECK-NEXT: ret
+ %res = call i32 @llvm.riscv.cv.simd.shuffle.sci.b(i32 %a, i32 192)
+ ret i32 %res
+}
+
+define i32 @test_cv_simd_shuffle2_h(i32 %rd, i32 %rs1, i32 %rs2) {
+; CHECK-LABEL: test_cv_simd_shuffle2_h:
+; CHECK: # %bb.0:
+; CHECK-NEXT: cv.shuffle2.h a0, a1, a2
+; CHECK-NEXT: ret
+ %res = call i32 @llvm.riscv.cv.simd.shuffle2.h(i32 %rs1, i32 %rs2, i32 %rd)
+ ret i32 %res
+}
+
+define i32 @test_cv_simd_shuffle2_b(i32 %rd, i32 %rs1, i32 %rs2) {
+; CHECK-LABEL: test_cv_simd_shuffle2_b:
+; CHECK: # %bb.0:
+; CHECK-NEXT: cv.shuffle2.b a0, a1, a2
+; CHECK-NEXT: ret
+ %res = call i32 @llvm.riscv.cv.simd.shuffle2.b(i32 %rs1, i32 %rs2, i32 %rd)
+ ret i32 %res
+}
+
+;===----------------------------------------------------------------------===;
+; PACK
+;===----------------------------------------------------------------------===;
+
+define i32 @test_cv_simd_packlo_h(i32 %a, i32 %b) {
+; CHECK-LABEL: test_cv_simd_packlo_h:
+; CHECK: # %bb.0:
+; CHECK-NEXT: cv.pack a0, a0, a1
+; CHECK-NEXT: ret
+ %res = call i32 @llvm.riscv.cv.simd.packlo.h(i32 %a, i32 %b)
+ ret i32 %res
+}
+
+define i32 @test_cv_simd_packhi_h(i32 %a, i32 %b) {
+; CHECK-LABEL: test_cv_simd_packhi_h:
+; CHECK: # %bb.0:
+; CHECK-NEXT: cv.pack.h a0, a0, a1
+; CHECK-NEXT: ret
+ %res = call i32 @llvm.riscv.cv.simd.packhi.h(i32 %a, i32 %b)
+ ret i32 %res
+}
+
+define i32 @test_cv_simd_packhi_b(i32 %rd, i32 %rs1, i32 %rs2) {
+; CHECK-LABEL: test_cv_simd_packhi_b:
+; CHECK: # %bb.0:
+; CHECK-NEXT: cv.packhi.b a0, a1, a2
+; CHECK-NEXT: ret
+ %res = call i32 @llvm.riscv.cv.simd.packhi.b(i32 %rd, i32 %rs1, i32 %rs2)
+ ret i32 %res
+}
+
+define i32 @test_cv_simd_packlo_b(i32 %rd, i32 %rs1, i32 %rs2) {
+; CHECK-LABEL: test_cv_simd_packlo_b:
+; CHECK: # %bb.0:
+; CHECK-NEXT: cv.packlo.b a0, a1, a2
+; CHECK-NEXT: ret
+ %res = call i32 @llvm.riscv.cv.simd.packlo.b(i32 %rd, i32 %rs1, i32 %rs2)
+ ret i32 %res
+}
+
+;===----------------------------------------------------------------------===;
+; COMPARE (representative subset)
+;===----------------------------------------------------------------------===;
+
+define i32 @test_cv_simd_cmpeq_h(i32 %a, i32 %b) {
+; CHECK-LABEL: test_cv_simd_cmpeq_h:
+; CHECK: # %bb.0:
+; CHECK-NEXT: cv.cmpeq.h a0, a0, a1
+; CHECK-NEXT: ret
+ %res = call i32 @llvm.riscv.cv.simd.cmpeq.h(i32 %a, i32 %b)
+ ret i32 %res
+}
+
+define i32 @test_cv_simd_cmpeq_b(i32 %a, i32 %b) {
+; CHECK-LABEL: test_cv_simd_cmpeq_b:
+; CHECK: # %bb.0:
+; CHECK-NEXT: cv.cmpeq.b a0, a0, a1
+; CHECK-NEXT: ret
+ %res = call i32 @llvm.riscv.cv.simd.cmpeq.b(i32 %a, i32 %b)
+ ret i32 %res
+}
+
+define i32 @test_cv_simd_cmpne_h(i32 %a, i32 %b) {
+; CHECK-LABEL: test_cv_simd_cmpne_h:
+; CHECK: # %bb.0:
+; CHECK-NEXT: cv.cmpne.h a0, a0, a1
+; CHECK-NEXT: ret
+ %res = call i32 @llvm.riscv.cv.simd.cmpne.h(i32 %a, i32 %b)
+ ret i32 %res
+}
+
+define i32 @test_cv_simd_cmpgt_h(i32 %a, i32 %b) {
+; CHECK-LABEL: test_cv_simd_cmpgt_h:
+; CHECK: # %bb.0:
+; CHECK-NEXT: cv.cmpgt.h a0, a0, a1
+; CHECK-NEXT: ret
+ %res = call i32 @llvm.riscv.cv.simd.cmpgt.h(i32 %a, i32 %b)
+ ret i32 %res
+}
+
+define i32 @test_cv_simd_cmpge_b(i32 %a, i32 %b) {
+; CHECK-LABEL: test_cv_simd_cmpge_b:
+; CHECK: # %bb.0:
+; CHECK-NEXT: cv.cmpge.b a0, a0, a1
+; CHECK-NEXT: ret
+ %res = call i32 @llvm.riscv.cv.simd.cmpge.b(i32 %a, i32 %b)
+ ret i32 %res
+}
+
+define i32 @test_cv_simd_cmplt_h(i32 %a, i32 %b) {
+; CHECK-LABEL: test_cv_simd_cmplt_h:
+; CHECK: # %bb.0:
+; CHECK-NEXT: cv.cmplt.h a0, a0, a1
+; CHECK-NEXT: ret
+ %res = call i32 @llvm.riscv.cv.simd.cmplt.h(i32 %a, i32 %b)
+ ret i32 %res
+}
+
+define i32 @test_cv_simd_cmple_b(i32 %a, i32 %b) {
+; CHECK-LABEL: test_cv_simd_cmple_b:
+; CHECK: # %bb.0:
+; CHECK-NEXT: cv.cmple.b a0, a0, a1
+; CHECK-NEXT: ret
+ %res = call i32 @llvm.riscv.cv.simd.cmple.b(i32 %a, i32 %b)
+ ret i32 %res
+}
+
+define i32 @test_cv_simd_cmpgtu_h(i32 %a, i32 %b) {
+; CHECK-LABEL: test_cv_simd_cmpgtu_h:
+; CHECK: # %bb.0:
+; CHECK-NEXT: cv.cmpgtu.h a0, a0, a1
+; CHECK-NEXT: ret
+ %res = call i32 @llvm.riscv.cv.simd.cmpgtu.h(i32 %a, i32 %b)
+ ret i32 %res
+}
+
+define i32 @test_cv_simd_cmpgeu_b(i32 %a, i32 %b) {
+; CHECK-LABEL: test_cv_simd_cmpgeu_b:
+; CHECK: # %bb.0:
+; CHECK-NEXT: cv.cmpgeu.b a0, a0, a1
+; CHECK-NEXT: ret
+ %res = call i32 @llvm.riscv.cv.simd.cmpgeu.b(i32 %a, i32 %b)
+ ret i32 %res
+}
+
+define i32 @test_cv_simd_cmpltu_h(i32 %a, i32 %b) {
+; CHECK-LABEL: test_cv_simd_cmpltu_h:
+; CHECK: # %bb.0:
+; CHECK-NEXT: cv.cmpltu.h a0, a0, a1
+; CHECK-NEXT: ret
+ %res = call i32 @llvm.riscv.cv.simd.cmpltu.h(i32 %a, i32 %b)
+ ret i32 %res
+}
+
+define i32 @test_cv_simd_cmpleu_b(i32 %a, i32 %b) {
+; CHECK-LABEL: test_cv_simd_cmpleu_b:
+; CHECK: # %bb.0:
+; CHECK-NEXT: cv.cmpleu.b a0, a0, a1
+; CHECK-NEXT: ret
+ %res = call i32 @llvm.riscv.cv.simd.cmpleu.b(i32 %a, i32 %b)
+ ret i32 %res
+}
+
+;===----------------------------------------------------------------------===;
+; COMPLEX: cplxmul / cplxconj / subrotmj
+;===----------------------------------------------------------------------===;
+
+define i32 @test_cv_simd_cplxmul_r(i32 %rs1, i32 %rs2, i32 %rd) {
+; CHECK-LABEL: test_cv_simd_cplxmul_r:
+; CHECK: # %bb.0:
+; CHECK-NEXT: cv.cplxmul.r a2, a0, a1
+; CHECK-NEXT: mv a0, a2
+; CHECK-NEXT: ret
+ %res = call i32 @llvm.riscv.cv.simd.cplxmul.r(i32 %rs1, i32 %rs2, i32 %rd, i32 0)
+ ret i32 %res
+}
+
+define i32 @test_cv_simd_cplxmul_r_div2(i32 %rs1, i32 %rs2, i32 %rd) {
+; CHECK-LABEL: test_cv_simd_cplxmul_r_div2:
+; CHECK: # %bb.0:
+; CHECK-NEXT: cv.cplxmul.r.div2 a2, a0, a1
+; CHECK-NEXT: mv a0, a2
+; CHECK-NEXT: ret
+ %res = call i32 @llvm.riscv.cv.simd.cplxmul.r(i32 %rs1, i32 %rs2, i32 %rd, i32 1)
+ ret i32 %res
+}
+
+define i32 @test_cv_simd_cplxmul_i(i32 %rs1, i32 %rs2, i32 %rd) {
+; CHECK-LABEL: test_cv_simd_cplxmul_i:
+; CHECK: # %bb.0:
+; CHECK-NEXT: cv.cplxmul.i a2, a0, a1
+; CHECK-NEXT: mv a0, a2
+; CHECK-NEXT: ret
+ %res = call i32 @llvm.riscv.cv.simd.cplxmul.i(i32 %rs1, i32 %rs2, i32 %rd, i32 0)
+ ret i32 %res
+}
+
+define i32 @test_cv_simd_cplxmul_i_div4(i32 %rs1, i32 %rs2, i32 %rd) {
+; CHECK-LABEL: test_cv_simd_cplxmul_i_div4:
+; CHECK: # %bb.0:
+; CHECK-NEXT: cv.cplxmul.i.div4 a2, a0, a1
+; CHECK-NEXT: mv a0, a2
+; CHECK-NEXT: ret
+ %res = call i32 @llvm.riscv.cv.simd.cplxmul.i(i32 %rs1, i32 %rs2, i32 %rd, i32 2)
+ ret i32 %res
+}
+
+define i32 @test_cv_simd_cplxconj(i32 %a) {
+; CHECK-LABEL: test_cv_simd_cplxconj:
+; CHECK: # %bb.0:
+; CHECK-NEXT: cv.cplxconj a0, a0
+; CHECK-NEXT: ret
+ %res = call i32 @llvm.riscv.cv.simd.cplxconj(i32 %a)
+ ret i32 %res
+}
+
+define i32 @test_cv_simd_subrotmj(i32 %a, i32 %b) {
+; CHECK-LABEL: test_cv_simd_subrotmj:
+; CHECK: # %bb.0:
+; CHECK-NEXT: cv.subrotmj a0, a0, a1
+; CHECK-NEXT: ret
+ %res = call i32 @llvm.riscv.cv.simd.subrotmj(i32 %a, i32 %b, i32 0)
+ ret i32 %res
+}
+
+define i32 @test_cv_simd_subrotmj_div2(i32 %a, i32 %b) {
+; CHECK-LABEL: test_cv_simd_subrotmj_div2:
+; CHECK: # %bb.0:
+; CHECK-NEXT: cv.subrotmj.div2 a0, a0, a1
+; CHECK-NEXT: ret
+ %res = call i32 @llvm.riscv.cv.simd.subrotmj(i32 %a, i32 %b, i32 1)
+ ret i32 %res
+}
+
+define i32 @test_cv_simd_subrotmj_div4(i32 %a, i32 %b) {
+; CHECK-LABEL: test_cv_simd_subrotmj_div4:
+; CHECK: # %bb.0:
+; CHECK-NEXT: cv.subrotmj.div4 a0, a0, a1
+; CHECK-NEXT: ret
+ %res = call i32 @llvm.riscv.cv.simd.subrotmj(i32 %a, i32 %b, i32 2)
+ ret i32 %res
+}
+
+define i32 @test_cv_simd_subrotmj_div8(i32 %a, i32 %b) {
+; CHECK-LABEL: test_cv_simd_subrotmj_div8:
+; CHECK: # %bb.0:
+; CHECK-NEXT: cv.subrotmj.div8 a0, a0, a1
+; CHECK-NEXT: ret
+ %res = call i32 @llvm.riscv.cv.simd.subrotmj(i32 %a, i32 %b, i32 3)
+ ret i32 %res
+}
+
+;===----------------------------------------------------------------------===;
+; Intrinsic declarations
+;===----------------------------------------------------------------------===;
+
+; ADD/SUB
+declare i32 @llvm.riscv.cv.simd.add.h(i32, i32, i32 immarg)
+declare i32 @llvm.riscv.cv.simd.add.b(i32, i32)
+declare i32 @llvm.riscv.cv.simd.add.sc.h(i32, i32)
+declare i32 @llvm.riscv.cv.simd.add.sc.b(i32, i32)
+declare i32 @llvm.riscv.cv.simd.sub.h(i32, i32, i32 immarg)
+declare i32 @llvm.riscv.cv.simd.sub.b(i32, i32)
+declare i32 @llvm.riscv.cv.simd.sub.sc.h(i32, i32)
+declare i32 @llvm.riscv.cv.simd.sub.sc.b(i32, i32)
+
+; AVG/AVGU
+declare i32 @llvm.riscv.cv.simd.avg.h(i32, i32)
+declare i32 @llvm.riscv.cv.simd.avg.b(i32, i32)
+declare i32 @llvm.riscv.cv.simd.avg.sc.h(i32, i32)
+declare i32 @llvm.riscv.cv.simd.avg.sc.b(i32, i32)
+declare i32 @llvm.riscv.cv.simd.avgu.h(i32, i32)
+declare i32 @llvm.riscv.cv.simd.avgu.b(i32, i32)
+declare i32 @llvm.riscv.cv.simd.avgu.sc.h(i32, i32)
+declare i32 @llvm.riscv.cv.simd.avgu.sc.b(i32, i32)
+
+; MIN/MINU/MAX/MAXU
+declare i32 @llvm.riscv.cv.simd.min.h(i32, i32)
+declare i32 @llvm.riscv.cv.simd.min.b(i32, i32)
+declare i32 @llvm.riscv.cv.simd.min.sc.h(i32, i32)
+declare i32 @llvm.riscv.cv.simd.min.sc.b(i32, i32)
+declare i32 @llvm.riscv.cv.simd.minu.h(i32, i32)
+declare i32 @llvm.riscv.cv.simd.minu.b(i32, i32)
+declare i32 @llvm.riscv.cv.simd.minu.sc.h(i32, i32)
+declare i32 @llvm.riscv.cv.simd.minu.sc.b(i32, i32)
+declare i32 @llvm.riscv.cv.simd.max.h(i32, i32)
+declare i32 @llvm.riscv.cv.simd.max.b(i32, i32)
+declare i32 @llvm.riscv.cv.simd.max.sc.h(i32, i32)
+declare i32 @llvm.riscv.cv.simd.max.sc.b(i32, i32)
+declare i32 @llvm.riscv.cv.simd.maxu.h(i32, i32)
+declare i32 @llvm.riscv.cv.simd.maxu.b(i32, i32)
+declare i32 @llvm.riscv.cv.simd.maxu.sc.h(i32, i32)
+declare i32 @llvm.riscv.cv.simd.maxu.sc.b(i32, i32)
+
+; SRL/SRA/SLL
+declare i32 @llvm.riscv.cv.simd.srl.h(i32, i32)
+declare i32 @llvm.riscv.cv.simd.srl.b(i32, i32)
+declare i32 @llvm.riscv.cv.simd.srl.sc.h(i32, i32)
+declare i32 @llvm.riscv.cv.simd.srl.sc.b(i32, i32)
+declare i32 @llvm.riscv.cv.simd.sra.h(i32, i32)
+declare i32 @llvm.riscv.cv.simd.sra.b(i32, i32)
+declare i32 @llvm.riscv.cv.simd.sra.sc.h(i32, i32)
+declare i32 @llvm.riscv.cv.simd.sra.sc.b(i32, i32)
+declare i32 @llvm.riscv.cv.simd.sll.h(i32, i32)
+declare i32 @llvm.riscv.cv.simd.sll.b(i32, i32)
+declare i32 @llvm.riscv.cv.simd.sll.sc.h(i32, i32)
+declare i32 @llvm.riscv.cv.simd.sll.sc.b(i32, i32)
+
+; OR/XOR/AND
+declare i32 @llvm.riscv.cv.simd.or.h(i32, i32)
+declare i32 @llvm.riscv.cv.simd.or.b(i32, i32)
+declare i32 @llvm.riscv.cv.simd.or.sc.h(i32, i32)
+declare i32 @llvm.riscv.cv.simd.or.sc.b(i32, i32)
+declare i32 @llvm.riscv.cv.simd.xor.h(i32, i32)
+declare i32 @llvm.riscv.cv.simd.xor.b(i32, i32)
+declare i32 @llvm.riscv.cv.simd.xor.sc.h(i32, i32)
+declare i32 @llvm.riscv.cv.simd.xor.sc.b(i32, i32)
+declare i32 @llvm.riscv.cv.simd.and.h(i32, i32)
+declare i32 @llvm.riscv.cv.simd.and.b(i32, i32)
+declare i32 @llvm.riscv.cv.simd.and.sc.h(i32, i32)
+declare i32 @llvm.riscv.cv.simd.and.sc.b(i32, i32)
+
+; ABS
+declare i32 @llvm.riscv.cv.simd.abs.h(i32)
+declare i32 @llvm.riscv.cv.simd.abs.b(i32)
+
+; DOT (non-accumulating)
+declare i32 @llvm.riscv.cv.simd.dotup.h(i32, i32)
+declare i32 @llvm.riscv.cv.simd.dotup.b(i32, i32)
+declare i32 @llvm.riscv.cv.simd.dotup.sc.h(i32, i32)
+declare i32 @llvm.riscv.cv.simd.dotup.sc.b(i32, i32)
+declare i32 @llvm.riscv.cv.simd.dotusp.h(i32, i32)
+declare i32 @llvm.riscv.cv.simd.dotusp.b(i32, i32)
+declare i32 @llvm.riscv.cv.simd.dotusp.sc.h(i32, i32)
+declare i32 @llvm.riscv.cv.simd.dotusp.sc.b(i32, i32)
+declare i32 @llvm.riscv.cv.simd.dotsp.h(i32, i32)
+declare i32 @llvm.riscv.cv.simd.dotsp.b(i32, i32)
+declare i32 @llvm.riscv.cv.simd.dotsp.sc.h(i32, i32)
+declare i32 @llvm.riscv.cv.simd.dotsp.sc.b(i32, i32)
+
+; SDOT (accumulating)
+declare i32 @llvm.riscv.cv.simd.sdotup.h(i32, i32, i32)
+declare i32 @llvm.riscv.cv.simd.sdotup.b(i32, i32, i32)
+declare i32 @llvm.riscv.cv.simd.sdotup.sc.h(i32, i32, i32)
+declare i32 @llvm.riscv.cv.simd.sdotup.sc.b(i32, i32, i32)
+declare i32 @llvm.riscv.cv.simd.sdotusp.h(i32, i32, i32)
+declare i32 @llvm.riscv.cv.simd.sdotusp.b(i32, i32, i32)
+declare i32 @llvm.riscv.cv.simd.sdotusp.sc.h(i32, i32, i32)
+declare i32 @llvm.riscv.cv.simd.sdotusp.sc.b(i32, i32, i32)
+declare i32 @llvm.riscv.cv.simd.sdotsp.h(i32, i32, i32)
+declare i32 @llvm.riscv.cv.simd.sdotsp.b(i32, i32, i32)
+declare i32 @llvm.riscv.cv.simd.sdotsp.sc.h(i32, i32, i32)
+declare i32 @llvm.riscv.cv.simd.sdotsp.sc.b(i32, i32, i32)
+
+; EXTRACT/EXTRACTU/INSERT
+declare i32 @llvm.riscv.cv.simd.extract.h(i32, i32 immarg)
+declare i32 @llvm.riscv.cv.simd.extract.b(i32, i32 immarg)
+declare i32 @llvm.riscv.cv.simd.extractu.h(i32, i32 immarg)
+declare i32 @llvm.riscv.cv.simd.extractu.b(i32, i32 immarg)
+declare i32 @llvm.riscv.cv.simd.insert.h(i32, i32, i32 immarg)
+declare i32 @llvm.riscv.cv.simd.insert.b(i32, i32, i32 immarg)
+
+; SHUFFLE
+declare i32 @llvm.riscv.cv.simd.shuffle.h(i32, i32)
+declare i32 @llvm.riscv.cv.simd.shuffle.b(i32, i32)
+declare i32 @llvm.riscv.cv.simd.shuffle.sci.h(i32, i32 immarg)
+declare i32 @llvm.riscv.cv.simd.shuffle.sci.b(i32, i32 immarg)
+declare i32 @llvm.riscv.cv.simd.shuffle2.h(i32, i32, i32)
+declare i32 @llvm.riscv.cv.simd.shuffle2.b(i32, i32, i32)
+
+; PACK
+declare i32 @llvm.riscv.cv.simd.packlo.h(i32, i32)
+declare i32 @llvm.riscv.cv.simd.packhi.h(i32, i32)
+declare i32 @llvm.riscv.cv.simd.packhi.b(i32, i32, i32)
+declare i32 @llvm.riscv.cv.simd.packlo.b(i32, i32, i32)
+
+; COMPARE
+declare i32 @llvm.riscv.cv.simd.cmpeq.h(i32, i32)
+declare i32 @llvm.riscv.cv.simd.cmpeq.b(i32, i32)
+declare i32 @llvm.riscv.cv.simd.cmpeq.sc.h(i32, i32)
+declare i32 @llvm.riscv.cv.simd.cmpeq.sc.b(i32, i32)
+declare i32 @llvm.riscv.cv.simd.cmpne.h(i32, i32)
+declare i32 @llvm.riscv.cv.simd.cmpne.b(i32, i32)
+declare i32 @llvm.riscv.cv.simd.cmpne.sc.h(i32, i32)
+declare i32 @llvm.riscv.cv.simd.cmpne.sc.b(i32, i32)
+declare i32 @llvm.riscv.cv.simd.cmpgt.h(i32, i32)
+declare i32 @llvm.riscv.cv.simd.cmpgt.b(i32, i32)
+declare i32 @llvm.riscv.cv.simd.cmpgt.sc.h(i32, i32)
+declare i32 @llvm.riscv.cv.simd.cmpgt.sc.b(i32, i32)
+declare i32 @llvm.riscv.cv.simd.cmpge.h(i32, i32)
+declare i32 @llvm.riscv.cv.simd.cmpge.b(i32, i32)
+declare i32 @llvm.riscv.cv.simd.cmpge.sc.h(i32, i32)
+declare i32 @llvm.riscv.cv.simd.cmpge.sc.b(i32, i32)
+declare i32 @llvm.riscv.cv.simd.cmplt.h(i32, i32)
+declare i32 @llvm.riscv.cv.simd.cmplt.b(i32, i32)
+declare i32 @llvm.riscv.cv.simd.cmplt.sc.h(i32, i32)
+declare i32 @llvm.riscv.cv.simd.cmplt.sc.b(i32, i32)
+declare i32 @llvm.riscv.cv.simd.cmple.h(i32, i32)
+declare i32 @llvm.riscv.cv.simd.cmple.b(i32, i32)
+declare i32 @llvm.riscv.cv.simd.cmple.sc.h(i32, i32)
+declare i32 @llvm.riscv.cv.simd.cmple.sc.b(i32, i32)
+declare i32 @llvm.riscv.cv.simd.cmpgtu.h(i32, i32)
+declare i32 @llvm.riscv.cv.simd.cmpgtu.b(i32, i32)
+declare i32 @llvm.riscv.cv.simd.cmpgtu.sc.h(i32, i32)
+declare i32 @llvm.riscv.cv.simd.cmpgtu.sc.b(i32, i32)
+declare i32 @llvm.riscv.cv.simd.cmpgeu.h(i32, i32)
+declare i32 @llvm.riscv.cv.simd.cmpgeu.b(i32, i32)
+declare i32 @llvm.riscv.cv.simd.cmpgeu.sc.h(i32, i32)
+declare i32 @llvm.riscv.cv.simd.cmpgeu.sc.b(i32, i32)
+declare i32 @llvm.riscv.cv.simd.cmpltu.h(i32, i32)
+declare i32 @llvm.riscv.cv.simd.cmpltu.b(i32, i32)
+declare i32 @llvm.riscv.cv.simd.cmpltu.sc.h(i32, i32)
+declare i32 @llvm.riscv.cv.simd.cmpltu.sc.b(i32, i32)
+declare i32 @llvm.riscv.cv.simd.cmpleu.h(i32, i32)
+declare i32 @llvm.riscv.cv.simd.cmpleu.b(i32, i32)
+declare i32 @llvm.riscv.cv.simd.cmpleu.sc.h(i32, i32)
+declare i32 @llvm.riscv.cv.simd.cmpleu.sc.b(i32, i32)
+
+; COMPLEX
+declare i32 @llvm.riscv.cv.simd.cplxmul.r(i32, i32, i32, i32 immarg)
+declare i32 @llvm.riscv.cv.simd.cplxmul.i(i32, i32, i32, i32 immarg)
+declare i32 @llvm.riscv.cv.simd.cplxconj(i32)
+declare i32 @llvm.riscv.cv.simd.subrotmj(i32, i32, i32 immarg)
>From fdc2e1062f056ae553509f2e3dafb2d28d54dd72 Mon Sep 17 00:00:00 2001
From: vitbur <vittorioburani at gmail.com>
Date: Tue, 31 Mar 2026 18:37:47 +0200
Subject: [PATCH 02/10] [Clang][RISCV] Add Clang builtins for `XCVelw`
extension
- `BuiltinsRISCVXCV.td`: add `elw_elw`
- `RISCV.cpp`: add dispatch cases
- `CIRGenBuiltinRISCV.cpp`: add NYI cases
- add `riscv_corev_elw.h` header file + addition in `CMakeLists.txt`
---
clang/include/clang/Basic/BuiltinsRISCVXCV.td | 7 +++++++
clang/lib/CIR/CodeGen/CIRGenBuiltinRISCV.cpp | 2 ++
clang/lib/CodeGen/TargetBuiltins/RISCV.cpp | 9 +++++++++
clang/lib/Headers/CMakeLists.txt | 1 +
clang/lib/Headers/riscv_corev_elw.h | 20 +++++++++++++++++++
5 files changed, 39 insertions(+)
create mode 100644 clang/lib/Headers/riscv_corev_elw.h
diff --git a/clang/include/clang/Basic/BuiltinsRISCVXCV.td b/clang/include/clang/Basic/BuiltinsRISCVXCV.td
index 65eb52b198775..a51ca3ae097a8 100644
--- a/clang/include/clang/Basic/BuiltinsRISCVXCV.td
+++ b/clang/include/clang/Basic/BuiltinsRISCVXCV.td
@@ -39,3 +39,10 @@ def alu_subuN : RISCVXCVBuiltin<"unsigned int(unsigned int, unsigned int, unsig
def alu_subRN : RISCVXCVBuiltin<"int(int, int, unsigned int)", "xcvalu">;
def alu_subuRN : RISCVXCVBuiltin<"unsigned int(unsigned int, unsigned int, unsigned int)", "xcvalu">;
} // Attributes = [NoThrow, Const]
+
+//===----------------------------------------------------------------------===//
+// XCVelw extension.
+//===----------------------------------------------------------------------===//
+let Attributes = [NoThrow] in {
+def elw_elw : RISCVXCVBuiltin<"int(int *)", "xcvelw">;
+} // Attributes = [NoThrow]
diff --git a/clang/lib/CIR/CodeGen/CIRGenBuiltinRISCV.cpp b/clang/lib/CIR/CodeGen/CIRGenBuiltinRISCV.cpp
index ec262922be942..c05a78c1aac16 100644
--- a/clang/lib/CIR/CodeGen/CIRGenBuiltinRISCV.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenBuiltinRISCV.cpp
@@ -184,6 +184,8 @@ CIRGenFunction::emitRISCVBuiltinExpr(unsigned builtinID, const CallExpr *e) {
case RISCV::BI__builtin_riscv_cv_alu_subRN:
case RISCV::BI__builtin_riscv_cv_alu_subuN:
case RISCV::BI__builtin_riscv_cv_alu_subuRN:
+ // XCVelw
+ case RISCV::BI__builtin_riscv_cv_elw_elw:
// XAndesPerf
case RISCV::BI__builtin_riscv_nds_ffb_32:
case RISCV::BI__builtin_riscv_nds_ffb_64:
diff --git a/clang/lib/CodeGen/TargetBuiltins/RISCV.cpp b/clang/lib/CodeGen/TargetBuiltins/RISCV.cpp
index a1e9acb7ec2c8..071c6df744cdc 100644
--- a/clang/lib/CodeGen/TargetBuiltins/RISCV.cpp
+++ b/clang/lib/CodeGen/TargetBuiltins/RISCV.cpp
@@ -1433,6 +1433,15 @@ Value *CodeGenFunction::EmitRISCVBuiltinExpr(unsigned BuiltinID,
ID = Intrinsic::riscv_cv_alu_subuRN;
break;
+ // XCVelw
+ case RISCV::BI__builtin_riscv_cv_elw_elw: {
+ // cv.elw rd, imm(rs1) — load word with event wait
+ // Emit as a volatile load from the memory-mapped address
+ // The builtin takes a pointer; emit as intrinsic call
+ ID = Intrinsic::riscv_cv_elw_elw;
+ break;
+ }
+
// XAndesPerf
case RISCV::BI__builtin_riscv_nds_ffb_32:
case RISCV::BI__builtin_riscv_nds_ffb_64:
diff --git a/clang/lib/Headers/CMakeLists.txt b/clang/lib/Headers/CMakeLists.txt
index 439f2725168ba..0de1618a3d311 100644
--- a/clang/lib/Headers/CMakeLists.txt
+++ b/clang/lib/Headers/CMakeLists.txt
@@ -138,6 +138,7 @@ set(riscv_files
# Vendor headers
andes_vector.h
riscv_corev_alu.h
+ riscv_corev_elw.h
riscv_mips.h
riscv_nds.h
riscv_packed_simd.h
diff --git a/clang/lib/Headers/riscv_corev_elw.h b/clang/lib/Headers/riscv_corev_elw.h
new file mode 100644
index 0000000000000..9676799b5b2e0
--- /dev/null
+++ b/clang/lib/Headers/riscv_corev_elw.h
@@ -0,0 +1,20 @@
+#ifndef __RISCV_COREV_ELW_H
+#define __RISCV_COREV_ELW_H
+#include <stdint.h>
+#if defined(__cplusplus)
+extern "C" {
+#endif
+#if defined(__riscv_xcvelw)
+#define __DEFAULT_FN_ATTRS \
+ __attribute__((__always_inline__, __nodebug__, __artificial__))
+
+// cv.elw rd, imm(rs1): event load word
+static __inline__ int32_t __DEFAULT_FN_ATTRS
+__riscv_cv_elw_elw(int32_t *ptr) {
+ return __builtin_riscv_cv_elw_elw(ptr);
+}
+#endif
+#if defined(__cplusplus)
+}
+#endif
+#endif
>From 1f3d3167720fcfd4dd60b384cb597c649da427a9 Mon Sep 17 00:00:00 2001
From: vitbur <vittorioburani at gmail.com>
Date: Tue, 31 Mar 2026 18:43:53 +0200
Subject: [PATCH 03/10] [Clang][RISCV] Add Clang builtins for `XCVmac`
extension
- `BuiltinsRISCVXCV.td`: add all mac attributes
- `SemaRISCV.cpp`: add range check for arg 1
- `RISCV.cpp`: add dispatch cases
- `CIRGenBuiltinRISCV.cpp`: add NYI cases
- add `riscv_corev_mac.h` header + `CMakeLists.txt` addition
---
clang/include/clang/Basic/BuiltinsRISCVXCV.td | 24 +++
clang/lib/CIR/CodeGen/CIRGenBuiltinRISCV.cpp | 19 ++
clang/lib/CodeGen/TargetBuiltins/RISCV.cpp | 56 +++++
clang/lib/Headers/CMakeLists.txt | 1 +
clang/lib/Headers/riscv_corev_mac.h | 192 ++++++++++++++++++
clang/lib/Sema/SemaRISCV.cpp | 21 +-
6 files changed, 312 insertions(+), 1 deletion(-)
create mode 100644 clang/lib/Headers/riscv_corev_mac.h
diff --git a/clang/include/clang/Basic/BuiltinsRISCVXCV.td b/clang/include/clang/Basic/BuiltinsRISCVXCV.td
index a51ca3ae097a8..0d6f2c56d19a3 100644
--- a/clang/include/clang/Basic/BuiltinsRISCVXCV.td
+++ b/clang/include/clang/Basic/BuiltinsRISCVXCV.td
@@ -46,3 +46,27 @@ def alu_subuRN : RISCVXCVBuiltin<"unsigned int(unsigned int, unsigned int, unsig
let Attributes = [NoThrow] in {
def elw_elw : RISCVXCVBuiltin<"int(int *)", "xcvelw">;
} // Attributes = [NoThrow]
+
+//===----------------------------------------------------------------------===//
+// XCVmac extension.
+//===----------------------------------------------------------------------===//
+let Attributes = [NoThrow, Const] in {
+def mac_mac : RISCVXCVBuiltin<"int(int, int, int)", "xcvmac">;
+def mac_msu : RISCVXCVBuiltin<"int(int, int, int)", "xcvmac">;
+def mac_muluN : RISCVXCVBuiltin<"unsigned int(unsigned int, unsigned int, _Constant unsigned int)", "xcvmac">;
+def mac_mulhhuN : RISCVXCVBuiltin<"unsigned int(unsigned int, unsigned int, _Constant unsigned int)", "xcvmac">;
+def mac_mulsN : RISCVXCVBuiltin<"int(unsigned int, unsigned int, _Constant unsigned int)", "xcvmac">;
+def mac_mulhhsN : RISCVXCVBuiltin<"int(unsigned int, unsigned int, _Constant unsigned int)", "xcvmac">;
+def mac_muluRN : RISCVXCVBuiltin<"unsigned int(unsigned int, unsigned int, _Constant unsigned int)", "xcvmac">;
+def mac_mulhhuRN : RISCVXCVBuiltin<"unsigned int(unsigned int, unsigned int, _Constant unsigned int)", "xcvmac">;
+def mac_mulsRN : RISCVXCVBuiltin<"int(unsigned int, unsigned int, _Constant unsigned int)", "xcvmac">;
+def mac_mulhhsRN : RISCVXCVBuiltin<"int(unsigned int, unsigned int, _Constant unsigned int)", "xcvmac">;
+def mac_macuN : RISCVXCVBuiltin<"unsigned int(unsigned int, unsigned int, unsigned int, _Constant unsigned int)", "xcvmac">;
+def mac_machhuN : RISCVXCVBuiltin<"unsigned int(unsigned int, unsigned int, unsigned int, _Constant unsigned int)", "xcvmac">;
+def mac_macsN : RISCVXCVBuiltin<"int(unsigned int, unsigned int, unsigned int, _Constant unsigned int)", "xcvmac">;
+def mac_machhsN : RISCVXCVBuiltin<"int(unsigned int, unsigned int, unsigned int, _Constant unsigned int)", "xcvmac">;
+def mac_macuRN : RISCVXCVBuiltin<"unsigned int(unsigned int, unsigned int, unsigned int, _Constant unsigned int)", "xcvmac">;
+def mac_machhuRN : RISCVXCVBuiltin<"unsigned int(unsigned int, unsigned int, unsigned int, _Constant unsigned int)", "xcvmac">;
+def mac_macsRN : RISCVXCVBuiltin<"int(unsigned int, unsigned int, unsigned int, _Constant unsigned int)", "xcvmac">;
+def mac_machhsRN : RISCVXCVBuiltin<"int(unsigned int, unsigned int, unsigned int, _Constant unsigned int)", "xcvmac">;
+} // Attributes = [NoThrow, Const]
diff --git a/clang/lib/CIR/CodeGen/CIRGenBuiltinRISCV.cpp b/clang/lib/CIR/CodeGen/CIRGenBuiltinRISCV.cpp
index c05a78c1aac16..55b4d8ae8c60b 100644
--- a/clang/lib/CIR/CodeGen/CIRGenBuiltinRISCV.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenBuiltinRISCV.cpp
@@ -186,6 +186,25 @@ CIRGenFunction::emitRISCVBuiltinExpr(unsigned builtinID, const CallExpr *e) {
case RISCV::BI__builtin_riscv_cv_alu_subuRN:
// XCVelw
case RISCV::BI__builtin_riscv_cv_elw_elw:
+ // XCVmac
+ case RISCV::BI__builtin_riscv_cv_mac_mac:
+ case RISCV::BI__builtin_riscv_cv_mac_msu:
+ case RISCV::BI__builtin_riscv_cv_mac_muluN:
+ case RISCV::BI__builtin_riscv_cv_mac_mulhhuN:
+ case RISCV::BI__builtin_riscv_cv_mac_mulsN:
+ case RISCV::BI__builtin_riscv_cv_mac_mulhhsN:
+ case RISCV::BI__builtin_riscv_cv_mac_muluRN:
+ case RISCV::BI__builtin_riscv_cv_mac_mulhhuRN:
+ case RISCV::BI__builtin_riscv_cv_mac_mulsRN:
+ case RISCV::BI__builtin_riscv_cv_mac_mulhhsRN:
+ case RISCV::BI__builtin_riscv_cv_mac_macuN:
+ case RISCV::BI__builtin_riscv_cv_mac_machhuN:
+ case RISCV::BI__builtin_riscv_cv_mac_macsN:
+ case RISCV::BI__builtin_riscv_cv_mac_machhsN:
+ case RISCV::BI__builtin_riscv_cv_mac_macuRN:
+ case RISCV::BI__builtin_riscv_cv_mac_machhuRN:
+ case RISCV::BI__builtin_riscv_cv_mac_macsRN:
+ case RISCV::BI__builtin_riscv_cv_mac_machhsRN:
// XAndesPerf
case RISCV::BI__builtin_riscv_nds_ffb_32:
case RISCV::BI__builtin_riscv_nds_ffb_64:
diff --git a/clang/lib/CodeGen/TargetBuiltins/RISCV.cpp b/clang/lib/CodeGen/TargetBuiltins/RISCV.cpp
index 071c6df744cdc..07feb6296833e 100644
--- a/clang/lib/CodeGen/TargetBuiltins/RISCV.cpp
+++ b/clang/lib/CodeGen/TargetBuiltins/RISCV.cpp
@@ -1442,6 +1442,62 @@ Value *CodeGenFunction::EmitRISCVBuiltinExpr(unsigned BuiltinID,
break;
}
+ // XCVmac
+ case RISCV::BI__builtin_riscv_cv_mac_mac:
+ ID = Intrinsic::riscv_cv_mac_mac;
+ break;
+ case RISCV::BI__builtin_riscv_cv_mac_msu:
+ ID = Intrinsic::riscv_cv_mac_msu;
+ break;
+ case RISCV::BI__builtin_riscv_cv_mac_muluN:
+ ID = Intrinsic::riscv_cv_mac_muluN;
+ break;
+ case RISCV::BI__builtin_riscv_cv_mac_mulhhuN:
+ ID = Intrinsic::riscv_cv_mac_mulhhuN;
+ break;
+ case RISCV::BI__builtin_riscv_cv_mac_mulsN:
+ ID = Intrinsic::riscv_cv_mac_mulsN;
+ break;
+ case RISCV::BI__builtin_riscv_cv_mac_mulhhsN:
+ ID = Intrinsic::riscv_cv_mac_mulhhsN;
+ break;
+ case RISCV::BI__builtin_riscv_cv_mac_muluRN:
+ ID = Intrinsic::riscv_cv_mac_muluRN;
+ break;
+ case RISCV::BI__builtin_riscv_cv_mac_mulhhuRN:
+ ID = Intrinsic::riscv_cv_mac_mulhhuRN;
+ break;
+ case RISCV::BI__builtin_riscv_cv_mac_mulsRN:
+ ID = Intrinsic::riscv_cv_mac_mulsRN;
+ break;
+ case RISCV::BI__builtin_riscv_cv_mac_mulhhsRN:
+ ID = Intrinsic::riscv_cv_mac_mulhhsRN;
+ break;
+ case RISCV::BI__builtin_riscv_cv_mac_macuN:
+ ID = Intrinsic::riscv_cv_mac_macuN;
+ break;
+ case RISCV::BI__builtin_riscv_cv_mac_machhuN:
+ ID = Intrinsic::riscv_cv_mac_machhuN;
+ break;
+ case RISCV::BI__builtin_riscv_cv_mac_macsN:
+ ID = Intrinsic::riscv_cv_mac_macsN;
+ break;
+ case RISCV::BI__builtin_riscv_cv_mac_machhsN:
+ ID = Intrinsic::riscv_cv_mac_machhsN;
+ break;
+ case RISCV::BI__builtin_riscv_cv_mac_macuRN:
+ ID = Intrinsic::riscv_cv_mac_macuRN;
+ break;
+ case RISCV::BI__builtin_riscv_cv_mac_machhuRN:
+ ID = Intrinsic::riscv_cv_mac_machhuRN;
+ break;
+ case RISCV::BI__builtin_riscv_cv_mac_macsRN:
+ ID = Intrinsic::riscv_cv_mac_macsRN;
+ break;
+ case RISCV::BI__builtin_riscv_cv_mac_machhsRN:
+ ID = Intrinsic::riscv_cv_mac_machhsRN;
+ break;
+
// XAndesPerf
case RISCV::BI__builtin_riscv_nds_ffb_32:
case RISCV::BI__builtin_riscv_nds_ffb_64:
diff --git a/clang/lib/Headers/CMakeLists.txt b/clang/lib/Headers/CMakeLists.txt
index 0de1618a3d311..e1021a6020305 100644
--- a/clang/lib/Headers/CMakeLists.txt
+++ b/clang/lib/Headers/CMakeLists.txt
@@ -139,6 +139,7 @@ set(riscv_files
andes_vector.h
riscv_corev_alu.h
riscv_corev_elw.h
+ riscv_corev_mac.h
riscv_mips.h
riscv_nds.h
riscv_packed_simd.h
diff --git a/clang/lib/Headers/riscv_corev_mac.h b/clang/lib/Headers/riscv_corev_mac.h
new file mode 100644
index 0000000000000..531c9b01f862f
--- /dev/null
+++ b/clang/lib/Headers/riscv_corev_mac.h
@@ -0,0 +1,192 @@
+/*===---- riscv_corev_mac.h - CORE-V multiply-accumulate intrinsics --------===
+ *
+ * Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+ * See https://llvm.org/LICENSE.txt for license information.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ *
+ *===-----------------------------------------------------------------------===
+ *
+ * This header provides C intrinsics for the CORE-V XCVmac ISA extension.
+ * Include this header when compiling with -march=..._xcvmac.
+ *
+ * Spec: https://github.com/openhwgroup/cv32e40p/blob/master/docs/source/
+ * instruction_set_extensions.rst (Multiply-Accumulate section)
+ *
+ *===-----------------------------------------------------------------------===
+ */
+
+#ifndef __RISCV_COREV_MAC_H
+#define __RISCV_COREV_MAC_H
+
+#include <stdint.h>
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+#if defined(__riscv_xcvmac)
+
+#define __DEFAULT_FN_ATTRS \
+ __attribute__((__always_inline__, __nodebug__, __artificial__))
+
+/* ---------------------------------------------------------------------------
+ * 32x32-bit MAC / MSU
+ *
+ * cv.mac rd, rs1, rs2 -> rd += rs1 * rs2
+ * cv.msu rd, rs1, rs2 -> rd -= rs1 * rs2
+ *
+ * These are the only two operations that take a plain GPR accumulator
+ * (no shift/round), so they can be static inline functions.
+ * --------------------------------------------------------------------------- */
+
+static __inline__ int32_t __DEFAULT_FN_ATTRS
+__riscv_cv_mac_mac(int32_t a, int32_t b, int32_t accumulator) {
+ return __builtin_riscv_cv_mac_mac(a, b, accumulator);
+}
+
+static __inline__ int32_t __DEFAULT_FN_ATTRS
+__riscv_cv_mac_msu(int32_t a, int32_t b, int32_t accumulator) {
+ return __builtin_riscv_cv_mac_msu(a, b, accumulator);
+}
+
+/* ---------------------------------------------------------------------------
+ * 16x16-bit multiply (lower halfwords), unsigned, with normalisation shift
+ *
+ * cv.mulun rd, rs1, rs2, imm5 -> rd = (u16(rs1) * u16(rs2)) >> imm5
+ * cv.mulhhun rd, rs1, rs2, imm5 -> rd = (u16hi(rs1) * u16hi(rs2)) >> imm5
+ * cv.mulurn rd, rs1, rs2, imm5 -> rd = (u16(rs1) * u16(rs2) + rnd) >> imm5
+ * cv.mulhhurn rd, rs1, rs2, imm5 -> rd = (u16hi(rs1)*u16hi(rs2) + rnd) >> imm5
+ *
+ * SHIFT must be a compile-time constant in [0, 31].
+ * These are macros so the SHIFT argument is passed as an immediate.
+ * --------------------------------------------------------------------------- */
+
+#define __riscv_cv_mac_muluN(__rs1, __rs2, __SHIFT) \
+ ((uint32_t)__builtin_riscv_cv_mac_muluN((uint32_t)(__rs1), \
+ (uint32_t)(__rs2), \
+ (uint32_t)(__SHIFT)))
+
+#define __riscv_cv_mac_mulhhuN(__rs1, __rs2, __SHIFT) \
+ ((uint32_t)__builtin_riscv_cv_mac_mulhhuN((uint32_t)(__rs1), \
+ (uint32_t)(__rs2), \
+ (uint32_t)(__SHIFT)))
+
+#define __riscv_cv_mac_muluRN(__rs1, __rs2, __SHIFT) \
+ ((uint32_t)__builtin_riscv_cv_mac_muluRN((uint32_t)(__rs1), \
+ (uint32_t)(__rs2), \
+ (uint32_t)(__SHIFT)))
+
+#define __riscv_cv_mac_mulhhuRN(__rs1, __rs2, __SHIFT) \
+ ((uint32_t)__builtin_riscv_cv_mac_mulhhuRN((uint32_t)(__rs1), \
+ (uint32_t)(__rs2), \
+ (uint32_t)(__SHIFT)))
+
+/* ---------------------------------------------------------------------------
+ * 16x16-bit multiply (lower halfwords), signed, with normalisation shift
+ *
+ * cv.mulsn rd, rs1, rs2, imm5 -> rd = (s16(rs1) * s16(rs2)) >> imm5
+ * cv.mulhhsn rd, rs1, rs2, imm5 -> rd = (s16hi(rs1)*s16hi(rs2)) >> imm5
+ * cv.mulsrn rd, rs1, rs2, imm5 -> rd = (s16(rs1) * s16(rs2) + rnd) >> imm5
+ * cv.mulhhsrn rd, rs1, rs2, imm5 -> rd = (s16hi(rs1)*s16hi(rs2)+rnd) >> imm5
+ *
+ * SHIFT must be a compile-time constant in [0, 31].
+ * --------------------------------------------------------------------------- */
+
+#define __riscv_cv_mac_mulsN(__rs1, __rs2, __SHIFT) \
+ ((int32_t)__builtin_riscv_cv_mac_mulsN((uint32_t)(__rs1), \
+ (uint32_t)(__rs2), \
+ (uint32_t)(__SHIFT)))
+
+#define __riscv_cv_mac_mulhhsN(__rs1, __rs2, __SHIFT) \
+ ((int32_t)__builtin_riscv_cv_mac_mulhhsN((uint32_t)(__rs1), \
+ (uint32_t)(__rs2), \
+ (uint32_t)(__SHIFT)))
+
+#define __riscv_cv_mac_mulsRN(__rs1, __rs2, __SHIFT) \
+ ((int32_t)__builtin_riscv_cv_mac_mulsRN((uint32_t)(__rs1), \
+ (uint32_t)(__rs2), \
+ (uint32_t)(__SHIFT)))
+
+#define __riscv_cv_mac_mulhhsRN(__rs1, __rs2, __SHIFT) \
+ ((int32_t)__builtin_riscv_cv_mac_mulhhsRN((uint32_t)(__rs1), \
+ (uint32_t)(__rs2), \
+ (uint32_t)(__SHIFT)))
+
+/* ---------------------------------------------------------------------------
+ * 16x16-bit multiply-accumulate (lower halfwords), unsigned
+ *
+ * cv.macun rd, rs1, rs2, imm5 -> rd = (rd + u16(rs1) * u16(rs2)) >> imm5
+ * cv.machhun rd, rs1, rs2, imm5 -> rd = (rd + u16hi(rs1)*u16hi(rs2)) >> imm5
+ * cv.macurn rd, rs1, rs2, imm5 -> rd = (rd + u16(rs1)*u16(rs2)+rnd) >> imm5
+ * cv.machhurn rd, rs1, rs2, imm5 -> rd = (rd+u16hi(rs1)*u16hi(rs2)+rnd)>>imm5
+ *
+ * SHIFT must be a compile-time constant in [0, 31].
+ * rD is the accumulator register (read-modify-write).
+ * --------------------------------------------------------------------------- */
+
+#define __riscv_cv_mac_macuN(__rD, __rs1, __rs2, __SHIFT) \
+ ((uint32_t)__builtin_riscv_cv_mac_macuN((uint32_t)(__rs1), \
+ (uint32_t)(__rs2), \
+ (uint32_t)(__rD), \
+ (uint32_t)(__SHIFT)))
+
+#define __riscv_cv_mac_machhuN(__rD, __rs1, __rs2, __SHIFT) \
+ ((uint32_t)__builtin_riscv_cv_mac_machhuN((uint32_t)(__rs1), \
+ (uint32_t)(__rs2), \
+ (uint32_t)(__rD), \
+ (uint32_t)(__SHIFT)))
+
+#define __riscv_cv_mac_macuRN(__rD, __rs1, __rs2, __SHIFT) \
+ ((uint32_t)__builtin_riscv_cv_mac_macuRN((uint32_t)(__rs1), \
+ (uint32_t)(__rs2), \
+ (uint32_t)(__rD), \
+ (uint32_t)(__SHIFT)))
+
+#define __riscv_cv_mac_machhuRN(__rD, __rs1, __rs2, __SHIFT) \
+ ((uint32_t)__builtin_riscv_cv_mac_machhuRN((uint32_t)(__rs1), \
+ (uint32_t)(__rs2), \
+ (uint32_t)(__rD), \
+ (uint32_t)(__SHIFT)))
+
+/* ---------------------------------------------------------------------------
+ * 16x16-bit multiply-accumulate (lower halfwords), signed
+ *
+ * cv.macsn rd, rs1, rs2, imm5 -> rd = (rd + s16(rs1) * s16(rs2)) >> imm5
+ * cv.machhsn rd, rs1, rs2, imm5 -> rd = (rd+s16hi(rs1)*s16hi(rs2)) >> imm5
+ * cv.macsrn rd, rs1, rs2, imm5 -> rd = (rd+s16(rs1)*s16(rs2)+rnd) >> imm5
+ * cv.machhsrn rd, rs1, rs2, imm5 -> rd = (rd+s16hi*s16hi+rnd) >> imm5
+ *
+ * SHIFT must be a compile-time constant in [0, 31].
+ * --------------------------------------------------------------------------- */
+
+#define __riscv_cv_mac_macsN(__rD, __rs1, __rs2, __SHIFT) \
+ ((int32_t)__builtin_riscv_cv_mac_macsN((uint32_t)(__rs1), \
+ (uint32_t)(__rs2), \
+ (uint32_t)(__rD), \
+ (uint32_t)(__SHIFT)))
+
+#define __riscv_cv_mac_machhsN(__rD, __rs1, __rs2, __SHIFT) \
+ ((int32_t)__builtin_riscv_cv_mac_machhsN((uint32_t)(__rs1), \
+ (uint32_t)(__rs2), \
+ (uint32_t)(__rD), \
+ (uint32_t)(__SHIFT)))
+
+#define __riscv_cv_mac_macsRN(__rD, __rs1, __rs2, __SHIFT) \
+ ((int32_t)__builtin_riscv_cv_mac_macsRN((uint32_t)(__rs1), \
+ (uint32_t)(__rs2), \
+ (uint32_t)(__rD), \
+ (uint32_t)(__SHIFT)))
+
+#define __riscv_cv_mac_machhsRN(__rD, __rs1, __rs2, __SHIFT) \
+ ((int32_t)__builtin_riscv_cv_mac_machhsRN((uint32_t)(__rs1), \
+ (uint32_t)(__rs2), \
+ (uint32_t)(__rD), \
+ (uint32_t)(__SHIFT)))
+
+#endif /* __riscv_xcvmac */
+
+#if defined(__cplusplus)
+}
+#endif
+
+#endif /* __RISCV_COREV_MAC_H */
diff --git a/clang/lib/Sema/SemaRISCV.cpp b/clang/lib/Sema/SemaRISCV.cpp
index 9647a7d913744..5711d87300b05 100644
--- a/clang/lib/Sema/SemaRISCV.cpp
+++ b/clang/lib/Sema/SemaRISCV.cpp
@@ -652,7 +652,26 @@ bool SemaRISCV::CheckBuiltinFunctionCall(const TargetInfo &TI,
break;
}
- }
+
+ // XCVmac — shift amount in [0, 31]
+ case RISCV::BI__builtin_riscv_cv_mac_muluN:
+ case RISCV::BI__builtin_riscv_cv_mac_mulhhuN:
+ case RISCV::BI__builtin_riscv_cv_mac_mulsN:
+ case RISCV::BI__builtin_riscv_cv_mac_mulhhsN:
+ case RISCV::BI__builtin_riscv_cv_mac_muluRN:
+ case RISCV::BI__builtin_riscv_cv_mac_mulhhuRN:
+ case RISCV::BI__builtin_riscv_cv_mac_mulsRN:
+ case RISCV::BI__builtin_riscv_cv_mac_mulhhsRN:
+ return SemaRef.BuiltinConstantArgRange(TheCall, 2, 0, 31);
+ case RISCV::BI__builtin_riscv_cv_mac_macuN:
+ case RISCV::BI__builtin_riscv_cv_mac_machhuN:
+ case RISCV::BI__builtin_riscv_cv_mac_macsN:
+ case RISCV::BI__builtin_riscv_cv_mac_machhsN:
+ case RISCV::BI__builtin_riscv_cv_mac_macuRN:
+ case RISCV::BI__builtin_riscv_cv_mac_machhuRN:
+ case RISCV::BI__builtin_riscv_cv_mac_macsRN:
+ case RISCV::BI__builtin_riscv_cv_mac_machhsRN:
+ return SemaRef.BuiltinConstantArgRange(TheCall, 3, 0, 31);
auto CheckVSetVL = [&](unsigned SEWOffset, unsigned LMULOffset) -> bool {
const FunctionDecl *FD = SemaRef.getCurFunctionDecl();
>From 691b15ccc7e74a9071e75b0b8dd79eec4a3b5b76 Mon Sep 17 00:00:00 2001
From: vitbur <vittorioburani at gmail.com>
Date: Tue, 31 Mar 2026 18:49:29 +0200
Subject: [PATCH 04/10] [Clang][RISCV] Add Clang builtins for `XCVsimd`
extension
- `BuiltinsRISCVXCV.td`: add all simd attributes
- `SemaRISCV.cpp`: add range check for arg 1
- `RISCV.cpp`: add dispatch cases
- `CIRGenBuiltinRISCV.cpp`: add NYI cases
- add `riscv_corev_simd.h` header + `CMakeLists.txt` addition
---
clang/include/clang/Basic/BuiltinsRISCVXCV.td | 177 +++++
clang/lib/CIR/CodeGen/CIRGenBuiltinRISCV.cpp | 156 ++++
clang/lib/CodeGen/TargetBuiltins/RISCV.cpp | 454 +++++++++++
clang/lib/Headers/CMakeLists.txt | 1 +
clang/lib/Headers/riscv_corev_simd.h | 707 ++++++++++++++++++
clang/lib/Sema/SemaRISCV.cpp | 31 +
6 files changed, 1526 insertions(+)
create mode 100644 clang/lib/Headers/riscv_corev_simd.h
diff --git a/clang/include/clang/Basic/BuiltinsRISCVXCV.td b/clang/include/clang/Basic/BuiltinsRISCVXCV.td
index 0d6f2c56d19a3..eb0bb58e4814d 100644
--- a/clang/include/clang/Basic/BuiltinsRISCVXCV.td
+++ b/clang/include/clang/Basic/BuiltinsRISCVXCV.td
@@ -70,3 +70,180 @@ def mac_machhuRN : RISCVXCVBuiltin<"unsigned int(unsigned int, unsigned int, uns
def mac_macsRN : RISCVXCVBuiltin<"int(unsigned int, unsigned int, unsigned int, _Constant unsigned int)", "xcvmac">;
def mac_machhsRN : RISCVXCVBuiltin<"int(unsigned int, unsigned int, unsigned int, _Constant unsigned int)", "xcvmac">;
} // Attributes = [NoThrow, Const]
+
+//===----------------------------------------------------------------------===//
+// XCVsimd extension.
+//===----------------------------------------------------------------------===//
+let Attributes = [NoThrow, Const] in {
+
+// ADD/SUB — halfword has div immediate; byte is plain
+def simd_add_h : RISCVXCVBuiltin<"unsigned int(unsigned int, unsigned int, _Constant unsigned int)", "xcvsimd">;
+def simd_add_b : RISCVXCVBuiltin<"unsigned int(unsigned int, unsigned int)", "xcvsimd">;
+def simd_add_sc_h : RISCVXCVBuiltin<"unsigned int(unsigned int, unsigned int)", "xcvsimd">;
+def simd_add_sc_b : RISCVXCVBuiltin<"unsigned int(unsigned int, unsigned int)", "xcvsimd">;
+def simd_sub_h : RISCVXCVBuiltin<"unsigned int(unsigned int, unsigned int, _Constant unsigned int)", "xcvsimd">;
+def simd_sub_b : RISCVXCVBuiltin<"unsigned int(unsigned int, unsigned int)", "xcvsimd">;
+def simd_sub_sc_h : RISCVXCVBuiltin<"unsigned int(unsigned int, unsigned int)", "xcvsimd">;
+def simd_sub_sc_b : RISCVXCVBuiltin<"unsigned int(unsigned int, unsigned int)", "xcvsimd">;
+
+// AVG (signed)
+def simd_avg_h : RISCVXCVBuiltin<"unsigned int(unsigned int, unsigned int)", "xcvsimd">;
+def simd_avg_b : RISCVXCVBuiltin<"unsigned int(unsigned int, unsigned int)", "xcvsimd">;
+def simd_avg_sc_h : RISCVXCVBuiltin<"unsigned int(unsigned int, unsigned int)", "xcvsimd">;
+def simd_avg_sc_b : RISCVXCVBuiltin<"unsigned int(unsigned int, unsigned int)", "xcvsimd">;
+
+// AVGU (unsigned)
+def simd_avgu_h : RISCVXCVBuiltin<"unsigned int(unsigned int, unsigned int)", "xcvsimd">;
+def simd_avgu_b : RISCVXCVBuiltin<"unsigned int(unsigned int, unsigned int)", "xcvsimd">;
+def simd_avgu_sc_h : RISCVXCVBuiltin<"unsigned int(unsigned int, unsigned int)", "xcvsimd">;
+def simd_avgu_sc_b : RISCVXCVBuiltin<"unsigned int(unsigned int, unsigned int)", "xcvsimd">;
+
+// MIN / MINU / MAX / MAXU
+def simd_min_h : RISCVXCVBuiltin<"unsigned int(unsigned int, unsigned int)", "xcvsimd">;
+def simd_min_b : RISCVXCVBuiltin<"unsigned int(unsigned int, unsigned int)", "xcvsimd">;
+def simd_min_sc_h : RISCVXCVBuiltin<"unsigned int(unsigned int, unsigned int)", "xcvsimd">;
+def simd_min_sc_b : RISCVXCVBuiltin<"unsigned int(unsigned int, unsigned int)", "xcvsimd">;
+def simd_minu_h : RISCVXCVBuiltin<"unsigned int(unsigned int, unsigned int)", "xcvsimd">;
+def simd_minu_b : RISCVXCVBuiltin<"unsigned int(unsigned int, unsigned int)", "xcvsimd">;
+def simd_minu_sc_h : RISCVXCVBuiltin<"unsigned int(unsigned int, unsigned int)", "xcvsimd">;
+def simd_minu_sc_b : RISCVXCVBuiltin<"unsigned int(unsigned int, unsigned int)", "xcvsimd">;
+def simd_max_h : RISCVXCVBuiltin<"unsigned int(unsigned int, unsigned int)", "xcvsimd">;
+def simd_max_b : RISCVXCVBuiltin<"unsigned int(unsigned int, unsigned int)", "xcvsimd">;
+def simd_max_sc_h : RISCVXCVBuiltin<"unsigned int(unsigned int, unsigned int)", "xcvsimd">;
+def simd_max_sc_b : RISCVXCVBuiltin<"unsigned int(unsigned int, unsigned int)", "xcvsimd">;
+def simd_maxu_h : RISCVXCVBuiltin<"unsigned int(unsigned int, unsigned int)", "xcvsimd">;
+def simd_maxu_b : RISCVXCVBuiltin<"unsigned int(unsigned int, unsigned int)", "xcvsimd">;
+def simd_maxu_sc_h : RISCVXCVBuiltin<"unsigned int(unsigned int, unsigned int)", "xcvsimd">;
+def simd_maxu_sc_b : RISCVXCVBuiltin<"unsigned int(unsigned int, unsigned int)", "xcvsimd">;
+
+// SRL / SRA / SLL (shifts — immediate versions take uimm6)
+def simd_srl_h : RISCVXCVBuiltin<"unsigned int(unsigned int, unsigned int)", "xcvsimd">;
+def simd_srl_b : RISCVXCVBuiltin<"unsigned int(unsigned int, unsigned int)", "xcvsimd">;
+def simd_srl_sc_h : RISCVXCVBuiltin<"unsigned int(unsigned int, unsigned int)", "xcvsimd">;
+def simd_srl_sc_b : RISCVXCVBuiltin<"unsigned int(unsigned int, unsigned int)", "xcvsimd">;
+def simd_sra_h : RISCVXCVBuiltin<"unsigned int(unsigned int, unsigned int)", "xcvsimd">;
+def simd_sra_b : RISCVXCVBuiltin<"unsigned int(unsigned int, unsigned int)", "xcvsimd">;
+def simd_sra_sc_h : RISCVXCVBuiltin<"unsigned int(unsigned int, unsigned int)", "xcvsimd">;
+def simd_sra_sc_b : RISCVXCVBuiltin<"unsigned int(unsigned int, unsigned int)", "xcvsimd">;
+def simd_sll_h : RISCVXCVBuiltin<"unsigned int(unsigned int, unsigned int)", "xcvsimd">;
+def simd_sll_b : RISCVXCVBuiltin<"unsigned int(unsigned int, unsigned int)", "xcvsimd">;
+def simd_sll_sc_h : RISCVXCVBuiltin<"unsigned int(unsigned int, unsigned int)", "xcvsimd">;
+def simd_sll_sc_b : RISCVXCVBuiltin<"unsigned int(unsigned int, unsigned int)", "xcvsimd">;
+
+// OR / XOR / AND
+def simd_or_h : RISCVXCVBuiltin<"unsigned int(unsigned int, unsigned int)", "xcvsimd">;
+def simd_or_b : RISCVXCVBuiltin<"unsigned int(unsigned int, unsigned int)", "xcvsimd">;
+def simd_or_sc_h : RISCVXCVBuiltin<"unsigned int(unsigned int, unsigned int)", "xcvsimd">;
+def simd_or_sc_b : RISCVXCVBuiltin<"unsigned int(unsigned int, unsigned int)", "xcvsimd">;
+def simd_xor_h : RISCVXCVBuiltin<"unsigned int(unsigned int, unsigned int)", "xcvsimd">;
+def simd_xor_b : RISCVXCVBuiltin<"unsigned int(unsigned int, unsigned int)", "xcvsimd">;
+def simd_xor_sc_h : RISCVXCVBuiltin<"unsigned int(unsigned int, unsigned int)", "xcvsimd">;
+def simd_xor_sc_b : RISCVXCVBuiltin<"unsigned int(unsigned int, unsigned int)", "xcvsimd">;
+def simd_and_h : RISCVXCVBuiltin<"unsigned int(unsigned int, unsigned int)", "xcvsimd">;
+def simd_and_b : RISCVXCVBuiltin<"unsigned int(unsigned int, unsigned int)", "xcvsimd">;
+def simd_and_sc_h : RISCVXCVBuiltin<"unsigned int(unsigned int, unsigned int)", "xcvsimd">;
+def simd_and_sc_b : RISCVXCVBuiltin<"unsigned int(unsigned int, unsigned int)", "xcvsimd">;
+
+// ABS
+def simd_abs_h : RISCVXCVBuiltin<"unsigned int(unsigned int)", "xcvsimd">;
+def simd_abs_b : RISCVXCVBuiltin<"unsigned int(unsigned int)", "xcvsimd">;
+
+// DOT PRODUCTS
+def simd_dotup_h : RISCVXCVBuiltin<"unsigned int(unsigned int, unsigned int)", "xcvsimd">;
+def simd_dotup_b : RISCVXCVBuiltin<"unsigned int(unsigned int, unsigned int)", "xcvsimd">;
+def simd_dotup_sc_h : RISCVXCVBuiltin<"unsigned int(unsigned int, unsigned int)", "xcvsimd">;
+def simd_dotup_sc_b : RISCVXCVBuiltin<"unsigned int(unsigned int, unsigned int)", "xcvsimd">;
+def simd_dotusp_h : RISCVXCVBuiltin<"int(unsigned int, unsigned int)", "xcvsimd">;
+def simd_dotusp_b : RISCVXCVBuiltin<"int(unsigned int, unsigned int)", "xcvsimd">;
+def simd_dotusp_sc_h : RISCVXCVBuiltin<"int(unsigned int, unsigned int)", "xcvsimd">;
+def simd_dotusp_sc_b : RISCVXCVBuiltin<"int(unsigned int, unsigned int)", "xcvsimd">;
+def simd_dotsp_h : RISCVXCVBuiltin<"int(unsigned int, unsigned int)", "xcvsimd">;
+def simd_dotsp_b : RISCVXCVBuiltin<"int(unsigned int, unsigned int)", "xcvsimd">;
+def simd_dotsp_sc_h : RISCVXCVBuiltin<"int(unsigned int, unsigned int)", "xcvsimd">;
+def simd_dotsp_sc_b : RISCVXCVBuiltin<"int(unsigned int, unsigned int)", "xcvsimd">;
+
+// SDOT (accumulating dot products — rd is both input and output)
+def simd_sdotup_h : RISCVXCVBuiltin<"unsigned int(unsigned int, unsigned int, unsigned int)", "xcvsimd">;
+def simd_sdotup_b : RISCVXCVBuiltin<"unsigned int(unsigned int, unsigned int, unsigned int)", "xcvsimd">;
+def simd_sdotup_sc_h : RISCVXCVBuiltin<"unsigned int(unsigned int, unsigned int, unsigned int)", "xcvsimd">;
+def simd_sdotup_sc_b : RISCVXCVBuiltin<"unsigned int(unsigned int, unsigned int, unsigned int)", "xcvsimd">;
+def simd_sdotusp_h : RISCVXCVBuiltin<"int(unsigned int, unsigned int, int)", "xcvsimd">;
+def simd_sdotusp_b : RISCVXCVBuiltin<"int(unsigned int, unsigned int, int)", "xcvsimd">;
+def simd_sdotusp_sc_h : RISCVXCVBuiltin<"int(unsigned int, unsigned int, int)", "xcvsimd">;
+def simd_sdotusp_sc_b : RISCVXCVBuiltin<"int(unsigned int, unsigned int, int)", "xcvsimd">;
+def simd_sdotsp_h : RISCVXCVBuiltin<"int(unsigned int, unsigned int, int)", "xcvsimd">;
+def simd_sdotsp_b : RISCVXCVBuiltin<"int(unsigned int, unsigned int, int)", "xcvsimd">;
+def simd_sdotsp_sc_h : RISCVXCVBuiltin<"int(unsigned int, unsigned int, int)", "xcvsimd">;
+def simd_sdotsp_sc_b : RISCVXCVBuiltin<"int(unsigned int, unsigned int, int)", "xcvsimd">;
+
+// EXTRACT / INSERT
+def simd_extract_h : RISCVXCVBuiltin<"int(unsigned int, _Constant unsigned int)", "xcvsimd">;
+def simd_extract_b : RISCVXCVBuiltin<"int(unsigned int, _Constant unsigned int)", "xcvsimd">;
+def simd_extractu_h : RISCVXCVBuiltin<"unsigned int(unsigned int, _Constant unsigned int)", "xcvsimd">;
+def simd_extractu_b : RISCVXCVBuiltin<"unsigned int(unsigned int, _Constant unsigned int)", "xcvsimd">;
+def simd_insert_h : RISCVXCVBuiltin<"unsigned int(unsigned int, unsigned int, _Constant unsigned int)", "xcvsimd">;
+def simd_insert_b : RISCVXCVBuiltin<"unsigned int(unsigned int, unsigned int, _Constant unsigned int)", "xcvsimd">;
+
+// SHUFFLE / SHUFFLE2
+def simd_shuffle_h : RISCVXCVBuiltin<"unsigned int(unsigned int, unsigned int)", "xcvsimd">;
+def simd_shuffle_b : RISCVXCVBuiltin<"unsigned int(unsigned int, unsigned int)", "xcvsimd">;
+def simd_shuffle_sci_h : RISCVXCVBuiltin<"unsigned int(unsigned int, _Constant unsigned int)", "xcvsimd">;
+def simd_shuffle_sci_b : RISCVXCVBuiltin<"unsigned int(unsigned int, _Constant unsigned int)", "xcvsimd">;
+def simd_shuffle2_h : RISCVXCVBuiltin<"unsigned int(unsigned int, unsigned int, unsigned int)", "xcvsimd">;
+def simd_shuffle2_b : RISCVXCVBuiltin<"unsigned int(unsigned int, unsigned int, unsigned int)", "xcvsimd">;
+
+// PACK
+def simd_packhi_h : RISCVXCVBuiltin<"unsigned int(unsigned int, unsigned int)", "xcvsimd">;
+def simd_packlo_h : RISCVXCVBuiltin<"unsigned int(unsigned int, unsigned int)", "xcvsimd">;
+def simd_packhi_b : RISCVXCVBuiltin<"unsigned int(unsigned int, unsigned int, unsigned int)", "xcvsimd">;
+def simd_packlo_b : RISCVXCVBuiltin<"unsigned int(unsigned int, unsigned int, unsigned int)", "xcvsimd">;
+
+// COMPARE (result is mask in packed reg)
+def simd_cmpeq_h : RISCVXCVBuiltin<"unsigned int(unsigned int, unsigned int)", "xcvsimd">;
+def simd_cmpeq_b : RISCVXCVBuiltin<"unsigned int(unsigned int, unsigned int)", "xcvsimd">;
+def simd_cmpeq_sc_h : RISCVXCVBuiltin<"unsigned int(unsigned int, unsigned int)", "xcvsimd">;
+def simd_cmpeq_sc_b : RISCVXCVBuiltin<"unsigned int(unsigned int, unsigned int)", "xcvsimd">;
+def simd_cmpne_h : RISCVXCVBuiltin<"unsigned int(unsigned int, unsigned int)", "xcvsimd">;
+def simd_cmpne_b : RISCVXCVBuiltin<"unsigned int(unsigned int, unsigned int)", "xcvsimd">;
+def simd_cmpne_sc_h : RISCVXCVBuiltin<"unsigned int(unsigned int, unsigned int)", "xcvsimd">;
+def simd_cmpne_sc_b : RISCVXCVBuiltin<"unsigned int(unsigned int, unsigned int)", "xcvsimd">;
+def simd_cmpgt_h : RISCVXCVBuiltin<"unsigned int(unsigned int, unsigned int)", "xcvsimd">;
+def simd_cmpgt_b : RISCVXCVBuiltin<"unsigned int(unsigned int, unsigned int)", "xcvsimd">;
+def simd_cmpgt_sc_h : RISCVXCVBuiltin<"unsigned int(unsigned int, unsigned int)", "xcvsimd">;
+def simd_cmpgt_sc_b : RISCVXCVBuiltin<"unsigned int(unsigned int, unsigned int)", "xcvsimd">;
+def simd_cmpge_h : RISCVXCVBuiltin<"unsigned int(unsigned int, unsigned int)", "xcvsimd">;
+def simd_cmpge_b : RISCVXCVBuiltin<"unsigned int(unsigned int, unsigned int)", "xcvsimd">;
+def simd_cmpge_sc_h : RISCVXCVBuiltin<"unsigned int(unsigned int, unsigned int)", "xcvsimd">;
+def simd_cmpge_sc_b : RISCVXCVBuiltin<"unsigned int(unsigned int, unsigned int)", "xcvsimd">;
+def simd_cmplt_h : RISCVXCVBuiltin<"unsigned int(unsigned int, unsigned int)", "xcvsimd">;
+def simd_cmplt_b : RISCVXCVBuiltin<"unsigned int(unsigned int, unsigned int)", "xcvsimd">;
+def simd_cmplt_sc_h : RISCVXCVBuiltin<"unsigned int(unsigned int, unsigned int)", "xcvsimd">;
+def simd_cmplt_sc_b : RISCVXCVBuiltin<"unsigned int(unsigned int, unsigned int)", "xcvsimd">;
+def simd_cmple_h : RISCVXCVBuiltin<"unsigned int(unsigned int, unsigned int)", "xcvsimd">;
+def simd_cmple_b : RISCVXCVBuiltin<"unsigned int(unsigned int, unsigned int)", "xcvsimd">;
+def simd_cmple_sc_h : RISCVXCVBuiltin<"unsigned int(unsigned int, unsigned int)", "xcvsimd">;
+def simd_cmple_sc_b : RISCVXCVBuiltin<"unsigned int(unsigned int, unsigned int)", "xcvsimd">;
+def simd_cmpgtu_h : RISCVXCVBuiltin<"unsigned int(unsigned int, unsigned int)", "xcvsimd">;
+def simd_cmpgtu_b : RISCVXCVBuiltin<"unsigned int(unsigned int, unsigned int)", "xcvsimd">;
+def simd_cmpgtu_sc_h : RISCVXCVBuiltin<"unsigned int(unsigned int, unsigned int)", "xcvsimd">;
+def simd_cmpgtu_sc_b : RISCVXCVBuiltin<"unsigned int(unsigned int, unsigned int)", "xcvsimd">;
+def simd_cmpgeu_h : RISCVXCVBuiltin<"unsigned int(unsigned int, unsigned int)", "xcvsimd">;
+def simd_cmpgeu_b : RISCVXCVBuiltin<"unsigned int(unsigned int, unsigned int)", "xcvsimd">;
+def simd_cmpgeu_sc_h : RISCVXCVBuiltin<"unsigned int(unsigned int, unsigned int)", "xcvsimd">;
+def simd_cmpgeu_sc_b : RISCVXCVBuiltin<"unsigned int(unsigned int, unsigned int)", "xcvsimd">;
+def simd_cmpltu_h : RISCVXCVBuiltin<"unsigned int(unsigned int, unsigned int)", "xcvsimd">;
+def simd_cmpltu_b : RISCVXCVBuiltin<"unsigned int(unsigned int, unsigned int)", "xcvsimd">;
+def simd_cmpltu_sc_h : RISCVXCVBuiltin<"unsigned int(unsigned int, unsigned int)", "xcvsimd">;
+def simd_cmpltu_sc_b : RISCVXCVBuiltin<"unsigned int(unsigned int, unsigned int)", "xcvsimd">;
+def simd_cmpleu_h : RISCVXCVBuiltin<"unsigned int(unsigned int, unsigned int)", "xcvsimd">;
+def simd_cmpleu_b : RISCVXCVBuiltin<"unsigned int(unsigned int, unsigned int)", "xcvsimd">;
+def simd_cmpleu_sc_h : RISCVXCVBuiltin<"unsigned int(unsigned int, unsigned int)", "xcvsimd">;
+def simd_cmpleu_sc_b : RISCVXCVBuiltin<"unsigned int(unsigned int, unsigned int)", "xcvsimd">;
+
+// COMPLEX NUMBER OPS
+def simd_cplxmul_r : RISCVXCVBuiltin<"unsigned int(unsigned int, unsigned int, unsigned int, _Constant unsigned int)", "xcvsimd">;
+def simd_cplxmul_i : RISCVXCVBuiltin<"unsigned int(unsigned int, unsigned int, unsigned int, _Constant unsigned int)", "xcvsimd">;
+def simd_cplxconj : RISCVXCVBuiltin<"unsigned int(unsigned int)", "xcvsimd">;
+def simd_subrotmj : RISCVXCVBuiltin<"unsigned int(unsigned int, unsigned int, _Constant unsigned int)", "xcvsimd">;
+
+} // Attributes = [NoThrow, Const]
diff --git a/clang/lib/CIR/CodeGen/CIRGenBuiltinRISCV.cpp b/clang/lib/CIR/CodeGen/CIRGenBuiltinRISCV.cpp
index 55b4d8ae8c60b..23c497acb2447 100644
--- a/clang/lib/CIR/CodeGen/CIRGenBuiltinRISCV.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenBuiltinRISCV.cpp
@@ -205,6 +205,162 @@ CIRGenFunction::emitRISCVBuiltinExpr(unsigned builtinID, const CallExpr *e) {
case RISCV::BI__builtin_riscv_cv_mac_machhuRN:
case RISCV::BI__builtin_riscv_cv_mac_macsRN:
case RISCV::BI__builtin_riscv_cv_mac_machhsRN:
+ // XCVsimd - ADD/SUB
+ case RISCV::BI__builtin_riscv_cv_simd_add_h:
+ case RISCV::BI__builtin_riscv_cv_simd_add_b:
+ case RISCV::BI__builtin_riscv_cv_simd_add_sc_h:
+ case RISCV::BI__builtin_riscv_cv_simd_add_sc_b:
+ case RISCV::BI__builtin_riscv_cv_simd_sub_h:
+ case RISCV::BI__builtin_riscv_cv_simd_sub_b:
+ case RISCV::BI__builtin_riscv_cv_simd_sub_sc_h:
+ case RISCV::BI__builtin_riscv_cv_simd_sub_sc_b:
+ // XCVsimd - AVG (signed)
+ case RISCV::BI__builtin_riscv_cv_simd_avg_h:
+ case RISCV::BI__builtin_riscv_cv_simd_avg_b:
+ case RISCV::BI__builtin_riscv_cv_simd_avg_sc_h:
+ case RISCV::BI__builtin_riscv_cv_simd_avg_sc_b:
+ // XCVsimd - AVGU (unsigned)
+ case RISCV::BI__builtin_riscv_cv_simd_avgu_h:
+ case RISCV::BI__builtin_riscv_cv_simd_avgu_b:
+ case RISCV::BI__builtin_riscv_cv_simd_avgu_sc_h:
+ case RISCV::BI__builtin_riscv_cv_simd_avgu_sc_b:
+ // XCVsimd - MIN / MINU / MAX / MAXU
+ case RISCV::BI__builtin_riscv_cv_simd_min_h:
+ case RISCV::BI__builtin_riscv_cv_simd_min_b:
+ case RISCV::BI__builtin_riscv_cv_simd_min_sc_h:
+ case RISCV::BI__builtin_riscv_cv_simd_min_sc_b:
+ case RISCV::BI__builtin_riscv_cv_simd_minu_h:
+ case RISCV::BI__builtin_riscv_cv_simd_minu_b:
+ case RISCV::BI__builtin_riscv_cv_simd_minu_sc_h:
+ case RISCV::BI__builtin_riscv_cv_simd_minu_sc_b:
+ case RISCV::BI__builtin_riscv_cv_simd_max_h:
+ case RISCV::BI__builtin_riscv_cv_simd_max_b:
+ case RISCV::BI__builtin_riscv_cv_simd_max_sc_h:
+ case RISCV::BI__builtin_riscv_cv_simd_max_sc_b:
+ case RISCV::BI__builtin_riscv_cv_simd_maxu_h:
+ case RISCV::BI__builtin_riscv_cv_simd_maxu_b:
+ case RISCV::BI__builtin_riscv_cv_simd_maxu_sc_h:
+ case RISCV::BI__builtin_riscv_cv_simd_maxu_sc_b:
+ // XCVsimd - SRL / SRA / SLL (shifts — immediate versions take uimm6)
+ case RISCV::BI__builtin_riscv_cv_simd_srl_h:
+ case RISCV::BI__builtin_riscv_cv_simd_srl_b:
+ case RISCV::BI__builtin_riscv_cv_simd_srl_sc_h:
+ case RISCV::BI__builtin_riscv_cv_simd_srl_sc_b:
+ case RISCV::BI__builtin_riscv_cv_simd_sra_h:
+ case RISCV::BI__builtin_riscv_cv_simd_sra_b:
+ case RISCV::BI__builtin_riscv_cv_simd_sra_sc_h:
+ case RISCV::BI__builtin_riscv_cv_simd_sra_sc_b:
+ case RISCV::BI__builtin_riscv_cv_simd_sll_h:
+ case RISCV::BI__builtin_riscv_cv_simd_sll_b:
+ case RISCV::BI__builtin_riscv_cv_simd_sll_sc_h:
+ case RISCV::BI__builtin_riscv_cv_simd_sll_sc_b:
+ // XCVsimd - OR / XOR / AND
+ case RISCV::BI__builtin_riscv_cv_simd_or_h:
+ case RISCV::BI__builtin_riscv_cv_simd_or_b:
+ case RISCV::BI__builtin_riscv_cv_simd_or_sc_h:
+ case RISCV::BI__builtin_riscv_cv_simd_or_sc_b:
+ case RISCV::BI__builtin_riscv_cv_simd_xor_h:
+ case RISCV::BI__builtin_riscv_cv_simd_xor_b:
+ case RISCV::BI__builtin_riscv_cv_simd_xor_sc_h:
+ case RISCV::BI__builtin_riscv_cv_simd_xor_sc_b:
+ case RISCV::BI__builtin_riscv_cv_simd_and_h:
+ case RISCV::BI__builtin_riscv_cv_simd_and_b:
+ case RISCV::BI__builtin_riscv_cv_simd_and_sc_h:
+ case RISCV::BI__builtin_riscv_cv_simd_and_sc_b:
+ // XCVsimd - ABS
+ case RISCV::BI__builtin_riscv_cv_simd_abs_h:
+ case RISCV::BI__builtin_riscv_cv_simd_abs_b:
+ // XCVsimd - DOT PRODUCTS
+ case RISCV::BI__builtin_riscv_cv_simd_dotup_h:
+ case RISCV::BI__builtin_riscv_cv_simd_dotup_b:
+ case RISCV::BI__builtin_riscv_cv_simd_dotup_sc_h:
+ case RISCV::BI__builtin_riscv_cv_simd_dotup_sc_b:
+ case RISCV::BI__builtin_riscv_cv_simd_dotusp_h:
+ case RISCV::BI__builtin_riscv_cv_simd_dotusp_b:
+ case RISCV::BI__builtin_riscv_cv_simd_dotusp_sc_h:
+ case RISCV::BI__builtin_riscv_cv_simd_dotusp_sc_b:
+ case RISCV::BI__builtin_riscv_cv_simd_dotsp_h:
+ case RISCV::BI__builtin_riscv_cv_simd_dotsp_b:
+ case RISCV::BI__builtin_riscv_cv_simd_dotsp_sc_h:
+ case RISCV::BI__builtin_riscv_cv_simd_dotsp_sc_b:
+ // XCVsimd - SDOT (accumulating dot products — rd is both input and output)
+ case RISCV::BI__builtin_riscv_cv_simd_sdotup_h:
+ case RISCV::BI__builtin_riscv_cv_simd_sdotup_b:
+ case RISCV::BI__builtin_riscv_cv_simd_sdotup_sc_h:
+ case RISCV::BI__builtin_riscv_cv_simd_sdotup_sc_b:
+ case RISCV::BI__builtin_riscv_cv_simd_sdotusp_h:
+ case RISCV::BI__builtin_riscv_cv_simd_sdotusp_b:
+ case RISCV::BI__builtin_riscv_cv_simd_sdotusp_sc_h:
+ case RISCV::BI__builtin_riscv_cv_simd_sdotusp_sc_b:
+ case RISCV::BI__builtin_riscv_cv_simd_sdotsp_h:
+ case RISCV::BI__builtin_riscv_cv_simd_sdotsp_b:
+ case RISCV::BI__builtin_riscv_cv_simd_sdotsp_sc_h:
+ case RISCV::BI__builtin_riscv_cv_simd_sdotsp_sc_b:
+ // XCVsimd - EXTRACT / INSERT
+ case RISCV::BI__builtin_riscv_cv_simd_extract_h:
+ case RISCV::BI__builtin_riscv_cv_simd_extract_b:
+ case RISCV::BI__builtin_riscv_cv_simd_extractu_h:
+ case RISCV::BI__builtin_riscv_cv_simd_extractu_b:
+ case RISCV::BI__builtin_riscv_cv_simd_insert_h:
+ case RISCV::BI__builtin_riscv_cv_simd_insert_b:
+ // XCVsimd - SHUFFLE / SHUFFLE2
+ case RISCV::BI__builtin_riscv_cv_simd_shuffle_h:
+ case RISCV::BI__builtin_riscv_cv_simd_shuffle_b:
+ case RISCV::BI__builtin_riscv_cv_simd_shuffle_sci_h:
+ case RISCV::BI__builtin_riscv_cv_simd_shuffle_sci_b:
+ case RISCV::BI__builtin_riscv_cv_simd_shuffle2_h:
+ case RISCV::BI__builtin_riscv_cv_simd_shuffle2_b:
+ // XCVsimd - PACK
+ case RISCV::BI__builtin_riscv_cv_simd_packhi_h:
+ case RISCV::BI__builtin_riscv_cv_simd_packlo_h:
+ case RISCV::BI__builtin_riscv_cv_simd_packhi_b:
+ case RISCV::BI__builtin_riscv_cv_simd_packlo_b:
+ // XCVsimd - COMPARE (result is mask in packed reg)
+ case RISCV::BI__builtin_riscv_cv_simd_cmpeq_h:
+ case RISCV::BI__builtin_riscv_cv_simd_cmpeq_b:
+ case RISCV::BI__builtin_riscv_cv_simd_cmpeq_sc_h:
+ case RISCV::BI__builtin_riscv_cv_simd_cmpeq_sc_b:
+ case RISCV::BI__builtin_riscv_cv_simd_cmpne_h:
+ case RISCV::BI__builtin_riscv_cv_simd_cmpne_b:
+ case RISCV::BI__builtin_riscv_cv_simd_cmpne_sc_h:
+ case RISCV::BI__builtin_riscv_cv_simd_cmpne_sc_b:
+ case RISCV::BI__builtin_riscv_cv_simd_cmpgt_h:
+ case RISCV::BI__builtin_riscv_cv_simd_cmpgt_b:
+ case RISCV::BI__builtin_riscv_cv_simd_cmpgt_sc_h:
+ case RISCV::BI__builtin_riscv_cv_simd_cmpgt_sc_b:
+ case RISCV::BI__builtin_riscv_cv_simd_cmpge_h:
+ case RISCV::BI__builtin_riscv_cv_simd_cmpge_b:
+ case RISCV::BI__builtin_riscv_cv_simd_cmpge_sc_h:
+ case RISCV::BI__builtin_riscv_cv_simd_cmpge_sc_b:
+ case RISCV::BI__builtin_riscv_cv_simd_cmplt_h:
+ case RISCV::BI__builtin_riscv_cv_simd_cmplt_b:
+ case RISCV::BI__builtin_riscv_cv_simd_cmplt_sc_h:
+ case RISCV::BI__builtin_riscv_cv_simd_cmplt_sc_b:
+ case RISCV::BI__builtin_riscv_cv_simd_cmple_h:
+ case RISCV::BI__builtin_riscv_cv_simd_cmple_b:
+ case RISCV::BI__builtin_riscv_cv_simd_cmple_sc_h:
+ case RISCV::BI__builtin_riscv_cv_simd_cmple_sc_b:
+ case RISCV::BI__builtin_riscv_cv_simd_cmpgtu_h:
+ case RISCV::BI__builtin_riscv_cv_simd_cmpgtu_b:
+ case RISCV::BI__builtin_riscv_cv_simd_cmpgtu_sc_h:
+ case RISCV::BI__builtin_riscv_cv_simd_cmpgtu_sc_b:
+ case RISCV::BI__builtin_riscv_cv_simd_cmpgeu_h:
+ case RISCV::BI__builtin_riscv_cv_simd_cmpgeu_b:
+ case RISCV::BI__builtin_riscv_cv_simd_cmpgeu_sc_h:
+ case RISCV::BI__builtin_riscv_cv_simd_cmpgeu_sc_b:
+ case RISCV::BI__builtin_riscv_cv_simd_cmpltu_h:
+ case RISCV::BI__builtin_riscv_cv_simd_cmpltu_b:
+ case RISCV::BI__builtin_riscv_cv_simd_cmpltu_sc_h:
+ case RISCV::BI__builtin_riscv_cv_simd_cmpltu_sc_b:
+ case RISCV::BI__builtin_riscv_cv_simd_cmpleu_h:
+ case RISCV::BI__builtin_riscv_cv_simd_cmpleu_b:
+ case RISCV::BI__builtin_riscv_cv_simd_cmpleu_sc_h:
+ case RISCV::BI__builtin_riscv_cv_simd_cmpleu_sc_b:
+ // XCVsimd - COMPLEX
+ case RISCV::BI__builtin_riscv_cv_simd_cplxmul_r:
+ case RISCV::BI__builtin_riscv_cv_simd_cplxmul_i:
+ case RISCV::BI__builtin_riscv_cv_simd_cplxconj:
+ case RISCV::BI__builtin_riscv_cv_simd_subrotmj:
// XAndesPerf
case RISCV::BI__builtin_riscv_nds_ffb_32:
case RISCV::BI__builtin_riscv_nds_ffb_64:
diff --git a/clang/lib/CodeGen/TargetBuiltins/RISCV.cpp b/clang/lib/CodeGen/TargetBuiltins/RISCV.cpp
index 07feb6296833e..1338eda9f876b 100644
--- a/clang/lib/CodeGen/TargetBuiltins/RISCV.cpp
+++ b/clang/lib/CodeGen/TargetBuiltins/RISCV.cpp
@@ -1498,6 +1498,460 @@ Value *CodeGenFunction::EmitRISCVBuiltinExpr(unsigned BuiltinID,
ID = Intrinsic::riscv_cv_mac_machhsRN;
break;
+ // XCVsimd - ADD/SUB
+ case RISCV::BI__builtin_riscv_cv_simd_add_h:
+ ID = Intrinsic::riscv_cv_simd_add_h;
+ break;
+ case RISCV::BI__builtin_riscv_cv_simd_add_b:
+ ID = Intrinsic::riscv_cv_simd_add_b;
+ break;
+ case RISCV::BI__builtin_riscv_cv_simd_add_sc_h:
+ ID = Intrinsic::riscv_cv_simd_add_sc_h;
+ break;
+ case RISCV::BI__builtin_riscv_cv_simd_add_sc_b:
+ ID = Intrinsic::riscv_cv_simd_add_sc_b;
+ break;
+ case RISCV::BI__builtin_riscv_cv_simd_sub_h:
+ ID = Intrinsic::riscv_cv_simd_sub_h;
+ break;
+ case RISCV::BI__builtin_riscv_cv_simd_sub_b:
+ ID = Intrinsic::riscv_cv_simd_sub_b;
+ break;
+ case RISCV::BI__builtin_riscv_cv_simd_sub_sc_h:
+ ID = Intrinsic::riscv_cv_simd_sub_sc_h;
+ break;
+ case RISCV::BI__builtin_riscv_cv_simd_sub_sc_b:
+ ID = Intrinsic::riscv_cv_simd_sub_sc_b;
+ break;
+
+ // XCVsimd - AVG (signed)
+ case RISCV::BI__builtin_riscv_cv_simd_avg_h:
+ ID = Intrinsic::riscv_cv_simd_avg_h;
+ break;
+ case RISCV::BI__builtin_riscv_cv_simd_avg_b:
+ ID = Intrinsic::riscv_cv_simd_avg_b;
+ break;
+ case RISCV::BI__builtin_riscv_cv_simd_avg_sc_h:
+ ID = Intrinsic::riscv_cv_simd_avg_sc_h;
+ break;
+ case RISCV::BI__builtin_riscv_cv_simd_avg_sc_b:
+ ID = Intrinsic::riscv_cv_simd_avg_sc_b;
+ break;
+
+ // XCVsimd - AVGU (unsigned)
+ case RISCV::BI__builtin_riscv_cv_simd_avgu_h:
+ ID = Intrinsic::riscv_cv_simd_avgu_h;
+ break;
+ case RISCV::BI__builtin_riscv_cv_simd_avgu_b:
+ ID = Intrinsic::riscv_cv_simd_avgu_b;
+ break;
+ case RISCV::BI__builtin_riscv_cv_simd_avgu_sc_h:
+ ID = Intrinsic::riscv_cv_simd_avgu_sc_h;
+ break;
+ case RISCV::BI__builtin_riscv_cv_simd_avgu_sc_b:
+ ID = Intrinsic::riscv_cv_simd_avgu_sc_b;
+ break;
+
+ // XCVsimd - MIN / MINU / MAX / MAXU
+ case RISCV::BI__builtin_riscv_cv_simd_min_h:
+ ID = Intrinsic::riscv_cv_simd_min_h;
+ break;
+ case RISCV::BI__builtin_riscv_cv_simd_min_b:
+ ID = Intrinsic::riscv_cv_simd_min_b;
+ break;
+ case RISCV::BI__builtin_riscv_cv_simd_min_sc_h:
+ ID = Intrinsic::riscv_cv_simd_min_sc_h;
+ break;
+ case RISCV::BI__builtin_riscv_cv_simd_min_sc_b:
+ ID = Intrinsic::riscv_cv_simd_min_sc_b;
+ break;
+ case RISCV::BI__builtin_riscv_cv_simd_minu_h:
+ ID = Intrinsic::riscv_cv_simd_minu_h;
+ break;
+ case RISCV::BI__builtin_riscv_cv_simd_minu_b:
+ ID = Intrinsic::riscv_cv_simd_minu_b;
+ break;
+ case RISCV::BI__builtin_riscv_cv_simd_minu_sc_h:
+ ID = Intrinsic::riscv_cv_simd_minu_sc_h;
+ break;
+ case RISCV::BI__builtin_riscv_cv_simd_minu_sc_b:
+ ID = Intrinsic::riscv_cv_simd_minu_sc_b;
+ break;
+ case RISCV::BI__builtin_riscv_cv_simd_max_h:
+ ID = Intrinsic::riscv_cv_simd_max_h;
+ break;
+ case RISCV::BI__builtin_riscv_cv_simd_max_b:
+ ID = Intrinsic::riscv_cv_simd_max_b;
+ break;
+ case RISCV::BI__builtin_riscv_cv_simd_max_sc_h:
+ ID = Intrinsic::riscv_cv_simd_max_sc_h;
+ break;
+ case RISCV::BI__builtin_riscv_cv_simd_max_sc_b:
+ ID = Intrinsic::riscv_cv_simd_max_sc_b;
+ break;
+ case RISCV::BI__builtin_riscv_cv_simd_maxu_h:
+ ID = Intrinsic::riscv_cv_simd_maxu_h;
+ break;
+ case RISCV::BI__builtin_riscv_cv_simd_maxu_b:
+ ID = Intrinsic::riscv_cv_simd_maxu_b;
+ break;
+ case RISCV::BI__builtin_riscv_cv_simd_maxu_sc_h:
+ ID = Intrinsic::riscv_cv_simd_maxu_sc_h;
+ break;
+ case RISCV::BI__builtin_riscv_cv_simd_maxu_sc_b:
+ ID = Intrinsic::riscv_cv_simd_maxu_sc_b;
+ break;
+
+ // XCVsimd - SRL / SRA / SLL (shifts — immediate versions take uimm6)
+ case RISCV::BI__builtin_riscv_cv_simd_srl_h:
+ ID = Intrinsic::riscv_cv_simd_srl_h;
+ break;
+ case RISCV::BI__builtin_riscv_cv_simd_srl_b:
+ ID = Intrinsic::riscv_cv_simd_srl_b;
+ break;
+ case RISCV::BI__builtin_riscv_cv_simd_srl_sc_h:
+ ID = Intrinsic::riscv_cv_simd_srl_sc_h;
+ break;
+ case RISCV::BI__builtin_riscv_cv_simd_srl_sc_b:
+ ID = Intrinsic::riscv_cv_simd_srl_sc_b;
+ break;
+ case RISCV::BI__builtin_riscv_cv_simd_sra_h:
+ ID = Intrinsic::riscv_cv_simd_sra_h;
+ break;
+ case RISCV::BI__builtin_riscv_cv_simd_sra_b:
+ ID = Intrinsic::riscv_cv_simd_sra_b;
+ break;
+ case RISCV::BI__builtin_riscv_cv_simd_sra_sc_h:
+ ID = Intrinsic::riscv_cv_simd_sra_sc_h;
+ break;
+ case RISCV::BI__builtin_riscv_cv_simd_sra_sc_b:
+ ID = Intrinsic::riscv_cv_simd_sra_sc_b;
+ break;
+ case RISCV::BI__builtin_riscv_cv_simd_sll_h:
+ ID = Intrinsic::riscv_cv_simd_sll_h;
+ break;
+ case RISCV::BI__builtin_riscv_cv_simd_sll_b:
+ ID = Intrinsic::riscv_cv_simd_sll_b;
+ break;
+ case RISCV::BI__builtin_riscv_cv_simd_sll_sc_h:
+ ID = Intrinsic::riscv_cv_simd_sll_sc_h;
+ break;
+ case RISCV::BI__builtin_riscv_cv_simd_sll_sc_b:
+ ID = Intrinsic::riscv_cv_simd_sll_sc_b;
+ break;
+
+ // XCVsimd - OR / XOR / AND
+ case RISCV::BI__builtin_riscv_cv_simd_or_h:
+ ID = Intrinsic::riscv_cv_simd_or_h;
+ break;
+ case RISCV::BI__builtin_riscv_cv_simd_or_b:
+ ID = Intrinsic::riscv_cv_simd_or_b;
+ break;
+ case RISCV::BI__builtin_riscv_cv_simd_or_sc_h:
+ ID = Intrinsic::riscv_cv_simd_or_sc_h;
+ break;
+ case RISCV::BI__builtin_riscv_cv_simd_or_sc_b:
+ ID = Intrinsic::riscv_cv_simd_or_sc_b;
+ break;
+ case RISCV::BI__builtin_riscv_cv_simd_xor_h:
+ ID = Intrinsic::riscv_cv_simd_xor_h;
+ break;
+ case RISCV::BI__builtin_riscv_cv_simd_xor_b:
+ ID = Intrinsic::riscv_cv_simd_xor_b;
+ break;
+ case RISCV::BI__builtin_riscv_cv_simd_xor_sc_h:
+ ID = Intrinsic::riscv_cv_simd_xor_sc_h;
+ break;
+ case RISCV::BI__builtin_riscv_cv_simd_xor_sc_b:
+ ID = Intrinsic::riscv_cv_simd_xor_sc_b;
+ break;
+ case RISCV::BI__builtin_riscv_cv_simd_and_h:
+ ID = Intrinsic::riscv_cv_simd_and_h;
+ break;
+ case RISCV::BI__builtin_riscv_cv_simd_and_b:
+ ID = Intrinsic::riscv_cv_simd_and_b;
+ break;
+ case RISCV::BI__builtin_riscv_cv_simd_and_sc_h:
+ ID = Intrinsic::riscv_cv_simd_and_sc_h;
+ break;
+ case RISCV::BI__builtin_riscv_cv_simd_and_sc_b:
+ ID = Intrinsic::riscv_cv_simd_and_sc_b;
+ break;
+
+ // XCVsimd - ABS
+ case RISCV::BI__builtin_riscv_cv_simd_abs_h:
+ ID = Intrinsic::riscv_cv_simd_abs_h;
+ break;
+ case RISCV::BI__builtin_riscv_cv_simd_abs_b:
+ ID = Intrinsic::riscv_cv_simd_abs_b;
+ break;
+
+ // XCVsimd - DOT PRODUCTS
+ case RISCV::BI__builtin_riscv_cv_simd_dotup_h:
+ ID = Intrinsic::riscv_cv_simd_dotup_h;
+ break;
+ case RISCV::BI__builtin_riscv_cv_simd_dotup_b:
+ ID = Intrinsic::riscv_cv_simd_dotup_b;
+ break;
+ case RISCV::BI__builtin_riscv_cv_simd_dotup_sc_h:
+ ID = Intrinsic::riscv_cv_simd_dotup_sc_h;
+ break;
+ case RISCV::BI__builtin_riscv_cv_simd_dotup_sc_b:
+ ID = Intrinsic::riscv_cv_simd_dotup_sc_b;
+ break;
+ case RISCV::BI__builtin_riscv_cv_simd_dotusp_h:
+ ID = Intrinsic::riscv_cv_simd_dotusp_h;
+ break;
+ case RISCV::BI__builtin_riscv_cv_simd_dotusp_b:
+ ID = Intrinsic::riscv_cv_simd_dotusp_b;
+ break;
+ case RISCV::BI__builtin_riscv_cv_simd_dotusp_sc_h:
+ ID = Intrinsic::riscv_cv_simd_dotusp_sc_h;
+ break;
+ case RISCV::BI__builtin_riscv_cv_simd_dotusp_sc_b:
+ ID = Intrinsic::riscv_cv_simd_dotusp_sc_b;
+ break;
+ case RISCV::BI__builtin_riscv_cv_simd_dotsp_h:
+ ID = Intrinsic::riscv_cv_simd_dotsp_h;
+ break;
+ case RISCV::BI__builtin_riscv_cv_simd_dotsp_b:
+ ID = Intrinsic::riscv_cv_simd_dotsp_b;
+ break;
+ case RISCV::BI__builtin_riscv_cv_simd_dotsp_sc_h:
+ ID = Intrinsic::riscv_cv_simd_dotsp_sc_h;
+ break;
+ case RISCV::BI__builtin_riscv_cv_simd_dotsp_sc_b:
+ ID = Intrinsic::riscv_cv_simd_dotsp_sc_b;
+ break;
+
+ // XCVsimd - SDOT (accumulating dot products — rd is both input and output)
+ case RISCV::BI__builtin_riscv_cv_simd_sdotup_h:
+ ID = Intrinsic::riscv_cv_simd_sdotup_h;
+ break;
+ case RISCV::BI__builtin_riscv_cv_simd_sdotup_b:
+ ID = Intrinsic::riscv_cv_simd_sdotup_b;
+ break;
+ case RISCV::BI__builtin_riscv_cv_simd_sdotup_sc_h:
+ ID = Intrinsic::riscv_cv_simd_sdotup_sc_h;
+ break;
+ case RISCV::BI__builtin_riscv_cv_simd_sdotup_sc_b:
+ ID = Intrinsic::riscv_cv_simd_sdotup_sc_b;
+ break;
+ case RISCV::BI__builtin_riscv_cv_simd_sdotusp_h:
+ ID = Intrinsic::riscv_cv_simd_sdotusp_h;
+ break;
+ case RISCV::BI__builtin_riscv_cv_simd_sdotusp_b:
+ ID = Intrinsic::riscv_cv_simd_sdotusp_b;
+ break;
+ case RISCV::BI__builtin_riscv_cv_simd_sdotusp_sc_h:
+ ID = Intrinsic::riscv_cv_simd_sdotusp_sc_h;
+ break;
+ case RISCV::BI__builtin_riscv_cv_simd_sdotusp_sc_b:
+ ID = Intrinsic::riscv_cv_simd_sdotusp_sc_b;
+ break;
+ case RISCV::BI__builtin_riscv_cv_simd_sdotsp_h:
+ ID = Intrinsic::riscv_cv_simd_sdotsp_h;
+ break;
+ case RISCV::BI__builtin_riscv_cv_simd_sdotsp_b:
+ ID = Intrinsic::riscv_cv_simd_sdotsp_b;
+ break;
+ case RISCV::BI__builtin_riscv_cv_simd_sdotsp_sc_h:
+ ID = Intrinsic::riscv_cv_simd_sdotsp_sc_h;
+ break;
+ case RISCV::BI__builtin_riscv_cv_simd_sdotsp_sc_b:
+ ID = Intrinsic::riscv_cv_simd_sdotsp_sc_b;
+ break;
+
+ // XCVsimd - EXTRACT / INSERT
+ case RISCV::BI__builtin_riscv_cv_simd_extract_h:
+ ID = Intrinsic::riscv_cv_simd_extract_h;
+ break;
+ case RISCV::BI__builtin_riscv_cv_simd_extract_b:
+ ID = Intrinsic::riscv_cv_simd_extract_b;
+ break;
+ case RISCV::BI__builtin_riscv_cv_simd_extractu_h:
+ ID = Intrinsic::riscv_cv_simd_extractu_h;
+ break;
+ case RISCV::BI__builtin_riscv_cv_simd_extractu_b:
+ ID = Intrinsic::riscv_cv_simd_extractu_b;
+ break;
+ case RISCV::BI__builtin_riscv_cv_simd_insert_h:
+ ID = Intrinsic::riscv_cv_simd_insert_h;
+ break;
+ case RISCV::BI__builtin_riscv_cv_simd_insert_b:
+ ID = Intrinsic::riscv_cv_simd_insert_b;
+ break;
+
+ // XCVsimd - SHUFFLE / SHUFFLE2
+ case RISCV::BI__builtin_riscv_cv_simd_shuffle_h:
+ ID = Intrinsic::riscv_cv_simd_shuffle_h;
+ break;
+ case RISCV::BI__builtin_riscv_cv_simd_shuffle_b:
+ ID = Intrinsic::riscv_cv_simd_shuffle_b;
+ break;
+ case RISCV::BI__builtin_riscv_cv_simd_shuffle_sci_h:
+ ID = Intrinsic::riscv_cv_simd_shuffle_sci_h;
+ break;
+ case RISCV::BI__builtin_riscv_cv_simd_shuffle_sci_b:
+ ID = Intrinsic::riscv_cv_simd_shuffle_sci_b;
+ break;
+ case RISCV::BI__builtin_riscv_cv_simd_shuffle2_h:
+ ID = Intrinsic::riscv_cv_simd_shuffle2_h;
+ break;
+ case RISCV::BI__builtin_riscv_cv_simd_shuffle2_b:
+ ID = Intrinsic::riscv_cv_simd_shuffle2_b;
+ break;
+
+ // XCVsimd - PACK
+ case RISCV::BI__builtin_riscv_cv_simd_packhi_h:
+ ID = Intrinsic::riscv_cv_simd_packhi_h;
+ break;
+ case RISCV::BI__builtin_riscv_cv_simd_packlo_h:
+ ID = Intrinsic::riscv_cv_simd_packlo_h;
+ break;
+ case RISCV::BI__builtin_riscv_cv_simd_packhi_b:
+ ID = Intrinsic::riscv_cv_simd_packhi_b;
+ break;
+ case RISCV::BI__builtin_riscv_cv_simd_packlo_b:
+ ID = Intrinsic::riscv_cv_simd_packlo_b;
+ break;
+
+ // XCVsimd - COMPARE (result is mask in packed reg)
+ case RISCV::BI__builtin_riscv_cv_simd_cmpeq_h:
+ ID = Intrinsic::riscv_cv_simd_cmpeq_h;
+ break;
+ case RISCV::BI__builtin_riscv_cv_simd_cmpeq_b:
+ ID = Intrinsic::riscv_cv_simd_cmpeq_b;
+ break;
+ case RISCV::BI__builtin_riscv_cv_simd_cmpeq_sc_h:
+ ID = Intrinsic::riscv_cv_simd_cmpeq_sc_h;
+ break;
+ case RISCV::BI__builtin_riscv_cv_simd_cmpeq_sc_b:
+ ID = Intrinsic::riscv_cv_simd_cmpeq_sc_b;
+ break;
+ case RISCV::BI__builtin_riscv_cv_simd_cmpne_h:
+ ID = Intrinsic::riscv_cv_simd_cmpne_h;
+ break;
+ case RISCV::BI__builtin_riscv_cv_simd_cmpne_b:
+ ID = Intrinsic::riscv_cv_simd_cmpne_b;
+ break;
+ case RISCV::BI__builtin_riscv_cv_simd_cmpne_sc_h:
+ ID = Intrinsic::riscv_cv_simd_cmpne_sc_h;
+ break;
+ case RISCV::BI__builtin_riscv_cv_simd_cmpne_sc_b:
+ ID = Intrinsic::riscv_cv_simd_cmpne_sc_b;
+ break;
+ case RISCV::BI__builtin_riscv_cv_simd_cmpgt_h:
+ ID = Intrinsic::riscv_cv_simd_cmpgt_h;
+ break;
+ case RISCV::BI__builtin_riscv_cv_simd_cmpgt_b:
+ ID = Intrinsic::riscv_cv_simd_cmpgt_b;
+ break;
+ case RISCV::BI__builtin_riscv_cv_simd_cmpgt_sc_h:
+ ID = Intrinsic::riscv_cv_simd_cmpgt_sc_h;
+ break;
+ case RISCV::BI__builtin_riscv_cv_simd_cmpgt_sc_b:
+ ID = Intrinsic::riscv_cv_simd_cmpgt_sc_b;
+ break;
+ case RISCV::BI__builtin_riscv_cv_simd_cmpge_h:
+ ID = Intrinsic::riscv_cv_simd_cmpge_h;
+ break;
+ case RISCV::BI__builtin_riscv_cv_simd_cmpge_b:
+ ID = Intrinsic::riscv_cv_simd_cmpge_b;
+ break;
+ case RISCV::BI__builtin_riscv_cv_simd_cmpge_sc_h:
+ ID = Intrinsic::riscv_cv_simd_cmpge_sc_h;
+ break;
+ case RISCV::BI__builtin_riscv_cv_simd_cmpge_sc_b:
+ ID = Intrinsic::riscv_cv_simd_cmpge_sc_b;
+ break;
+ case RISCV::BI__builtin_riscv_cv_simd_cmplt_h:
+ ID = Intrinsic::riscv_cv_simd_cmplt_h;
+ break;
+ case RISCV::BI__builtin_riscv_cv_simd_cmplt_b:
+ ID = Intrinsic::riscv_cv_simd_cmplt_b;
+ break;
+ case RISCV::BI__builtin_riscv_cv_simd_cmplt_sc_h:
+ ID = Intrinsic::riscv_cv_simd_cmplt_sc_h;
+ break;
+ case RISCV::BI__builtin_riscv_cv_simd_cmplt_sc_b:
+ ID = Intrinsic::riscv_cv_simd_cmplt_sc_b;
+ break;
+ case RISCV::BI__builtin_riscv_cv_simd_cmple_h:
+ ID = Intrinsic::riscv_cv_simd_cmple_h;
+ break;
+ case RISCV::BI__builtin_riscv_cv_simd_cmple_b:
+ ID = Intrinsic::riscv_cv_simd_cmple_b;
+ break;
+ case RISCV::BI__builtin_riscv_cv_simd_cmple_sc_h:
+ ID = Intrinsic::riscv_cv_simd_cmple_sc_h;
+ break;
+ case RISCV::BI__builtin_riscv_cv_simd_cmple_sc_b:
+ ID = Intrinsic::riscv_cv_simd_cmple_sc_b;
+ break;
+ case RISCV::BI__builtin_riscv_cv_simd_cmpgtu_h:
+ ID = Intrinsic::riscv_cv_simd_cmpgtu_h;
+ break;
+ case RISCV::BI__builtin_riscv_cv_simd_cmpgtu_b:
+ ID = Intrinsic::riscv_cv_simd_cmpgtu_b;
+ break;
+ case RISCV::BI__builtin_riscv_cv_simd_cmpgtu_sc_h:
+ ID = Intrinsic::riscv_cv_simd_cmpgtu_sc_h;
+ break;
+ case RISCV::BI__builtin_riscv_cv_simd_cmpgtu_sc_b:
+ ID = Intrinsic::riscv_cv_simd_cmpgtu_sc_b;
+ break;
+ case RISCV::BI__builtin_riscv_cv_simd_cmpgeu_h:
+ ID = Intrinsic::riscv_cv_simd_cmpgeu_h;
+ break;
+ case RISCV::BI__builtin_riscv_cv_simd_cmpgeu_b:
+ ID = Intrinsic::riscv_cv_simd_cmpgeu_b;
+ break;
+ case RISCV::BI__builtin_riscv_cv_simd_cmpgeu_sc_h:
+ ID = Intrinsic::riscv_cv_simd_cmpgeu_sc_h;
+ break;
+ case RISCV::BI__builtin_riscv_cv_simd_cmpgeu_sc_b:
+ ID = Intrinsic::riscv_cv_simd_cmpgeu_sc_b;
+ break;
+ case RISCV::BI__builtin_riscv_cv_simd_cmpltu_h:
+ ID = Intrinsic::riscv_cv_simd_cmpltu_h;
+ break;
+ case RISCV::BI__builtin_riscv_cv_simd_cmpltu_b:
+ ID = Intrinsic::riscv_cv_simd_cmpltu_b;
+ break;
+ case RISCV::BI__builtin_riscv_cv_simd_cmpltu_sc_h:
+ ID = Intrinsic::riscv_cv_simd_cmpltu_sc_h;
+ break;
+ case RISCV::BI__builtin_riscv_cv_simd_cmpltu_sc_b:
+ ID = Intrinsic::riscv_cv_simd_cmpltu_sc_b;
+ break;
+ case RISCV::BI__builtin_riscv_cv_simd_cmpleu_h:
+ ID = Intrinsic::riscv_cv_simd_cmpleu_h;
+ break;
+ case RISCV::BI__builtin_riscv_cv_simd_cmpleu_b:
+ ID = Intrinsic::riscv_cv_simd_cmpleu_b;
+ break;
+ case RISCV::BI__builtin_riscv_cv_simd_cmpleu_sc_h:
+ ID = Intrinsic::riscv_cv_simd_cmpleu_sc_h;
+ break;
+ case RISCV::BI__builtin_riscv_cv_simd_cmpleu_sc_b:
+ ID = Intrinsic::riscv_cv_simd_cmpleu_sc_b;
+ break;
+
+ // XCVsimd - COMPLEX
+ case RISCV::BI__builtin_riscv_cv_simd_cplxmul_r:
+ ID = Intrinsic::riscv_cv_simd_cplxmul_r;
+ break;
+ case RISCV::BI__builtin_riscv_cv_simd_cplxmul_i:
+ ID = Intrinsic::riscv_cv_simd_cplxmul_i;
+ break;
+ case RISCV::BI__builtin_riscv_cv_simd_cplxconj:
+ ID = Intrinsic::riscv_cv_simd_cplxconj;
+ break;
+ case RISCV::BI__builtin_riscv_cv_simd_subrotmj:
+ ID = Intrinsic::riscv_cv_simd_subrotmj;
+ break;
+
// XAndesPerf
case RISCV::BI__builtin_riscv_nds_ffb_32:
case RISCV::BI__builtin_riscv_nds_ffb_64:
diff --git a/clang/lib/Headers/CMakeLists.txt b/clang/lib/Headers/CMakeLists.txt
index e1021a6020305..b314bfdffea45 100644
--- a/clang/lib/Headers/CMakeLists.txt
+++ b/clang/lib/Headers/CMakeLists.txt
@@ -140,6 +140,7 @@ set(riscv_files
riscv_corev_alu.h
riscv_corev_elw.h
riscv_corev_mac.h
+ riscv_corev_simd.h
riscv_mips.h
riscv_nds.h
riscv_packed_simd.h
diff --git a/clang/lib/Headers/riscv_corev_simd.h b/clang/lib/Headers/riscv_corev_simd.h
new file mode 100644
index 0000000000000..a1b7164b3977e
--- /dev/null
+++ b/clang/lib/Headers/riscv_corev_simd.h
@@ -0,0 +1,707 @@
+/*===---- riscv_corev_simd.h - CORE-V SIMD intrinsics ----------------------===
+ *
+ * Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+ * See https://llvm.org/LICENSE.txt for license information.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ *
+ *===-----------------------------------------------------------------------===
+ *
+ * This header provides C intrinsics for the CORE-V XCVsimd ISA extension.
+ * Include this header when compiling with -march=..._xcvsimd.
+ *
+ * All operations work on packed sub-word elements within a 32-bit GPR:
+ * - .h variants operate on two packed int16 / uint16 (halfwords)
+ * - .b variants operate on four packed int8 / uint8 (bytes)
+ * - .sc variants use the lower halfword/byte of a GPR as a scalar operand
+ * - .sci variants use a sign-extended 6-bit immediate as a scalar operand
+ *
+ * Spec: https://docs.openhwgroup.org/projects/cv32e40p-user-manual/en/latest/
+ * instruction_set_extensions.html#simd
+ *
+ *===-----------------------------------------------------------------------===
+ */
+
+#ifndef __RISCV_COREV_SIMD_H
+#define __RISCV_COREV_SIMD_H
+
+#include <stdint.h>
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+#if defined(__riscv_xcvsimd)
+
+#define __DEFAULT_FN_ATTRS \
+ __attribute__((__always_inline__, __nodebug__, __artificial__))
+
+/* ===========================================================================
+ * ADD / SUB
+ *
+ * .h: cv.add.h rd, rs1, rs2 (or .div2/.div4/.div8)
+ * .b: cv.add.b rd, rs1, rs2
+ *
+ * The _h variant takes a div-shift code as third argument (0=no shift,
+ * 1=/2, 2=/4, 3=/8). This is an immediate, so it must be a compile-time
+ * constant — hence the macro form.
+ * =========================================================================== */
+
+/* add.h with div-by-N right shift (DIVCODE in [0,3]) */
+#define __riscv_cv_simd_add_h(__rs1, __rs2, __DIVCODE) \
+ ((uint32_t)__builtin_riscv_cv_simd_add_h((uint32_t)(__rs1), \
+ (uint32_t)(__rs2), \
+ (uint32_t)(__DIVCODE)))
+
+static __inline__ uint32_t __DEFAULT_FN_ATTRS
+__riscv_cv_simd_add_b(uint32_t a, uint32_t b) {
+ return __builtin_riscv_cv_simd_add_b(a, b);
+}
+static __inline__ uint32_t __DEFAULT_FN_ATTRS
+__riscv_cv_simd_add_sc_h(uint32_t a, uint32_t b) {
+ return __builtin_riscv_cv_simd_add_sc_h(a, b);
+}
+static __inline__ uint32_t __DEFAULT_FN_ATTRS
+__riscv_cv_simd_add_sc_b(uint32_t a, uint32_t b) {
+ return __builtin_riscv_cv_simd_add_sc_b(a, b);
+}
+
+/* sub.h with div-by-N right shift (DIVCODE in [0,3]) */
+#define __riscv_cv_simd_sub_h(__rs1, __rs2, __DIVCODE) \
+ ((uint32_t)__builtin_riscv_cv_simd_sub_h((uint32_t)(__rs1), \
+ (uint32_t)(__rs2), \
+ (uint32_t)(__DIVCODE)))
+
+static __inline__ uint32_t __DEFAULT_FN_ATTRS
+__riscv_cv_simd_sub_b(uint32_t a, uint32_t b) {
+ return __builtin_riscv_cv_simd_sub_b(a, b);
+}
+static __inline__ uint32_t __DEFAULT_FN_ATTRS
+__riscv_cv_simd_sub_sc_h(uint32_t a, uint32_t b) {
+ return __builtin_riscv_cv_simd_sub_sc_h(a, b);
+}
+static __inline__ uint32_t __DEFAULT_FN_ATTRS
+__riscv_cv_simd_sub_sc_b(uint32_t a, uint32_t b) {
+ return __builtin_riscv_cv_simd_sub_sc_b(a, b);
+}
+
+/* ===========================================================================
+ * AVG / AVGU (signed and unsigned average)
+ * =========================================================================== */
+
+static __inline__ uint32_t __DEFAULT_FN_ATTRS
+__riscv_cv_simd_avg_h(uint32_t a, uint32_t b) {
+ return __builtin_riscv_cv_simd_avg_h(a, b);
+}
+static __inline__ uint32_t __DEFAULT_FN_ATTRS
+__riscv_cv_simd_avg_b(uint32_t a, uint32_t b) {
+ return __builtin_riscv_cv_simd_avg_b(a, b);
+}
+static __inline__ uint32_t __DEFAULT_FN_ATTRS
+__riscv_cv_simd_avg_sc_h(uint32_t a, uint32_t b) {
+ return __builtin_riscv_cv_simd_avg_sc_h(a, b);
+}
+static __inline__ uint32_t __DEFAULT_FN_ATTRS
+__riscv_cv_simd_avg_sc_b(uint32_t a, uint32_t b) {
+ return __builtin_riscv_cv_simd_avg_sc_b(a, b);
+}
+
+static __inline__ uint32_t __DEFAULT_FN_ATTRS
+__riscv_cv_simd_avgu_h(uint32_t a, uint32_t b) {
+ return __builtin_riscv_cv_simd_avgu_h(a, b);
+}
+static __inline__ uint32_t __DEFAULT_FN_ATTRS
+__riscv_cv_simd_avgu_b(uint32_t a, uint32_t b) {
+ return __builtin_riscv_cv_simd_avgu_b(a, b);
+}
+static __inline__ uint32_t __DEFAULT_FN_ATTRS
+__riscv_cv_simd_avgu_sc_h(uint32_t a, uint32_t b) {
+ return __builtin_riscv_cv_simd_avgu_sc_h(a, b);
+}
+static __inline__ uint32_t __DEFAULT_FN_ATTRS
+__riscv_cv_simd_avgu_sc_b(uint32_t a, uint32_t b) {
+ return __builtin_riscv_cv_simd_avgu_sc_b(a, b);
+}
+
+/* ===========================================================================
+ * MIN / MINU (signed and unsigned per-element minimum)
+ * =========================================================================== */
+
+static __inline__ uint32_t __DEFAULT_FN_ATTRS
+__riscv_cv_simd_min_h(uint32_t a, uint32_t b) {
+ return __builtin_riscv_cv_simd_min_h(a, b);
+}
+static __inline__ uint32_t __DEFAULT_FN_ATTRS
+__riscv_cv_simd_min_b(uint32_t a, uint32_t b) {
+ return __builtin_riscv_cv_simd_min_b(a, b);
+}
+static __inline__ uint32_t __DEFAULT_FN_ATTRS
+__riscv_cv_simd_min_sc_h(uint32_t a, uint32_t b) {
+ return __builtin_riscv_cv_simd_min_sc_h(a, b);
+}
+static __inline__ uint32_t __DEFAULT_FN_ATTRS
+__riscv_cv_simd_min_sc_b(uint32_t a, uint32_t b) {
+ return __builtin_riscv_cv_simd_min_sc_b(a, b);
+}
+
+static __inline__ uint32_t __DEFAULT_FN_ATTRS
+__riscv_cv_simd_minu_h(uint32_t a, uint32_t b) {
+ return __builtin_riscv_cv_simd_minu_h(a, b);
+}
+static __inline__ uint32_t __DEFAULT_FN_ATTRS
+__riscv_cv_simd_minu_b(uint32_t a, uint32_t b) {
+ return __builtin_riscv_cv_simd_minu_b(a, b);
+}
+static __inline__ uint32_t __DEFAULT_FN_ATTRS
+__riscv_cv_simd_minu_sc_h(uint32_t a, uint32_t b) {
+ return __builtin_riscv_cv_simd_minu_sc_h(a, b);
+}
+static __inline__ uint32_t __DEFAULT_FN_ATTRS
+__riscv_cv_simd_minu_sc_b(uint32_t a, uint32_t b) {
+ return __builtin_riscv_cv_simd_minu_sc_b(a, b);
+}
+
+/* ===========================================================================
+ * MAX / MAXU (signed and unsigned per-element maximum)
+ * =========================================================================== */
+
+static __inline__ uint32_t __DEFAULT_FN_ATTRS
+__riscv_cv_simd_max_h(uint32_t a, uint32_t b) {
+ return __builtin_riscv_cv_simd_max_h(a, b);
+}
+static __inline__ uint32_t __DEFAULT_FN_ATTRS
+__riscv_cv_simd_max_b(uint32_t a, uint32_t b) {
+ return __builtin_riscv_cv_simd_max_b(a, b);
+}
+static __inline__ uint32_t __DEFAULT_FN_ATTRS
+__riscv_cv_simd_max_sc_h(uint32_t a, uint32_t b) {
+ return __builtin_riscv_cv_simd_max_sc_h(a, b);
+}
+static __inline__ uint32_t __DEFAULT_FN_ATTRS
+__riscv_cv_simd_max_sc_b(uint32_t a, uint32_t b) {
+ return __builtin_riscv_cv_simd_max_sc_b(a, b);
+}
+
+static __inline__ uint32_t __DEFAULT_FN_ATTRS
+__riscv_cv_simd_maxu_h(uint32_t a, uint32_t b) {
+ return __builtin_riscv_cv_simd_maxu_h(a, b);
+}
+static __inline__ uint32_t __DEFAULT_FN_ATTRS
+__riscv_cv_simd_maxu_b(uint32_t a, uint32_t b) {
+ return __builtin_riscv_cv_simd_maxu_b(a, b);
+}
+static __inline__ uint32_t __DEFAULT_FN_ATTRS
+__riscv_cv_simd_maxu_sc_h(uint32_t a, uint32_t b) {
+ return __builtin_riscv_cv_simd_maxu_sc_h(a, b);
+}
+static __inline__ uint32_t __DEFAULT_FN_ATTRS
+__riscv_cv_simd_maxu_sc_b(uint32_t a, uint32_t b) {
+ return __builtin_riscv_cv_simd_maxu_sc_b(a, b);
+}
+
+/* ===========================================================================
+ * SHIFT: SRL / SRA / SLL
+ * .sc variants take a GPR shift amount (lower bits used)
+ * No .sci variant for shifts (the instruction encodes a small immediate
+ * directly in the funct3 space; use the .sc_h/.sc_b with a constant GPR).
+ * =========================================================================== */
+
+static __inline__ uint32_t __DEFAULT_FN_ATTRS
+__riscv_cv_simd_srl_h(uint32_t a, uint32_t b) {
+ return __builtin_riscv_cv_simd_srl_h(a, b);
+}
+static __inline__ uint32_t __DEFAULT_FN_ATTRS
+__riscv_cv_simd_srl_b(uint32_t a, uint32_t b) {
+ return __builtin_riscv_cv_simd_srl_b(a, b);
+}
+static __inline__ uint32_t __DEFAULT_FN_ATTRS
+__riscv_cv_simd_srl_sc_h(uint32_t a, uint32_t b) {
+ return __builtin_riscv_cv_simd_srl_sc_h(a, b);
+}
+static __inline__ uint32_t __DEFAULT_FN_ATTRS
+__riscv_cv_simd_srl_sc_b(uint32_t a, uint32_t b) {
+ return __builtin_riscv_cv_simd_srl_sc_b(a, b);
+}
+
+static __inline__ uint32_t __DEFAULT_FN_ATTRS
+__riscv_cv_simd_sra_h(uint32_t a, uint32_t b) {
+ return __builtin_riscv_cv_simd_sra_h(a, b);
+}
+static __inline__ uint32_t __DEFAULT_FN_ATTRS
+__riscv_cv_simd_sra_b(uint32_t a, uint32_t b) {
+ return __builtin_riscv_cv_simd_sra_b(a, b);
+}
+static __inline__ uint32_t __DEFAULT_FN_ATTRS
+__riscv_cv_simd_sra_sc_h(uint32_t a, uint32_t b) {
+ return __builtin_riscv_cv_simd_sra_sc_h(a, b);
+}
+static __inline__ uint32_t __DEFAULT_FN_ATTRS
+__riscv_cv_simd_sra_sc_b(uint32_t a, uint32_t b) {
+ return __builtin_riscv_cv_simd_sra_sc_b(a, b);
+}
+
+static __inline__ uint32_t __DEFAULT_FN_ATTRS
+__riscv_cv_simd_sll_h(uint32_t a, uint32_t b) {
+ return __builtin_riscv_cv_simd_sll_h(a, b);
+}
+static __inline__ uint32_t __DEFAULT_FN_ATTRS
+__riscv_cv_simd_sll_b(uint32_t a, uint32_t b) {
+ return __builtin_riscv_cv_simd_sll_b(a, b);
+}
+static __inline__ uint32_t __DEFAULT_FN_ATTRS
+__riscv_cv_simd_sll_sc_h(uint32_t a, uint32_t b) {
+ return __builtin_riscv_cv_simd_sll_sc_h(a, b);
+}
+static __inline__ uint32_t __DEFAULT_FN_ATTRS
+__riscv_cv_simd_sll_sc_b(uint32_t a, uint32_t b) {
+ return __builtin_riscv_cv_simd_sll_sc_b(a, b);
+}
+
+/* ===========================================================================
+ * BITWISE: OR / XOR / AND
+ * =========================================================================== */
+
+static __inline__ uint32_t __DEFAULT_FN_ATTRS
+__riscv_cv_simd_or_h(uint32_t a, uint32_t b) {
+ return __builtin_riscv_cv_simd_or_h(a, b);
+}
+static __inline__ uint32_t __DEFAULT_FN_ATTRS
+__riscv_cv_simd_or_b(uint32_t a, uint32_t b) {
+ return __builtin_riscv_cv_simd_or_b(a, b);
+}
+static __inline__ uint32_t __DEFAULT_FN_ATTRS
+__riscv_cv_simd_or_sc_h(uint32_t a, uint32_t b) {
+ return __builtin_riscv_cv_simd_or_sc_h(a, b);
+}
+static __inline__ uint32_t __DEFAULT_FN_ATTRS
+__riscv_cv_simd_or_sc_b(uint32_t a, uint32_t b) {
+ return __builtin_riscv_cv_simd_or_sc_b(a, b);
+}
+
+static __inline__ uint32_t __DEFAULT_FN_ATTRS
+__riscv_cv_simd_xor_h(uint32_t a, uint32_t b) {
+ return __builtin_riscv_cv_simd_xor_h(a, b);
+}
+static __inline__ uint32_t __DEFAULT_FN_ATTRS
+__riscv_cv_simd_xor_b(uint32_t a, uint32_t b) {
+ return __builtin_riscv_cv_simd_xor_b(a, b);
+}
+static __inline__ uint32_t __DEFAULT_FN_ATTRS
+__riscv_cv_simd_xor_sc_h(uint32_t a, uint32_t b) {
+ return __builtin_riscv_cv_simd_xor_sc_h(a, b);
+}
+static __inline__ uint32_t __DEFAULT_FN_ATTRS
+__riscv_cv_simd_xor_sc_b(uint32_t a, uint32_t b) {
+ return __builtin_riscv_cv_simd_xor_sc_b(a, b);
+}
+
+static __inline__ uint32_t __DEFAULT_FN_ATTRS
+__riscv_cv_simd_and_h(uint32_t a, uint32_t b) {
+ return __builtin_riscv_cv_simd_and_h(a, b);
+}
+static __inline__ uint32_t __DEFAULT_FN_ATTRS
+__riscv_cv_simd_and_b(uint32_t a, uint32_t b) {
+ return __builtin_riscv_cv_simd_and_b(a, b);
+}
+static __inline__ uint32_t __DEFAULT_FN_ATTRS
+__riscv_cv_simd_and_sc_h(uint32_t a, uint32_t b) {
+ return __builtin_riscv_cv_simd_and_sc_h(a, b);
+}
+static __inline__ uint32_t __DEFAULT_FN_ATTRS
+__riscv_cv_simd_and_sc_b(uint32_t a, uint32_t b) {
+ return __builtin_riscv_cv_simd_and_sc_b(a, b);
+}
+
+/* ===========================================================================
+ * ABS (per-element absolute value)
+ * =========================================================================== */
+
+static __inline__ uint32_t __DEFAULT_FN_ATTRS
+__riscv_cv_simd_abs_h(uint32_t a) {
+ return __builtin_riscv_cv_simd_abs_h(a);
+}
+static __inline__ uint32_t __DEFAULT_FN_ATTRS
+__riscv_cv_simd_abs_b(uint32_t a) {
+ return __builtin_riscv_cv_simd_abs_b(a);
+}
+
+/* ===========================================================================
+ * DOT PRODUCTS
+ *
+ * dotup — unsigned × unsigned dot product (result is uint32)
+ * dotusp — unsigned × signed dot product (result is int32)
+ * dotsp — signed × signed dot product (result is int32)
+ *
+ * sdot* — same but adds result to accumulator register rd (read-modify-write)
+ * =========================================================================== */
+
+/* dotup */
+static __inline__ uint32_t __DEFAULT_FN_ATTRS
+__riscv_cv_simd_dotup_h(uint32_t a, uint32_t b) {
+ return __builtin_riscv_cv_simd_dotup_h(a, b);
+}
+static __inline__ uint32_t __DEFAULT_FN_ATTRS
+__riscv_cv_simd_dotup_b(uint32_t a, uint32_t b) {
+ return __builtin_riscv_cv_simd_dotup_b(a, b);
+}
+static __inline__ uint32_t __DEFAULT_FN_ATTRS
+__riscv_cv_simd_dotup_sc_h(uint32_t a, uint32_t b) {
+ return __builtin_riscv_cv_simd_dotup_sc_h(a, b);
+}
+static __inline__ uint32_t __DEFAULT_FN_ATTRS
+__riscv_cv_simd_dotup_sc_b(uint32_t a, uint32_t b) {
+ return __builtin_riscv_cv_simd_dotup_sc_b(a, b);
+}
+
+/* dotusp */
+static __inline__ int32_t __DEFAULT_FN_ATTRS
+__riscv_cv_simd_dotusp_h(uint32_t a, uint32_t b) {
+ return __builtin_riscv_cv_simd_dotusp_h(a, b);
+}
+static __inline__ int32_t __DEFAULT_FN_ATTRS
+__riscv_cv_simd_dotusp_b(uint32_t a, uint32_t b) {
+ return __builtin_riscv_cv_simd_dotusp_b(a, b);
+}
+static __inline__ int32_t __DEFAULT_FN_ATTRS
+__riscv_cv_simd_dotusp_sc_h(uint32_t a, uint32_t b) {
+ return __builtin_riscv_cv_simd_dotusp_sc_h(a, b);
+}
+static __inline__ int32_t __DEFAULT_FN_ATTRS
+__riscv_cv_simd_dotusp_sc_b(uint32_t a, uint32_t b) {
+ return __builtin_riscv_cv_simd_dotusp_sc_b(a, b);
+}
+
+/* dotsp */
+static __inline__ int32_t __DEFAULT_FN_ATTRS
+__riscv_cv_simd_dotsp_h(uint32_t a, uint32_t b) {
+ return __builtin_riscv_cv_simd_dotsp_h(a, b);
+}
+static __inline__ int32_t __DEFAULT_FN_ATTRS
+__riscv_cv_simd_dotsp_b(uint32_t a, uint32_t b) {
+ return __builtin_riscv_cv_simd_dotsp_b(a, b);
+}
+static __inline__ int32_t __DEFAULT_FN_ATTRS
+__riscv_cv_simd_dotsp_sc_h(uint32_t a, uint32_t b) {
+ return __builtin_riscv_cv_simd_dotsp_sc_h(a, b);
+}
+static __inline__ int32_t __DEFAULT_FN_ATTRS
+__riscv_cv_simd_dotsp_sc_b(uint32_t a, uint32_t b) {
+ return __builtin_riscv_cv_simd_dotsp_sc_b(a, b);
+}
+
+/* sdotup (unsigned × unsigned, accumulating) */
+static __inline__ uint32_t __DEFAULT_FN_ATTRS
+__riscv_cv_simd_sdotup_h(uint32_t a, uint32_t b, uint32_t acc) {
+ return __builtin_riscv_cv_simd_sdotup_h(a, b, acc);
+}
+static __inline__ uint32_t __DEFAULT_FN_ATTRS
+__riscv_cv_simd_sdotup_b(uint32_t a, uint32_t b, uint32_t acc) {
+ return __builtin_riscv_cv_simd_sdotup_b(a, b, acc);
+}
+static __inline__ uint32_t __DEFAULT_FN_ATTRS
+__riscv_cv_simd_sdotup_sc_h(uint32_t a, uint32_t b, uint32_t acc) {
+ return __builtin_riscv_cv_simd_sdotup_sc_h(a, b, acc);
+}
+static __inline__ uint32_t __DEFAULT_FN_ATTRS
+__riscv_cv_simd_sdotup_sc_b(uint32_t a, uint32_t b, uint32_t acc) {
+ return __builtin_riscv_cv_simd_sdotup_sc_b(a, b, acc);
+}
+
+/* sdotusp (unsigned × signed, accumulating) */
+static __inline__ int32_t __DEFAULT_FN_ATTRS
+__riscv_cv_simd_sdotusp_h(uint32_t a, uint32_t b, int32_t acc) {
+ return __builtin_riscv_cv_simd_sdotusp_h(a, b, acc);
+}
+static __inline__ int32_t __DEFAULT_FN_ATTRS
+__riscv_cv_simd_sdotusp_b(uint32_t a, uint32_t b, int32_t acc) {
+ return __builtin_riscv_cv_simd_sdotusp_b(a, b, acc);
+}
+static __inline__ int32_t __DEFAULT_FN_ATTRS
+__riscv_cv_simd_sdotusp_sc_h(uint32_t a, uint32_t b, int32_t acc) {
+ return __builtin_riscv_cv_simd_sdotusp_sc_h(a, b, acc);
+}
+static __inline__ int32_t __DEFAULT_FN_ATTRS
+__riscv_cv_simd_sdotusp_sc_b(uint32_t a, uint32_t b, int32_t acc) {
+ return __builtin_riscv_cv_simd_sdotusp_sc_b(a, b, acc);
+}
+
+/* sdotsp (signed × signed, accumulating) */
+static __inline__ int32_t __DEFAULT_FN_ATTRS
+__riscv_cv_simd_sdotsp_h(uint32_t a, uint32_t b, int32_t acc) {
+ return __builtin_riscv_cv_simd_sdotsp_h(a, b, acc);
+}
+static __inline__ int32_t __DEFAULT_FN_ATTRS
+__riscv_cv_simd_sdotsp_b(uint32_t a, uint32_t b, int32_t acc) {
+ return __builtin_riscv_cv_simd_sdotsp_b(a, b, acc);
+}
+static __inline__ int32_t __DEFAULT_FN_ATTRS
+__riscv_cv_simd_sdotsp_sc_h(uint32_t a, uint32_t b, int32_t acc) {
+ return __builtin_riscv_cv_simd_sdotsp_sc_h(a, b, acc);
+}
+static __inline__ int32_t __DEFAULT_FN_ATTRS
+__riscv_cv_simd_sdotsp_sc_b(uint32_t a, uint32_t b, int32_t acc) {
+ return __builtin_riscv_cv_simd_sdotsp_sc_b(a, b, acc);
+}
+
+/* ===========================================================================
+ * EXTRACT / EXTRACTU / INSERT
+ *
+ * cv.extract.h rd, rs1, IMM — extract halfword IMM (0 or 1), sign-extended
+ * cv.extract.b rd, rs1, IMM — extract byte IMM (0..3), sign-extended
+ * cv.extractu.h rd, rs1, IMM — extract halfword IMM, zero-extended
+ * cv.extractu.b rd, rs1, IMM — extract byte IMM, zero-extended
+ * cv.insert.h rd, rs1, IMM — insert lower halfword of rs1 into rd at IMM
+ * cv.insert.b rd, rs1, IMM — insert lower byte of rs1 into rd at IMM
+ *
+ * IMM is an immediate (compile-time constant), so macros are used.
+ * =========================================================================== */
+
+#define __riscv_cv_simd_extract_h(__rs1, __IMM) \
+ ((int32_t)__builtin_riscv_cv_simd_extract_h((uint32_t)(__rs1), \
+ (uint32_t)(__IMM)))
+
+#define __riscv_cv_simd_extract_b(__rs1, __IMM) \
+ ((int32_t)__builtin_riscv_cv_simd_extract_b((uint32_t)(__rs1), \
+ (uint32_t)(__IMM)))
+
+#define __riscv_cv_simd_extractu_h(__rs1, __IMM) \
+ ((uint32_t)__builtin_riscv_cv_simd_extractu_h((uint32_t)(__rs1), \
+ (uint32_t)(__IMM)))
+
+#define __riscv_cv_simd_extractu_b(__rs1, __IMM) \
+ ((uint32_t)__builtin_riscv_cv_simd_extractu_b((uint32_t)(__rs1), \
+ (uint32_t)(__IMM)))
+
+/* insert: rd is both input and output (read-modify-write accumulator).
+ The intrinsic prototype is (rs1, rd_in, IMM) -> rd_out. */
+#define __riscv_cv_simd_insert_h(__rD, __rs1, __IMM) \
+ ((uint32_t)__builtin_riscv_cv_simd_insert_h((uint32_t)(__rD), \
+ (uint32_t)(__rs1), \
+ (uint32_t)(__IMM)))
+
+#define __riscv_cv_simd_insert_b(__rD, __rs1, __IMM) \
+ ((uint32_t)__builtin_riscv_cv_simd_insert_b((uint32_t)(__rD), \
+ (uint32_t)(__rs1), \
+ (uint32_t)(__IMM)))
+
+/* ===========================================================================
+ * SHUFFLE / SHUFFLE2
+ *
+ * cv.shuffle.h rd, rs1, rs2 — shuffle halfwords of rs1 using rs2 mask
+ * cv.shuffle.b rd, rs1, rs2 — shuffle bytes of rs1 using rs2 mask
+ * cv.shuffle.sci.h rd, rs1, IMM — shuffle halfwords using 2-bit imm
+ * cv.shuffle.sci.b rd, rs1, IMM — shuffle bytes using 8-bit imm
+ * (split internally into SHUFFLEIx.sci.b)
+ * cv.shuffle2.h rd, rs1, rs2 — interleave shuffle using rs2 mask + rd input
+ * cv.shuffle2.b rd, rs1, rs2 — interleave shuffle using rs2 mask + rd input
+ * =========================================================================== */
+
+static __inline__ uint32_t __DEFAULT_FN_ATTRS
+__riscv_cv_simd_shuffle_h(uint32_t a, uint32_t mask) {
+ return __builtin_riscv_cv_simd_shuffle_h(a, mask);
+}
+static __inline__ uint32_t __DEFAULT_FN_ATTRS
+__riscv_cv_simd_shuffle_b(uint32_t a, uint32_t mask) {
+ return __builtin_riscv_cv_simd_shuffle_b(a, mask);
+}
+
+/* shuffle.sci.h — IMM is a 2-bit immediate [0,3] */
+#define __riscv_cv_simd_shuffle_sci_h(__rs1, __IMM) \
+ ((uint32_t)__builtin_riscv_cv_simd_shuffle_sci_h((uint32_t)(__rs1), \
+ (uint32_t)(__IMM)))
+
+/* shuffle.sci.b — IMM is an 8-bit immediate [0,255].
+ The backend splits this into two bits (top 2 → SHUFFLEIx selector) + 6-bit
+ payload, emitting the correct CV_SHUFFLEIx_SCI_B instruction. */
+#define __riscv_cv_simd_shuffle_sci_b(__rs1, __IMM) \
+ ((uint32_t)__builtin_riscv_cv_simd_shuffle_sci_b((uint32_t)(__rs1), \
+ (uint32_t)(__IMM)))
+
+/* shuffle2: rd is read-modify-write (used as additional input lane) */
+static __inline__ uint32_t __DEFAULT_FN_ATTRS
+__riscv_cv_simd_shuffle2_h(uint32_t rD, uint32_t rs1, uint32_t rs2) {
+ return __builtin_riscv_cv_simd_shuffle2_h(rs1, rs2, rD);
+}
+static __inline__ uint32_t __DEFAULT_FN_ATTRS
+__riscv_cv_simd_shuffle2_b(uint32_t rD, uint32_t rs1, uint32_t rs2) {
+ return __builtin_riscv_cv_simd_shuffle2_b(rs1, rs2, rD);
+}
+
+/* ===========================================================================
+ * PACK
+ *
+ * cv.pack rd, rs1, rs2 — pack lower halfwords: rd = {rs1[15:0], rs2[15:0]}
+ * cv.pack.h rd, rs1, rs2 — pack upper halfwords: rd = {rs1[31:16], rs2[31:16]}
+ * cv.packhi.b rd, rs1, rs2 — pack odd bytes: rd = {rs1[31:24],rs1[15:8],
+ * rs2[31:24],rs2[15:8]}
+ * cv.packlo.b rd, rs1, rs2 — pack even bytes: rd = {rs1[23:16],rs1[7:0],
+ * rs2[23:16],rs2[7:0]}
+ *
+ * packhi/packlo: rd is read-modify-write.
+ * =========================================================================== */
+
+static __inline__ uint32_t __DEFAULT_FN_ATTRS
+__riscv_cv_simd_packlo_h(uint32_t rs1, uint32_t rs2) {
+ return __builtin_riscv_cv_simd_packlo_h(rs1, rs2);
+}
+static __inline__ uint32_t __DEFAULT_FN_ATTRS
+__riscv_cv_simd_packhi_h(uint32_t rs1, uint32_t rs2) {
+ return __builtin_riscv_cv_simd_packhi_h(rs1, rs2);
+}
+
+/* packhi/packlo.b: rD is the accumulator half that keeps unmodified bytes */
+static __inline__ uint32_t __DEFAULT_FN_ATTRS
+__riscv_cv_simd_packhi_b(uint32_t rD, uint32_t rs1, uint32_t rs2) {
+ return __builtin_riscv_cv_simd_packhi_b(rD, rs1, rs2);
+}
+static __inline__ uint32_t __DEFAULT_FN_ATTRS
+__riscv_cv_simd_packlo_b(uint32_t rD, uint32_t rs1, uint32_t rs2) {
+ return __builtin_riscv_cv_simd_packlo_b(rD, rs1, rs2);
+}
+
+/* ===========================================================================
+ * COMPARE (per-element, result is all-1s or all-0s per lane)
+ * =========================================================================== */
+
+/* cmpeq */
+static __inline__ uint32_t __DEFAULT_FN_ATTRS
+__riscv_cv_simd_cmpeq_h(uint32_t a, uint32_t b) { return __builtin_riscv_cv_simd_cmpeq_h(a, b); }
+static __inline__ uint32_t __DEFAULT_FN_ATTRS
+__riscv_cv_simd_cmpeq_b(uint32_t a, uint32_t b) { return __builtin_riscv_cv_simd_cmpeq_b(a, b); }
+static __inline__ uint32_t __DEFAULT_FN_ATTRS
+__riscv_cv_simd_cmpeq_sc_h(uint32_t a, uint32_t b) { return __builtin_riscv_cv_simd_cmpeq_sc_h(a, b); }
+static __inline__ uint32_t __DEFAULT_FN_ATTRS
+__riscv_cv_simd_cmpeq_sc_b(uint32_t a, uint32_t b) { return __builtin_riscv_cv_simd_cmpeq_sc_b(a, b); }
+
+/* cmpne */
+static __inline__ uint32_t __DEFAULT_FN_ATTRS
+__riscv_cv_simd_cmpne_h(uint32_t a, uint32_t b) { return __builtin_riscv_cv_simd_cmpne_h(a, b); }
+static __inline__ uint32_t __DEFAULT_FN_ATTRS
+__riscv_cv_simd_cmpne_b(uint32_t a, uint32_t b) { return __builtin_riscv_cv_simd_cmpne_b(a, b); }
+static __inline__ uint32_t __DEFAULT_FN_ATTRS
+__riscv_cv_simd_cmpne_sc_h(uint32_t a, uint32_t b) { return __builtin_riscv_cv_simd_cmpne_sc_h(a, b); }
+static __inline__ uint32_t __DEFAULT_FN_ATTRS
+__riscv_cv_simd_cmpne_sc_b(uint32_t a, uint32_t b) { return __builtin_riscv_cv_simd_cmpne_sc_b(a, b); }
+
+/* cmpgt (signed greater-than) */
+static __inline__ uint32_t __DEFAULT_FN_ATTRS
+__riscv_cv_simd_cmpgt_h(uint32_t a, uint32_t b) { return __builtin_riscv_cv_simd_cmpgt_h(a, b); }
+static __inline__ uint32_t __DEFAULT_FN_ATTRS
+__riscv_cv_simd_cmpgt_b(uint32_t a, uint32_t b) { return __builtin_riscv_cv_simd_cmpgt_b(a, b); }
+static __inline__ uint32_t __DEFAULT_FN_ATTRS
+__riscv_cv_simd_cmpgt_sc_h(uint32_t a, uint32_t b) { return __builtin_riscv_cv_simd_cmpgt_sc_h(a, b); }
+static __inline__ uint32_t __DEFAULT_FN_ATTRS
+__riscv_cv_simd_cmpgt_sc_b(uint32_t a, uint32_t b) { return __builtin_riscv_cv_simd_cmpgt_sc_b(a, b); }
+
+/* cmpge (signed greater-or-equal) */
+static __inline__ uint32_t __DEFAULT_FN_ATTRS
+__riscv_cv_simd_cmpge_h(uint32_t a, uint32_t b) { return __builtin_riscv_cv_simd_cmpge_h(a, b); }
+static __inline__ uint32_t __DEFAULT_FN_ATTRS
+__riscv_cv_simd_cmpge_b(uint32_t a, uint32_t b) { return __builtin_riscv_cv_simd_cmpge_b(a, b); }
+static __inline__ uint32_t __DEFAULT_FN_ATTRS
+__riscv_cv_simd_cmpge_sc_h(uint32_t a, uint32_t b) { return __builtin_riscv_cv_simd_cmpge_sc_h(a, b); }
+static __inline__ uint32_t __DEFAULT_FN_ATTRS
+__riscv_cv_simd_cmpge_sc_b(uint32_t a, uint32_t b) { return __builtin_riscv_cv_simd_cmpge_sc_b(a, b); }
+
+/* cmplt (signed less-than) */
+static __inline__ uint32_t __DEFAULT_FN_ATTRS
+__riscv_cv_simd_cmplt_h(uint32_t a, uint32_t b) { return __builtin_riscv_cv_simd_cmplt_h(a, b); }
+static __inline__ uint32_t __DEFAULT_FN_ATTRS
+__riscv_cv_simd_cmplt_b(uint32_t a, uint32_t b) { return __builtin_riscv_cv_simd_cmplt_b(a, b); }
+static __inline__ uint32_t __DEFAULT_FN_ATTRS
+__riscv_cv_simd_cmplt_sc_h(uint32_t a, uint32_t b) { return __builtin_riscv_cv_simd_cmplt_sc_h(a, b); }
+static __inline__ uint32_t __DEFAULT_FN_ATTRS
+__riscv_cv_simd_cmplt_sc_b(uint32_t a, uint32_t b) { return __builtin_riscv_cv_simd_cmplt_sc_b(a, b); }
+
+/* cmple (signed less-or-equal) */
+static __inline__ uint32_t __DEFAULT_FN_ATTRS
+__riscv_cv_simd_cmple_h(uint32_t a, uint32_t b) { return __builtin_riscv_cv_simd_cmple_h(a, b); }
+static __inline__ uint32_t __DEFAULT_FN_ATTRS
+__riscv_cv_simd_cmple_b(uint32_t a, uint32_t b) { return __builtin_riscv_cv_simd_cmple_b(a, b); }
+static __inline__ uint32_t __DEFAULT_FN_ATTRS
+__riscv_cv_simd_cmple_sc_h(uint32_t a, uint32_t b) { return __builtin_riscv_cv_simd_cmple_sc_h(a, b); }
+static __inline__ uint32_t __DEFAULT_FN_ATTRS
+__riscv_cv_simd_cmple_sc_b(uint32_t a, uint32_t b) { return __builtin_riscv_cv_simd_cmple_sc_b(a, b); }
+
+/* cmpgtu (unsigned greater-than) */
+static __inline__ uint32_t __DEFAULT_FN_ATTRS
+__riscv_cv_simd_cmpgtu_h(uint32_t a, uint32_t b) { return __builtin_riscv_cv_simd_cmpgtu_h(a, b); }
+static __inline__ uint32_t __DEFAULT_FN_ATTRS
+__riscv_cv_simd_cmpgtu_b(uint32_t a, uint32_t b) { return __builtin_riscv_cv_simd_cmpgtu_b(a, b); }
+static __inline__ uint32_t __DEFAULT_FN_ATTRS
+__riscv_cv_simd_cmpgtu_sc_h(uint32_t a, uint32_t b) { return __builtin_riscv_cv_simd_cmpgtu_sc_h(a, b); }
+static __inline__ uint32_t __DEFAULT_FN_ATTRS
+__riscv_cv_simd_cmpgtu_sc_b(uint32_t a, uint32_t b) { return __builtin_riscv_cv_simd_cmpgtu_sc_b(a, b); }
+
+/* cmpgeu (unsigned greater-or-equal) */
+static __inline__ uint32_t __DEFAULT_FN_ATTRS
+__riscv_cv_simd_cmpgeu_h(uint32_t a, uint32_t b) { return __builtin_riscv_cv_simd_cmpgeu_h(a, b); }
+static __inline__ uint32_t __DEFAULT_FN_ATTRS
+__riscv_cv_simd_cmpgeu_b(uint32_t a, uint32_t b) { return __builtin_riscv_cv_simd_cmpgeu_b(a, b); }
+static __inline__ uint32_t __DEFAULT_FN_ATTRS
+__riscv_cv_simd_cmpgeu_sc_h(uint32_t a, uint32_t b) { return __builtin_riscv_cv_simd_cmpgeu_sc_h(a, b); }
+static __inline__ uint32_t __DEFAULT_FN_ATTRS
+__riscv_cv_simd_cmpgeu_sc_b(uint32_t a, uint32_t b) { return __builtin_riscv_cv_simd_cmpgeu_sc_b(a, b); }
+
+/* cmpltu (unsigned less-than) */
+static __inline__ uint32_t __DEFAULT_FN_ATTRS
+__riscv_cv_simd_cmpltu_h(uint32_t a, uint32_t b) { return __builtin_riscv_cv_simd_cmpltu_h(a, b); }
+static __inline__ uint32_t __DEFAULT_FN_ATTRS
+__riscv_cv_simd_cmpltu_b(uint32_t a, uint32_t b) { return __builtin_riscv_cv_simd_cmpltu_b(a, b); }
+static __inline__ uint32_t __DEFAULT_FN_ATTRS
+__riscv_cv_simd_cmpltu_sc_h(uint32_t a, uint32_t b) { return __builtin_riscv_cv_simd_cmpltu_sc_h(a, b); }
+static __inline__ uint32_t __DEFAULT_FN_ATTRS
+__riscv_cv_simd_cmpltu_sc_b(uint32_t a, uint32_t b) { return __builtin_riscv_cv_simd_cmpltu_sc_b(a, b); }
+
+/* cmpleu (unsigned less-or-equal) */
+static __inline__ uint32_t __DEFAULT_FN_ATTRS
+__riscv_cv_simd_cmpleu_h(uint32_t a, uint32_t b) { return __builtin_riscv_cv_simd_cmpleu_h(a, b); }
+static __inline__ uint32_t __DEFAULT_FN_ATTRS
+__riscv_cv_simd_cmpleu_b(uint32_t a, uint32_t b) { return __builtin_riscv_cv_simd_cmpleu_b(a, b); }
+static __inline__ uint32_t __DEFAULT_FN_ATTRS
+__riscv_cv_simd_cmpleu_sc_h(uint32_t a, uint32_t b) { return __builtin_riscv_cv_simd_cmpleu_sc_h(a, b); }
+static __inline__ uint32_t __DEFAULT_FN_ATTRS
+__riscv_cv_simd_cmpleu_sc_b(uint32_t a, uint32_t b) { return __builtin_riscv_cv_simd_cmpleu_sc_b(a, b); }
+
+/* ===========================================================================
+ * COMPLEX NUMBER OPERATIONS
+ *
+ * cv.cplxmul.r rd, rs1, rs2 [, divcode] — complex multiply, real part
+ * cv.cplxmul.i rd, rs1, rs2 [, divcode] — complex multiply, imaginary part
+ * divcode: 0=no shift, 1=/2, 2=/4, 3=/8 (compile-time constant)
+ * rd is read-modify-write (accumulator for the real or imag lane)
+ *
+ * cv.cplxconj rd, rs1 — complex conjugate (negate imaginary part)
+ *
+ * cv.subrotmj rd, rs1, rs2 [, divcode] — subtract + rotate by -j
+ * result = ((rs1 - rs2) >> div) rotated by -j (swap re/im, negate new im)
+ * =========================================================================== */
+
+#define __riscv_cv_simd_cplxmul_r(__rD, __rs1, __rs2, __DIVCODE) \
+ ((uint32_t)__builtin_riscv_cv_simd_cplxmul_r((uint32_t)(__rs1), \
+ (uint32_t)(__rs2), \
+ (uint32_t)(__rD), \
+ (uint32_t)(__DIVCODE)))
+
+#define __riscv_cv_simd_cplxmul_i(__rD, __rs1, __rs2, __DIVCODE) \
+ ((uint32_t)__builtin_riscv_cv_simd_cplxmul_i((uint32_t)(__rs1), \
+ (uint32_t)(__rs2), \
+ (uint32_t)(__rD), \
+ (uint32_t)(__DIVCODE)))
+
+static __inline__ uint32_t __DEFAULT_FN_ATTRS
+__riscv_cv_simd_cplxconj(uint32_t a) {
+ return __builtin_riscv_cv_simd_cplxconj(a);
+}
+
+#define __riscv_cv_simd_subrotmj(__rs1, __rs2, __DIVCODE) \
+ ((uint32_t)__builtin_riscv_cv_simd_subrotmj((uint32_t)(__rs1), \
+ (uint32_t)(__rs2), \
+ (uint32_t)(__DIVCODE)))
+
+#endif /* __riscv_xcvsimd */
+
+#if defined(__cplusplus)
+}
+#endif
+
+#endif /* __RISCV_COREV_SIMD_H */
diff --git a/clang/lib/Sema/SemaRISCV.cpp b/clang/lib/Sema/SemaRISCV.cpp
index 5711d87300b05..480fbff686f7a 100644
--- a/clang/lib/Sema/SemaRISCV.cpp
+++ b/clang/lib/Sema/SemaRISCV.cpp
@@ -673,6 +673,37 @@ bool SemaRISCV::CheckBuiltinFunctionCall(const TargetInfo &TI,
case RISCV::BI__builtin_riscv_cv_mac_machhsRN:
return SemaRef.BuiltinConstantArgRange(TheCall, 3, 0, 31);
+ // XCVsimd — extract/insert index
+ case RISCV::BI__builtin_riscv_cv_simd_extract_h:
+ case RISCV::BI__builtin_riscv_cv_simd_extractu_h:
+ return SemaRef.BuiltinConstantArgRange(TheCall, 1, 0, 1); // [0,1] for 2 halfwords
+ case RISCV::BI__builtin_riscv_cv_simd_insert_h:
+ return SemaRef.BuiltinConstantArgRange(TheCall, 2, 0, 1); // [0,1] for 2 halfwords
+ case RISCV::BI__builtin_riscv_cv_simd_extract_b:
+ case RISCV::BI__builtin_riscv_cv_simd_extractu_b:
+ return SemaRef.BuiltinConstantArgRange(TheCall, 1, 0, 3); // [0,3] for 4 bytes
+ case RISCV::BI__builtin_riscv_cv_simd_insert_b:
+ return SemaRef.BuiltinConstantArgRange(TheCall, 2, 0, 3); // [0,3] for 4 bytes
+ // Note: insert has index at arg 2 not 1
+ // Shuffle SCI — 6-bit immediate [0, 63]
+ case RISCV::BI__builtin_riscv_cv_simd_shuffle_sci_h:
+ return SemaRef.BuiltinConstantArgRange(TheCall, 1, 0, 3);
+ case RISCV::BI__builtin_riscv_cv_simd_shuffle_sci_b:
+ return SemaRef.BuiltinConstantArgRange(TheCall, 1, 0, 255); // 8-bit, split by codegen
+
+ // add_h / sub_h div code [0,3] (0=no shift, 1=/2, 2=/4, 3=/8)
+ case RISCV::BI__builtin_riscv_cv_simd_add_h:
+ case RISCV::BI__builtin_riscv_cv_simd_sub_h:
+ return SemaRef.BuiltinConstantArgRange(TheCall, 2, 0, 3);
+
+ // complex mul div code [0,3]
+ case RISCV::BI__builtin_riscv_cv_simd_cplxmul_r:
+ case RISCV::BI__builtin_riscv_cv_simd_cplxmul_i:
+ return SemaRef.BuiltinConstantArgRange(TheCall, 3, 0, 3);
+ case RISCV::BI__builtin_riscv_cv_simd_subrotmj:
+ return SemaRef.BuiltinConstantArgRange(TheCall, 2, 0, 3);
+ }
+
auto CheckVSetVL = [&](unsigned SEWOffset, unsigned LMULOffset) -> bool {
const FunctionDecl *FD = SemaRef.getCurFunctionDecl();
llvm::StringMap<bool> FunctionFeatureMap;
>From 04fa62659da05b239d443598afee0fc6143e353f Mon Sep 17 00:00:00 2001
From: vitbur <vittorioburani at gmail.com>
Date: Wed, 1 Apr 2026 11:02:44 +0200
Subject: [PATCH 05/10] [Clang][RISCV] Add Clang builtins for `XCVbitmanip`
extension
- `BuiltinsRISCVXCV.td`: add all bitmanip attributes
- `SemaRISCV.cpp`: add range checks
- `RISCV.cpp`: add dispatch cases
- `CIRGenBuiltinRISCV.cpp`: add NYI cases
- add `riscv_corev_bitmanip.h` header + `CMakeLists.txt` addition
---
clang/include/clang/Basic/BuiltinsRISCVXCV.td | 13 ++
clang/lib/CIR/CodeGen/CIRGenBuiltinRISCV.cpp | 8 ++
clang/lib/CodeGen/TargetBuiltins/RISCV.cpp | 23 ++++
clang/lib/Headers/CMakeLists.txt | 1 +
clang/lib/Headers/riscv_corev_bitmanip.h | 117 ++++++++++++++++++
clang/lib/Sema/SemaRISCV.cpp | 5 +
6 files changed, 167 insertions(+)
create mode 100644 clang/lib/Headers/riscv_corev_bitmanip.h
diff --git a/clang/include/clang/Basic/BuiltinsRISCVXCV.td b/clang/include/clang/Basic/BuiltinsRISCVXCV.td
index eb0bb58e4814d..31b4788345096 100644
--- a/clang/include/clang/Basic/BuiltinsRISCVXCV.td
+++ b/clang/include/clang/Basic/BuiltinsRISCVXCV.td
@@ -40,6 +40,19 @@ def alu_subRN : RISCVXCVBuiltin<"int(int, int, unsigned int)", "xcvalu">;
def alu_subuRN : RISCVXCVBuiltin<"unsigned int(unsigned int, unsigned int, unsigned int)", "xcvalu">;
} // Attributes = [NoThrow, Const]
+//===----------------------------------------------------------------------===//
+// XCVbitmanip extension.
+//===----------------------------------------------------------------------===//
+let Attributes = [NoThrow, Const] in {
+def bitmanip_extract : RISCVXCVBuiltin<"int(unsigned int, unsigned int)", "xcvbitmanip">;
+def bitmanip_extractu : RISCVXCVBuiltin<"unsigned int(unsigned int, unsigned int)", "xcvbitmanip">;
+def bitmanip_bclr : RISCVXCVBuiltin<"unsigned int(unsigned int, unsigned int)", "xcvbitmanip">;
+def bitmanip_bset : RISCVXCVBuiltin<"unsigned int(unsigned int, unsigned int)", "xcvbitmanip">;
+def bitmanip_insert : RISCVXCVBuiltin<"unsigned int(unsigned int, unsigned int, unsigned int)", "xcvbitmanip">;
+def bitmanip_clb : RISCVXCVBuiltin<"unsigned int(unsigned int)", "xcvbitmanip">;
+def bitmanip_bitrev : RISCVXCVBuiltin<"unsigned int(unsigned int, _Constant unsigned int, _Constant unsigned int)", "xcvbitmanip">;
+} // Attributes = [NoThrow, Const]
+
//===----------------------------------------------------------------------===//
// XCVelw extension.
//===----------------------------------------------------------------------===//
diff --git a/clang/lib/CIR/CodeGen/CIRGenBuiltinRISCV.cpp b/clang/lib/CIR/CodeGen/CIRGenBuiltinRISCV.cpp
index 23c497acb2447..47ec19193b322 100644
--- a/clang/lib/CIR/CodeGen/CIRGenBuiltinRISCV.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenBuiltinRISCV.cpp
@@ -184,6 +184,14 @@ CIRGenFunction::emitRISCVBuiltinExpr(unsigned builtinID, const CallExpr *e) {
case RISCV::BI__builtin_riscv_cv_alu_subRN:
case RISCV::BI__builtin_riscv_cv_alu_subuN:
case RISCV::BI__builtin_riscv_cv_alu_subuRN:
+ // XCVbitmanip
+ case RISCV::BI__builtin_riscv_cv_bitmanip_extract:
+ case RISCV::BI__builtin_riscv_cv_bitmanip_extractu:
+ case RISCV::BI__builtin_riscv_cv_bitmanip_bclr:
+ case RISCV::BI__builtin_riscv_cv_bitmanip_bset:
+ case RISCV::BI__builtin_riscv_cv_bitmanip_insert:
+ case RISCV::BI__builtin_riscv_cv_bitmanip_clb:
+ case RISCV::BI__builtin_riscv_cv_bitmanip_bitrev:
// XCVelw
case RISCV::BI__builtin_riscv_cv_elw_elw:
// XCVmac
diff --git a/clang/lib/CodeGen/TargetBuiltins/RISCV.cpp b/clang/lib/CodeGen/TargetBuiltins/RISCV.cpp
index 1338eda9f876b..5fde76c4ce3d4 100644
--- a/clang/lib/CodeGen/TargetBuiltins/RISCV.cpp
+++ b/clang/lib/CodeGen/TargetBuiltins/RISCV.cpp
@@ -1433,6 +1433,29 @@ Value *CodeGenFunction::EmitRISCVBuiltinExpr(unsigned BuiltinID,
ID = Intrinsic::riscv_cv_alu_subuRN;
break;
+ // XCVbitmanip
+ case RISCV::BI__builtin_riscv_cv_bitmanip_extract:
+ ID = Intrinsic::riscv_cv_bitmanip_extract;
+ break;
+ case RISCV::BI__builtin_riscv_cv_bitmanip_extractu:
+ ID = Intrinsic::riscv_cv_bitmanip_extractu;
+ break;
+ case RISCV::BI__builtin_riscv_cv_bitmanip_bclr:
+ ID = Intrinsic::riscv_cv_bitmanip_bclr;
+ break;
+ case RISCV::BI__builtin_riscv_cv_bitmanip_bset:
+ ID = Intrinsic::riscv_cv_bitmanip_bset;
+ break;
+ case RISCV::BI__builtin_riscv_cv_bitmanip_insert:
+ ID = Intrinsic::riscv_cv_bitmanip_insert;
+ break;
+ case RISCV::BI__builtin_riscv_cv_bitmanip_clb:
+ ID = Intrinsic::riscv_cv_bitmanip_clb;
+ break;
+ case RISCV::BI__builtin_riscv_cv_bitmanip_bitrev:
+ ID = Intrinsic::riscv_cv_bitmanip_bitrev;
+ break;
+
// XCVelw
case RISCV::BI__builtin_riscv_cv_elw_elw: {
// cv.elw rd, imm(rs1) — load word with event wait
diff --git a/clang/lib/Headers/CMakeLists.txt b/clang/lib/Headers/CMakeLists.txt
index b314bfdffea45..6216151fb060f 100644
--- a/clang/lib/Headers/CMakeLists.txt
+++ b/clang/lib/Headers/CMakeLists.txt
@@ -138,6 +138,7 @@ set(riscv_files
# Vendor headers
andes_vector.h
riscv_corev_alu.h
+ riscv_corev_bitmanip.h
riscv_corev_elw.h
riscv_corev_mac.h
riscv_corev_simd.h
diff --git a/clang/lib/Headers/riscv_corev_bitmanip.h b/clang/lib/Headers/riscv_corev_bitmanip.h
new file mode 100644
index 0000000000000..7676e44df87bd
--- /dev/null
+++ b/clang/lib/Headers/riscv_corev_bitmanip.h
@@ -0,0 +1,117 @@
+/*===---- riscv_corev_bitmanip.h - CORE-V bit-manipulation intrinsics ------===
+ *
+ * Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+ * See https://llvm.org/LICENSE.txt for license information.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ *
+ *===-----------------------------------------------------------------------===
+ *
+ * This header provides C intrinsics for the CORE-V XCVbitmanip ISA extension.
+ * Include this header when compiling with -march=..._xcvbitmanip.
+ *
+ * Spec: https://github.com/openhwgroup/cv32e40p/blob/master/docs/source/
+ * instruction_set_extensions.rst (Bit Manipulation section)
+ *
+ *===-----------------------------------------------------------------------===
+ */
+
+#ifndef __RISCV_COREV_BITMANIP_H
+#define __RISCV_COREV_BITMANIP_H
+
+#include <stdint.h>
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+#if defined(__riscv_xcvbitmanip)
+
+#define __DEFAULT_FN_ATTRS \
+ __attribute__((__always_inline__, __nodebug__, __artificial__))
+
+/* ---------------------------------------------------------------------------
+ * cv.extract rd, rs1, IS3, IS2
+ * rd = SignExtend(rs1[IS3+IS2-1 : IS2], 32)
+ * IS3 = bit-width (uimm5), IS2 = lower bit index (uimm5)
+ * The two immediates are packed as a single uimm10: IS3<<5 | IS2
+ * IMM must be a compile-time constant.
+ * --------------------------------------------------------------------------- */
+#define __riscv_cv_bitmanip_extract(__rs1, __IMM) \
+ ((int32_t)__builtin_riscv_cv_bitmanip_extract((uint32_t)(__rs1), \
+ (uint32_t)(__IMM)))
+
+/* ---------------------------------------------------------------------------
+ * cv.extractu rd, rs1, IS3, IS2
+ * rd = ZeroExtend(rs1[IS3+IS2-1 : IS2], 32)
+ * --------------------------------------------------------------------------- */
+#define __riscv_cv_bitmanip_extractu(__rs1, __IMM) \
+ ((uint32_t)__builtin_riscv_cv_bitmanip_extractu((uint32_t)(__rs1), \
+ (uint32_t)(__IMM)))
+
+/* ---------------------------------------------------------------------------
+ * cv.bclr rd, rs1, IS3, IS2
+ * rd = rs1 & ~(((1 << IS3) - 1) << IS2) (clear IS3 bits starting at IS2)
+ * --------------------------------------------------------------------------- */
+#define __riscv_cv_bitmanip_bclr(__rs1, __IMM) \
+ ((uint32_t)__builtin_riscv_cv_bitmanip_bclr((uint32_t)(__rs1), \
+ (uint32_t)(__IMM)))
+
+/* ---------------------------------------------------------------------------
+ * cv.bset rd, rs1, IS3, IS2
+ * rd = rs1 | (((1 << IS3) - 1) << IS2) (set IS3 bits starting at IS2)
+ * --------------------------------------------------------------------------- */
+#define __riscv_cv_bitmanip_bset(__rs1, __IMM) \
+ ((uint32_t)__builtin_riscv_cv_bitmanip_bset((uint32_t)(__rs1), \
+ (uint32_t)(__IMM)))
+
+/* ---------------------------------------------------------------------------
+ * cv.insert rd, rs1, IS3, IS2
+ * rd[IS3+IS2-1 : IS2] = rs1[IS3-1 : 0]
+ * rd is read-modify-write (the bits outside the target range are preserved).
+ * IS3 = bit-width (uimm5), IS2 = lower bit index (uimm5)
+ * The two immediates are packed as a single uimm10: IS3<<5 | IS2
+ * --------------------------------------------------------------------------- */
+#define __riscv_cv_bitmanip_insert(__rD, __rs1, __IMM) \
+ ((uint32_t)__builtin_riscv_cv_bitmanip_insert((uint32_t)(__rs1), \
+ (uint32_t)(__IMM), \
+ (uint32_t)(__rD)))
+
+/* ---------------------------------------------------------------------------
+ * cv.clb rd, rs1
+ * rd = number of consecutive leading bits equal to the sign bit (after the
+ * sign bit itself), i.e. count leading bits equal to bit 31.
+ * Equivalent to max(0, clz(rs1) + clz(~rs1) - 1).
+ *
+ * Note: ff1 (find-first-one from LSB), fl1 (find-last-one from LSB), cnt
+ * (popcount) and ror (rotate-right) are intentionally absent from this header.
+ * The compiler automatically selects cv.ff1 / cv.fl1 / cv.cnt / cv.ror from
+ * standard C expressions (__builtin_ctz, __builtin_clz, __builtin_popcount,
+ * rotate patterns) when -march includes xcvbitmanip. No explicit builtin call
+ * is required or provided for those four operations.
+ * --------------------------------------------------------------------------- */
+static __inline__ uint32_t __DEFAULT_FN_ATTRS
+__riscv_cv_bitmanip_clb(uint32_t a) {
+ return __builtin_riscv_cv_bitmanip_clb(a);
+}
+
+/* ---------------------------------------------------------------------------
+ * cv.bitrev rd, rs1, IS2, IS3
+ * Reverses groups of (2^IS2) bits within each (IS3+1)-bit segment of rs1.
+ * IS2 = radix (uimm2, 0..3), IS3 = number of significant bits minus 1 (uimm5)
+ * Both IS2 and IS3 must be compile-time constants.
+ *
+ * Example: cv.bitrev t0, t0, 2, 23 reverses groups of 4 bits within each
+ * 24-bit window.
+ * --------------------------------------------------------------------------- */
+#define __riscv_cv_bitmanip_bitrev(__rs1, __IS2, __IS3) \
+ ((uint32_t)__builtin_riscv_cv_bitmanip_bitrev((uint32_t)(__rs1), \
+ (uint32_t)(__IS2), \
+ (uint32_t)(__IS3)))
+
+#endif /* __riscv_xcvbitmanip */
+
+#if defined(__cplusplus)
+}
+#endif
+
+#endif /* __RISCV_COREV_BITMANIP_H */
diff --git a/clang/lib/Sema/SemaRISCV.cpp b/clang/lib/Sema/SemaRISCV.cpp
index 480fbff686f7a..0af3053ff3db9 100644
--- a/clang/lib/Sema/SemaRISCV.cpp
+++ b/clang/lib/Sema/SemaRISCV.cpp
@@ -653,6 +653,11 @@ bool SemaRISCV::CheckBuiltinFunctionCall(const TargetInfo &TI,
break;
}
+ // XCVbitmanip — bitrev: IS2 (radix) in [0,3], IS3 (pts) in [0,31]
+ case RISCV::BI__builtin_riscv_cv_bitmanip_bitrev:
+ return SemaRef.BuiltinConstantArgRange(TheCall, 1, 0, 3) ||
+ SemaRef.BuiltinConstantArgRange(TheCall, 2, 0, 31);
+
// XCVmac — shift amount in [0, 31]
case RISCV::BI__builtin_riscv_cv_mac_muluN:
case RISCV::BI__builtin_riscv_cv_mac_mulhhuN:
>From 3fad9ce51b4f100688b9c3403755374f0f7ffc6a Mon Sep 17 00:00:00 2001
From: vitbur <vittorioburani at gmail.com>
Date: Tue, 7 Apr 2026 18:45:18 +0200
Subject: [PATCH 06/10] [Clang][RISCV] Add tests for `XCVelw` builtins
- add `rvv-xcvelw-builtins.c`
---
.../test/CodeGen/RISCV/rvv-xcvelw-builtins.c | 20 +++++++++++++++++++
1 file changed, 20 insertions(+)
create mode 100644 clang/test/CodeGen/RISCV/rvv-xcvelw-builtins.c
diff --git a/clang/test/CodeGen/RISCV/rvv-xcvelw-builtins.c b/clang/test/CodeGen/RISCV/rvv-xcvelw-builtins.c
new file mode 100644
index 0000000000000..0eb41ec3261e4
--- /dev/null
+++ b/clang/test/CodeGen/RISCV/rvv-xcvelw-builtins.c
@@ -0,0 +1,20 @@
+// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py
+// RUN: %clang_cc1 -triple riscv32 -target-feature +xcvelw -emit-llvm %s -o - \
+// RUN: | FileCheck %s
+
+// This file tests that the XCVelw Clang builtin is correctly lowered
+// to its corresponding LLVM IR intrinsic.
+
+#include <stdint.h>
+
+// CHECK-LABEL: @test_elw(
+// CHECK-NEXT: entry:
+// CHECK-NEXT: [[ADDR_ADDR:%.*]] = alloca ptr, align 4
+// CHECK-NEXT: store ptr [[ADDR:%.*]], ptr [[ADDR_ADDR]], align 4
+// CHECK-NEXT: [[TMP0:%.*]] = load ptr, ptr [[ADDR_ADDR]], align 4
+// CHECK-NEXT: [[TMP1:%.*]] = call i32 @llvm.riscv.cv.elw.elw(ptr [[TMP0]])
+// CHECK-NEXT: ret i32 [[TMP1]]
+//
+int32_t test_elw(int32_t *addr) {
+ return __builtin_riscv_cv_elw_elw(addr);
+}
>From df4d6dba06f7b676c506ba0190dd145607fff0d5 Mon Sep 17 00:00:00 2001
From: vitbur <vittorioburani at gmail.com>
Date: Tue, 7 Apr 2026 18:46:56 +0200
Subject: [PATCH 07/10] [Clang][RISCV] Add tests for `XCVmac` builtins
- add `rvv-xcvmac-builtins.c`
- add Sema tests for XCVmac in `rvv-xcv-sema.c`
---
.../test/CodeGen/RISCV/rvv-xcvmac-builtins.c | 318 ++++++++++++++++++
clang/test/Sema/rvv-xcv-sema.c | 17 +
2 files changed, 335 insertions(+)
create mode 100644 clang/test/CodeGen/RISCV/rvv-xcvmac-builtins.c
create mode 100644 clang/test/Sema/rvv-xcv-sema.c
diff --git a/clang/test/CodeGen/RISCV/rvv-xcvmac-builtins.c b/clang/test/CodeGen/RISCV/rvv-xcvmac-builtins.c
new file mode 100644
index 0000000000000..84d7d9c02c5a2
--- /dev/null
+++ b/clang/test/CodeGen/RISCV/rvv-xcvmac-builtins.c
@@ -0,0 +1,318 @@
+// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py
+// RUN: %clang_cc1 -triple riscv32 -target-feature +xcvmac -emit-llvm %s -o - \
+// RUN: | FileCheck %s
+
+// This file tests that XCVmac Clang builtins are correctly lowered
+// to their corresponding LLVM IR intrinsics.
+
+#include <stdint.h>
+
+// ---- 32x32 MAC/MSU ----
+
+// CHECK-LABEL: @test_mac(
+// CHECK-NEXT: entry:
+// CHECK-NEXT: [[A_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT: [[B_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT: [[ACC_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT: store i32 [[A:%.*]], ptr [[A_ADDR]], align 4
+// CHECK-NEXT: store i32 [[B:%.*]], ptr [[B_ADDR]], align 4
+// CHECK-NEXT: store i32 [[ACC:%.*]], ptr [[ACC_ADDR]], align 4
+// CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[A_ADDR]], align 4
+// CHECK-NEXT: [[TMP1:%.*]] = load i32, ptr [[B_ADDR]], align 4
+// CHECK-NEXT: [[TMP2:%.*]] = load i32, ptr [[ACC_ADDR]], align 4
+// CHECK-NEXT: [[TMP3:%.*]] = call i32 @llvm.riscv.cv.mac.mac(i32 [[TMP0]], i32 [[TMP1]], i32 [[TMP2]])
+// CHECK-NEXT: ret i32 [[TMP3]]
+//
+int32_t test_mac(int32_t a, int32_t b, int32_t acc) {
+ return __builtin_riscv_cv_mac_mac(a, b, acc);
+}
+
+// CHECK-LABEL: @test_msu(
+// CHECK-NEXT: entry:
+// CHECK-NEXT: [[A_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT: [[B_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT: [[ACC_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT: store i32 [[A:%.*]], ptr [[A_ADDR]], align 4
+// CHECK-NEXT: store i32 [[B:%.*]], ptr [[B_ADDR]], align 4
+// CHECK-NEXT: store i32 [[ACC:%.*]], ptr [[ACC_ADDR]], align 4
+// CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[A_ADDR]], align 4
+// CHECK-NEXT: [[TMP1:%.*]] = load i32, ptr [[B_ADDR]], align 4
+// CHECK-NEXT: [[TMP2:%.*]] = load i32, ptr [[ACC_ADDR]], align 4
+// CHECK-NEXT: [[TMP3:%.*]] = call i32 @llvm.riscv.cv.mac.msu(i32 [[TMP0]], i32 [[TMP1]], i32 [[TMP2]])
+// CHECK-NEXT: ret i32 [[TMP3]]
+//
+int32_t test_msu(int32_t a, int32_t b, int32_t acc) {
+ return __builtin_riscv_cv_mac_msu(a, b, acc);
+}
+
+// ---- Unsigned 16x16 multiply with shift ----
+
+// CHECK-LABEL: @test_muluN(
+// CHECK-NEXT: entry:
+// CHECK-NEXT: [[A_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT: [[B_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT: store i32 [[A:%.*]], ptr [[A_ADDR]], align 4
+// CHECK-NEXT: store i32 [[B:%.*]], ptr [[B_ADDR]], align 4
+// CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[A_ADDR]], align 4
+// CHECK-NEXT: [[TMP1:%.*]] = load i32, ptr [[B_ADDR]], align 4
+// CHECK-NEXT: [[TMP2:%.*]] = call i32 @llvm.riscv.cv.mac.muluN(i32 [[TMP0]], i32 [[TMP1]], i32 5)
+// CHECK-NEXT: ret i32 [[TMP2]]
+//
+uint32_t test_muluN(uint32_t a, uint32_t b) {
+ return __builtin_riscv_cv_mac_muluN(a, b, 5);
+}
+
+// CHECK-LABEL: @test_mulhhuN(
+// CHECK-NEXT: entry:
+// CHECK-NEXT: [[A_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT: [[B_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT: store i32 [[A:%.*]], ptr [[A_ADDR]], align 4
+// CHECK-NEXT: store i32 [[B:%.*]], ptr [[B_ADDR]], align 4
+// CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[A_ADDR]], align 4
+// CHECK-NEXT: [[TMP1:%.*]] = load i32, ptr [[B_ADDR]], align 4
+// CHECK-NEXT: [[TMP2:%.*]] = call i32 @llvm.riscv.cv.mac.mulhhuN(i32 [[TMP0]], i32 [[TMP1]], i32 5)
+// CHECK-NEXT: ret i32 [[TMP2]]
+//
+uint32_t test_mulhhuN(uint32_t a, uint32_t b) {
+ return __builtin_riscv_cv_mac_mulhhuN(a, b, 5);
+}
+
+// CHECK-LABEL: @test_muluRN(
+// CHECK-NEXT: entry:
+// CHECK-NEXT: [[A_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT: [[B_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT: store i32 [[A:%.*]], ptr [[A_ADDR]], align 4
+// CHECK-NEXT: store i32 [[B:%.*]], ptr [[B_ADDR]], align 4
+// CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[A_ADDR]], align 4
+// CHECK-NEXT: [[TMP1:%.*]] = load i32, ptr [[B_ADDR]], align 4
+// CHECK-NEXT: [[TMP2:%.*]] = call i32 @llvm.riscv.cv.mac.muluRN(i32 [[TMP0]], i32 [[TMP1]], i32 5)
+// CHECK-NEXT: ret i32 [[TMP2]]
+//
+uint32_t test_muluRN(uint32_t a, uint32_t b) {
+ return __builtin_riscv_cv_mac_muluRN(a, b, 5);
+}
+
+// CHECK-LABEL: @test_mulhhuRN(
+// CHECK-NEXT: entry:
+// CHECK-NEXT: [[A_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT: [[B_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT: store i32 [[A:%.*]], ptr [[A_ADDR]], align 4
+// CHECK-NEXT: store i32 [[B:%.*]], ptr [[B_ADDR]], align 4
+// CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[A_ADDR]], align 4
+// CHECK-NEXT: [[TMP1:%.*]] = load i32, ptr [[B_ADDR]], align 4
+// CHECK-NEXT: [[TMP2:%.*]] = call i32 @llvm.riscv.cv.mac.mulhhuRN(i32 [[TMP0]], i32 [[TMP1]], i32 5)
+// CHECK-NEXT: ret i32 [[TMP2]]
+//
+uint32_t test_mulhhuRN(uint32_t a, uint32_t b) {
+ return __builtin_riscv_cv_mac_mulhhuRN(a, b, 5);
+}
+
+// ---- Signed 16x16 multiply with shift ----
+
+// CHECK-LABEL: @test_mulsN(
+// CHECK-NEXT: entry:
+// CHECK-NEXT: [[A_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT: [[B_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT: store i32 [[A:%.*]], ptr [[A_ADDR]], align 4
+// CHECK-NEXT: store i32 [[B:%.*]], ptr [[B_ADDR]], align 4
+// CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[A_ADDR]], align 4
+// CHECK-NEXT: [[TMP1:%.*]] = load i32, ptr [[B_ADDR]], align 4
+// CHECK-NEXT: [[TMP2:%.*]] = call i32 @llvm.riscv.cv.mac.mulsN(i32 [[TMP0]], i32 [[TMP1]], i32 5)
+// CHECK-NEXT: ret i32 [[TMP2]]
+//
+int32_t test_mulsN(uint32_t a, uint32_t b) {
+ return __builtin_riscv_cv_mac_mulsN(a, b, 5);
+}
+
+// CHECK-LABEL: @test_mulhhsN(
+// CHECK-NEXT: entry:
+// CHECK-NEXT: [[A_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT: [[B_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT: store i32 [[A:%.*]], ptr [[A_ADDR]], align 4
+// CHECK-NEXT: store i32 [[B:%.*]], ptr [[B_ADDR]], align 4
+// CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[A_ADDR]], align 4
+// CHECK-NEXT: [[TMP1:%.*]] = load i32, ptr [[B_ADDR]], align 4
+// CHECK-NEXT: [[TMP2:%.*]] = call i32 @llvm.riscv.cv.mac.mulhhsN(i32 [[TMP0]], i32 [[TMP1]], i32 5)
+// CHECK-NEXT: ret i32 [[TMP2]]
+//
+int32_t test_mulhhsN(uint32_t a, uint32_t b) {
+ return __builtin_riscv_cv_mac_mulhhsN(a, b, 5);
+}
+
+// CHECK-LABEL: @test_mulsRN(
+// CHECK-NEXT: entry:
+// CHECK-NEXT: [[A_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT: [[B_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT: store i32 [[A:%.*]], ptr [[A_ADDR]], align 4
+// CHECK-NEXT: store i32 [[B:%.*]], ptr [[B_ADDR]], align 4
+// CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[A_ADDR]], align 4
+// CHECK-NEXT: [[TMP1:%.*]] = load i32, ptr [[B_ADDR]], align 4
+// CHECK-NEXT: [[TMP2:%.*]] = call i32 @llvm.riscv.cv.mac.mulsRN(i32 [[TMP0]], i32 [[TMP1]], i32 5)
+// CHECK-NEXT: ret i32 [[TMP2]]
+//
+int32_t test_mulsRN(uint32_t a, uint32_t b) {
+ return __builtin_riscv_cv_mac_mulsRN(a, b, 5);
+}
+
+// CHECK-LABEL: @test_mulhhsRN(
+// CHECK-NEXT: entry:
+// CHECK-NEXT: [[A_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT: [[B_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT: store i32 [[A:%.*]], ptr [[A_ADDR]], align 4
+// CHECK-NEXT: store i32 [[B:%.*]], ptr [[B_ADDR]], align 4
+// CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[A_ADDR]], align 4
+// CHECK-NEXT: [[TMP1:%.*]] = load i32, ptr [[B_ADDR]], align 4
+// CHECK-NEXT: [[TMP2:%.*]] = call i32 @llvm.riscv.cv.mac.mulhhsRN(i32 [[TMP0]], i32 [[TMP1]], i32 5)
+// CHECK-NEXT: ret i32 [[TMP2]]
+//
+int32_t test_mulhhsRN(uint32_t a, uint32_t b) {
+ return __builtin_riscv_cv_mac_mulhhsRN(a, b, 5);
+}
+
+// ---- Unsigned 16x16 MAC with shift ----
+
+// CHECK-LABEL: @test_macuN(
+// CHECK-NEXT: entry:
+// CHECK-NEXT: [[A_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT: [[B_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT: [[ACC_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT: store i32 [[A:%.*]], ptr [[A_ADDR]], align 4
+// CHECK-NEXT: store i32 [[B:%.*]], ptr [[B_ADDR]], align 4
+// CHECK-NEXT: store i32 [[ACC:%.*]], ptr [[ACC_ADDR]], align 4
+// CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[A_ADDR]], align 4
+// CHECK-NEXT: [[TMP1:%.*]] = load i32, ptr [[B_ADDR]], align 4
+// CHECK-NEXT: [[TMP2:%.*]] = load i32, ptr [[ACC_ADDR]], align 4
+// CHECK-NEXT: [[TMP3:%.*]] = call i32 @llvm.riscv.cv.mac.macuN(i32 [[TMP0]], i32 [[TMP1]], i32 [[TMP2]], i32 5)
+// CHECK-NEXT: ret i32 [[TMP3]]
+//
+uint32_t test_macuN(uint32_t a, uint32_t b, uint32_t acc) {
+ return __builtin_riscv_cv_mac_macuN(a, b, acc, 5);
+}
+
+// CHECK-LABEL: @test_machhuN(
+// CHECK-NEXT: entry:
+// CHECK-NEXT: [[A_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT: [[B_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT: [[ACC_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT: store i32 [[A:%.*]], ptr [[A_ADDR]], align 4
+// CHECK-NEXT: store i32 [[B:%.*]], ptr [[B_ADDR]], align 4
+// CHECK-NEXT: store i32 [[ACC:%.*]], ptr [[ACC_ADDR]], align 4
+// CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[A_ADDR]], align 4
+// CHECK-NEXT: [[TMP1:%.*]] = load i32, ptr [[B_ADDR]], align 4
+// CHECK-NEXT: [[TMP2:%.*]] = load i32, ptr [[ACC_ADDR]], align 4
+// CHECK-NEXT: [[TMP3:%.*]] = call i32 @llvm.riscv.cv.mac.machhuN(i32 [[TMP0]], i32 [[TMP1]], i32 [[TMP2]], i32 5)
+// CHECK-NEXT: ret i32 [[TMP3]]
+//
+uint32_t test_machhuN(uint32_t a, uint32_t b, uint32_t acc) {
+ return __builtin_riscv_cv_mac_machhuN(a, b, acc, 5);
+}
+
+// CHECK-LABEL: @test_macuRN(
+// CHECK-NEXT: entry:
+// CHECK-NEXT: [[A_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT: [[B_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT: [[ACC_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT: store i32 [[A:%.*]], ptr [[A_ADDR]], align 4
+// CHECK-NEXT: store i32 [[B:%.*]], ptr [[B_ADDR]], align 4
+// CHECK-NEXT: store i32 [[ACC:%.*]], ptr [[ACC_ADDR]], align 4
+// CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[A_ADDR]], align 4
+// CHECK-NEXT: [[TMP1:%.*]] = load i32, ptr [[B_ADDR]], align 4
+// CHECK-NEXT: [[TMP2:%.*]] = load i32, ptr [[ACC_ADDR]], align 4
+// CHECK-NEXT: [[TMP3:%.*]] = call i32 @llvm.riscv.cv.mac.macuRN(i32 [[TMP0]], i32 [[TMP1]], i32 [[TMP2]], i32 5)
+// CHECK-NEXT: ret i32 [[TMP3]]
+//
+uint32_t test_macuRN(uint32_t a, uint32_t b, uint32_t acc) {
+ return __builtin_riscv_cv_mac_macuRN(a, b, acc, 5);
+}
+
+// CHECK-LABEL: @test_machhuRN(
+// CHECK-NEXT: entry:
+// CHECK-NEXT: [[A_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT: [[B_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT: [[ACC_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT: store i32 [[A:%.*]], ptr [[A_ADDR]], align 4
+// CHECK-NEXT: store i32 [[B:%.*]], ptr [[B_ADDR]], align 4
+// CHECK-NEXT: store i32 [[ACC:%.*]], ptr [[ACC_ADDR]], align 4
+// CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[A_ADDR]], align 4
+// CHECK-NEXT: [[TMP1:%.*]] = load i32, ptr [[B_ADDR]], align 4
+// CHECK-NEXT: [[TMP2:%.*]] = load i32, ptr [[ACC_ADDR]], align 4
+// CHECK-NEXT: [[TMP3:%.*]] = call i32 @llvm.riscv.cv.mac.machhuRN(i32 [[TMP0]], i32 [[TMP1]], i32 [[TMP2]], i32 5)
+// CHECK-NEXT: ret i32 [[TMP3]]
+//
+uint32_t test_machhuRN(uint32_t a, uint32_t b, uint32_t acc) {
+ return __builtin_riscv_cv_mac_machhuRN(a, b, acc, 5);
+}
+
+// ---- Signed 16x16 MAC with shift ----
+
+// CHECK-LABEL: @test_macsN(
+// CHECK-NEXT: entry:
+// CHECK-NEXT: [[A_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT: [[B_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT: [[ACC_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT: store i32 [[A:%.*]], ptr [[A_ADDR]], align 4
+// CHECK-NEXT: store i32 [[B:%.*]], ptr [[B_ADDR]], align 4
+// CHECK-NEXT: store i32 [[ACC:%.*]], ptr [[ACC_ADDR]], align 4
+// CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[A_ADDR]], align 4
+// CHECK-NEXT: [[TMP1:%.*]] = load i32, ptr [[B_ADDR]], align 4
+// CHECK-NEXT: [[TMP2:%.*]] = load i32, ptr [[ACC_ADDR]], align 4
+// CHECK-NEXT: [[TMP3:%.*]] = call i32 @llvm.riscv.cv.mac.macsN(i32 [[TMP0]], i32 [[TMP1]], i32 [[TMP2]], i32 5)
+// CHECK-NEXT: ret i32 [[TMP3]]
+//
+int32_t test_macsN(uint32_t a, uint32_t b, uint32_t acc) {
+ return __builtin_riscv_cv_mac_macsN(a, b, acc, 5);
+}
+
+// CHECK-LABEL: @test_machhsN(
+// CHECK-NEXT: entry:
+// CHECK-NEXT: [[A_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT: [[B_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT: [[ACC_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT: store i32 [[A:%.*]], ptr [[A_ADDR]], align 4
+// CHECK-NEXT: store i32 [[B:%.*]], ptr [[B_ADDR]], align 4
+// CHECK-NEXT: store i32 [[ACC:%.*]], ptr [[ACC_ADDR]], align 4
+// CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[A_ADDR]], align 4
+// CHECK-NEXT: [[TMP1:%.*]] = load i32, ptr [[B_ADDR]], align 4
+// CHECK-NEXT: [[TMP2:%.*]] = load i32, ptr [[ACC_ADDR]], align 4
+// CHECK-NEXT: [[TMP3:%.*]] = call i32 @llvm.riscv.cv.mac.machhsN(i32 [[TMP0]], i32 [[TMP1]], i32 [[TMP2]], i32 5)
+// CHECK-NEXT: ret i32 [[TMP3]]
+//
+int32_t test_machhsN(uint32_t a, uint32_t b, uint32_t acc) {
+ return __builtin_riscv_cv_mac_machhsN(a, b, acc, 5);
+}
+
+// CHECK-LABEL: @test_macsRN(
+// CHECK-NEXT: entry:
+// CHECK-NEXT: [[A_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT: [[B_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT: [[ACC_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT: store i32 [[A:%.*]], ptr [[A_ADDR]], align 4
+// CHECK-NEXT: store i32 [[B:%.*]], ptr [[B_ADDR]], align 4
+// CHECK-NEXT: store i32 [[ACC:%.*]], ptr [[ACC_ADDR]], align 4
+// CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[A_ADDR]], align 4
+// CHECK-NEXT: [[TMP1:%.*]] = load i32, ptr [[B_ADDR]], align 4
+// CHECK-NEXT: [[TMP2:%.*]] = load i32, ptr [[ACC_ADDR]], align 4
+// CHECK-NEXT: [[TMP3:%.*]] = call i32 @llvm.riscv.cv.mac.macsRN(i32 [[TMP0]], i32 [[TMP1]], i32 [[TMP2]], i32 5)
+// CHECK-NEXT: ret i32 [[TMP3]]
+//
+int32_t test_macsRN(uint32_t a, uint32_t b, uint32_t acc) {
+ return __builtin_riscv_cv_mac_macsRN(a, b, acc, 5);
+}
+
+// CHECK-LABEL: @test_machhsRN(
+// CHECK-NEXT: entry:
+// CHECK-NEXT: [[A_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT: [[B_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT: [[ACC_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT: store i32 [[A:%.*]], ptr [[A_ADDR]], align 4
+// CHECK-NEXT: store i32 [[B:%.*]], ptr [[B_ADDR]], align 4
+// CHECK-NEXT: store i32 [[ACC:%.*]], ptr [[ACC_ADDR]], align 4
+// CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[A_ADDR]], align 4
+// CHECK-NEXT: [[TMP1:%.*]] = load i32, ptr [[B_ADDR]], align 4
+// CHECK-NEXT: [[TMP2:%.*]] = load i32, ptr [[ACC_ADDR]], align 4
+// CHECK-NEXT: [[TMP3:%.*]] = call i32 @llvm.riscv.cv.mac.machhsRN(i32 [[TMP0]], i32 [[TMP1]], i32 [[TMP2]], i32 5)
+// CHECK-NEXT: ret i32 [[TMP3]]
+//
+int32_t test_machhsRN(uint32_t a, uint32_t b, uint32_t acc) {
+ return __builtin_riscv_cv_mac_machhsRN(a, b, acc, 5);
+}
diff --git a/clang/test/Sema/rvv-xcv-sema.c b/clang/test/Sema/rvv-xcv-sema.c
new file mode 100644
index 0000000000000..681e6c7c385dd
--- /dev/null
+++ b/clang/test/Sema/rvv-xcv-sema.c
@@ -0,0 +1,17 @@
+// RUN: %clang_cc1 -triple riscv32 -target-feature +xcvmac -target-feature +xcvsimd \
+// RUN: -target-feature +xcvbitmanip -fsyntax-only -verify %s
+
+// This file tests that Sema range checks correctly reject out-of-range
+// immediate arguments for XCV builtins.
+
+#include <stdint.h>
+
+// ===== XCVmac — shift must be in [0, 31] =====
+
+void test_mac_range(uint32_t a, uint32_t b, uint32_t c) {
+ (void)__builtin_riscv_cv_mac_muluN(a, b, 31); // OK: max value
+ (void)__builtin_riscv_cv_mac_muluN(a, b, 32); // expected-error {{argument value 32 is outside the valid range [0, 31]}}
+ (void)__builtin_riscv_cv_mac_mulsN(a, b, 0); // OK: min value
+ (void)__builtin_riscv_cv_mac_macuN(a, b, c, 31); // OK
+ (void)__builtin_riscv_cv_mac_macuN(a, b, c, 32); // expected-error {{argument value 32 is outside the valid range [0, 31]}}
+}
>From 410e6b40654daf9ae29aec131a072e373c723323 Mon Sep 17 00:00:00 2001
From: vitbur <vittorioburani at gmail.com>
Date: Tue, 7 Apr 2026 18:48:34 +0200
Subject: [PATCH 08/10] [Clang][RISCV] Add tests for `XCVsimd` builtins
- add `rvv-xcvsimd-builtins.c`
- add Sema tests for XCVsimd in `rvv-xcv-sema.c`
---
.../test/CodeGen/RISCV/rvv-xcvsimd-builtins.c | 1219 +++++++++++++++++
clang/test/Sema/rvv-xcv-sema.c | 40 +
2 files changed, 1259 insertions(+)
create mode 100644 clang/test/CodeGen/RISCV/rvv-xcvsimd-builtins.c
diff --git a/clang/test/CodeGen/RISCV/rvv-xcvsimd-builtins.c b/clang/test/CodeGen/RISCV/rvv-xcvsimd-builtins.c
new file mode 100644
index 0000000000000..5e163c81d36d4
--- /dev/null
+++ b/clang/test/CodeGen/RISCV/rvv-xcvsimd-builtins.c
@@ -0,0 +1,1219 @@
+// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py
+// RUN: %clang_cc1 -triple riscv32 -target-feature +xcvsimd -emit-llvm %s -o - \
+// RUN: | FileCheck %s
+
+// This file tests that XCVsimd Clang builtins are correctly lowered
+// to their corresponding LLVM IR intrinsics.
+
+#include <stdint.h>
+
+// ===== ADD / SUB =====
+
+// CHECK-LABEL: @test_add_h(
+// CHECK-NEXT: entry:
+// CHECK-NEXT: [[A_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT: [[B_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT: store i32 [[A:%.*]], ptr [[A_ADDR]], align 4
+// CHECK-NEXT: store i32 [[B:%.*]], ptr [[B_ADDR]], align 4
+// CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[A_ADDR]], align 4
+// CHECK-NEXT: [[TMP1:%.*]] = load i32, ptr [[B_ADDR]], align 4
+// CHECK-NEXT: [[TMP2:%.*]] = call i32 @llvm.riscv.cv.simd.add.h(i32 [[TMP0]], i32 [[TMP1]], i32 0)
+// CHECK-NEXT: ret i32 [[TMP2]]
+//
+uint32_t test_add_h(uint32_t a, uint32_t b) {
+ return __builtin_riscv_cv_simd_add_h(a, b, 0);
+}
+
+// CHECK-LABEL: @test_add_h_div2(
+// CHECK-NEXT: entry:
+// CHECK-NEXT: [[A_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT: [[B_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT: store i32 [[A:%.*]], ptr [[A_ADDR]], align 4
+// CHECK-NEXT: store i32 [[B:%.*]], ptr [[B_ADDR]], align 4
+// CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[A_ADDR]], align 4
+// CHECK-NEXT: [[TMP1:%.*]] = load i32, ptr [[B_ADDR]], align 4
+// CHECK-NEXT: [[TMP2:%.*]] = call i32 @llvm.riscv.cv.simd.add.h(i32 [[TMP0]], i32 [[TMP1]], i32 1)
+// CHECK-NEXT: ret i32 [[TMP2]]
+//
+uint32_t test_add_h_div2(uint32_t a, uint32_t b) {
+ return __builtin_riscv_cv_simd_add_h(a, b, 1);
+}
+
+// CHECK-LABEL: @test_add_b(
+// CHECK-NEXT: entry:
+// CHECK-NEXT: [[A_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT: [[B_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT: store i32 [[A:%.*]], ptr [[A_ADDR]], align 4
+// CHECK-NEXT: store i32 [[B:%.*]], ptr [[B_ADDR]], align 4
+// CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[A_ADDR]], align 4
+// CHECK-NEXT: [[TMP1:%.*]] = load i32, ptr [[B_ADDR]], align 4
+// CHECK-NEXT: [[TMP2:%.*]] = call i32 @llvm.riscv.cv.simd.add.b(i32 [[TMP0]], i32 [[TMP1]])
+// CHECK-NEXT: ret i32 [[TMP2]]
+//
+uint32_t test_add_b(uint32_t a, uint32_t b) {
+ return __builtin_riscv_cv_simd_add_b(a, b);
+}
+
+// CHECK-LABEL: @test_add_sc_h(
+// CHECK-NEXT: entry:
+// CHECK-NEXT: [[A_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT: [[B_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT: store i32 [[A:%.*]], ptr [[A_ADDR]], align 4
+// CHECK-NEXT: store i32 [[B:%.*]], ptr [[B_ADDR]], align 4
+// CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[A_ADDR]], align 4
+// CHECK-NEXT: [[TMP1:%.*]] = load i32, ptr [[B_ADDR]], align 4
+// CHECK-NEXT: [[TMP2:%.*]] = call i32 @llvm.riscv.cv.simd.add.sc.h(i32 [[TMP0]], i32 [[TMP1]])
+// CHECK-NEXT: ret i32 [[TMP2]]
+//
+uint32_t test_add_sc_h(uint32_t a, uint32_t b) {
+ return __builtin_riscv_cv_simd_add_sc_h(a, b);
+}
+
+// CHECK-LABEL: @test_add_sc_b(
+// CHECK-NEXT: entry:
+// CHECK-NEXT: [[A_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT: [[B_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT: store i32 [[A:%.*]], ptr [[A_ADDR]], align 4
+// CHECK-NEXT: store i32 [[B:%.*]], ptr [[B_ADDR]], align 4
+// CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[A_ADDR]], align 4
+// CHECK-NEXT: [[TMP1:%.*]] = load i32, ptr [[B_ADDR]], align 4
+// CHECK-NEXT: [[TMP2:%.*]] = call i32 @llvm.riscv.cv.simd.add.sc.b(i32 [[TMP0]], i32 [[TMP1]])
+// CHECK-NEXT: ret i32 [[TMP2]]
+//
+uint32_t test_add_sc_b(uint32_t a, uint32_t b) {
+ return __builtin_riscv_cv_simd_add_sc_b(a, b);
+}
+
+// CHECK-LABEL: @test_sub_h(
+// CHECK-NEXT: entry:
+// CHECK-NEXT: [[A_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT: [[B_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT: store i32 [[A:%.*]], ptr [[A_ADDR]], align 4
+// CHECK-NEXT: store i32 [[B:%.*]], ptr [[B_ADDR]], align 4
+// CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[A_ADDR]], align 4
+// CHECK-NEXT: [[TMP1:%.*]] = load i32, ptr [[B_ADDR]], align 4
+// CHECK-NEXT: [[TMP2:%.*]] = call i32 @llvm.riscv.cv.simd.sub.h(i32 [[TMP0]], i32 [[TMP1]], i32 0)
+// CHECK-NEXT: ret i32 [[TMP2]]
+//
+uint32_t test_sub_h(uint32_t a, uint32_t b) {
+ return __builtin_riscv_cv_simd_sub_h(a, b, 0);
+}
+
+// CHECK-LABEL: @test_sub_b(
+// CHECK-NEXT: entry:
+// CHECK-NEXT: [[A_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT: [[B_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT: store i32 [[A:%.*]], ptr [[A_ADDR]], align 4
+// CHECK-NEXT: store i32 [[B:%.*]], ptr [[B_ADDR]], align 4
+// CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[A_ADDR]], align 4
+// CHECK-NEXT: [[TMP1:%.*]] = load i32, ptr [[B_ADDR]], align 4
+// CHECK-NEXT: [[TMP2:%.*]] = call i32 @llvm.riscv.cv.simd.sub.b(i32 [[TMP0]], i32 [[TMP1]])
+// CHECK-NEXT: ret i32 [[TMP2]]
+//
+uint32_t test_sub_b(uint32_t a, uint32_t b) {
+ return __builtin_riscv_cv_simd_sub_b(a, b);
+}
+
+// CHECK-LABEL: @test_sub_sc_h(
+// CHECK-NEXT: entry:
+// CHECK-NEXT: [[A_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT: [[B_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT: store i32 [[A:%.*]], ptr [[A_ADDR]], align 4
+// CHECK-NEXT: store i32 [[B:%.*]], ptr [[B_ADDR]], align 4
+// CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[A_ADDR]], align 4
+// CHECK-NEXT: [[TMP1:%.*]] = load i32, ptr [[B_ADDR]], align 4
+// CHECK-NEXT: [[TMP2:%.*]] = call i32 @llvm.riscv.cv.simd.sub.sc.h(i32 [[TMP0]], i32 [[TMP1]])
+// CHECK-NEXT: ret i32 [[TMP2]]
+//
+uint32_t test_sub_sc_h(uint32_t a, uint32_t b) {
+ return __builtin_riscv_cv_simd_sub_sc_h(a, b);
+}
+
+// CHECK-LABEL: @test_sub_sc_b(
+// CHECK-NEXT: entry:
+// CHECK-NEXT: [[A_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT: [[B_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT: store i32 [[A:%.*]], ptr [[A_ADDR]], align 4
+// CHECK-NEXT: store i32 [[B:%.*]], ptr [[B_ADDR]], align 4
+// CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[A_ADDR]], align 4
+// CHECK-NEXT: [[TMP1:%.*]] = load i32, ptr [[B_ADDR]], align 4
+// CHECK-NEXT: [[TMP2:%.*]] = call i32 @llvm.riscv.cv.simd.sub.sc.b(i32 [[TMP0]], i32 [[TMP1]])
+// CHECK-NEXT: ret i32 [[TMP2]]
+//
+uint32_t test_sub_sc_b(uint32_t a, uint32_t b) {
+ return __builtin_riscv_cv_simd_sub_sc_b(a, b);
+}
+
+// ===== AVG / AVGU =====
+
+// CHECK-LABEL: @test_avg_h(
+// CHECK-NEXT: entry:
+// CHECK-NEXT: [[A_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT: [[B_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT: store i32 [[A:%.*]], ptr [[A_ADDR]], align 4
+// CHECK-NEXT: store i32 [[B:%.*]], ptr [[B_ADDR]], align 4
+// CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[A_ADDR]], align 4
+// CHECK-NEXT: [[TMP1:%.*]] = load i32, ptr [[B_ADDR]], align 4
+// CHECK-NEXT: [[TMP2:%.*]] = call i32 @llvm.riscv.cv.simd.avg.h(i32 [[TMP0]], i32 [[TMP1]])
+// CHECK-NEXT: ret i32 [[TMP2]]
+//
+uint32_t test_avg_h(uint32_t a, uint32_t b) {
+ return __builtin_riscv_cv_simd_avg_h(a, b);
+}
+
+// CHECK-LABEL: @test_avg_b(
+// CHECK-NEXT: entry:
+// CHECK-NEXT: [[A_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT: [[B_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT: store i32 [[A:%.*]], ptr [[A_ADDR]], align 4
+// CHECK-NEXT: store i32 [[B:%.*]], ptr [[B_ADDR]], align 4
+// CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[A_ADDR]], align 4
+// CHECK-NEXT: [[TMP1:%.*]] = load i32, ptr [[B_ADDR]], align 4
+// CHECK-NEXT: [[TMP2:%.*]] = call i32 @llvm.riscv.cv.simd.avg.b(i32 [[TMP0]], i32 [[TMP1]])
+// CHECK-NEXT: ret i32 [[TMP2]]
+//
+uint32_t test_avg_b(uint32_t a, uint32_t b) {
+ return __builtin_riscv_cv_simd_avg_b(a, b);
+}
+
+// CHECK-LABEL: @test_avg_sc_h(
+// CHECK-NEXT: entry:
+// CHECK-NEXT: [[A_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT: [[B_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT: store i32 [[A:%.*]], ptr [[A_ADDR]], align 4
+// CHECK-NEXT: store i32 [[B:%.*]], ptr [[B_ADDR]], align 4
+// CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[A_ADDR]], align 4
+// CHECK-NEXT: [[TMP1:%.*]] = load i32, ptr [[B_ADDR]], align 4
+// CHECK-NEXT: [[TMP2:%.*]] = call i32 @llvm.riscv.cv.simd.avg.sc.h(i32 [[TMP0]], i32 [[TMP1]])
+// CHECK-NEXT: ret i32 [[TMP2]]
+//
+uint32_t test_avg_sc_h(uint32_t a, uint32_t b) {
+ return __builtin_riscv_cv_simd_avg_sc_h(a, b);
+}
+
+// CHECK-LABEL: @test_avg_sc_b(
+// CHECK-NEXT: entry:
+// CHECK-NEXT: [[A_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT: [[B_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT: store i32 [[A:%.*]], ptr [[A_ADDR]], align 4
+// CHECK-NEXT: store i32 [[B:%.*]], ptr [[B_ADDR]], align 4
+// CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[A_ADDR]], align 4
+// CHECK-NEXT: [[TMP1:%.*]] = load i32, ptr [[B_ADDR]], align 4
+// CHECK-NEXT: [[TMP2:%.*]] = call i32 @llvm.riscv.cv.simd.avg.sc.b(i32 [[TMP0]], i32 [[TMP1]])
+// CHECK-NEXT: ret i32 [[TMP2]]
+//
+uint32_t test_avg_sc_b(uint32_t a, uint32_t b) {
+ return __builtin_riscv_cv_simd_avg_sc_b(a, b);
+}
+
+// CHECK-LABEL: @test_avgu_h(
+// CHECK-NEXT: entry:
+// CHECK-NEXT: [[A_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT: [[B_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT: store i32 [[A:%.*]], ptr [[A_ADDR]], align 4
+// CHECK-NEXT: store i32 [[B:%.*]], ptr [[B_ADDR]], align 4
+// CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[A_ADDR]], align 4
+// CHECK-NEXT: [[TMP1:%.*]] = load i32, ptr [[B_ADDR]], align 4
+// CHECK-NEXT: [[TMP2:%.*]] = call i32 @llvm.riscv.cv.simd.avgu.h(i32 [[TMP0]], i32 [[TMP1]])
+// CHECK-NEXT: ret i32 [[TMP2]]
+//
+uint32_t test_avgu_h(uint32_t a, uint32_t b) {
+ return __builtin_riscv_cv_simd_avgu_h(a, b);
+}
+
+// CHECK-LABEL: @test_avgu_b(
+// CHECK-NEXT: entry:
+// CHECK-NEXT: [[A_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT: [[B_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT: store i32 [[A:%.*]], ptr [[A_ADDR]], align 4
+// CHECK-NEXT: store i32 [[B:%.*]], ptr [[B_ADDR]], align 4
+// CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[A_ADDR]], align 4
+// CHECK-NEXT: [[TMP1:%.*]] = load i32, ptr [[B_ADDR]], align 4
+// CHECK-NEXT: [[TMP2:%.*]] = call i32 @llvm.riscv.cv.simd.avgu.b(i32 [[TMP0]], i32 [[TMP1]])
+// CHECK-NEXT: ret i32 [[TMP2]]
+//
+uint32_t test_avgu_b(uint32_t a, uint32_t b) {
+ return __builtin_riscv_cv_simd_avgu_b(a, b);
+}
+
+// CHECK-LABEL: @test_avgu_sc_h(
+// CHECK-NEXT: entry:
+// CHECK-NEXT: [[A_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT: [[B_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT: store i32 [[A:%.*]], ptr [[A_ADDR]], align 4
+// CHECK-NEXT: store i32 [[B:%.*]], ptr [[B_ADDR]], align 4
+// CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[A_ADDR]], align 4
+// CHECK-NEXT: [[TMP1:%.*]] = load i32, ptr [[B_ADDR]], align 4
+// CHECK-NEXT: [[TMP2:%.*]] = call i32 @llvm.riscv.cv.simd.avgu.sc.h(i32 [[TMP0]], i32 [[TMP1]])
+// CHECK-NEXT: ret i32 [[TMP2]]
+//
+uint32_t test_avgu_sc_h(uint32_t a, uint32_t b) {
+ return __builtin_riscv_cv_simd_avgu_sc_h(a, b);
+}
+
+// CHECK-LABEL: @test_avgu_sc_b(
+// CHECK-NEXT: entry:
+// CHECK-NEXT: [[A_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT: [[B_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT: store i32 [[A:%.*]], ptr [[A_ADDR]], align 4
+// CHECK-NEXT: store i32 [[B:%.*]], ptr [[B_ADDR]], align 4
+// CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[A_ADDR]], align 4
+// CHECK-NEXT: [[TMP1:%.*]] = load i32, ptr [[B_ADDR]], align 4
+// CHECK-NEXT: [[TMP2:%.*]] = call i32 @llvm.riscv.cv.simd.avgu.sc.b(i32 [[TMP0]], i32 [[TMP1]])
+// CHECK-NEXT: ret i32 [[TMP2]]
+//
+uint32_t test_avgu_sc_b(uint32_t a, uint32_t b) {
+ return __builtin_riscv_cv_simd_avgu_sc_b(a, b);
+}
+
+// ===== MIN / MINU / MAX / MAXU (representative) =====
+
+// CHECK-LABEL: @test_min_h(
+// CHECK-NEXT: entry:
+// CHECK-NEXT: [[A_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT: [[B_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT: store i32 [[A:%.*]], ptr [[A_ADDR]], align 4
+// CHECK-NEXT: store i32 [[B:%.*]], ptr [[B_ADDR]], align 4
+// CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[A_ADDR]], align 4
+// CHECK-NEXT: [[TMP1:%.*]] = load i32, ptr [[B_ADDR]], align 4
+// CHECK-NEXT: [[TMP2:%.*]] = call i32 @llvm.riscv.cv.simd.min.h(i32 [[TMP0]], i32 [[TMP1]])
+// CHECK-NEXT: ret i32 [[TMP2]]
+//
+uint32_t test_min_h(uint32_t a, uint32_t b) {
+ return __builtin_riscv_cv_simd_min_h(a, b);
+}
+
+// CHECK-LABEL: @test_min_b(
+// CHECK-NEXT: entry:
+// CHECK-NEXT: [[A_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT: [[B_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT: store i32 [[A:%.*]], ptr [[A_ADDR]], align 4
+// CHECK-NEXT: store i32 [[B:%.*]], ptr [[B_ADDR]], align 4
+// CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[A_ADDR]], align 4
+// CHECK-NEXT: [[TMP1:%.*]] = load i32, ptr [[B_ADDR]], align 4
+// CHECK-NEXT: [[TMP2:%.*]] = call i32 @llvm.riscv.cv.simd.min.b(i32 [[TMP0]], i32 [[TMP1]])
+// CHECK-NEXT: ret i32 [[TMP2]]
+//
+uint32_t test_min_b(uint32_t a, uint32_t b) {
+ return __builtin_riscv_cv_simd_min_b(a, b);
+}
+
+// CHECK-LABEL: @test_min_sc_h(
+// CHECK-NEXT: entry:
+// CHECK-NEXT: [[A_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT: [[B_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT: store i32 [[A:%.*]], ptr [[A_ADDR]], align 4
+// CHECK-NEXT: store i32 [[B:%.*]], ptr [[B_ADDR]], align 4
+// CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[A_ADDR]], align 4
+// CHECK-NEXT: [[TMP1:%.*]] = load i32, ptr [[B_ADDR]], align 4
+// CHECK-NEXT: [[TMP2:%.*]] = call i32 @llvm.riscv.cv.simd.min.sc.h(i32 [[TMP0]], i32 [[TMP1]])
+// CHECK-NEXT: ret i32 [[TMP2]]
+//
+uint32_t test_min_sc_h(uint32_t a, uint32_t b) {
+ return __builtin_riscv_cv_simd_min_sc_h(a, b);
+}
+
+// CHECK-LABEL: @test_min_sc_b(
+// CHECK-NEXT: entry:
+// CHECK-NEXT: [[A_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT: [[B_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT: store i32 [[A:%.*]], ptr [[A_ADDR]], align 4
+// CHECK-NEXT: store i32 [[B:%.*]], ptr [[B_ADDR]], align 4
+// CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[A_ADDR]], align 4
+// CHECK-NEXT: [[TMP1:%.*]] = load i32, ptr [[B_ADDR]], align 4
+// CHECK-NEXT: [[TMP2:%.*]] = call i32 @llvm.riscv.cv.simd.min.sc.b(i32 [[TMP0]], i32 [[TMP1]])
+// CHECK-NEXT: ret i32 [[TMP2]]
+//
+uint32_t test_min_sc_b(uint32_t a, uint32_t b) {
+ return __builtin_riscv_cv_simd_min_sc_b(a, b);
+}
+
+// CHECK-LABEL: @test_minu_h(
+// CHECK-NEXT: entry:
+// CHECK-NEXT: [[A_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT: [[B_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT: store i32 [[A:%.*]], ptr [[A_ADDR]], align 4
+// CHECK-NEXT: store i32 [[B:%.*]], ptr [[B_ADDR]], align 4
+// CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[A_ADDR]], align 4
+// CHECK-NEXT: [[TMP1:%.*]] = load i32, ptr [[B_ADDR]], align 4
+// CHECK-NEXT: [[TMP2:%.*]] = call i32 @llvm.riscv.cv.simd.minu.h(i32 [[TMP0]], i32 [[TMP1]])
+// CHECK-NEXT: ret i32 [[TMP2]]
+//
+uint32_t test_minu_h(uint32_t a, uint32_t b) {
+ return __builtin_riscv_cv_simd_minu_h(a, b);
+}
+
+// CHECK-LABEL: @test_max_h(
+// CHECK-NEXT: entry:
+// CHECK-NEXT: [[A_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT: [[B_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT: store i32 [[A:%.*]], ptr [[A_ADDR]], align 4
+// CHECK-NEXT: store i32 [[B:%.*]], ptr [[B_ADDR]], align 4
+// CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[A_ADDR]], align 4
+// CHECK-NEXT: [[TMP1:%.*]] = load i32, ptr [[B_ADDR]], align 4
+// CHECK-NEXT: [[TMP2:%.*]] = call i32 @llvm.riscv.cv.simd.max.h(i32 [[TMP0]], i32 [[TMP1]])
+// CHECK-NEXT: ret i32 [[TMP2]]
+//
+uint32_t test_max_h(uint32_t a, uint32_t b) {
+ return __builtin_riscv_cv_simd_max_h(a, b);
+}
+
+// CHECK-LABEL: @test_maxu_h(
+// CHECK-NEXT: entry:
+// CHECK-NEXT: [[A_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT: [[B_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT: store i32 [[A:%.*]], ptr [[A_ADDR]], align 4
+// CHECK-NEXT: store i32 [[B:%.*]], ptr [[B_ADDR]], align 4
+// CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[A_ADDR]], align 4
+// CHECK-NEXT: [[TMP1:%.*]] = load i32, ptr [[B_ADDR]], align 4
+// CHECK-NEXT: [[TMP2:%.*]] = call i32 @llvm.riscv.cv.simd.maxu.h(i32 [[TMP0]], i32 [[TMP1]])
+// CHECK-NEXT: ret i32 [[TMP2]]
+//
+uint32_t test_maxu_h(uint32_t a, uint32_t b) {
+ return __builtin_riscv_cv_simd_maxu_h(a, b);
+}
+
+// ===== SRL / SRA / SLL (representative) =====
+
+// CHECK-LABEL: @test_srl_h(
+// CHECK-NEXT: entry:
+// CHECK-NEXT: [[A_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT: [[B_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT: store i32 [[A:%.*]], ptr [[A_ADDR]], align 4
+// CHECK-NEXT: store i32 [[B:%.*]], ptr [[B_ADDR]], align 4
+// CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[A_ADDR]], align 4
+// CHECK-NEXT: [[TMP1:%.*]] = load i32, ptr [[B_ADDR]], align 4
+// CHECK-NEXT: [[TMP2:%.*]] = call i32 @llvm.riscv.cv.simd.srl.h(i32 [[TMP0]], i32 [[TMP1]])
+// CHECK-NEXT: ret i32 [[TMP2]]
+//
+uint32_t test_srl_h(uint32_t a, uint32_t b) {
+ return __builtin_riscv_cv_simd_srl_h(a, b);
+}
+
+// CHECK-LABEL: @test_sra_h(
+// CHECK-NEXT: entry:
+// CHECK-NEXT: [[A_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT: [[B_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT: store i32 [[A:%.*]], ptr [[A_ADDR]], align 4
+// CHECK-NEXT: store i32 [[B:%.*]], ptr [[B_ADDR]], align 4
+// CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[A_ADDR]], align 4
+// CHECK-NEXT: [[TMP1:%.*]] = load i32, ptr [[B_ADDR]], align 4
+// CHECK-NEXT: [[TMP2:%.*]] = call i32 @llvm.riscv.cv.simd.sra.h(i32 [[TMP0]], i32 [[TMP1]])
+// CHECK-NEXT: ret i32 [[TMP2]]
+//
+uint32_t test_sra_h(uint32_t a, uint32_t b) {
+ return __builtin_riscv_cv_simd_sra_h(a, b);
+}
+
+// CHECK-LABEL: @test_sll_h(
+// CHECK-NEXT: entry:
+// CHECK-NEXT: [[A_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT: [[B_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT: store i32 [[A:%.*]], ptr [[A_ADDR]], align 4
+// CHECK-NEXT: store i32 [[B:%.*]], ptr [[B_ADDR]], align 4
+// CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[A_ADDR]], align 4
+// CHECK-NEXT: [[TMP1:%.*]] = load i32, ptr [[B_ADDR]], align 4
+// CHECK-NEXT: [[TMP2:%.*]] = call i32 @llvm.riscv.cv.simd.sll.h(i32 [[TMP0]], i32 [[TMP1]])
+// CHECK-NEXT: ret i32 [[TMP2]]
+//
+uint32_t test_sll_h(uint32_t a, uint32_t b) {
+ return __builtin_riscv_cv_simd_sll_h(a, b);
+}
+
+// CHECK-LABEL: @test_srl_sc_b(
+// CHECK-NEXT: entry:
+// CHECK-NEXT: [[A_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT: [[B_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT: store i32 [[A:%.*]], ptr [[A_ADDR]], align 4
+// CHECK-NEXT: store i32 [[B:%.*]], ptr [[B_ADDR]], align 4
+// CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[A_ADDR]], align 4
+// CHECK-NEXT: [[TMP1:%.*]] = load i32, ptr [[B_ADDR]], align 4
+// CHECK-NEXT: [[TMP2:%.*]] = call i32 @llvm.riscv.cv.simd.srl.sc.b(i32 [[TMP0]], i32 [[TMP1]])
+// CHECK-NEXT: ret i32 [[TMP2]]
+//
+uint32_t test_srl_sc_b(uint32_t a, uint32_t b) {
+ return __builtin_riscv_cv_simd_srl_sc_b(a, b);
+}
+
+// ===== OR / XOR / AND (representative) =====
+
+// CHECK-LABEL: @test_or_h(
+// CHECK-NEXT: entry:
+// CHECK-NEXT: [[A_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT: [[B_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT: store i32 [[A:%.*]], ptr [[A_ADDR]], align 4
+// CHECK-NEXT: store i32 [[B:%.*]], ptr [[B_ADDR]], align 4
+// CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[A_ADDR]], align 4
+// CHECK-NEXT: [[TMP1:%.*]] = load i32, ptr [[B_ADDR]], align 4
+// CHECK-NEXT: [[TMP2:%.*]] = call i32 @llvm.riscv.cv.simd.or.h(i32 [[TMP0]], i32 [[TMP1]])
+// CHECK-NEXT: ret i32 [[TMP2]]
+//
+uint32_t test_or_h(uint32_t a, uint32_t b) {
+ return __builtin_riscv_cv_simd_or_h(a, b);
+}
+
+// CHECK-LABEL: @test_xor_h(
+// CHECK-NEXT: entry:
+// CHECK-NEXT: [[A_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT: [[B_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT: store i32 [[A:%.*]], ptr [[A_ADDR]], align 4
+// CHECK-NEXT: store i32 [[B:%.*]], ptr [[B_ADDR]], align 4
+// CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[A_ADDR]], align 4
+// CHECK-NEXT: [[TMP1:%.*]] = load i32, ptr [[B_ADDR]], align 4
+// CHECK-NEXT: [[TMP2:%.*]] = call i32 @llvm.riscv.cv.simd.xor.h(i32 [[TMP0]], i32 [[TMP1]])
+// CHECK-NEXT: ret i32 [[TMP2]]
+//
+uint32_t test_xor_h(uint32_t a, uint32_t b) {
+ return __builtin_riscv_cv_simd_xor_h(a, b);
+}
+
+// CHECK-LABEL: @test_and_h(
+// CHECK-NEXT: entry:
+// CHECK-NEXT: [[A_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT: [[B_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT: store i32 [[A:%.*]], ptr [[A_ADDR]], align 4
+// CHECK-NEXT: store i32 [[B:%.*]], ptr [[B_ADDR]], align 4
+// CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[A_ADDR]], align 4
+// CHECK-NEXT: [[TMP1:%.*]] = load i32, ptr [[B_ADDR]], align 4
+// CHECK-NEXT: [[TMP2:%.*]] = call i32 @llvm.riscv.cv.simd.and.h(i32 [[TMP0]], i32 [[TMP1]])
+// CHECK-NEXT: ret i32 [[TMP2]]
+//
+uint32_t test_and_h(uint32_t a, uint32_t b) {
+ return __builtin_riscv_cv_simd_and_h(a, b);
+}
+
+// ===== ABS =====
+
+// CHECK-LABEL: @test_abs_h(
+// CHECK-NEXT: entry:
+// CHECK-NEXT: [[A_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT: store i32 [[A:%.*]], ptr [[A_ADDR]], align 4
+// CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[A_ADDR]], align 4
+// CHECK-NEXT: [[TMP1:%.*]] = call i32 @llvm.riscv.cv.simd.abs.h(i32 [[TMP0]])
+// CHECK-NEXT: ret i32 [[TMP1]]
+//
+uint32_t test_abs_h(uint32_t a) {
+ return __builtin_riscv_cv_simd_abs_h(a);
+}
+
+// CHECK-LABEL: @test_abs_b(
+// CHECK-NEXT: entry:
+// CHECK-NEXT: [[A_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT: store i32 [[A:%.*]], ptr [[A_ADDR]], align 4
+// CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[A_ADDR]], align 4
+// CHECK-NEXT: [[TMP1:%.*]] = call i32 @llvm.riscv.cv.simd.abs.b(i32 [[TMP0]])
+// CHECK-NEXT: ret i32 [[TMP1]]
+//
+uint32_t test_abs_b(uint32_t a) {
+ return __builtin_riscv_cv_simd_abs_b(a);
+}
+
+// ===== DOT PRODUCTS =====
+
+// CHECK-LABEL: @test_dotup_h(
+// CHECK-NEXT: entry:
+// CHECK-NEXT: [[A_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT: [[B_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT: store i32 [[A:%.*]], ptr [[A_ADDR]], align 4
+// CHECK-NEXT: store i32 [[B:%.*]], ptr [[B_ADDR]], align 4
+// CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[A_ADDR]], align 4
+// CHECK-NEXT: [[TMP1:%.*]] = load i32, ptr [[B_ADDR]], align 4
+// CHECK-NEXT: [[TMP2:%.*]] = call i32 @llvm.riscv.cv.simd.dotup.h(i32 [[TMP0]], i32 [[TMP1]])
+// CHECK-NEXT: ret i32 [[TMP2]]
+//
+uint32_t test_dotup_h(uint32_t a, uint32_t b) {
+ return __builtin_riscv_cv_simd_dotup_h(a, b);
+}
+
+// CHECK-LABEL: @test_dotup_b(
+// CHECK-NEXT: entry:
+// CHECK-NEXT: [[A_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT: [[B_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT: store i32 [[A:%.*]], ptr [[A_ADDR]], align 4
+// CHECK-NEXT: store i32 [[B:%.*]], ptr [[B_ADDR]], align 4
+// CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[A_ADDR]], align 4
+// CHECK-NEXT: [[TMP1:%.*]] = load i32, ptr [[B_ADDR]], align 4
+// CHECK-NEXT: [[TMP2:%.*]] = call i32 @llvm.riscv.cv.simd.dotup.b(i32 [[TMP0]], i32 [[TMP1]])
+// CHECK-NEXT: ret i32 [[TMP2]]
+//
+uint32_t test_dotup_b(uint32_t a, uint32_t b) {
+ return __builtin_riscv_cv_simd_dotup_b(a, b);
+}
+
+// CHECK-LABEL: @test_dotup_sc_h(
+// CHECK-NEXT: entry:
+// CHECK-NEXT: [[A_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT: [[B_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT: store i32 [[A:%.*]], ptr [[A_ADDR]], align 4
+// CHECK-NEXT: store i32 [[B:%.*]], ptr [[B_ADDR]], align 4
+// CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[A_ADDR]], align 4
+// CHECK-NEXT: [[TMP1:%.*]] = load i32, ptr [[B_ADDR]], align 4
+// CHECK-NEXT: [[TMP2:%.*]] = call i32 @llvm.riscv.cv.simd.dotup.sc.h(i32 [[TMP0]], i32 [[TMP1]])
+// CHECK-NEXT: ret i32 [[TMP2]]
+//
+uint32_t test_dotup_sc_h(uint32_t a, uint32_t b) {
+ return __builtin_riscv_cv_simd_dotup_sc_h(a, b);
+}
+
+// CHECK-LABEL: @test_dotusp_h(
+// CHECK-NEXT: entry:
+// CHECK-NEXT: [[A_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT: [[B_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT: store i32 [[A:%.*]], ptr [[A_ADDR]], align 4
+// CHECK-NEXT: store i32 [[B:%.*]], ptr [[B_ADDR]], align 4
+// CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[A_ADDR]], align 4
+// CHECK-NEXT: [[TMP1:%.*]] = load i32, ptr [[B_ADDR]], align 4
+// CHECK-NEXT: [[TMP2:%.*]] = call i32 @llvm.riscv.cv.simd.dotusp.h(i32 [[TMP0]], i32 [[TMP1]])
+// CHECK-NEXT: ret i32 [[TMP2]]
+//
+int32_t test_dotusp_h(uint32_t a, uint32_t b) {
+ return __builtin_riscv_cv_simd_dotusp_h(a, b);
+}
+
+// CHECK-LABEL: @test_dotsp_h(
+// CHECK-NEXT: entry:
+// CHECK-NEXT: [[A_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT: [[B_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT: store i32 [[A:%.*]], ptr [[A_ADDR]], align 4
+// CHECK-NEXT: store i32 [[B:%.*]], ptr [[B_ADDR]], align 4
+// CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[A_ADDR]], align 4
+// CHECK-NEXT: [[TMP1:%.*]] = load i32, ptr [[B_ADDR]], align 4
+// CHECK-NEXT: [[TMP2:%.*]] = call i32 @llvm.riscv.cv.simd.dotsp.h(i32 [[TMP0]], i32 [[TMP1]])
+// CHECK-NEXT: ret i32 [[TMP2]]
+//
+int32_t test_dotsp_h(uint32_t a, uint32_t b) {
+ return __builtin_riscv_cv_simd_dotsp_h(a, b);
+}
+
+// ===== SDOT (accumulating) =====
+
+// CHECK-LABEL: @test_sdotup_h(
+// CHECK-NEXT: entry:
+// CHECK-NEXT: [[A_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT: [[B_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT: [[ACC_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT: store i32 [[A:%.*]], ptr [[A_ADDR]], align 4
+// CHECK-NEXT: store i32 [[B:%.*]], ptr [[B_ADDR]], align 4
+// CHECK-NEXT: store i32 [[ACC:%.*]], ptr [[ACC_ADDR]], align 4
+// CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[A_ADDR]], align 4
+// CHECK-NEXT: [[TMP1:%.*]] = load i32, ptr [[B_ADDR]], align 4
+// CHECK-NEXT: [[TMP2:%.*]] = load i32, ptr [[ACC_ADDR]], align 4
+// CHECK-NEXT: [[TMP3:%.*]] = call i32 @llvm.riscv.cv.simd.sdotup.h(i32 [[TMP0]], i32 [[TMP1]], i32 [[TMP2]])
+// CHECK-NEXT: ret i32 [[TMP3]]
+//
+uint32_t test_sdotup_h(uint32_t a, uint32_t b, uint32_t acc) {
+ return __builtin_riscv_cv_simd_sdotup_h(a, b, acc);
+}
+
+// CHECK-LABEL: @test_sdotup_b(
+// CHECK-NEXT: entry:
+// CHECK-NEXT: [[A_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT: [[B_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT: [[ACC_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT: store i32 [[A:%.*]], ptr [[A_ADDR]], align 4
+// CHECK-NEXT: store i32 [[B:%.*]], ptr [[B_ADDR]], align 4
+// CHECK-NEXT: store i32 [[ACC:%.*]], ptr [[ACC_ADDR]], align 4
+// CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[A_ADDR]], align 4
+// CHECK-NEXT: [[TMP1:%.*]] = load i32, ptr [[B_ADDR]], align 4
+// CHECK-NEXT: [[TMP2:%.*]] = load i32, ptr [[ACC_ADDR]], align 4
+// CHECK-NEXT: [[TMP3:%.*]] = call i32 @llvm.riscv.cv.simd.sdotup.b(i32 [[TMP0]], i32 [[TMP1]], i32 [[TMP2]])
+// CHECK-NEXT: ret i32 [[TMP3]]
+//
+uint32_t test_sdotup_b(uint32_t a, uint32_t b, uint32_t acc) {
+ return __builtin_riscv_cv_simd_sdotup_b(a, b, acc);
+}
+
+// CHECK-LABEL: @test_sdotusp_h(
+// CHECK-NEXT: entry:
+// CHECK-NEXT: [[A_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT: [[B_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT: [[ACC_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT: store i32 [[A:%.*]], ptr [[A_ADDR]], align 4
+// CHECK-NEXT: store i32 [[B:%.*]], ptr [[B_ADDR]], align 4
+// CHECK-NEXT: store i32 [[ACC:%.*]], ptr [[ACC_ADDR]], align 4
+// CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[A_ADDR]], align 4
+// CHECK-NEXT: [[TMP1:%.*]] = load i32, ptr [[B_ADDR]], align 4
+// CHECK-NEXT: [[TMP2:%.*]] = load i32, ptr [[ACC_ADDR]], align 4
+// CHECK-NEXT: [[TMP3:%.*]] = call i32 @llvm.riscv.cv.simd.sdotusp.h(i32 [[TMP0]], i32 [[TMP1]], i32 [[TMP2]])
+// CHECK-NEXT: ret i32 [[TMP3]]
+//
+int32_t test_sdotusp_h(uint32_t a, uint32_t b, int32_t acc) {
+ return __builtin_riscv_cv_simd_sdotusp_h(a, b, acc);
+}
+
+// CHECK-LABEL: @test_sdotsp_h(
+// CHECK-NEXT: entry:
+// CHECK-NEXT: [[A_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT: [[B_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT: [[ACC_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT: store i32 [[A:%.*]], ptr [[A_ADDR]], align 4
+// CHECK-NEXT: store i32 [[B:%.*]], ptr [[B_ADDR]], align 4
+// CHECK-NEXT: store i32 [[ACC:%.*]], ptr [[ACC_ADDR]], align 4
+// CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[A_ADDR]], align 4
+// CHECK-NEXT: [[TMP1:%.*]] = load i32, ptr [[B_ADDR]], align 4
+// CHECK-NEXT: [[TMP2:%.*]] = load i32, ptr [[ACC_ADDR]], align 4
+// CHECK-NEXT: [[TMP3:%.*]] = call i32 @llvm.riscv.cv.simd.sdotsp.h(i32 [[TMP0]], i32 [[TMP1]], i32 [[TMP2]])
+// CHECK-NEXT: ret i32 [[TMP3]]
+//
+int32_t test_sdotsp_h(uint32_t a, uint32_t b, int32_t acc) {
+ return __builtin_riscv_cv_simd_sdotsp_h(a, b, acc);
+}
+
+// CHECK-LABEL: @test_sdotsp_sc_h(
+// CHECK-NEXT: entry:
+// CHECK-NEXT: [[A_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT: [[B_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT: [[ACC_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT: store i32 [[A:%.*]], ptr [[A_ADDR]], align 4
+// CHECK-NEXT: store i32 [[B:%.*]], ptr [[B_ADDR]], align 4
+// CHECK-NEXT: store i32 [[ACC:%.*]], ptr [[ACC_ADDR]], align 4
+// CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[A_ADDR]], align 4
+// CHECK-NEXT: [[TMP1:%.*]] = load i32, ptr [[B_ADDR]], align 4
+// CHECK-NEXT: [[TMP2:%.*]] = load i32, ptr [[ACC_ADDR]], align 4
+// CHECK-NEXT: [[TMP3:%.*]] = call i32 @llvm.riscv.cv.simd.sdotsp.sc.h(i32 [[TMP0]], i32 [[TMP1]], i32 [[TMP2]])
+// CHECK-NEXT: ret i32 [[TMP3]]
+//
+int32_t test_sdotsp_sc_h(uint32_t a, uint32_t b, int32_t acc) {
+ return __builtin_riscv_cv_simd_sdotsp_sc_h(a, b, acc);
+}
+
+// CHECK-LABEL: @test_sdotsp_sc_b(
+// CHECK-NEXT: entry:
+// CHECK-NEXT: [[A_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT: [[B_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT: [[ACC_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT: store i32 [[A:%.*]], ptr [[A_ADDR]], align 4
+// CHECK-NEXT: store i32 [[B:%.*]], ptr [[B_ADDR]], align 4
+// CHECK-NEXT: store i32 [[ACC:%.*]], ptr [[ACC_ADDR]], align 4
+// CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[A_ADDR]], align 4
+// CHECK-NEXT: [[TMP1:%.*]] = load i32, ptr [[B_ADDR]], align 4
+// CHECK-NEXT: [[TMP2:%.*]] = load i32, ptr [[ACC_ADDR]], align 4
+// CHECK-NEXT: [[TMP3:%.*]] = call i32 @llvm.riscv.cv.simd.sdotsp.sc.b(i32 [[TMP0]], i32 [[TMP1]], i32 [[TMP2]])
+// CHECK-NEXT: ret i32 [[TMP3]]
+//
+int32_t test_sdotsp_sc_b(uint32_t a, uint32_t b, int32_t acc) {
+ return __builtin_riscv_cv_simd_sdotsp_sc_b(a, b, acc);
+}
+
+// ===== EXTRACT / EXTRACTU / INSERT =====
+
+// CHECK-LABEL: @test_extract_h(
+// CHECK-NEXT: entry:
+// CHECK-NEXT: [[A_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT: store i32 [[A:%.*]], ptr [[A_ADDR]], align 4
+// CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[A_ADDR]], align 4
+// CHECK-NEXT: [[TMP1:%.*]] = call i32 @llvm.riscv.cv.simd.extract.h(i32 [[TMP0]], i32 1)
+// CHECK-NEXT: ret i32 [[TMP1]]
+//
+int32_t test_extract_h(uint32_t a) {
+ return __builtin_riscv_cv_simd_extract_h(a, 1);
+}
+
+// CHECK-LABEL: @test_extract_b(
+// CHECK-NEXT: entry:
+// CHECK-NEXT: [[A_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT: store i32 [[A:%.*]], ptr [[A_ADDR]], align 4
+// CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[A_ADDR]], align 4
+// CHECK-NEXT: [[TMP1:%.*]] = call i32 @llvm.riscv.cv.simd.extract.b(i32 [[TMP0]], i32 3)
+// CHECK-NEXT: ret i32 [[TMP1]]
+//
+int32_t test_extract_b(uint32_t a) {
+ return __builtin_riscv_cv_simd_extract_b(a, 3);
+}
+
+// CHECK-LABEL: @test_extractu_h(
+// CHECK-NEXT: entry:
+// CHECK-NEXT: [[A_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT: store i32 [[A:%.*]], ptr [[A_ADDR]], align 4
+// CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[A_ADDR]], align 4
+// CHECK-NEXT: [[TMP1:%.*]] = call i32 @llvm.riscv.cv.simd.extractu.h(i32 [[TMP0]], i32 0)
+// CHECK-NEXT: ret i32 [[TMP1]]
+//
+uint32_t test_extractu_h(uint32_t a) {
+ return __builtin_riscv_cv_simd_extractu_h(a, 0);
+}
+
+// CHECK-LABEL: @test_extractu_b(
+// CHECK-NEXT: entry:
+// CHECK-NEXT: [[A_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT: store i32 [[A:%.*]], ptr [[A_ADDR]], align 4
+// CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[A_ADDR]], align 4
+// CHECK-NEXT: [[TMP1:%.*]] = call i32 @llvm.riscv.cv.simd.extractu.b(i32 [[TMP0]], i32 2)
+// CHECK-NEXT: ret i32 [[TMP1]]
+//
+uint32_t test_extractu_b(uint32_t a) {
+ return __builtin_riscv_cv_simd_extractu_b(a, 2);
+}
+
+// CHECK-LABEL: @test_insert_h(
+// CHECK-NEXT: entry:
+// CHECK-NEXT: [[RD_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT: [[RS1_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT: store i32 [[RD:%.*]], ptr [[RD_ADDR]], align 4
+// CHECK-NEXT: store i32 [[RS1:%.*]], ptr [[RS1_ADDR]], align 4
+// CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[RD_ADDR]], align 4
+// CHECK-NEXT: [[TMP1:%.*]] = load i32, ptr [[RS1_ADDR]], align 4
+// CHECK-NEXT: [[TMP2:%.*]] = call i32 @llvm.riscv.cv.simd.insert.h(i32 [[TMP0]], i32 [[TMP1]], i32 1)
+// CHECK-NEXT: ret i32 [[TMP2]]
+//
+uint32_t test_insert_h(uint32_t rd, uint32_t rs1) {
+ return __builtin_riscv_cv_simd_insert_h(rd, rs1, 1);
+}
+
+// CHECK-LABEL: @test_insert_b(
+// CHECK-NEXT: entry:
+// CHECK-NEXT: [[RD_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT: [[RS1_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT: store i32 [[RD:%.*]], ptr [[RD_ADDR]], align 4
+// CHECK-NEXT: store i32 [[RS1:%.*]], ptr [[RS1_ADDR]], align 4
+// CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[RD_ADDR]], align 4
+// CHECK-NEXT: [[TMP1:%.*]] = load i32, ptr [[RS1_ADDR]], align 4
+// CHECK-NEXT: [[TMP2:%.*]] = call i32 @llvm.riscv.cv.simd.insert.b(i32 [[TMP0]], i32 [[TMP1]], i32 2)
+// CHECK-NEXT: ret i32 [[TMP2]]
+//
+uint32_t test_insert_b(uint32_t rd, uint32_t rs1) {
+ return __builtin_riscv_cv_simd_insert_b(rd, rs1, 2);
+}
+
+// ===== SHUFFLE / SHUFFLE2 =====
+
+// CHECK-LABEL: @test_shuffle_h(
+// CHECK-NEXT: entry:
+// CHECK-NEXT: [[A_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT: [[MASK_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT: store i32 [[A:%.*]], ptr [[A_ADDR]], align 4
+// CHECK-NEXT: store i32 [[MASK:%.*]], ptr [[MASK_ADDR]], align 4
+// CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[A_ADDR]], align 4
+// CHECK-NEXT: [[TMP1:%.*]] = load i32, ptr [[MASK_ADDR]], align 4
+// CHECK-NEXT: [[TMP2:%.*]] = call i32 @llvm.riscv.cv.simd.shuffle.h(i32 [[TMP0]], i32 [[TMP1]])
+// CHECK-NEXT: ret i32 [[TMP2]]
+//
+uint32_t test_shuffle_h(uint32_t a, uint32_t mask) {
+ return __builtin_riscv_cv_simd_shuffle_h(a, mask);
+}
+
+// CHECK-LABEL: @test_shuffle_b(
+// CHECK-NEXT: entry:
+// CHECK-NEXT: [[A_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT: [[MASK_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT: store i32 [[A:%.*]], ptr [[A_ADDR]], align 4
+// CHECK-NEXT: store i32 [[MASK:%.*]], ptr [[MASK_ADDR]], align 4
+// CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[A_ADDR]], align 4
+// CHECK-NEXT: [[TMP1:%.*]] = load i32, ptr [[MASK_ADDR]], align 4
+// CHECK-NEXT: [[TMP2:%.*]] = call i32 @llvm.riscv.cv.simd.shuffle.b(i32 [[TMP0]], i32 [[TMP1]])
+// CHECK-NEXT: ret i32 [[TMP2]]
+//
+uint32_t test_shuffle_b(uint32_t a, uint32_t mask) {
+ return __builtin_riscv_cv_simd_shuffle_b(a, mask);
+}
+
+// CHECK-LABEL: @test_shuffle_sci_h(
+// CHECK-NEXT: entry:
+// CHECK-NEXT: [[A_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT: store i32 [[A:%.*]], ptr [[A_ADDR]], align 4
+// CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[A_ADDR]], align 4
+// CHECK-NEXT: [[TMP1:%.*]] = call i32 @llvm.riscv.cv.simd.shuffle.sci.h(i32 [[TMP0]], i32 2)
+// CHECK-NEXT: ret i32 [[TMP1]]
+//
+uint32_t test_shuffle_sci_h(uint32_t a) {
+ return __builtin_riscv_cv_simd_shuffle_sci_h(a, 2);
+}
+
+// CHECK-LABEL: @test_shuffle_sci_b(
+// CHECK-NEXT: entry:
+// CHECK-NEXT: [[A_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT: store i32 [[A:%.*]], ptr [[A_ADDR]], align 4
+// CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[A_ADDR]], align 4
+// CHECK-NEXT: [[TMP1:%.*]] = call i32 @llvm.riscv.cv.simd.shuffle.sci.b(i32 [[TMP0]], i32 69)
+// CHECK-NEXT: ret i32 [[TMP1]]
+//
+uint32_t test_shuffle_sci_b(uint32_t a) {
+ return __builtin_riscv_cv_simd_shuffle_sci_b(a, 69);
+}
+
+// CHECK-LABEL: @test_shuffle2_h(
+// CHECK-NEXT: entry:
+// CHECK-NEXT: [[RS1_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT: [[RS2_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT: [[RD_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT: store i32 [[RS1:%.*]], ptr [[RS1_ADDR]], align 4
+// CHECK-NEXT: store i32 [[RS2:%.*]], ptr [[RS2_ADDR]], align 4
+// CHECK-NEXT: store i32 [[RD:%.*]], ptr [[RD_ADDR]], align 4
+// CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[RS1_ADDR]], align 4
+// CHECK-NEXT: [[TMP1:%.*]] = load i32, ptr [[RS2_ADDR]], align 4
+// CHECK-NEXT: [[TMP2:%.*]] = load i32, ptr [[RD_ADDR]], align 4
+// CHECK-NEXT: [[TMP3:%.*]] = call i32 @llvm.riscv.cv.simd.shuffle2.h(i32 [[TMP0]], i32 [[TMP1]], i32 [[TMP2]])
+// CHECK-NEXT: ret i32 [[TMP3]]
+//
+uint32_t test_shuffle2_h(uint32_t rs1, uint32_t rs2, uint32_t rd) {
+ return __builtin_riscv_cv_simd_shuffle2_h(rs1, rs2, rd);
+}
+
+// CHECK-LABEL: @test_shuffle2_b(
+// CHECK-NEXT: entry:
+// CHECK-NEXT: [[RS1_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT: [[RS2_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT: [[RD_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT: store i32 [[RS1:%.*]], ptr [[RS1_ADDR]], align 4
+// CHECK-NEXT: store i32 [[RS2:%.*]], ptr [[RS2_ADDR]], align 4
+// CHECK-NEXT: store i32 [[RD:%.*]], ptr [[RD_ADDR]], align 4
+// CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[RS1_ADDR]], align 4
+// CHECK-NEXT: [[TMP1:%.*]] = load i32, ptr [[RS2_ADDR]], align 4
+// CHECK-NEXT: [[TMP2:%.*]] = load i32, ptr [[RD_ADDR]], align 4
+// CHECK-NEXT: [[TMP3:%.*]] = call i32 @llvm.riscv.cv.simd.shuffle2.b(i32 [[TMP0]], i32 [[TMP1]], i32 [[TMP2]])
+// CHECK-NEXT: ret i32 [[TMP3]]
+//
+uint32_t test_shuffle2_b(uint32_t rs1, uint32_t rs2, uint32_t rd) {
+ return __builtin_riscv_cv_simd_shuffle2_b(rs1, rs2, rd);
+}
+
+// ===== PACK =====
+
+// CHECK-LABEL: @test_packhi_h(
+// CHECK-NEXT: entry:
+// CHECK-NEXT: [[A_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT: [[B_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT: store i32 [[A:%.*]], ptr [[A_ADDR]], align 4
+// CHECK-NEXT: store i32 [[B:%.*]], ptr [[B_ADDR]], align 4
+// CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[A_ADDR]], align 4
+// CHECK-NEXT: [[TMP1:%.*]] = load i32, ptr [[B_ADDR]], align 4
+// CHECK-NEXT: [[TMP2:%.*]] = call i32 @llvm.riscv.cv.simd.packhi.h(i32 [[TMP0]], i32 [[TMP1]])
+// CHECK-NEXT: ret i32 [[TMP2]]
+//
+uint32_t test_packhi_h(uint32_t a, uint32_t b) {
+ return __builtin_riscv_cv_simd_packhi_h(a, b);
+}
+
+// CHECK-LABEL: @test_packlo_h(
+// CHECK-NEXT: entry:
+// CHECK-NEXT: [[A_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT: [[B_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT: store i32 [[A:%.*]], ptr [[A_ADDR]], align 4
+// CHECK-NEXT: store i32 [[B:%.*]], ptr [[B_ADDR]], align 4
+// CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[A_ADDR]], align 4
+// CHECK-NEXT: [[TMP1:%.*]] = load i32, ptr [[B_ADDR]], align 4
+// CHECK-NEXT: [[TMP2:%.*]] = call i32 @llvm.riscv.cv.simd.packlo.h(i32 [[TMP0]], i32 [[TMP1]])
+// CHECK-NEXT: ret i32 [[TMP2]]
+//
+uint32_t test_packlo_h(uint32_t a, uint32_t b) {
+ return __builtin_riscv_cv_simd_packlo_h(a, b);
+}
+
+// CHECK-LABEL: @test_packhi_b(
+// CHECK-NEXT: entry:
+// CHECK-NEXT: [[RD_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT: [[RS1_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT: [[RS2_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT: store i32 [[RD:%.*]], ptr [[RD_ADDR]], align 4
+// CHECK-NEXT: store i32 [[RS1:%.*]], ptr [[RS1_ADDR]], align 4
+// CHECK-NEXT: store i32 [[RS2:%.*]], ptr [[RS2_ADDR]], align 4
+// CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[RD_ADDR]], align 4
+// CHECK-NEXT: [[TMP1:%.*]] = load i32, ptr [[RS1_ADDR]], align 4
+// CHECK-NEXT: [[TMP2:%.*]] = load i32, ptr [[RS2_ADDR]], align 4
+// CHECK-NEXT: [[TMP3:%.*]] = call i32 @llvm.riscv.cv.simd.packhi.b(i32 [[TMP0]], i32 [[TMP1]], i32 [[TMP2]])
+// CHECK-NEXT: ret i32 [[TMP3]]
+//
+uint32_t test_packhi_b(uint32_t rd, uint32_t rs1, uint32_t rs2) {
+ return __builtin_riscv_cv_simd_packhi_b(rd, rs1, rs2);
+}
+
+// CHECK-LABEL: @test_packlo_b(
+// CHECK-NEXT: entry:
+// CHECK-NEXT: [[RD_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT: [[RS1_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT: [[RS2_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT: store i32 [[RD:%.*]], ptr [[RD_ADDR]], align 4
+// CHECK-NEXT: store i32 [[RS1:%.*]], ptr [[RS1_ADDR]], align 4
+// CHECK-NEXT: store i32 [[RS2:%.*]], ptr [[RS2_ADDR]], align 4
+// CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[RD_ADDR]], align 4
+// CHECK-NEXT: [[TMP1:%.*]] = load i32, ptr [[RS1_ADDR]], align 4
+// CHECK-NEXT: [[TMP2:%.*]] = load i32, ptr [[RS2_ADDR]], align 4
+// CHECK-NEXT: [[TMP3:%.*]] = call i32 @llvm.riscv.cv.simd.packlo.b(i32 [[TMP0]], i32 [[TMP1]], i32 [[TMP2]])
+// CHECK-NEXT: ret i32 [[TMP3]]
+//
+uint32_t test_packlo_b(uint32_t rd, uint32_t rs1, uint32_t rs2) {
+ return __builtin_riscv_cv_simd_packlo_b(rd, rs1, rs2);
+}
+
+// ===== COMPARE (representative) =====
+
+// CHECK-LABEL: @test_cmpeq_h(
+// CHECK-NEXT: entry:
+// CHECK-NEXT: [[A_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT: [[B_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT: store i32 [[A:%.*]], ptr [[A_ADDR]], align 4
+// CHECK-NEXT: store i32 [[B:%.*]], ptr [[B_ADDR]], align 4
+// CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[A_ADDR]], align 4
+// CHECK-NEXT: [[TMP1:%.*]] = load i32, ptr [[B_ADDR]], align 4
+// CHECK-NEXT: [[TMP2:%.*]] = call i32 @llvm.riscv.cv.simd.cmpeq.h(i32 [[TMP0]], i32 [[TMP1]])
+// CHECK-NEXT: ret i32 [[TMP2]]
+//
+uint32_t test_cmpeq_h(uint32_t a, uint32_t b) {
+ return __builtin_riscv_cv_simd_cmpeq_h(a, b);
+}
+
+// CHECK-LABEL: @test_cmpeq_b(
+// CHECK-NEXT: entry:
+// CHECK-NEXT: [[A_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT: [[B_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT: store i32 [[A:%.*]], ptr [[A_ADDR]], align 4
+// CHECK-NEXT: store i32 [[B:%.*]], ptr [[B_ADDR]], align 4
+// CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[A_ADDR]], align 4
+// CHECK-NEXT: [[TMP1:%.*]] = load i32, ptr [[B_ADDR]], align 4
+// CHECK-NEXT: [[TMP2:%.*]] = call i32 @llvm.riscv.cv.simd.cmpeq.b(i32 [[TMP0]], i32 [[TMP1]])
+// CHECK-NEXT: ret i32 [[TMP2]]
+//
+uint32_t test_cmpeq_b(uint32_t a, uint32_t b) {
+ return __builtin_riscv_cv_simd_cmpeq_b(a, b);
+}
+
+// CHECK-LABEL: @test_cmpne_h(
+// CHECK-NEXT: entry:
+// CHECK-NEXT: [[A_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT: [[B_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT: store i32 [[A:%.*]], ptr [[A_ADDR]], align 4
+// CHECK-NEXT: store i32 [[B:%.*]], ptr [[B_ADDR]], align 4
+// CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[A_ADDR]], align 4
+// CHECK-NEXT: [[TMP1:%.*]] = load i32, ptr [[B_ADDR]], align 4
+// CHECK-NEXT: [[TMP2:%.*]] = call i32 @llvm.riscv.cv.simd.cmpne.h(i32 [[TMP0]], i32 [[TMP1]])
+// CHECK-NEXT: ret i32 [[TMP2]]
+//
+uint32_t test_cmpne_h(uint32_t a, uint32_t b) {
+ return __builtin_riscv_cv_simd_cmpne_h(a, b);
+}
+
+// CHECK-LABEL: @test_cmpgt_h(
+// CHECK-NEXT: entry:
+// CHECK-NEXT: [[A_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT: [[B_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT: store i32 [[A:%.*]], ptr [[A_ADDR]], align 4
+// CHECK-NEXT: store i32 [[B:%.*]], ptr [[B_ADDR]], align 4
+// CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[A_ADDR]], align 4
+// CHECK-NEXT: [[TMP1:%.*]] = load i32, ptr [[B_ADDR]], align 4
+// CHECK-NEXT: [[TMP2:%.*]] = call i32 @llvm.riscv.cv.simd.cmpgt.h(i32 [[TMP0]], i32 [[TMP1]])
+// CHECK-NEXT: ret i32 [[TMP2]]
+//
+uint32_t test_cmpgt_h(uint32_t a, uint32_t b) {
+ return __builtin_riscv_cv_simd_cmpgt_h(a, b);
+}
+
+// CHECK-LABEL: @test_cmpge_sc_h(
+// CHECK-NEXT: entry:
+// CHECK-NEXT: [[A_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT: [[B_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT: store i32 [[A:%.*]], ptr [[A_ADDR]], align 4
+// CHECK-NEXT: store i32 [[B:%.*]], ptr [[B_ADDR]], align 4
+// CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[A_ADDR]], align 4
+// CHECK-NEXT: [[TMP1:%.*]] = load i32, ptr [[B_ADDR]], align 4
+// CHECK-NEXT: [[TMP2:%.*]] = call i32 @llvm.riscv.cv.simd.cmpge.sc.h(i32 [[TMP0]], i32 [[TMP1]])
+// CHECK-NEXT: ret i32 [[TMP2]]
+//
+uint32_t test_cmpge_sc_h(uint32_t a, uint32_t b) {
+ return __builtin_riscv_cv_simd_cmpge_sc_h(a, b);
+}
+
+// CHECK-LABEL: @test_cmplt_b(
+// CHECK-NEXT: entry:
+// CHECK-NEXT: [[A_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT: [[B_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT: store i32 [[A:%.*]], ptr [[A_ADDR]], align 4
+// CHECK-NEXT: store i32 [[B:%.*]], ptr [[B_ADDR]], align 4
+// CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[A_ADDR]], align 4
+// CHECK-NEXT: [[TMP1:%.*]] = load i32, ptr [[B_ADDR]], align 4
+// CHECK-NEXT: [[TMP2:%.*]] = call i32 @llvm.riscv.cv.simd.cmplt.b(i32 [[TMP0]], i32 [[TMP1]])
+// CHECK-NEXT: ret i32 [[TMP2]]
+//
+uint32_t test_cmplt_b(uint32_t a, uint32_t b) {
+ return __builtin_riscv_cv_simd_cmplt_b(a, b);
+}
+
+// CHECK-LABEL: @test_cmple_sc_b(
+// CHECK-NEXT: entry:
+// CHECK-NEXT: [[A_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT: [[B_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT: store i32 [[A:%.*]], ptr [[A_ADDR]], align 4
+// CHECK-NEXT: store i32 [[B:%.*]], ptr [[B_ADDR]], align 4
+// CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[A_ADDR]], align 4
+// CHECK-NEXT: [[TMP1:%.*]] = load i32, ptr [[B_ADDR]], align 4
+// CHECK-NEXT: [[TMP2:%.*]] = call i32 @llvm.riscv.cv.simd.cmple.sc.b(i32 [[TMP0]], i32 [[TMP1]])
+// CHECK-NEXT: ret i32 [[TMP2]]
+//
+uint32_t test_cmple_sc_b(uint32_t a, uint32_t b) {
+ return __builtin_riscv_cv_simd_cmple_sc_b(a, b);
+}
+
+// CHECK-LABEL: @test_cmpgtu_h(
+// CHECK-NEXT: entry:
+// CHECK-NEXT: [[A_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT: [[B_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT: store i32 [[A:%.*]], ptr [[A_ADDR]], align 4
+// CHECK-NEXT: store i32 [[B:%.*]], ptr [[B_ADDR]], align 4
+// CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[A_ADDR]], align 4
+// CHECK-NEXT: [[TMP1:%.*]] = load i32, ptr [[B_ADDR]], align 4
+// CHECK-NEXT: [[TMP2:%.*]] = call i32 @llvm.riscv.cv.simd.cmpgtu.h(i32 [[TMP0]], i32 [[TMP1]])
+// CHECK-NEXT: ret i32 [[TMP2]]
+//
+uint32_t test_cmpgtu_h(uint32_t a, uint32_t b) {
+ return __builtin_riscv_cv_simd_cmpgtu_h(a, b);
+}
+
+// CHECK-LABEL: @test_cmpgeu_b(
+// CHECK-NEXT: entry:
+// CHECK-NEXT: [[A_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT: [[B_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT: store i32 [[A:%.*]], ptr [[A_ADDR]], align 4
+// CHECK-NEXT: store i32 [[B:%.*]], ptr [[B_ADDR]], align 4
+// CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[A_ADDR]], align 4
+// CHECK-NEXT: [[TMP1:%.*]] = load i32, ptr [[B_ADDR]], align 4
+// CHECK-NEXT: [[TMP2:%.*]] = call i32 @llvm.riscv.cv.simd.cmpgeu.b(i32 [[TMP0]], i32 [[TMP1]])
+// CHECK-NEXT: ret i32 [[TMP2]]
+//
+uint32_t test_cmpgeu_b(uint32_t a, uint32_t b) {
+ return __builtin_riscv_cv_simd_cmpgeu_b(a, b);
+}
+
+// CHECK-LABEL: @test_cmpltu_sc_h(
+// CHECK-NEXT: entry:
+// CHECK-NEXT: [[A_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT: [[B_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT: store i32 [[A:%.*]], ptr [[A_ADDR]], align 4
+// CHECK-NEXT: store i32 [[B:%.*]], ptr [[B_ADDR]], align 4
+// CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[A_ADDR]], align 4
+// CHECK-NEXT: [[TMP1:%.*]] = load i32, ptr [[B_ADDR]], align 4
+// CHECK-NEXT: [[TMP2:%.*]] = call i32 @llvm.riscv.cv.simd.cmpltu.sc.h(i32 [[TMP0]], i32 [[TMP1]])
+// CHECK-NEXT: ret i32 [[TMP2]]
+//
+uint32_t test_cmpltu_sc_h(uint32_t a, uint32_t b) {
+ return __builtin_riscv_cv_simd_cmpltu_sc_h(a, b);
+}
+
+// CHECK-LABEL: @test_cmpleu_b(
+// CHECK-NEXT: entry:
+// CHECK-NEXT: [[A_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT: [[B_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT: store i32 [[A:%.*]], ptr [[A_ADDR]], align 4
+// CHECK-NEXT: store i32 [[B:%.*]], ptr [[B_ADDR]], align 4
+// CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[A_ADDR]], align 4
+// CHECK-NEXT: [[TMP1:%.*]] = load i32, ptr [[B_ADDR]], align 4
+// CHECK-NEXT: [[TMP2:%.*]] = call i32 @llvm.riscv.cv.simd.cmpleu.b(i32 [[TMP0]], i32 [[TMP1]])
+// CHECK-NEXT: ret i32 [[TMP2]]
+//
+uint32_t test_cmpleu_b(uint32_t a, uint32_t b) {
+ return __builtin_riscv_cv_simd_cmpleu_b(a, b);
+}
+
+// ===== COMPLEX =====
+
+// CHECK-LABEL: @test_cplxmul_r(
+// CHECK-NEXT: entry:
+// CHECK-NEXT: [[RS1_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT: [[RS2_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT: [[RD_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT: store i32 [[RS1:%.*]], ptr [[RS1_ADDR]], align 4
+// CHECK-NEXT: store i32 [[RS2:%.*]], ptr [[RS2_ADDR]], align 4
+// CHECK-NEXT: store i32 [[RD:%.*]], ptr [[RD_ADDR]], align 4
+// CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[RS1_ADDR]], align 4
+// CHECK-NEXT: [[TMP1:%.*]] = load i32, ptr [[RS2_ADDR]], align 4
+// CHECK-NEXT: [[TMP2:%.*]] = load i32, ptr [[RD_ADDR]], align 4
+// CHECK-NEXT: [[TMP3:%.*]] = call i32 @llvm.riscv.cv.simd.cplxmul.r(i32 [[TMP0]], i32 [[TMP1]], i32 [[TMP2]], i32 0)
+// CHECK-NEXT: ret i32 [[TMP3]]
+//
+uint32_t test_cplxmul_r(uint32_t rs1, uint32_t rs2, uint32_t rd) {
+ return __builtin_riscv_cv_simd_cplxmul_r(rs1, rs2, rd, 0);
+}
+
+// CHECK-LABEL: @test_cplxmul_r_div2(
+// CHECK-NEXT: entry:
+// CHECK-NEXT: [[RS1_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT: [[RS2_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT: [[RD_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT: store i32 [[RS1:%.*]], ptr [[RS1_ADDR]], align 4
+// CHECK-NEXT: store i32 [[RS2:%.*]], ptr [[RS2_ADDR]], align 4
+// CHECK-NEXT: store i32 [[RD:%.*]], ptr [[RD_ADDR]], align 4
+// CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[RS1_ADDR]], align 4
+// CHECK-NEXT: [[TMP1:%.*]] = load i32, ptr [[RS2_ADDR]], align 4
+// CHECK-NEXT: [[TMP2:%.*]] = load i32, ptr [[RD_ADDR]], align 4
+// CHECK-NEXT: [[TMP3:%.*]] = call i32 @llvm.riscv.cv.simd.cplxmul.r(i32 [[TMP0]], i32 [[TMP1]], i32 [[TMP2]], i32 1)
+// CHECK-NEXT: ret i32 [[TMP3]]
+//
+uint32_t test_cplxmul_r_div2(uint32_t rs1, uint32_t rs2, uint32_t rd) {
+ return __builtin_riscv_cv_simd_cplxmul_r(rs1, rs2, rd, 1);
+}
+
+// CHECK-LABEL: @test_cplxmul_i(
+// CHECK-NEXT: entry:
+// CHECK-NEXT: [[RS1_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT: [[RS2_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT: [[RD_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT: store i32 [[RS1:%.*]], ptr [[RS1_ADDR]], align 4
+// CHECK-NEXT: store i32 [[RS2:%.*]], ptr [[RS2_ADDR]], align 4
+// CHECK-NEXT: store i32 [[RD:%.*]], ptr [[RD_ADDR]], align 4
+// CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[RS1_ADDR]], align 4
+// CHECK-NEXT: [[TMP1:%.*]] = load i32, ptr [[RS2_ADDR]], align 4
+// CHECK-NEXT: [[TMP2:%.*]] = load i32, ptr [[RD_ADDR]], align 4
+// CHECK-NEXT: [[TMP3:%.*]] = call i32 @llvm.riscv.cv.simd.cplxmul.i(i32 [[TMP0]], i32 [[TMP1]], i32 [[TMP2]], i32 0)
+// CHECK-NEXT: ret i32 [[TMP3]]
+//
+uint32_t test_cplxmul_i(uint32_t rs1, uint32_t rs2, uint32_t rd) {
+ return __builtin_riscv_cv_simd_cplxmul_i(rs1, rs2, rd, 0);
+}
+
+// CHECK-LABEL: @test_cplxmul_i_div4(
+// CHECK-NEXT: entry:
+// CHECK-NEXT: [[RS1_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT: [[RS2_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT: [[RD_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT: store i32 [[RS1:%.*]], ptr [[RS1_ADDR]], align 4
+// CHECK-NEXT: store i32 [[RS2:%.*]], ptr [[RS2_ADDR]], align 4
+// CHECK-NEXT: store i32 [[RD:%.*]], ptr [[RD_ADDR]], align 4
+// CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[RS1_ADDR]], align 4
+// CHECK-NEXT: [[TMP1:%.*]] = load i32, ptr [[RS2_ADDR]], align 4
+// CHECK-NEXT: [[TMP2:%.*]] = load i32, ptr [[RD_ADDR]], align 4
+// CHECK-NEXT: [[TMP3:%.*]] = call i32 @llvm.riscv.cv.simd.cplxmul.i(i32 [[TMP0]], i32 [[TMP1]], i32 [[TMP2]], i32 2)
+// CHECK-NEXT: ret i32 [[TMP3]]
+//
+uint32_t test_cplxmul_i_div4(uint32_t rs1, uint32_t rs2, uint32_t rd) {
+ return __builtin_riscv_cv_simd_cplxmul_i(rs1, rs2, rd, 2);
+}
+
+// CHECK-LABEL: @test_cplxconj(
+// CHECK-NEXT: entry:
+// CHECK-NEXT: [[A_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT: store i32 [[A:%.*]], ptr [[A_ADDR]], align 4
+// CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[A_ADDR]], align 4
+// CHECK-NEXT: [[TMP1:%.*]] = call i32 @llvm.riscv.cv.simd.cplxconj(i32 [[TMP0]])
+// CHECK-NEXT: ret i32 [[TMP1]]
+//
+uint32_t test_cplxconj(uint32_t a) {
+ return __builtin_riscv_cv_simd_cplxconj(a);
+}
+
+// CHECK-LABEL: @test_subrotmj(
+// CHECK-NEXT: entry:
+// CHECK-NEXT: [[A_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT: [[B_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT: store i32 [[A:%.*]], ptr [[A_ADDR]], align 4
+// CHECK-NEXT: store i32 [[B:%.*]], ptr [[B_ADDR]], align 4
+// CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[A_ADDR]], align 4
+// CHECK-NEXT: [[TMP1:%.*]] = load i32, ptr [[B_ADDR]], align 4
+// CHECK-NEXT: [[TMP2:%.*]] = call i32 @llvm.riscv.cv.simd.subrotmj(i32 [[TMP0]], i32 [[TMP1]], i32 0)
+// CHECK-NEXT: ret i32 [[TMP2]]
+//
+uint32_t test_subrotmj(uint32_t a, uint32_t b) {
+ return __builtin_riscv_cv_simd_subrotmj(a, b, 0);
+}
+
+// CHECK-LABEL: @test_subrotmj_div8(
+// CHECK-NEXT: entry:
+// CHECK-NEXT: [[A_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT: [[B_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT: store i32 [[A:%.*]], ptr [[A_ADDR]], align 4
+// CHECK-NEXT: store i32 [[B:%.*]], ptr [[B_ADDR]], align 4
+// CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[A_ADDR]], align 4
+// CHECK-NEXT: [[TMP1:%.*]] = load i32, ptr [[B_ADDR]], align 4
+// CHECK-NEXT: [[TMP2:%.*]] = call i32 @llvm.riscv.cv.simd.subrotmj(i32 [[TMP0]], i32 [[TMP1]], i32 3)
+// CHECK-NEXT: ret i32 [[TMP2]]
+//
+uint32_t test_subrotmj_div8(uint32_t a, uint32_t b) {
+ return __builtin_riscv_cv_simd_subrotmj(a, b, 3);
+}
diff --git a/clang/test/Sema/rvv-xcv-sema.c b/clang/test/Sema/rvv-xcv-sema.c
index 681e6c7c385dd..7f873ecc02c14 100644
--- a/clang/test/Sema/rvv-xcv-sema.c
+++ b/clang/test/Sema/rvv-xcv-sema.c
@@ -15,3 +15,43 @@ void test_mac_range(uint32_t a, uint32_t b, uint32_t c) {
(void)__builtin_riscv_cv_mac_macuN(a, b, c, 31); // OK
(void)__builtin_riscv_cv_mac_macuN(a, b, c, 32); // expected-error {{argument value 32 is outside the valid range [0, 31]}}
}
+
+// ===== XCVsimd — various immediate ranges =====
+
+void test_simd_extract_range(uint32_t a) {
+ (void)__builtin_riscv_cv_simd_extract_h(a, 0); // OK
+ (void)__builtin_riscv_cv_simd_extract_h(a, 1); // OK: max for halfword
+ (void)__builtin_riscv_cv_simd_extract_h(a, 2); // expected-error {{argument value 2 is outside the valid range [0, 1]}}
+ (void)__builtin_riscv_cv_simd_extract_b(a, 3); // OK: max for byte
+ (void)__builtin_riscv_cv_simd_extract_b(a, 4); // expected-error {{argument value 4 is outside the valid range [0, 3]}}
+}
+
+void test_simd_insert_range(uint32_t a, uint32_t b) {
+ (void)__builtin_riscv_cv_simd_insert_h(a, b, 1); // OK
+ (void)__builtin_riscv_cv_simd_insert_h(a, b, 2); // expected-error {{argument value 2 is outside the valid range [0, 1]}}
+ (void)__builtin_riscv_cv_simd_insert_b(a, b, 3); // OK
+ (void)__builtin_riscv_cv_simd_insert_b(a, b, 4); // expected-error {{argument value 4 is outside the valid range [0, 3]}}
+}
+
+void test_simd_shuffle_sci_range(uint32_t a) {
+ (void)__builtin_riscv_cv_simd_shuffle_sci_h(a, 3); // OK: max for 2-bit
+ (void)__builtin_riscv_cv_simd_shuffle_sci_h(a, 4); // expected-error {{argument value 4 is outside the valid range [0, 3]}}
+ (void)__builtin_riscv_cv_simd_shuffle_sci_b(a, 255); // OK: max for 8-bit
+ (void)__builtin_riscv_cv_simd_shuffle_sci_b(a, 256); // expected-error {{argument value 256 is outside the valid range [0, 255]}}
+}
+
+void test_simd_add_h_range(uint32_t a, uint32_t b) {
+ (void)__builtin_riscv_cv_simd_add_h(a, b, 0); // OK
+ (void)__builtin_riscv_cv_simd_add_h(a, b, 3); // OK: max divcode
+ (void)__builtin_riscv_cv_simd_add_h(a, b, 4); // expected-error {{argument value 4 is outside the valid range [0, 3]}}
+}
+
+void test_simd_cplxmul_range(uint32_t a, uint32_t b, uint32_t c) {
+ (void)__builtin_riscv_cv_simd_cplxmul_r(a, b, c, 3); // OK
+ (void)__builtin_riscv_cv_simd_cplxmul_r(a, b, c, 4); // expected-error {{argument value 4 is outside the valid range [0, 3]}}
+}
+
+void test_simd_subrotmj_range(uint32_t a, uint32_t b) {
+ (void)__builtin_riscv_cv_simd_subrotmj(a, b, 3); // OK
+ (void)__builtin_riscv_cv_simd_subrotmj(a, b, 4); // expected-error {{argument value 4 is outside the valid range [0, 3]}}
+}
>From 7dda09142d0f914f46b6dfe22803ec0e22f3ee1b Mon Sep 17 00:00:00 2001
From: vitbur <vittorioburani at gmail.com>
Date: Tue, 7 Apr 2026 18:48:54 +0200
Subject: [PATCH 09/10] [Clang][RISCV] Add tests for `XCVbitmanip` builtins
- add `rvv-xcvbitmanip-builtins.c`
- add Sema tests for XCVbitmanip in `rvv-xcv-sema.c`
---
.../CodeGen/RISCV/rvv-xcvbitmanip-builtins.c | 95 +++++++++++++++++++
clang/test/Sema/rvv-xcv-sema.c | 8 ++
2 files changed, 103 insertions(+)
create mode 100644 clang/test/CodeGen/RISCV/rvv-xcvbitmanip-builtins.c
diff --git a/clang/test/CodeGen/RISCV/rvv-xcvbitmanip-builtins.c b/clang/test/CodeGen/RISCV/rvv-xcvbitmanip-builtins.c
new file mode 100644
index 0000000000000..98e976bc4122b
--- /dev/null
+++ b/clang/test/CodeGen/RISCV/rvv-xcvbitmanip-builtins.c
@@ -0,0 +1,95 @@
+// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py
+// RUN: %clang_cc1 -triple riscv32 -target-feature +xcvbitmanip -emit-llvm %s -o - \
+// RUN: | FileCheck %s
+
+// This file tests that XCVbitmanip Clang builtins are correctly lowered
+// to their corresponding LLVM IR intrinsics.
+
+#include <stdint.h>
+
+// CHECK-LABEL: @test_extract(
+// CHECK-NEXT: entry:
+// CHECK-NEXT: [[A_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT: store i32 [[A:%.*]], ptr [[A_ADDR]], align 4
+// CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[A_ADDR]], align 4
+// CHECK-NEXT: [[TMP1:%.*]] = call i32 @llvm.riscv.cv.bitmanip.extract(i32 [[TMP0]], i32 164)
+// CHECK-NEXT: ret i32 [[TMP1]]
+//
+uint32_t test_extract(uint32_t a) {
+ return __builtin_riscv_cv_bitmanip_extract(a, 164);
+}
+
+// CHECK-LABEL: @test_extractu(
+// CHECK-NEXT: entry:
+// CHECK-NEXT: [[A_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT: store i32 [[A:%.*]], ptr [[A_ADDR]], align 4
+// CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[A_ADDR]], align 4
+// CHECK-NEXT: [[TMP1:%.*]] = call i32 @llvm.riscv.cv.bitmanip.extractu(i32 [[TMP0]], i32 164)
+// CHECK-NEXT: ret i32 [[TMP1]]
+//
+uint32_t test_extractu(uint32_t a) {
+ return __builtin_riscv_cv_bitmanip_extractu(a, 164);
+}
+
+// CHECK-LABEL: @test_bclr(
+// CHECK-NEXT: entry:
+// CHECK-NEXT: [[A_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT: store i32 [[A:%.*]], ptr [[A_ADDR]], align 4
+// CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[A_ADDR]], align 4
+// CHECK-NEXT: [[TMP1:%.*]] = call i32 @llvm.riscv.cv.bitmanip.bclr(i32 [[TMP0]], i32 164)
+// CHECK-NEXT: ret i32 [[TMP1]]
+//
+uint32_t test_bclr(uint32_t a) {
+ return __builtin_riscv_cv_bitmanip_bclr(a, 164);
+}
+
+// CHECK-LABEL: @test_bset(
+// CHECK-NEXT: entry:
+// CHECK-NEXT: [[A_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT: store i32 [[A:%.*]], ptr [[A_ADDR]], align 4
+// CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[A_ADDR]], align 4
+// CHECK-NEXT: [[TMP1:%.*]] = call i32 @llvm.riscv.cv.bitmanip.bset(i32 [[TMP0]], i32 164)
+// CHECK-NEXT: ret i32 [[TMP1]]
+//
+uint32_t test_bset(uint32_t a) {
+ return __builtin_riscv_cv_bitmanip_bset(a, 164);
+}
+
+// CHECK-LABEL: @test_insert(
+// CHECK-NEXT: entry:
+// CHECK-NEXT: [[A_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT: [[RD_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT: store i32 [[A:%.*]], ptr [[A_ADDR]], align 4
+// CHECK-NEXT: store i32 [[RD:%.*]], ptr [[RD_ADDR]], align 4
+// CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[A_ADDR]], align 4
+// CHECK-NEXT: [[TMP1:%.*]] = load i32, ptr [[RD_ADDR]], align 4
+// CHECK-NEXT: [[TMP2:%.*]] = call i32 @llvm.riscv.cv.bitmanip.insert(i32 [[TMP0]], i32 164, i32 [[TMP1]])
+// CHECK-NEXT: ret i32 [[TMP2]]
+//
+uint32_t test_insert(uint32_t a, uint32_t rd) {
+ return __builtin_riscv_cv_bitmanip_insert(a, 164, rd);
+}
+
+// CHECK-LABEL: @test_clb(
+// CHECK-NEXT: entry:
+// CHECK-NEXT: [[A_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT: store i32 [[A:%.*]], ptr [[A_ADDR]], align 4
+// CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[A_ADDR]], align 4
+// CHECK-NEXT: [[TMP1:%.*]] = call i32 @llvm.riscv.cv.bitmanip.clb(i32 [[TMP0]])
+// CHECK-NEXT: ret i32 [[TMP1]]
+//
+uint32_t test_clb(uint32_t a) {
+ return __builtin_riscv_cv_bitmanip_clb(a);
+}
+
+// CHECK-LABEL: @test_bitrev(
+// CHECK-NEXT: entry:
+// CHECK-NEXT: [[A_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT: store i32 [[A:%.*]], ptr [[A_ADDR]], align 4
+// CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[A_ADDR]], align 4
+// CHECK-NEXT: [[TMP1:%.*]] = call i32 @llvm.riscv.cv.bitmanip.bitrev(i32 [[TMP0]], i32 2, i32 23)
+// CHECK-NEXT: ret i32 [[TMP1]]
+//
+uint32_t test_bitrev(uint32_t a) {
+ return __builtin_riscv_cv_bitmanip_bitrev(a, 2, 23);
+}
diff --git a/clang/test/Sema/rvv-xcv-sema.c b/clang/test/Sema/rvv-xcv-sema.c
index 7f873ecc02c14..b7e28fe28791c 100644
--- a/clang/test/Sema/rvv-xcv-sema.c
+++ b/clang/test/Sema/rvv-xcv-sema.c
@@ -55,3 +55,11 @@ void test_simd_subrotmj_range(uint32_t a, uint32_t b) {
(void)__builtin_riscv_cv_simd_subrotmj(a, b, 3); // OK
(void)__builtin_riscv_cv_simd_subrotmj(a, b, 4); // expected-error {{argument value 4 is outside the valid range [0, 3]}}
}
+
+// ===== XCVbitmanip — bitrev ranges =====
+
+void test_bitmanip_bitrev_range(uint32_t a) {
+ (void)__builtin_riscv_cv_bitmanip_bitrev(a, 3, 31); // OK: max values
+ (void)__builtin_riscv_cv_bitmanip_bitrev(a, 4, 0); // expected-error {{argument value 4 is outside the valid range [0, 3]}}
+ (void)__builtin_riscv_cv_bitmanip_bitrev(a, 0, 32); // expected-error {{argument value 32 is outside the valid range [0, 31]}}
+}
>From 8cc8f0f3ca6c7c15bf174c3f8e9ae2ffe8a44d1e Mon Sep 17 00:00:00 2001
From: vitbur <vittorioburani at gmail.com>
Date: Fri, 19 Jun 2026 18:51:40 +0200
Subject: [PATCH 10/10] [Clang][RISCV] Apply clang-format to XCV builtin
sources
---
clang/lib/Headers/riscv_corev_bitmanip.h | 49 ++--
clang/lib/Headers/riscv_corev_elw.h | 5 +-
clang/lib/Headers/riscv_corev_mac.h | 145 ++++++------
clang/lib/Headers/riscv_corev_simd.h | 289 +++++++++++++++--------
clang/lib/Sema/SemaRISCV.cpp | 15 +-
5 files changed, 296 insertions(+), 207 deletions(-)
diff --git a/clang/lib/Headers/riscv_corev_bitmanip.h b/clang/lib/Headers/riscv_corev_bitmanip.h
index 7676e44df87bd..d48c53f6c8a26 100644
--- a/clang/lib/Headers/riscv_corev_bitmanip.h
+++ b/clang/lib/Headers/riscv_corev_bitmanip.h
@@ -26,7 +26,7 @@ extern "C" {
#if defined(__riscv_xcvbitmanip)
-#define __DEFAULT_FN_ATTRS \
+#define __DEFAULT_FN_ATTRS \
__attribute__((__always_inline__, __nodebug__, __artificial__))
/* ---------------------------------------------------------------------------
@@ -35,34 +35,38 @@ extern "C" {
* IS3 = bit-width (uimm5), IS2 = lower bit index (uimm5)
* The two immediates are packed as a single uimm10: IS3<<5 | IS2
* IMM must be a compile-time constant.
- * --------------------------------------------------------------------------- */
-#define __riscv_cv_bitmanip_extract(__rs1, __IMM) \
+ * ---------------------------------------------------------------------------
+ */
+#define __riscv_cv_bitmanip_extract(__rs1, __IMM) \
((int32_t)__builtin_riscv_cv_bitmanip_extract((uint32_t)(__rs1), \
- (uint32_t)(__IMM)))
+ (uint32_t)(__IMM)))
/* ---------------------------------------------------------------------------
* cv.extractu rd, rs1, IS3, IS2
* rd = ZeroExtend(rs1[IS3+IS2-1 : IS2], 32)
- * --------------------------------------------------------------------------- */
+ * ---------------------------------------------------------------------------
+ */
#define __riscv_cv_bitmanip_extractu(__rs1, __IMM) \
- ((uint32_t)__builtin_riscv_cv_bitmanip_extractu((uint32_t)(__rs1), \
- (uint32_t)(__IMM)))
+ ((uint32_t)__builtin_riscv_cv_bitmanip_extractu((uint32_t)(__rs1), \
+ (uint32_t)(__IMM)))
/* ---------------------------------------------------------------------------
* cv.bclr rd, rs1, IS3, IS2
* rd = rs1 & ~(((1 << IS3) - 1) << IS2) (clear IS3 bits starting at IS2)
- * --------------------------------------------------------------------------- */
+ * ---------------------------------------------------------------------------
+ */
#define __riscv_cv_bitmanip_bclr(__rs1, __IMM) \
- ((uint32_t)__builtin_riscv_cv_bitmanip_bclr((uint32_t)(__rs1), \
- (uint32_t)(__IMM)))
+ ((uint32_t)__builtin_riscv_cv_bitmanip_bclr((uint32_t)(__rs1), \
+ (uint32_t)(__IMM)))
/* ---------------------------------------------------------------------------
* cv.bset rd, rs1, IS3, IS2
* rd = rs1 | (((1 << IS3) - 1) << IS2) (set IS3 bits starting at IS2)
- * --------------------------------------------------------------------------- */
+ * ---------------------------------------------------------------------------
+ */
#define __riscv_cv_bitmanip_bset(__rs1, __IMM) \
- ((uint32_t)__builtin_riscv_cv_bitmanip_bset((uint32_t)(__rs1), \
- (uint32_t)(__IMM)))
+ ((uint32_t)__builtin_riscv_cv_bitmanip_bset((uint32_t)(__rs1), \
+ (uint32_t)(__IMM)))
/* ---------------------------------------------------------------------------
* cv.insert rd, rs1, IS3, IS2
@@ -70,11 +74,11 @@ extern "C" {
* rd is read-modify-write (the bits outside the target range are preserved).
* IS3 = bit-width (uimm5), IS2 = lower bit index (uimm5)
* The two immediates are packed as a single uimm10: IS3<<5 | IS2
- * --------------------------------------------------------------------------- */
+ * ---------------------------------------------------------------------------
+ */
#define __riscv_cv_bitmanip_insert(__rD, __rs1, __IMM) \
- ((uint32_t)__builtin_riscv_cv_bitmanip_insert((uint32_t)(__rs1), \
- (uint32_t)(__IMM), \
- (uint32_t)(__rD)))
+ ((uint32_t)__builtin_riscv_cv_bitmanip_insert( \
+ (uint32_t)(__rs1), (uint32_t)(__IMM), (uint32_t)(__rD)))
/* ---------------------------------------------------------------------------
* cv.clb rd, rs1
@@ -88,7 +92,8 @@ extern "C" {
* standard C expressions (__builtin_ctz, __builtin_clz, __builtin_popcount,
* rotate patterns) when -march includes xcvbitmanip. No explicit builtin call
* is required or provided for those four operations.
- * --------------------------------------------------------------------------- */
+ * ---------------------------------------------------------------------------
+ */
static __inline__ uint32_t __DEFAULT_FN_ATTRS
__riscv_cv_bitmanip_clb(uint32_t a) {
return __builtin_riscv_cv_bitmanip_clb(a);
@@ -102,11 +107,11 @@ __riscv_cv_bitmanip_clb(uint32_t a) {
*
* Example: cv.bitrev t0, t0, 2, 23 reverses groups of 4 bits within each
* 24-bit window.
- * --------------------------------------------------------------------------- */
+ * ---------------------------------------------------------------------------
+ */
#define __riscv_cv_bitmanip_bitrev(__rs1, __IS2, __IS3) \
- ((uint32_t)__builtin_riscv_cv_bitmanip_bitrev((uint32_t)(__rs1), \
- (uint32_t)(__IS2), \
- (uint32_t)(__IS3)))
+ ((uint32_t)__builtin_riscv_cv_bitmanip_bitrev( \
+ (uint32_t)(__rs1), (uint32_t)(__IS2), (uint32_t)(__IS3)))
#endif /* __riscv_xcvbitmanip */
diff --git a/clang/lib/Headers/riscv_corev_elw.h b/clang/lib/Headers/riscv_corev_elw.h
index 9676799b5b2e0..f0583ad35c543 100644
--- a/clang/lib/Headers/riscv_corev_elw.h
+++ b/clang/lib/Headers/riscv_corev_elw.h
@@ -5,12 +5,11 @@
extern "C" {
#endif
#if defined(__riscv_xcvelw)
-#define __DEFAULT_FN_ATTRS \
+#define __DEFAULT_FN_ATTRS \
__attribute__((__always_inline__, __nodebug__, __artificial__))
// cv.elw rd, imm(rs1): event load word
-static __inline__ int32_t __DEFAULT_FN_ATTRS
-__riscv_cv_elw_elw(int32_t *ptr) {
+static __inline__ int32_t __DEFAULT_FN_ATTRS __riscv_cv_elw_elw(int32_t *ptr) {
return __builtin_riscv_cv_elw_elw(ptr);
}
#endif
diff --git a/clang/lib/Headers/riscv_corev_mac.h b/clang/lib/Headers/riscv_corev_mac.h
index 531c9b01f862f..dccb8ae9dbf81 100644
--- a/clang/lib/Headers/riscv_corev_mac.h
+++ b/clang/lib/Headers/riscv_corev_mac.h
@@ -26,18 +26,19 @@ extern "C" {
#if defined(__riscv_xcvmac)
-#define __DEFAULT_FN_ATTRS \
+#define __DEFAULT_FN_ATTRS \
__attribute__((__always_inline__, __nodebug__, __artificial__))
/* ---------------------------------------------------------------------------
* 32x32-bit MAC / MSU
*
- * cv.mac rd, rs1, rs2 -> rd += rs1 * rs2
- * cv.msu rd, rs1, rs2 -> rd -= rs1 * rs2
+ * cv.mac rd, rs1, rs2 -> rd += rs1 * rs2
+ * cv.msu rd, rs1, rs2 -> rd -= rs1 * rs2
*
* These are the only two operations that take a plain GPR accumulator
* (no shift/round), so they can be static inline functions.
- * --------------------------------------------------------------------------- */
+ * ---------------------------------------------------------------------------
+ */
static __inline__ int32_t __DEFAULT_FN_ATTRS
__riscv_cv_mac_mac(int32_t a, int32_t b, int32_t accumulator) {
@@ -52,136 +53,124 @@ __riscv_cv_mac_msu(int32_t a, int32_t b, int32_t accumulator) {
/* ---------------------------------------------------------------------------
* 16x16-bit multiply (lower halfwords), unsigned, with normalisation shift
*
- * cv.mulun rd, rs1, rs2, imm5 -> rd = (u16(rs1) * u16(rs2)) >> imm5
- * cv.mulhhun rd, rs1, rs2, imm5 -> rd = (u16hi(rs1) * u16hi(rs2)) >> imm5
- * cv.mulurn rd, rs1, rs2, imm5 -> rd = (u16(rs1) * u16(rs2) + rnd) >> imm5
- * cv.mulhhurn rd, rs1, rs2, imm5 -> rd = (u16hi(rs1)*u16hi(rs2) + rnd) >> imm5
+ * cv.mulun rd, rs1, rs2, imm5 -> rd = (u16(rs1) * u16(rs2)) >> imm5
+ * cv.mulhhun rd, rs1, rs2, imm5 -> rd = (u16hi(rs1) * u16hi(rs2)) >> imm5
+ * cv.mulurn rd, rs1, rs2, imm5 -> rd = (u16(rs1) * u16(rs2) + rnd) >> imm5
+ * cv.mulhhurn rd, rs1, rs2, imm5 -> rd = (u16hi(rs1)*u16hi(rs2) + rnd) >> imm5
*
* SHIFT must be a compile-time constant in [0, 31].
* These are macros so the SHIFT argument is passed as an immediate.
- * --------------------------------------------------------------------------- */
+ * ---------------------------------------------------------------------------
+ */
#define __riscv_cv_mac_muluN(__rs1, __rs2, __SHIFT) \
- ((uint32_t)__builtin_riscv_cv_mac_muluN((uint32_t)(__rs1), \
- (uint32_t)(__rs2), \
- (uint32_t)(__SHIFT)))
+ ((uint32_t)__builtin_riscv_cv_mac_muluN( \
+ (uint32_t)(__rs1), (uint32_t)(__rs2), (uint32_t)(__SHIFT)))
#define __riscv_cv_mac_mulhhuN(__rs1, __rs2, __SHIFT) \
- ((uint32_t)__builtin_riscv_cv_mac_mulhhuN((uint32_t)(__rs1), \
- (uint32_t)(__rs2), \
- (uint32_t)(__SHIFT)))
+ ((uint32_t)__builtin_riscv_cv_mac_mulhhuN( \
+ (uint32_t)(__rs1), (uint32_t)(__rs2), (uint32_t)(__SHIFT)))
#define __riscv_cv_mac_muluRN(__rs1, __rs2, __SHIFT) \
- ((uint32_t)__builtin_riscv_cv_mac_muluRN((uint32_t)(__rs1), \
- (uint32_t)(__rs2), \
- (uint32_t)(__SHIFT)))
+ ((uint32_t)__builtin_riscv_cv_mac_muluRN( \
+ (uint32_t)(__rs1), (uint32_t)(__rs2), (uint32_t)(__SHIFT)))
#define __riscv_cv_mac_mulhhuRN(__rs1, __rs2, __SHIFT) \
- ((uint32_t)__builtin_riscv_cv_mac_mulhhuRN((uint32_t)(__rs1), \
- (uint32_t)(__rs2), \
- (uint32_t)(__SHIFT)))
+ ((uint32_t)__builtin_riscv_cv_mac_mulhhuRN( \
+ (uint32_t)(__rs1), (uint32_t)(__rs2), (uint32_t)(__SHIFT)))
/* ---------------------------------------------------------------------------
* 16x16-bit multiply (lower halfwords), signed, with normalisation shift
*
- * cv.mulsn rd, rs1, rs2, imm5 -> rd = (s16(rs1) * s16(rs2)) >> imm5
- * cv.mulhhsn rd, rs1, rs2, imm5 -> rd = (s16hi(rs1)*s16hi(rs2)) >> imm5
- * cv.mulsrn rd, rs1, rs2, imm5 -> rd = (s16(rs1) * s16(rs2) + rnd) >> imm5
- * cv.mulhhsrn rd, rs1, rs2, imm5 -> rd = (s16hi(rs1)*s16hi(rs2)+rnd) >> imm5
+ * cv.mulsn rd, rs1, rs2, imm5 -> rd = (s16(rs1) * s16(rs2)) >> imm5
+ * cv.mulhhsn rd, rs1, rs2, imm5 -> rd = (s16hi(rs1)*s16hi(rs2)) >> imm5
+ * cv.mulsrn rd, rs1, rs2, imm5 -> rd = (s16(rs1) * s16(rs2) + rnd) >> imm5
+ * cv.mulhhsrn rd, rs1, rs2, imm5 -> rd = (s16hi(rs1)*s16hi(rs2)+rnd) >> imm5
*
* SHIFT must be a compile-time constant in [0, 31].
- * --------------------------------------------------------------------------- */
+ * ---------------------------------------------------------------------------
+ */
#define __riscv_cv_mac_mulsN(__rs1, __rs2, __SHIFT) \
- ((int32_t)__builtin_riscv_cv_mac_mulsN((uint32_t)(__rs1), \
- (uint32_t)(__rs2), \
- (uint32_t)(__SHIFT)))
+ ((int32_t)__builtin_riscv_cv_mac_mulsN((uint32_t)(__rs1), (uint32_t)(__rs2), \
+ (uint32_t)(__SHIFT)))
#define __riscv_cv_mac_mulhhsN(__rs1, __rs2, __SHIFT) \
- ((int32_t)__builtin_riscv_cv_mac_mulhhsN((uint32_t)(__rs1), \
- (uint32_t)(__rs2), \
- (uint32_t)(__SHIFT)))
+ ((int32_t)__builtin_riscv_cv_mac_mulhhsN( \
+ (uint32_t)(__rs1), (uint32_t)(__rs2), (uint32_t)(__SHIFT)))
#define __riscv_cv_mac_mulsRN(__rs1, __rs2, __SHIFT) \
- ((int32_t)__builtin_riscv_cv_mac_mulsRN((uint32_t)(__rs1), \
- (uint32_t)(__rs2), \
- (uint32_t)(__SHIFT)))
+ ((int32_t)__builtin_riscv_cv_mac_mulsRN( \
+ (uint32_t)(__rs1), (uint32_t)(__rs2), (uint32_t)(__SHIFT)))
#define __riscv_cv_mac_mulhhsRN(__rs1, __rs2, __SHIFT) \
- ((int32_t)__builtin_riscv_cv_mac_mulhhsRN((uint32_t)(__rs1), \
- (uint32_t)(__rs2), \
- (uint32_t)(__SHIFT)))
+ ((int32_t)__builtin_riscv_cv_mac_mulhhsRN( \
+ (uint32_t)(__rs1), (uint32_t)(__rs2), (uint32_t)(__SHIFT)))
/* ---------------------------------------------------------------------------
* 16x16-bit multiply-accumulate (lower halfwords), unsigned
*
- * cv.macun rd, rs1, rs2, imm5 -> rd = (rd + u16(rs1) * u16(rs2)) >> imm5
- * cv.machhun rd, rs1, rs2, imm5 -> rd = (rd + u16hi(rs1)*u16hi(rs2)) >> imm5
- * cv.macurn rd, rs1, rs2, imm5 -> rd = (rd + u16(rs1)*u16(rs2)+rnd) >> imm5
- * cv.machhurn rd, rs1, rs2, imm5 -> rd = (rd+u16hi(rs1)*u16hi(rs2)+rnd)>>imm5
+ * cv.macun rd, rs1, rs2, imm5 -> rd = (rd + u16(rs1) * u16(rs2)) >> imm5
+ * cv.machhun rd, rs1, rs2, imm5 -> rd = (rd + u16hi(rs1)*u16hi(rs2)) >> imm5
+ * cv.macurn rd, rs1, rs2, imm5 -> rd = (rd + u16(rs1)*u16(rs2)+rnd) >> imm5
+ * cv.machhurn rd, rs1, rs2, imm5 -> rd = (rd+u16hi(rs1)*u16hi(rs2)+rnd)>>imm5
*
* SHIFT must be a compile-time constant in [0, 31].
* rD is the accumulator register (read-modify-write).
- * --------------------------------------------------------------------------- */
+ * ---------------------------------------------------------------------------
+ */
#define __riscv_cv_mac_macuN(__rD, __rs1, __rs2, __SHIFT) \
((uint32_t)__builtin_riscv_cv_mac_macuN((uint32_t)(__rs1), \
- (uint32_t)(__rs2), \
- (uint32_t)(__rD), \
- (uint32_t)(__SHIFT)))
+ (uint32_t)(__rs2), (uint32_t)(__rD), \
+ (uint32_t)(__SHIFT)))
#define __riscv_cv_mac_machhuN(__rD, __rs1, __rs2, __SHIFT) \
- ((uint32_t)__builtin_riscv_cv_mac_machhuN((uint32_t)(__rs1), \
- (uint32_t)(__rs2), \
- (uint32_t)(__rD), \
- (uint32_t)(__SHIFT)))
+ ((uint32_t)__builtin_riscv_cv_mac_machhuN( \
+ (uint32_t)(__rs1), (uint32_t)(__rs2), (uint32_t)(__rD), \
+ (uint32_t)(__SHIFT)))
#define __riscv_cv_mac_macuRN(__rD, __rs1, __rs2, __SHIFT) \
- ((uint32_t)__builtin_riscv_cv_mac_macuRN((uint32_t)(__rs1), \
- (uint32_t)(__rs2), \
- (uint32_t)(__rD), \
- (uint32_t)(__SHIFT)))
+ ((uint32_t)__builtin_riscv_cv_mac_macuRN( \
+ (uint32_t)(__rs1), (uint32_t)(__rs2), (uint32_t)(__rD), \
+ (uint32_t)(__SHIFT)))
#define __riscv_cv_mac_machhuRN(__rD, __rs1, __rs2, __SHIFT) \
- ((uint32_t)__builtin_riscv_cv_mac_machhuRN((uint32_t)(__rs1), \
- (uint32_t)(__rs2), \
- (uint32_t)(__rD), \
- (uint32_t)(__SHIFT)))
+ ((uint32_t)__builtin_riscv_cv_mac_machhuRN( \
+ (uint32_t)(__rs1), (uint32_t)(__rs2), (uint32_t)(__rD), \
+ (uint32_t)(__SHIFT)))
/* ---------------------------------------------------------------------------
* 16x16-bit multiply-accumulate (lower halfwords), signed
*
- * cv.macsn rd, rs1, rs2, imm5 -> rd = (rd + s16(rs1) * s16(rs2)) >> imm5
- * cv.machhsn rd, rs1, rs2, imm5 -> rd = (rd+s16hi(rs1)*s16hi(rs2)) >> imm5
- * cv.macsrn rd, rs1, rs2, imm5 -> rd = (rd+s16(rs1)*s16(rs2)+rnd) >> imm5
- * cv.machhsrn rd, rs1, rs2, imm5 -> rd = (rd+s16hi*s16hi+rnd) >> imm5
+ * cv.macsn rd, rs1, rs2, imm5 -> rd = (rd + s16(rs1) * s16(rs2)) >> imm5
+ * cv.machhsn rd, rs1, rs2, imm5 -> rd = (rd+s16hi(rs1)*s16hi(rs2)) >> imm5
+ * cv.macsrn rd, rs1, rs2, imm5 -> rd = (rd+s16(rs1)*s16(rs2)+rnd) >> imm5
+ * cv.machhsrn rd, rs1, rs2, imm5 -> rd = (rd+s16hi*s16hi+rnd) >> imm5
*
* SHIFT must be a compile-time constant in [0, 31].
- * --------------------------------------------------------------------------- */
+ * ---------------------------------------------------------------------------
+ */
#define __riscv_cv_mac_macsN(__rD, __rs1, __rs2, __SHIFT) \
- ((int32_t)__builtin_riscv_cv_mac_macsN((uint32_t)(__rs1), \
- (uint32_t)(__rs2), \
- (uint32_t)(__rD), \
- (uint32_t)(__SHIFT)))
+ ((int32_t)__builtin_riscv_cv_mac_macsN((uint32_t)(__rs1), (uint32_t)(__rs2), \
+ (uint32_t)(__rD), \
+ (uint32_t)(__SHIFT)))
#define __riscv_cv_mac_machhsN(__rD, __rs1, __rs2, __SHIFT) \
- ((int32_t)__builtin_riscv_cv_mac_machhsN((uint32_t)(__rs1), \
- (uint32_t)(__rs2), \
- (uint32_t)(__rD), \
- (uint32_t)(__SHIFT)))
+ ((int32_t)__builtin_riscv_cv_mac_machhsN( \
+ (uint32_t)(__rs1), (uint32_t)(__rs2), (uint32_t)(__rD), \
+ (uint32_t)(__SHIFT)))
#define __riscv_cv_mac_macsRN(__rD, __rs1, __rs2, __SHIFT) \
((int32_t)__builtin_riscv_cv_mac_macsRN((uint32_t)(__rs1), \
- (uint32_t)(__rs2), \
- (uint32_t)(__rD), \
- (uint32_t)(__SHIFT)))
+ (uint32_t)(__rs2), (uint32_t)(__rD), \
+ (uint32_t)(__SHIFT)))
#define __riscv_cv_mac_machhsRN(__rD, __rs1, __rs2, __SHIFT) \
- ((int32_t)__builtin_riscv_cv_mac_machhsRN((uint32_t)(__rs1), \
- (uint32_t)(__rs2), \
- (uint32_t)(__rD), \
- (uint32_t)(__SHIFT)))
+ ((int32_t)__builtin_riscv_cv_mac_machhsRN( \
+ (uint32_t)(__rs1), (uint32_t)(__rs2), (uint32_t)(__rD), \
+ (uint32_t)(__SHIFT)))
#endif /* __riscv_xcvmac */
diff --git a/clang/lib/Headers/riscv_corev_simd.h b/clang/lib/Headers/riscv_corev_simd.h
index a1b7164b3977e..3127d0eebfe92 100644
--- a/clang/lib/Headers/riscv_corev_simd.h
+++ b/clang/lib/Headers/riscv_corev_simd.h
@@ -32,7 +32,7 @@ extern "C" {
#if defined(__riscv_xcvsimd)
-#define __DEFAULT_FN_ATTRS \
+#define __DEFAULT_FN_ATTRS \
__attribute__((__always_inline__, __nodebug__, __artificial__))
/* ===========================================================================
@@ -44,16 +44,16 @@ extern "C" {
* The _h variant takes a div-shift code as third argument (0=no shift,
* 1=/2, 2=/4, 3=/8). This is an immediate, so it must be a compile-time
* constant — hence the macro form.
- * =========================================================================== */
+ * ===========================================================================
+ */
/* add.h with div-by-N right shift (DIVCODE in [0,3]) */
#define __riscv_cv_simd_add_h(__rs1, __rs2, __DIVCODE) \
- ((uint32_t)__builtin_riscv_cv_simd_add_h((uint32_t)(__rs1), \
- (uint32_t)(__rs2), \
- (uint32_t)(__DIVCODE)))
+ ((uint32_t)__builtin_riscv_cv_simd_add_h( \
+ (uint32_t)(__rs1), (uint32_t)(__rs2), (uint32_t)(__DIVCODE)))
-static __inline__ uint32_t __DEFAULT_FN_ATTRS
-__riscv_cv_simd_add_b(uint32_t a, uint32_t b) {
+static __inline__ uint32_t
+ __DEFAULT_FN_ATTRS __riscv_cv_simd_add_b(uint32_t a, uint32_t b) {
return __builtin_riscv_cv_simd_add_b(a, b);
}
static __inline__ uint32_t __DEFAULT_FN_ATTRS
@@ -67,12 +67,11 @@ __riscv_cv_simd_add_sc_b(uint32_t a, uint32_t b) {
/* sub.h with div-by-N right shift (DIVCODE in [0,3]) */
#define __riscv_cv_simd_sub_h(__rs1, __rs2, __DIVCODE) \
- ((uint32_t)__builtin_riscv_cv_simd_sub_h((uint32_t)(__rs1), \
- (uint32_t)(__rs2), \
- (uint32_t)(__DIVCODE)))
+ ((uint32_t)__builtin_riscv_cv_simd_sub_h( \
+ (uint32_t)(__rs1), (uint32_t)(__rs2), (uint32_t)(__DIVCODE)))
-static __inline__ uint32_t __DEFAULT_FN_ATTRS
-__riscv_cv_simd_sub_b(uint32_t a, uint32_t b) {
+static __inline__ uint32_t
+ __DEFAULT_FN_ATTRS __riscv_cv_simd_sub_b(uint32_t a, uint32_t b) {
return __builtin_riscv_cv_simd_sub_b(a, b);
}
static __inline__ uint32_t __DEFAULT_FN_ATTRS
@@ -86,7 +85,8 @@ __riscv_cv_simd_sub_sc_b(uint32_t a, uint32_t b) {
/* ===========================================================================
* AVG / AVGU (signed and unsigned average)
- * =========================================================================== */
+ * ===========================================================================
+ */
static __inline__ uint32_t __DEFAULT_FN_ATTRS
__riscv_cv_simd_avg_h(uint32_t a, uint32_t b) {
@@ -124,7 +124,8 @@ __riscv_cv_simd_avgu_sc_b(uint32_t a, uint32_t b) {
/* ===========================================================================
* MIN / MINU (signed and unsigned per-element minimum)
- * =========================================================================== */
+ * ===========================================================================
+ */
static __inline__ uint32_t __DEFAULT_FN_ATTRS
__riscv_cv_simd_min_h(uint32_t a, uint32_t b) {
@@ -162,7 +163,8 @@ __riscv_cv_simd_minu_sc_b(uint32_t a, uint32_t b) {
/* ===========================================================================
* MAX / MAXU (signed and unsigned per-element maximum)
- * =========================================================================== */
+ * ===========================================================================
+ */
static __inline__ uint32_t __DEFAULT_FN_ATTRS
__riscv_cv_simd_max_h(uint32_t a, uint32_t b) {
@@ -203,7 +205,8 @@ __riscv_cv_simd_maxu_sc_b(uint32_t a, uint32_t b) {
* .sc variants take a GPR shift amount (lower bits used)
* No .sci variant for shifts (the instruction encodes a small immediate
* directly in the funct3 space; use the .sc_h/.sc_b with a constant GPR).
- * =========================================================================== */
+ * ===========================================================================
+ */
static __inline__ uint32_t __DEFAULT_FN_ATTRS
__riscv_cv_simd_srl_h(uint32_t a, uint32_t b) {
@@ -258,14 +261,15 @@ __riscv_cv_simd_sll_sc_b(uint32_t a, uint32_t b) {
/* ===========================================================================
* BITWISE: OR / XOR / AND
- * =========================================================================== */
+ * ===========================================================================
+ */
-static __inline__ uint32_t __DEFAULT_FN_ATTRS
-__riscv_cv_simd_or_h(uint32_t a, uint32_t b) {
+static __inline__ uint32_t __DEFAULT_FN_ATTRS __riscv_cv_simd_or_h(uint32_t a,
+ uint32_t b) {
return __builtin_riscv_cv_simd_or_h(a, b);
}
-static __inline__ uint32_t __DEFAULT_FN_ATTRS
-__riscv_cv_simd_or_b(uint32_t a, uint32_t b) {
+static __inline__ uint32_t __DEFAULT_FN_ATTRS __riscv_cv_simd_or_b(uint32_t a,
+ uint32_t b) {
return __builtin_riscv_cv_simd_or_b(a, b);
}
static __inline__ uint32_t __DEFAULT_FN_ATTRS
@@ -313,7 +317,8 @@ __riscv_cv_simd_and_sc_b(uint32_t a, uint32_t b) {
/* ===========================================================================
* ABS (per-element absolute value)
- * =========================================================================== */
+ * ===========================================================================
+ */
static __inline__ uint32_t __DEFAULT_FN_ATTRS
__riscv_cv_simd_abs_h(uint32_t a) {
@@ -332,7 +337,8 @@ __riscv_cv_simd_abs_b(uint32_t a) {
* dotsp — signed × signed dot product (result is int32)
*
* sdot* — same but adds result to accumulator register rd (read-modify-write)
- * =========================================================================== */
+ * ===========================================================================
+ */
/* dotup */
static __inline__ uint32_t __DEFAULT_FN_ATTRS
@@ -453,35 +459,34 @@ __riscv_cv_simd_sdotsp_sc_b(uint32_t a, uint32_t b, int32_t acc) {
* cv.insert.b rd, rs1, IMM — insert lower byte of rs1 into rd at IMM
*
* IMM is an immediate (compile-time constant), so macros are used.
- * =========================================================================== */
+ * ===========================================================================
+ */
#define __riscv_cv_simd_extract_h(__rs1, __IMM) \
((int32_t)__builtin_riscv_cv_simd_extract_h((uint32_t)(__rs1), \
- (uint32_t)(__IMM)))
+ (uint32_t)(__IMM)))
#define __riscv_cv_simd_extract_b(__rs1, __IMM) \
((int32_t)__builtin_riscv_cv_simd_extract_b((uint32_t)(__rs1), \
- (uint32_t)(__IMM)))
+ (uint32_t)(__IMM)))
#define __riscv_cv_simd_extractu_h(__rs1, __IMM) \
((uint32_t)__builtin_riscv_cv_simd_extractu_h((uint32_t)(__rs1), \
- (uint32_t)(__IMM)))
+ (uint32_t)(__IMM)))
#define __riscv_cv_simd_extractu_b(__rs1, __IMM) \
((uint32_t)__builtin_riscv_cv_simd_extractu_b((uint32_t)(__rs1), \
- (uint32_t)(__IMM)))
+ (uint32_t)(__IMM)))
/* insert: rd is both input and output (read-modify-write accumulator).
The intrinsic prototype is (rs1, rd_in, IMM) -> rd_out. */
#define __riscv_cv_simd_insert_h(__rD, __rs1, __IMM) \
- ((uint32_t)__builtin_riscv_cv_simd_insert_h((uint32_t)(__rD), \
- (uint32_t)(__rs1), \
- (uint32_t)(__IMM)))
+ ((uint32_t)__builtin_riscv_cv_simd_insert_h( \
+ (uint32_t)(__rD), (uint32_t)(__rs1), (uint32_t)(__IMM)))
#define __riscv_cv_simd_insert_b(__rD, __rs1, __IMM) \
- ((uint32_t)__builtin_riscv_cv_simd_insert_b((uint32_t)(__rD), \
- (uint32_t)(__rs1), \
- (uint32_t)(__IMM)))
+ ((uint32_t)__builtin_riscv_cv_simd_insert_b( \
+ (uint32_t)(__rD), (uint32_t)(__rs1), (uint32_t)(__IMM)))
/* ===========================================================================
* SHUFFLE / SHUFFLE2
@@ -493,7 +498,8 @@ __riscv_cv_simd_sdotsp_sc_b(uint32_t a, uint32_t b, int32_t acc) {
* (split internally into SHUFFLEIx.sci.b)
* cv.shuffle2.h rd, rs1, rs2 — interleave shuffle using rs2 mask + rd input
* cv.shuffle2.b rd, rs1, rs2 — interleave shuffle using rs2 mask + rd input
- * =========================================================================== */
+ * ===========================================================================
+ */
static __inline__ uint32_t __DEFAULT_FN_ATTRS
__riscv_cv_simd_shuffle_h(uint32_t a, uint32_t mask) {
@@ -507,14 +513,14 @@ __riscv_cv_simd_shuffle_b(uint32_t a, uint32_t mask) {
/* shuffle.sci.h — IMM is a 2-bit immediate [0,3] */
#define __riscv_cv_simd_shuffle_sci_h(__rs1, __IMM) \
((uint32_t)__builtin_riscv_cv_simd_shuffle_sci_h((uint32_t)(__rs1), \
- (uint32_t)(__IMM)))
+ (uint32_t)(__IMM)))
/* shuffle.sci.b — IMM is an 8-bit immediate [0,255].
The backend splits this into two bits (top 2 → SHUFFLEIx selector) + 6-bit
payload, emitting the correct CV_SHUFFLEIx_SCI_B instruction. */
#define __riscv_cv_simd_shuffle_sci_b(__rs1, __IMM) \
((uint32_t)__builtin_riscv_cv_simd_shuffle_sci_b((uint32_t)(__rs1), \
- (uint32_t)(__IMM)))
+ (uint32_t)(__IMM)))
/* shuffle2: rd is read-modify-write (used as additional input lane) */
static __inline__ uint32_t __DEFAULT_FN_ATTRS
@@ -529,15 +535,21 @@ __riscv_cv_simd_shuffle2_b(uint32_t rD, uint32_t rs1, uint32_t rs2) {
/* ===========================================================================
* PACK
*
- * cv.pack rd, rs1, rs2 — pack lower halfwords: rd = {rs1[15:0], rs2[15:0]}
- * cv.pack.h rd, rs1, rs2 — pack upper halfwords: rd = {rs1[31:16], rs2[31:16]}
- * cv.packhi.b rd, rs1, rs2 — pack odd bytes: rd = {rs1[31:24],rs1[15:8],
- * rs2[31:24],rs2[15:8]}
- * cv.packlo.b rd, rs1, rs2 — pack even bytes: rd = {rs1[23:16],rs1[7:0],
- * rs2[23:16],rs2[7:0]}
+ * cv.pack rd, rs1, rs2 — pack lower halfwords:
+ * rd = {rs1[15:0], rs2[15:0]}
+ *
+ * cv.pack.h rd, rs1, rs2 — pack upper halfwords:
+ * rd = {rs1[31:16], rs2[31:16]}
+ *
+ * cv.packhi.b rd, rs1, rs2 — pack odd bytes:
+ * rd = {rs1[31:24],rs1[15:8], rs2[31:24],rs2[15:8]}
+ *
+ * cv.packlo.b rd, rs1, rs2 — pack even bytes:
+ * rd = {rs1[23:16],rs1[7:0], rs2[23:16],rs2[7:0]}
*
* packhi/packlo: rd is read-modify-write.
- * =========================================================================== */
+ * ===========================================================================
+ */
static __inline__ uint32_t __DEFAULT_FN_ATTRS
__riscv_cv_simd_packlo_h(uint32_t rs1, uint32_t rs2) {
@@ -560,107 +572,188 @@ __riscv_cv_simd_packlo_b(uint32_t rD, uint32_t rs1, uint32_t rs2) {
/* ===========================================================================
* COMPARE (per-element, result is all-1s or all-0s per lane)
- * =========================================================================== */
+ * ===========================================================================
+ */
/* cmpeq */
static __inline__ uint32_t __DEFAULT_FN_ATTRS
-__riscv_cv_simd_cmpeq_h(uint32_t a, uint32_t b) { return __builtin_riscv_cv_simd_cmpeq_h(a, b); }
+__riscv_cv_simd_cmpeq_h(uint32_t a, uint32_t b) {
+ return __builtin_riscv_cv_simd_cmpeq_h(a, b);
+}
static __inline__ uint32_t __DEFAULT_FN_ATTRS
-__riscv_cv_simd_cmpeq_b(uint32_t a, uint32_t b) { return __builtin_riscv_cv_simd_cmpeq_b(a, b); }
+__riscv_cv_simd_cmpeq_b(uint32_t a, uint32_t b) {
+ return __builtin_riscv_cv_simd_cmpeq_b(a, b);
+}
static __inline__ uint32_t __DEFAULT_FN_ATTRS
-__riscv_cv_simd_cmpeq_sc_h(uint32_t a, uint32_t b) { return __builtin_riscv_cv_simd_cmpeq_sc_h(a, b); }
+__riscv_cv_simd_cmpeq_sc_h(uint32_t a, uint32_t b) {
+ return __builtin_riscv_cv_simd_cmpeq_sc_h(a, b);
+}
static __inline__ uint32_t __DEFAULT_FN_ATTRS
-__riscv_cv_simd_cmpeq_sc_b(uint32_t a, uint32_t b) { return __builtin_riscv_cv_simd_cmpeq_sc_b(a, b); }
+__riscv_cv_simd_cmpeq_sc_b(uint32_t a, uint32_t b) {
+ return __builtin_riscv_cv_simd_cmpeq_sc_b(a, b);
+}
/* cmpne */
static __inline__ uint32_t __DEFAULT_FN_ATTRS
-__riscv_cv_simd_cmpne_h(uint32_t a, uint32_t b) { return __builtin_riscv_cv_simd_cmpne_h(a, b); }
+__riscv_cv_simd_cmpne_h(uint32_t a, uint32_t b) {
+ return __builtin_riscv_cv_simd_cmpne_h(a, b);
+}
static __inline__ uint32_t __DEFAULT_FN_ATTRS
-__riscv_cv_simd_cmpne_b(uint32_t a, uint32_t b) { return __builtin_riscv_cv_simd_cmpne_b(a, b); }
+__riscv_cv_simd_cmpne_b(uint32_t a, uint32_t b) {
+ return __builtin_riscv_cv_simd_cmpne_b(a, b);
+}
static __inline__ uint32_t __DEFAULT_FN_ATTRS
-__riscv_cv_simd_cmpne_sc_h(uint32_t a, uint32_t b) { return __builtin_riscv_cv_simd_cmpne_sc_h(a, b); }
+__riscv_cv_simd_cmpne_sc_h(uint32_t a, uint32_t b) {
+ return __builtin_riscv_cv_simd_cmpne_sc_h(a, b);
+}
static __inline__ uint32_t __DEFAULT_FN_ATTRS
-__riscv_cv_simd_cmpne_sc_b(uint32_t a, uint32_t b) { return __builtin_riscv_cv_simd_cmpne_sc_b(a, b); }
+__riscv_cv_simd_cmpne_sc_b(uint32_t a, uint32_t b) {
+ return __builtin_riscv_cv_simd_cmpne_sc_b(a, b);
+}
/* cmpgt (signed greater-than) */
static __inline__ uint32_t __DEFAULT_FN_ATTRS
-__riscv_cv_simd_cmpgt_h(uint32_t a, uint32_t b) { return __builtin_riscv_cv_simd_cmpgt_h(a, b); }
+__riscv_cv_simd_cmpgt_h(uint32_t a, uint32_t b) {
+ return __builtin_riscv_cv_simd_cmpgt_h(a, b);
+}
static __inline__ uint32_t __DEFAULT_FN_ATTRS
-__riscv_cv_simd_cmpgt_b(uint32_t a, uint32_t b) { return __builtin_riscv_cv_simd_cmpgt_b(a, b); }
+__riscv_cv_simd_cmpgt_b(uint32_t a, uint32_t b) {
+ return __builtin_riscv_cv_simd_cmpgt_b(a, b);
+}
static __inline__ uint32_t __DEFAULT_FN_ATTRS
-__riscv_cv_simd_cmpgt_sc_h(uint32_t a, uint32_t b) { return __builtin_riscv_cv_simd_cmpgt_sc_h(a, b); }
+__riscv_cv_simd_cmpgt_sc_h(uint32_t a, uint32_t b) {
+ return __builtin_riscv_cv_simd_cmpgt_sc_h(a, b);
+}
static __inline__ uint32_t __DEFAULT_FN_ATTRS
-__riscv_cv_simd_cmpgt_sc_b(uint32_t a, uint32_t b) { return __builtin_riscv_cv_simd_cmpgt_sc_b(a, b); }
+__riscv_cv_simd_cmpgt_sc_b(uint32_t a, uint32_t b) {
+ return __builtin_riscv_cv_simd_cmpgt_sc_b(a, b);
+}
/* cmpge (signed greater-or-equal) */
static __inline__ uint32_t __DEFAULT_FN_ATTRS
-__riscv_cv_simd_cmpge_h(uint32_t a, uint32_t b) { return __builtin_riscv_cv_simd_cmpge_h(a, b); }
+__riscv_cv_simd_cmpge_h(uint32_t a, uint32_t b) {
+ return __builtin_riscv_cv_simd_cmpge_h(a, b);
+}
static __inline__ uint32_t __DEFAULT_FN_ATTRS
-__riscv_cv_simd_cmpge_b(uint32_t a, uint32_t b) { return __builtin_riscv_cv_simd_cmpge_b(a, b); }
+__riscv_cv_simd_cmpge_b(uint32_t a, uint32_t b) {
+ return __builtin_riscv_cv_simd_cmpge_b(a, b);
+}
static __inline__ uint32_t __DEFAULT_FN_ATTRS
-__riscv_cv_simd_cmpge_sc_h(uint32_t a, uint32_t b) { return __builtin_riscv_cv_simd_cmpge_sc_h(a, b); }
+__riscv_cv_simd_cmpge_sc_h(uint32_t a, uint32_t b) {
+ return __builtin_riscv_cv_simd_cmpge_sc_h(a, b);
+}
static __inline__ uint32_t __DEFAULT_FN_ATTRS
-__riscv_cv_simd_cmpge_sc_b(uint32_t a, uint32_t b) { return __builtin_riscv_cv_simd_cmpge_sc_b(a, b); }
+__riscv_cv_simd_cmpge_sc_b(uint32_t a, uint32_t b) {
+ return __builtin_riscv_cv_simd_cmpge_sc_b(a, b);
+}
/* cmplt (signed less-than) */
static __inline__ uint32_t __DEFAULT_FN_ATTRS
-__riscv_cv_simd_cmplt_h(uint32_t a, uint32_t b) { return __builtin_riscv_cv_simd_cmplt_h(a, b); }
+__riscv_cv_simd_cmplt_h(uint32_t a, uint32_t b) {
+ return __builtin_riscv_cv_simd_cmplt_h(a, b);
+}
static __inline__ uint32_t __DEFAULT_FN_ATTRS
-__riscv_cv_simd_cmplt_b(uint32_t a, uint32_t b) { return __builtin_riscv_cv_simd_cmplt_b(a, b); }
+__riscv_cv_simd_cmplt_b(uint32_t a, uint32_t b) {
+ return __builtin_riscv_cv_simd_cmplt_b(a, b);
+}
static __inline__ uint32_t __DEFAULT_FN_ATTRS
-__riscv_cv_simd_cmplt_sc_h(uint32_t a, uint32_t b) { return __builtin_riscv_cv_simd_cmplt_sc_h(a, b); }
+__riscv_cv_simd_cmplt_sc_h(uint32_t a, uint32_t b) {
+ return __builtin_riscv_cv_simd_cmplt_sc_h(a, b);
+}
static __inline__ uint32_t __DEFAULT_FN_ATTRS
-__riscv_cv_simd_cmplt_sc_b(uint32_t a, uint32_t b) { return __builtin_riscv_cv_simd_cmplt_sc_b(a, b); }
+__riscv_cv_simd_cmplt_sc_b(uint32_t a, uint32_t b) {
+ return __builtin_riscv_cv_simd_cmplt_sc_b(a, b);
+}
/* cmple (signed less-or-equal) */
static __inline__ uint32_t __DEFAULT_FN_ATTRS
-__riscv_cv_simd_cmple_h(uint32_t a, uint32_t b) { return __builtin_riscv_cv_simd_cmple_h(a, b); }
+__riscv_cv_simd_cmple_h(uint32_t a, uint32_t b) {
+ return __builtin_riscv_cv_simd_cmple_h(a, b);
+}
static __inline__ uint32_t __DEFAULT_FN_ATTRS
-__riscv_cv_simd_cmple_b(uint32_t a, uint32_t b) { return __builtin_riscv_cv_simd_cmple_b(a, b); }
+__riscv_cv_simd_cmple_b(uint32_t a, uint32_t b) {
+ return __builtin_riscv_cv_simd_cmple_b(a, b);
+}
static __inline__ uint32_t __DEFAULT_FN_ATTRS
-__riscv_cv_simd_cmple_sc_h(uint32_t a, uint32_t b) { return __builtin_riscv_cv_simd_cmple_sc_h(a, b); }
+__riscv_cv_simd_cmple_sc_h(uint32_t a, uint32_t b) {
+ return __builtin_riscv_cv_simd_cmple_sc_h(a, b);
+}
static __inline__ uint32_t __DEFAULT_FN_ATTRS
-__riscv_cv_simd_cmple_sc_b(uint32_t a, uint32_t b) { return __builtin_riscv_cv_simd_cmple_sc_b(a, b); }
+__riscv_cv_simd_cmple_sc_b(uint32_t a, uint32_t b) {
+ return __builtin_riscv_cv_simd_cmple_sc_b(a, b);
+}
/* cmpgtu (unsigned greater-than) */
static __inline__ uint32_t __DEFAULT_FN_ATTRS
-__riscv_cv_simd_cmpgtu_h(uint32_t a, uint32_t b) { return __builtin_riscv_cv_simd_cmpgtu_h(a, b); }
+__riscv_cv_simd_cmpgtu_h(uint32_t a, uint32_t b) {
+ return __builtin_riscv_cv_simd_cmpgtu_h(a, b);
+}
static __inline__ uint32_t __DEFAULT_FN_ATTRS
-__riscv_cv_simd_cmpgtu_b(uint32_t a, uint32_t b) { return __builtin_riscv_cv_simd_cmpgtu_b(a, b); }
+__riscv_cv_simd_cmpgtu_b(uint32_t a, uint32_t b) {
+ return __builtin_riscv_cv_simd_cmpgtu_b(a, b);
+}
static __inline__ uint32_t __DEFAULT_FN_ATTRS
-__riscv_cv_simd_cmpgtu_sc_h(uint32_t a, uint32_t b) { return __builtin_riscv_cv_simd_cmpgtu_sc_h(a, b); }
+__riscv_cv_simd_cmpgtu_sc_h(uint32_t a, uint32_t b) {
+ return __builtin_riscv_cv_simd_cmpgtu_sc_h(a, b);
+}
static __inline__ uint32_t __DEFAULT_FN_ATTRS
-__riscv_cv_simd_cmpgtu_sc_b(uint32_t a, uint32_t b) { return __builtin_riscv_cv_simd_cmpgtu_sc_b(a, b); }
+__riscv_cv_simd_cmpgtu_sc_b(uint32_t a, uint32_t b) {
+ return __builtin_riscv_cv_simd_cmpgtu_sc_b(a, b);
+}
/* cmpgeu (unsigned greater-or-equal) */
static __inline__ uint32_t __DEFAULT_FN_ATTRS
-__riscv_cv_simd_cmpgeu_h(uint32_t a, uint32_t b) { return __builtin_riscv_cv_simd_cmpgeu_h(a, b); }
+__riscv_cv_simd_cmpgeu_h(uint32_t a, uint32_t b) {
+ return __builtin_riscv_cv_simd_cmpgeu_h(a, b);
+}
static __inline__ uint32_t __DEFAULT_FN_ATTRS
-__riscv_cv_simd_cmpgeu_b(uint32_t a, uint32_t b) { return __builtin_riscv_cv_simd_cmpgeu_b(a, b); }
+__riscv_cv_simd_cmpgeu_b(uint32_t a, uint32_t b) {
+ return __builtin_riscv_cv_simd_cmpgeu_b(a, b);
+}
static __inline__ uint32_t __DEFAULT_FN_ATTRS
-__riscv_cv_simd_cmpgeu_sc_h(uint32_t a, uint32_t b) { return __builtin_riscv_cv_simd_cmpgeu_sc_h(a, b); }
+__riscv_cv_simd_cmpgeu_sc_h(uint32_t a, uint32_t b) {
+ return __builtin_riscv_cv_simd_cmpgeu_sc_h(a, b);
+}
static __inline__ uint32_t __DEFAULT_FN_ATTRS
-__riscv_cv_simd_cmpgeu_sc_b(uint32_t a, uint32_t b) { return __builtin_riscv_cv_simd_cmpgeu_sc_b(a, b); }
+__riscv_cv_simd_cmpgeu_sc_b(uint32_t a, uint32_t b) {
+ return __builtin_riscv_cv_simd_cmpgeu_sc_b(a, b);
+}
/* cmpltu (unsigned less-than) */
static __inline__ uint32_t __DEFAULT_FN_ATTRS
-__riscv_cv_simd_cmpltu_h(uint32_t a, uint32_t b) { return __builtin_riscv_cv_simd_cmpltu_h(a, b); }
+__riscv_cv_simd_cmpltu_h(uint32_t a, uint32_t b) {
+ return __builtin_riscv_cv_simd_cmpltu_h(a, b);
+}
static __inline__ uint32_t __DEFAULT_FN_ATTRS
-__riscv_cv_simd_cmpltu_b(uint32_t a, uint32_t b) { return __builtin_riscv_cv_simd_cmpltu_b(a, b); }
+__riscv_cv_simd_cmpltu_b(uint32_t a, uint32_t b) {
+ return __builtin_riscv_cv_simd_cmpltu_b(a, b);
+}
static __inline__ uint32_t __DEFAULT_FN_ATTRS
-__riscv_cv_simd_cmpltu_sc_h(uint32_t a, uint32_t b) { return __builtin_riscv_cv_simd_cmpltu_sc_h(a, b); }
+__riscv_cv_simd_cmpltu_sc_h(uint32_t a, uint32_t b) {
+ return __builtin_riscv_cv_simd_cmpltu_sc_h(a, b);
+}
static __inline__ uint32_t __DEFAULT_FN_ATTRS
-__riscv_cv_simd_cmpltu_sc_b(uint32_t a, uint32_t b) { return __builtin_riscv_cv_simd_cmpltu_sc_b(a, b); }
+__riscv_cv_simd_cmpltu_sc_b(uint32_t a, uint32_t b) {
+ return __builtin_riscv_cv_simd_cmpltu_sc_b(a, b);
+}
/* cmpleu (unsigned less-or-equal) */
static __inline__ uint32_t __DEFAULT_FN_ATTRS
-__riscv_cv_simd_cmpleu_h(uint32_t a, uint32_t b) { return __builtin_riscv_cv_simd_cmpleu_h(a, b); }
+__riscv_cv_simd_cmpleu_h(uint32_t a, uint32_t b) {
+ return __builtin_riscv_cv_simd_cmpleu_h(a, b);
+}
static __inline__ uint32_t __DEFAULT_FN_ATTRS
-__riscv_cv_simd_cmpleu_b(uint32_t a, uint32_t b) { return __builtin_riscv_cv_simd_cmpleu_b(a, b); }
+__riscv_cv_simd_cmpleu_b(uint32_t a, uint32_t b) {
+ return __builtin_riscv_cv_simd_cmpleu_b(a, b);
+}
static __inline__ uint32_t __DEFAULT_FN_ATTRS
-__riscv_cv_simd_cmpleu_sc_h(uint32_t a, uint32_t b) { return __builtin_riscv_cv_simd_cmpleu_sc_h(a, b); }
+__riscv_cv_simd_cmpleu_sc_h(uint32_t a, uint32_t b) {
+ return __builtin_riscv_cv_simd_cmpleu_sc_h(a, b);
+}
static __inline__ uint32_t __DEFAULT_FN_ATTRS
-__riscv_cv_simd_cmpleu_sc_b(uint32_t a, uint32_t b) { return __builtin_riscv_cv_simd_cmpleu_sc_b(a, b); }
+__riscv_cv_simd_cmpleu_sc_b(uint32_t a, uint32_t b) {
+ return __builtin_riscv_cv_simd_cmpleu_sc_b(a, b);
+}
/* ===========================================================================
* COMPLEX NUMBER OPERATIONS
@@ -674,29 +767,27 @@ __riscv_cv_simd_cmpleu_sc_b(uint32_t a, uint32_t b) { return __builtin_riscv_cv_
*
* cv.subrotmj rd, rs1, rs2 [, divcode] — subtract + rotate by -j
* result = ((rs1 - rs2) >> div) rotated by -j (swap re/im, negate new im)
- * =========================================================================== */
+ * ===========================================================================
+ */
#define __riscv_cv_simd_cplxmul_r(__rD, __rs1, __rs2, __DIVCODE) \
- ((uint32_t)__builtin_riscv_cv_simd_cplxmul_r((uint32_t)(__rs1), \
- (uint32_t)(__rs2), \
- (uint32_t)(__rD), \
- (uint32_t)(__DIVCODE)))
+ ((uint32_t)__builtin_riscv_cv_simd_cplxmul_r( \
+ (uint32_t)(__rs1), (uint32_t)(__rs2), (uint32_t)(__rD), \
+ (uint32_t)(__DIVCODE)))
#define __riscv_cv_simd_cplxmul_i(__rD, __rs1, __rs2, __DIVCODE) \
- ((uint32_t)__builtin_riscv_cv_simd_cplxmul_i((uint32_t)(__rs1), \
- (uint32_t)(__rs2), \
- (uint32_t)(__rD), \
- (uint32_t)(__DIVCODE)))
+ ((uint32_t)__builtin_riscv_cv_simd_cplxmul_i( \
+ (uint32_t)(__rs1), (uint32_t)(__rs2), (uint32_t)(__rD), \
+ (uint32_t)(__DIVCODE)))
-static __inline__ uint32_t __DEFAULT_FN_ATTRS
-__riscv_cv_simd_cplxconj(uint32_t a) {
+static __inline__ uint32_t
+ __DEFAULT_FN_ATTRS __riscv_cv_simd_cplxconj(uint32_t a) {
return __builtin_riscv_cv_simd_cplxconj(a);
}
#define __riscv_cv_simd_subrotmj(__rs1, __rs2, __DIVCODE) \
- ((uint32_t)__builtin_riscv_cv_simd_subrotmj((uint32_t)(__rs1), \
- (uint32_t)(__rs2), \
- (uint32_t)(__DIVCODE)))
+ ((uint32_t)__builtin_riscv_cv_simd_subrotmj( \
+ (uint32_t)(__rs1), (uint32_t)(__rs2), (uint32_t)(__DIVCODE)))
#endif /* __riscv_xcvsimd */
diff --git a/clang/lib/Sema/SemaRISCV.cpp b/clang/lib/Sema/SemaRISCV.cpp
index 0af3053ff3db9..40e89529d4656 100644
--- a/clang/lib/Sema/SemaRISCV.cpp
+++ b/clang/lib/Sema/SemaRISCV.cpp
@@ -679,22 +679,27 @@ bool SemaRISCV::CheckBuiltinFunctionCall(const TargetInfo &TI,
return SemaRef.BuiltinConstantArgRange(TheCall, 3, 0, 31);
// XCVsimd — extract/insert index
+ // [0,1] for 2 halfwords
case RISCV::BI__builtin_riscv_cv_simd_extract_h:
case RISCV::BI__builtin_riscv_cv_simd_extractu_h:
- return SemaRef.BuiltinConstantArgRange(TheCall, 1, 0, 1); // [0,1] for 2 halfwords
+ return SemaRef.BuiltinConstantArgRange(TheCall, 1, 0, 1);
+ // [0,1] for 2 halfwords
case RISCV::BI__builtin_riscv_cv_simd_insert_h:
- return SemaRef.BuiltinConstantArgRange(TheCall, 2, 0, 1); // [0,1] for 2 halfwords
+ return SemaRef.BuiltinConstantArgRange(TheCall, 2, 0, 1);
+ // [0,3] for 4 bytes
case RISCV::BI__builtin_riscv_cv_simd_extract_b:
case RISCV::BI__builtin_riscv_cv_simd_extractu_b:
- return SemaRef.BuiltinConstantArgRange(TheCall, 1, 0, 3); // [0,3] for 4 bytes
+ return SemaRef.BuiltinConstantArgRange(TheCall, 1, 0, 3);
+ // [0,3] for 4 bytes
case RISCV::BI__builtin_riscv_cv_simd_insert_b:
- return SemaRef.BuiltinConstantArgRange(TheCall, 2, 0, 3); // [0,3] for 4 bytes
+ return SemaRef.BuiltinConstantArgRange(TheCall, 2, 0, 3);
// Note: insert has index at arg 2 not 1
// Shuffle SCI — 6-bit immediate [0, 63]
case RISCV::BI__builtin_riscv_cv_simd_shuffle_sci_h:
return SemaRef.BuiltinConstantArgRange(TheCall, 1, 0, 3);
+ // 8-bit, split by codegen
case RISCV::BI__builtin_riscv_cv_simd_shuffle_sci_b:
- return SemaRef.BuiltinConstantArgRange(TheCall, 1, 0, 255); // 8-bit, split by codegen
+ return SemaRef.BuiltinConstantArgRange(TheCall, 1, 0, 255);
// add_h / sub_h div code [0,3] (0=no shift, 1=/2, 2=/4, 3=/8)
case RISCV::BI__builtin_riscv_cv_simd_add_h:
More information about the cfe-commits
mailing list