[clang] [llvm] [RISCV][P-ext] Add scalar rev16 intrinsic (PR #230704)
Craig Topper via cfe-commits
cfe-commits at lists.llvm.org
Mon Oct 12 21:06:15 PDT 2026
https://github.com/topperc updated https://github.com/llvm/llvm-project/pull/230704
>From 46ee996e15db9a6c94359dc6161296dd9730b596 Mon Sep 17 00:00:00 2001
From: Craig Topper <craig.topper at sifive.com>
Date: Fri, 9 Oct 2026 16:04:34 -0700
Subject: [PATCH] [RISCV][P-ext] Add scalar rev16 intrinsic
Assisted-by: Claude
---
clang/include/clang/Basic/BuiltinsRISCV.td | 3 +++
clang/lib/CodeGen/TargetBuiltins/RISCV.cpp | 5 +++++
clang/lib/Headers/riscv_packed_simd.h | 1 +
clang/test/CodeGen/RISCV/rvp-intrinsics.c | 10 ++++++++++
.../intrinsic-header-tests/riscv_packed_simd.c | 4 ++++
llvm/include/llvm/IR/IntrinsicsRISCV.td | 4 ++++
llvm/lib/Target/RISCV/RISCVInstrInfoP.td | 1 +
llvm/test/CodeGen/RISCV/rv64p.ll | 11 +++++++++++
8 files changed, 39 insertions(+)
diff --git a/clang/include/clang/Basic/BuiltinsRISCV.td b/clang/include/clang/Basic/BuiltinsRISCV.td
index c647c25c6ee4e..dce7927887103 100644
--- a/clang/include/clang/Basic/BuiltinsRISCV.td
+++ b/clang/include/clang/Basic/BuiltinsRISCV.td
@@ -261,6 +261,9 @@ def pmerge_u8x8 : RISCVBuiltin<"_Vector<8, unsigned char>(_Vector<8, unsigned ch
def pmerge_u16x4 : RISCVBuiltin<"_Vector<4, unsigned short>(_Vector<4, unsigned short>, _Vector<4, unsigned short>, _Vector<4, unsigned short>)">;
def pmerge_u32x2 : RISCVBuiltin<"_Vector<2, unsigned int>(_Vector<2, unsigned int>, _Vector<2, unsigned int>, _Vector<2, unsigned int>)">;
+// Scalar Bitmanip
+def rev16_64 : RISCVBuiltin<"uint64_t(uint64_t)", "64bit">;
+
// Scalar Multiply High
def mulh_i32 : RISCVBuiltin<"int32_t(int32_t, int32_t)">;
def mulhr_i32 : RISCVBuiltin<"int32_t(int32_t, int32_t)">;
diff --git a/clang/lib/CodeGen/TargetBuiltins/RISCV.cpp b/clang/lib/CodeGen/TargetBuiltins/RISCV.cpp
index 8158543e232c3..b9f6437086bf2 100644
--- a/clang/lib/CodeGen/TargetBuiltins/RISCV.cpp
+++ b/clang/lib/CodeGen/TargetBuiltins/RISCV.cpp
@@ -1199,6 +1199,11 @@ Value *CodeGenFunction::EmitRISCVBuiltinExpr(unsigned BuiltinID,
break;
}
+ // P extension scalar bitmanip
+ case RISCV::BI__builtin_riscv_rev16_64:
+ ID = Intrinsic::riscv_rev16_64;
+ break;
+
// Packed Widening Shifts
case RISCV::BI__builtin_riscv_pwsll_s_u16x4:
case RISCV::BI__builtin_riscv_pwsll_s_u32x2:
diff --git a/clang/lib/Headers/riscv_packed_simd.h b/clang/lib/Headers/riscv_packed_simd.h
index a155278342d23..6a7734a264477 100644
--- a/clang/lib/Headers/riscv_packed_simd.h
+++ b/clang/lib/Headers/riscv_packed_simd.h
@@ -420,6 +420,7 @@ typedef uint32_t uint32x2_t __attribute__((__vector_size__(8)));
__packed_unary_builtin(rev_32, uint32_t, __builtin_bitreverse32)
#if __riscv_xlen == 64
__packed_unary_builtin(rev_64, uint64_t, __builtin_bitreverse64)
+__packed_unary_builtin(rev16_64, uint64_t, __builtin_riscv_rev16_64)
#endif
/* Scalar Saturating Addition and Subtraction */
diff --git a/clang/test/CodeGen/RISCV/rvp-intrinsics.c b/clang/test/CodeGen/RISCV/rvp-intrinsics.c
index 41f94d48d8de2..770103080718a 100644
--- a/clang/test/CodeGen/RISCV/rvp-intrinsics.c
+++ b/clang/test/CodeGen/RISCV/rvp-intrinsics.c
@@ -36,6 +36,16 @@ uint32_t test_rev_32(uint32_t a) {
uint64_t test_rev_64(uint64_t a) {
return __riscv_rev_64(a);
}
+
+// RV64-LABEL: define dso_local i64 @test_rev16_64(
+// RV64-SAME: i64 noundef [[A:%.*]]) #[[ATTR0]] {
+// RV64-NEXT: [[ENTRY:.*:]]
+// RV64-NEXT: [[TMP0:%.*]] = call i64 @llvm.riscv.rev16.64(i64 [[A]])
+// RV64-NEXT: ret i64 [[TMP0]]
+//
+uint64_t test_rev16_64(uint64_t a) {
+ return __riscv_rev16_64(a);
+}
#endif
/* Scalar Saturating Addition and Subtraction */
diff --git a/cross-project-tests/intrinsic-header-tests/riscv_packed_simd.c b/cross-project-tests/intrinsic-header-tests/riscv_packed_simd.c
index 9b462245dc786..c3d49cc623eb5 100644
--- a/cross-project-tests/intrinsic-header-tests/riscv_packed_simd.c
+++ b/cross-project-tests/intrinsic-header-tests/riscv_packed_simd.c
@@ -23,6 +23,10 @@ uint32_t test_rev_32(uint32_t a) { return __riscv_rev_32(a); }
// RV64-LABEL: test_rev_64:
// RV64: rev{{[[:space:]]}}
uint64_t test_rev_64(uint64_t a) { return __riscv_rev_64(a); }
+
+// RV64-LABEL: test_rev16_64:
+// RV64: rev16{{[[:space:]]}}
+uint64_t test_rev16_64(uint64_t a) { return __riscv_rev16_64(a); }
#endif
// CHECK-LABEL: test_sadd_i32:
diff --git a/llvm/include/llvm/IR/IntrinsicsRISCV.td b/llvm/include/llvm/IR/IntrinsicsRISCV.td
index 284c28f935479..e09645dbebbcd 100644
--- a/llvm/include/llvm/IR/IntrinsicsRISCV.td
+++ b/llvm/include/llvm/IR/IntrinsicsRISCV.td
@@ -2140,6 +2140,10 @@ class RVPBinaryIntrinsic
[IntrNoMem, IntrSpeculatable]>;
def int_riscv_pmerge : RVPTernaryIntrinsic;
+ // Reverse the order of the 16-bit halfwords of a 64-bit value (RV64 only).
+ def int_riscv_rev16_64 : DefaultAttrsIntrinsic<[llvm_i64_ty], [llvm_i64_ty],
+ [IntrNoMem, IntrSpeculatable]>;
+
// Packed Sign and Zero Extend.
class RVPExtIntrinsic
: DefaultAttrsIntrinsic<[llvm_anyvector_ty],
diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfoP.td b/llvm/lib/Target/RISCV/RISCVInstrInfoP.td
index 1de2f17c4ff29..80c7b442e94e5 100644
--- a/llvm/lib/Target/RISCV/RISCVInstrInfoP.td
+++ b/llvm/lib/Target/RISCV/RISCVInstrInfoP.td
@@ -3199,6 +3199,7 @@ let append Predicates = [IsRV32] in {
let append Predicates = [IsRV64] in {
def : PatGpr<riscv_absw, ABSW>;
def : PatGpr<riscv_clsw, CLSW>;
+ def : PatGpr<int_riscv_rev16_64, REV16_RV64>;
def : PatGpr<bitreverse, REV_RV64>;
diff --git a/llvm/test/CodeGen/RISCV/rv64p.ll b/llvm/test/CodeGen/RISCV/rv64p.ll
index cdc39e8bc1589..cb997bd92c627 100644
--- a/llvm/test/CodeGen/RISCV/rv64p.ll
+++ b/llvm/test/CodeGen/RISCV/rv64p.ll
@@ -1796,3 +1796,14 @@ define i64 @and_mul_32bitsplat(i64 %x) {
%b = mul i64 %a, u0x0080402010080400
ret i64 %b
}
+
+declare i64 @llvm.riscv.rev16.64(i64)
+
+define i64 @rev16_intrinsic(i64 %x) {
+; CHECK-LABEL: rev16_intrinsic:
+; CHECK: # %bb.0:
+; CHECK-NEXT: rev16 a0, a0
+; CHECK-NEXT: ret
+ %r = call i64 @llvm.riscv.rev16.64(i64 %x)
+ ret i64 %r
+}
More information about the cfe-commits
mailing list