https://github.com/sihuan created 
https://github.com/llvm/llvm-project/pull/207936

Add the __riscv_pabdsumu/pabdsumau_* header wrappers over new __builtin_riscv_* 
builtins, lowering to the llvm.riscv.pabdsumu/pabdsumau intrinsics.

>From e14c29fa693dba6637a9855b304d57461a29e40a Mon Sep 17 00:00:00 2001
From: SiHuaN <[email protected]>
Date: Fri, 3 Jul 2026 03:59:30 +0000
Subject: [PATCH] [Clang][RISCV] packed absolute difference sum intrinsics

Add the __riscv_pabdsumu/pabdsumau_* header wrappers over new
__builtin_riscv_* builtins, lowering to the llvm.riscv.pabdsumu/pabdsumau
intrinsics.
---
 clang/include/clang/Basic/BuiltinsRISCV.td    |  10 ++
 clang/lib/CodeGen/TargetBuiltins/RISCV.cpp    |  28 ++++
 clang/lib/Headers/riscv_packed_simd.h         |  24 ++++
 clang/test/CodeGen/RISCV/rvp-intrinsics.c     | 122 ++++++++++++++++++
 .../riscv_packed_simd.c                       |  47 +++++++
 5 files changed, 231 insertions(+)

diff --git a/clang/include/clang/Basic/BuiltinsRISCV.td 
b/clang/include/clang/Basic/BuiltinsRISCV.td
index 785e41324ad78..df94565b0a242 100644
--- a/clang/include/clang/Basic/BuiltinsRISCV.td
+++ b/clang/include/clang/Basic/BuiltinsRISCV.td
@@ -247,6 +247,16 @@ def pmerge_i16x4 : RISCVBuiltin<"_Vector<4, 
short>(_Vector<4, short>, _Vector<4,
 def pmerge_u32x2 : RISCVBuiltin<"_Vector<2, unsigned int>(_Vector<2, unsigned 
int>, _Vector<2, unsigned int>, _Vector<2, unsigned int>)">;
 def pmerge_i32x2 : RISCVBuiltin<"_Vector<2, int>(_Vector<2, int>, _Vector<2, 
int>, _Vector<2, unsigned int>)">;
 
+// Packed Absolute Difference Sum (32-bit)
+def pabdsumu_u8x4_u32 : RISCVBuiltin<"unsigned int(_Vector<4, unsigned char>, 
_Vector<4, unsigned char>)">;
+def pabdsumau_u8x4_u32 : RISCVBuiltin<"unsigned int(unsigned int, _Vector<4, 
unsigned char>, _Vector<4, unsigned char>)">;
+
+// Packed Absolute Difference Sum (64-bit)
+def pabdsumu_u8x8_u32 : RISCVBuiltin<"unsigned int(_Vector<8, unsigned char>, 
_Vector<8, unsigned char>)">;
+def pabdsumu_u8x8_u64 : RISCVBuiltin<"uint64_t(_Vector<8, unsigned char>, 
_Vector<8, unsigned char>)">;
+def pabdsumau_u8x8_u32 : RISCVBuiltin<"unsigned int(unsigned int, _Vector<8, 
unsigned char>, _Vector<8, unsigned char>)">;
+def pabdsumau_u8x8_u64 : RISCVBuiltin<"uint64_t(uint64_t, _Vector<8, unsigned 
char>, _Vector<8, unsigned char>)">;
+
 } // Features = "experimental-p"
 
 
//===----------------------------------------------------------------------===//
diff --git a/clang/lib/CodeGen/TargetBuiltins/RISCV.cpp 
b/clang/lib/CodeGen/TargetBuiltins/RISCV.cpp
index 588e229499082..168d24eddf7b6 100644
--- a/clang/lib/CodeGen/TargetBuiltins/RISCV.cpp
+++ b/clang/lib/CodeGen/TargetBuiltins/RISCV.cpp
@@ -1392,6 +1392,34 @@ Value *CodeGenFunction::EmitRISCVBuiltinExpr(unsigned 
BuiltinID,
     break;
   }
 
+  // Packed Absolute Difference Sum
+  case RISCV::BI__builtin_riscv_pabdsumu_u8x4_u32:
+  case RISCV::BI__builtin_riscv_pabdsumu_u8x8_u32:
+  case RISCV::BI__builtin_riscv_pabdsumu_u8x8_u64:
+  case RISCV::BI__builtin_riscv_pabdsumau_u8x4_u32:
+  case RISCV::BI__builtin_riscv_pabdsumau_u8x8_u32:
+  case RISCV::BI__builtin_riscv_pabdsumau_u8x8_u64: {
+    switch (BuiltinID) {
+    default:
+      llvm_unreachable("unexpected builtin ID");
+    case RISCV::BI__builtin_riscv_pabdsumu_u8x4_u32:
+    case RISCV::BI__builtin_riscv_pabdsumu_u8x8_u32:
+    case RISCV::BI__builtin_riscv_pabdsumu_u8x8_u64:
+      ID = Intrinsic::riscv_pabdsumu;
+      break;
+    case RISCV::BI__builtin_riscv_pabdsumau_u8x4_u32:
+    case RISCV::BI__builtin_riscv_pabdsumau_u8x8_u32:
+    case RISCV::BI__builtin_riscv_pabdsumau_u8x8_u64:
+      ID = Intrinsic::riscv_pabdsumau;
+      break;
+    }
+
+    // The two vector sources are the last two arguments; the accumulate form
+    // has an extra accumulator argument first.
+    IntrinsicTypes = {ResultType, Ops.back()->getType()};
+    break;
+  }
+
   // Zk builtins
 
   // Zknh
diff --git a/clang/lib/Headers/riscv_packed_simd.h 
b/clang/lib/Headers/riscv_packed_simd.h
index c5edc123f64fa..aca82f298ef21 100644
--- a/clang/lib/Headers/riscv_packed_simd.h
+++ b/clang/lib/Headers/riscv_packed_simd.h
@@ -130,6 +130,18 @@ typedef uint32_t uint32x2_t 
__attribute__((__vector_size__(8)));
     return __builtin_shufflevector(__rs1, __rs1, 7, 6, 5, 4, 3, 2, 1, 0);      
\
   }
 
+#define __packed_abdsum(name, rty, ty, builtin)                                
\
+  static __inline__ rty __DEFAULT_FN_ATTRS __riscv_##name(ty __rs1,            
\
+                                                          ty __rs2) {          
\
+    return builtin(__rs1, __rs2);                                              
\
+  }
+
+#define __packed_abdsum_acc(name, rty, ty, builtin)                            
\
+  static __inline__ rty __DEFAULT_FN_ATTRS __riscv_##name(rty __rd, ty __rs1,  
\
+                                                          ty __rs2) {          
\
+    return builtin(__rd, __rs1, __rs2);                                        
\
+  }
+
 // clang-format off: macro call sites have no trailing semicolons, which
 // confuses clang-format into a deeply nested expression.
 
@@ -497,6 +509,16 @@ __packed_merge_builtin(pmerge_i16x4, int16x4_t, 
uint16x4_t, __builtin_riscv_pmer
 __packed_merge_builtin(pmerge_u32x2, uint32x2_t, uint32x2_t, 
__builtin_riscv_pmerge_u32x2)
 __packed_merge_builtin(pmerge_i32x2, int32x2_t, uint32x2_t, 
__builtin_riscv_pmerge_i32x2)
 
+/* Packed Absolute Difference Sum (32-bit) */
+__packed_abdsum(pabdsumu_u8x4_u32, uint32_t, uint8x4_t, 
__builtin_riscv_pabdsumu_u8x4_u32)
+__packed_abdsum_acc(pabdsumau_u8x4_u32, uint32_t, uint8x4_t, 
__builtin_riscv_pabdsumau_u8x4_u32)
+
+/* Packed Absolute Difference Sum (64-bit) */
+__packed_abdsum(pabdsumu_u8x8_u32, uint32_t, uint8x8_t, 
__builtin_riscv_pabdsumu_u8x8_u32)
+__packed_abdsum(pabdsumu_u8x8_u64, uint64_t, uint8x8_t, 
__builtin_riscv_pabdsumu_u8x8_u64)
+__packed_abdsum_acc(pabdsumau_u8x8_u32, uint32_t, uint8x8_t, 
__builtin_riscv_pabdsumau_u8x8_u32)
+__packed_abdsum_acc(pabdsumau_u8x8_u64, uint64_t, uint8x8_t, 
__builtin_riscv_pabdsumau_u8x8_u64)
+
 // clang-format on
 
 #undef __packed_splat2
@@ -521,6 +543,8 @@ __packed_merge_builtin(pmerge_i32x2, int32x2_t, uint32x2_t, 
__builtin_riscv_pmer
 #undef __packed_reverse2
 #undef __packed_reverse4
 #undef __packed_reverse8
+#undef __packed_abdsum
+#undef __packed_abdsum_acc
 #undef __DEFAULT_FN_ATTRS
 
 #if defined(__cplusplus)
diff --git a/clang/test/CodeGen/RISCV/rvp-intrinsics.c 
b/clang/test/CodeGen/RISCV/rvp-intrinsics.c
index 3791b0ddf508d..e0398aa5b19ba 100644
--- a/clang/test/CodeGen/RISCV/rvp-intrinsics.c
+++ b/clang/test/CodeGen/RISCV/rvp-intrinsics.c
@@ -6575,3 +6575,125 @@ int32x2_t test_prev_i32x2(int32x2_t rs1) {
 uint32x2_t test_prev_u32x2(uint32x2_t rs1) {
   return __riscv_prev_u32x2(rs1);
 }
+
+/* Packed Absolute Difference Sum (32-bit) */
+// RV32-LABEL: define dso_local i32 @test_pabdsumu_u8x4_u32(
+// RV32-SAME: i32 noundef [[RS1_COERCE:%.*]], i32 noundef [[RS2_COERCE:%.*]]) 
#[[ATTR0]] {
+// RV32-NEXT:  [[ENTRY:.*:]]
+// RV32-NEXT:    [[TMP0:%.*]] = bitcast i32 [[RS1_COERCE]] to <4 x i8>
+// RV32-NEXT:    [[TMP1:%.*]] = bitcast i32 [[RS2_COERCE]] to <4 x i8>
+// RV32-NEXT:    [[TMP2:%.*]] = call i32 @llvm.riscv.pabdsumu.i32.v4i8(<4 x 
i8> [[TMP0]], <4 x i8> [[TMP1]])
+// RV32-NEXT:    ret i32 [[TMP2]]
+//
+// RV64-LABEL: define dso_local signext i32 @test_pabdsumu_u8x4_u32(
+// RV64-SAME: i32 noundef [[RS1_COERCE:%.*]], i32 noundef [[RS2_COERCE:%.*]]) 
#[[ATTR0]] {
+// RV64-NEXT:  [[ENTRY:.*:]]
+// RV64-NEXT:    [[TMP0:%.*]] = bitcast i32 [[RS1_COERCE]] to <4 x i8>
+// RV64-NEXT:    [[TMP1:%.*]] = bitcast i32 [[RS2_COERCE]] to <4 x i8>
+// RV64-NEXT:    [[TMP2:%.*]] = call i32 @llvm.riscv.pabdsumu.i32.v4i8(<4 x 
i8> [[TMP0]], <4 x i8> [[TMP1]])
+// RV64-NEXT:    ret i32 [[TMP2]]
+//
+uint32_t test_pabdsumu_u8x4_u32(uint8x4_t rs1, uint8x4_t rs2) {
+  return __riscv_pabdsumu_u8x4_u32(rs1, rs2);
+}
+
+// RV32-LABEL: define dso_local i32 @test_pabdsumau_u8x4_u32(
+// RV32-SAME: i32 noundef [[RD:%.*]], i32 noundef [[RS1_COERCE:%.*]], i32 
noundef [[RS2_COERCE:%.*]]) #[[ATTR0]] {
+// RV32-NEXT:  [[ENTRY:.*:]]
+// RV32-NEXT:    [[TMP0:%.*]] = bitcast i32 [[RS1_COERCE]] to <4 x i8>
+// RV32-NEXT:    [[TMP1:%.*]] = bitcast i32 [[RS2_COERCE]] to <4 x i8>
+// RV32-NEXT:    [[TMP2:%.*]] = call i32 @llvm.riscv.pabdsumau.i32.v4i8(i32 
[[RD]], <4 x i8> [[TMP0]], <4 x i8> [[TMP1]])
+// RV32-NEXT:    ret i32 [[TMP2]]
+//
+// RV64-LABEL: define dso_local signext i32 @test_pabdsumau_u8x4_u32(
+// RV64-SAME: i32 noundef signext [[RD:%.*]], i32 noundef [[RS1_COERCE:%.*]], 
i32 noundef [[RS2_COERCE:%.*]]) #[[ATTR0]] {
+// RV64-NEXT:  [[ENTRY:.*:]]
+// RV64-NEXT:    [[TMP0:%.*]] = bitcast i32 [[RS1_COERCE]] to <4 x i8>
+// RV64-NEXT:    [[TMP1:%.*]] = bitcast i32 [[RS2_COERCE]] to <4 x i8>
+// RV64-NEXT:    [[TMP2:%.*]] = call i32 @llvm.riscv.pabdsumau.i32.v4i8(i32 
[[RD]], <4 x i8> [[TMP0]], <4 x i8> [[TMP1]])
+// RV64-NEXT:    ret i32 [[TMP2]]
+//
+uint32_t test_pabdsumau_u8x4_u32(uint32_t rd, uint8x4_t rs1, uint8x4_t rs2) {
+  return __riscv_pabdsumau_u8x4_u32(rd, rs1, rs2);
+}
+
+/* Packed Absolute Difference Sum (64-bit) */
+// RV32-LABEL: define dso_local i32 @test_pabdsumu_u8x8_u32(
+// RV32-SAME: i64 noundef [[RS1_COERCE:%.*]], i64 noundef [[RS2_COERCE:%.*]]) 
#[[ATTR0]] {
+// RV32-NEXT:  [[ENTRY:.*:]]
+// RV32-NEXT:    [[TMP0:%.*]] = bitcast i64 [[RS1_COERCE]] to <8 x i8>
+// RV32-NEXT:    [[TMP1:%.*]] = bitcast i64 [[RS2_COERCE]] to <8 x i8>
+// RV32-NEXT:    [[TMP2:%.*]] = call i32 @llvm.riscv.pabdsumu.i32.v8i8(<8 x 
i8> [[TMP0]], <8 x i8> [[TMP1]])
+// RV32-NEXT:    ret i32 [[TMP2]]
+//
+// RV64-LABEL: define dso_local signext i32 @test_pabdsumu_u8x8_u32(
+// RV64-SAME: i64 noundef [[RS1_COERCE:%.*]], i64 noundef [[RS2_COERCE:%.*]]) 
#[[ATTR0]] {
+// RV64-NEXT:  [[ENTRY:.*:]]
+// RV64-NEXT:    [[TMP0:%.*]] = bitcast i64 [[RS1_COERCE]] to <8 x i8>
+// RV64-NEXT:    [[TMP1:%.*]] = bitcast i64 [[RS2_COERCE]] to <8 x i8>
+// RV64-NEXT:    [[TMP2:%.*]] = call i32 @llvm.riscv.pabdsumu.i32.v8i8(<8 x 
i8> [[TMP0]], <8 x i8> [[TMP1]])
+// RV64-NEXT:    ret i32 [[TMP2]]
+//
+uint32_t test_pabdsumu_u8x8_u32(uint8x8_t rs1, uint8x8_t rs2) {
+  return __riscv_pabdsumu_u8x8_u32(rs1, rs2);
+}
+
+// RV32-LABEL: define dso_local i64 @test_pabdsumu_u8x8_u64(
+// RV32-SAME: i64 noundef [[RS1_COERCE:%.*]], i64 noundef [[RS2_COERCE:%.*]]) 
#[[ATTR0]] {
+// RV32-NEXT:  [[ENTRY:.*:]]
+// RV32-NEXT:    [[TMP0:%.*]] = bitcast i64 [[RS1_COERCE]] to <8 x i8>
+// RV32-NEXT:    [[TMP1:%.*]] = bitcast i64 [[RS2_COERCE]] to <8 x i8>
+// RV32-NEXT:    [[TMP2:%.*]] = call i64 @llvm.riscv.pabdsumu.i64.v8i8(<8 x 
i8> [[TMP0]], <8 x i8> [[TMP1]])
+// RV32-NEXT:    ret i64 [[TMP2]]
+//
+// RV64-LABEL: define dso_local i64 @test_pabdsumu_u8x8_u64(
+// RV64-SAME: i64 noundef [[RS1_COERCE:%.*]], i64 noundef [[RS2_COERCE:%.*]]) 
#[[ATTR0]] {
+// RV64-NEXT:  [[ENTRY:.*:]]
+// RV64-NEXT:    [[TMP0:%.*]] = bitcast i64 [[RS1_COERCE]] to <8 x i8>
+// RV64-NEXT:    [[TMP1:%.*]] = bitcast i64 [[RS2_COERCE]] to <8 x i8>
+// RV64-NEXT:    [[TMP2:%.*]] = call i64 @llvm.riscv.pabdsumu.i64.v8i8(<8 x 
i8> [[TMP0]], <8 x i8> [[TMP1]])
+// RV64-NEXT:    ret i64 [[TMP2]]
+//
+uint64_t test_pabdsumu_u8x8_u64(uint8x8_t rs1, uint8x8_t rs2) {
+  return __riscv_pabdsumu_u8x8_u64(rs1, rs2);
+}
+
+// RV32-LABEL: define dso_local i32 @test_pabdsumau_u8x8_u32(
+// RV32-SAME: i32 noundef [[RD:%.*]], i64 noundef [[RS1_COERCE:%.*]], i64 
noundef [[RS2_COERCE:%.*]]) #[[ATTR0]] {
+// RV32-NEXT:  [[ENTRY:.*:]]
+// RV32-NEXT:    [[TMP0:%.*]] = bitcast i64 [[RS1_COERCE]] to <8 x i8>
+// RV32-NEXT:    [[TMP1:%.*]] = bitcast i64 [[RS2_COERCE]] to <8 x i8>
+// RV32-NEXT:    [[TMP2:%.*]] = call i32 @llvm.riscv.pabdsumau.i32.v8i8(i32 
[[RD]], <8 x i8> [[TMP0]], <8 x i8> [[TMP1]])
+// RV32-NEXT:    ret i32 [[TMP2]]
+//
+// RV64-LABEL: define dso_local signext i32 @test_pabdsumau_u8x8_u32(
+// RV64-SAME: i32 noundef signext [[RD:%.*]], i64 noundef [[RS1_COERCE:%.*]], 
i64 noundef [[RS2_COERCE:%.*]]) #[[ATTR0]] {
+// RV64-NEXT:  [[ENTRY:.*:]]
+// RV64-NEXT:    [[TMP0:%.*]] = bitcast i64 [[RS1_COERCE]] to <8 x i8>
+// RV64-NEXT:    [[TMP1:%.*]] = bitcast i64 [[RS2_COERCE]] to <8 x i8>
+// RV64-NEXT:    [[TMP2:%.*]] = call i32 @llvm.riscv.pabdsumau.i32.v8i8(i32 
[[RD]], <8 x i8> [[TMP0]], <8 x i8> [[TMP1]])
+// RV64-NEXT:    ret i32 [[TMP2]]
+//
+uint32_t test_pabdsumau_u8x8_u32(uint32_t rd, uint8x8_t rs1, uint8x8_t rs2) {
+  return __riscv_pabdsumau_u8x8_u32(rd, rs1, rs2);
+}
+
+// RV32-LABEL: define dso_local i64 @test_pabdsumau_u8x8_u64(
+// RV32-SAME: i64 noundef [[RD:%.*]], i64 noundef [[RS1_COERCE:%.*]], i64 
noundef [[RS2_COERCE:%.*]]) #[[ATTR0]] {
+// RV32-NEXT:  [[ENTRY:.*:]]
+// RV32-NEXT:    [[TMP0:%.*]] = bitcast i64 [[RS1_COERCE]] to <8 x i8>
+// RV32-NEXT:    [[TMP1:%.*]] = bitcast i64 [[RS2_COERCE]] to <8 x i8>
+// RV32-NEXT:    [[TMP2:%.*]] = call i64 @llvm.riscv.pabdsumau.i64.v8i8(i64 
[[RD]], <8 x i8> [[TMP0]], <8 x i8> [[TMP1]])
+// RV32-NEXT:    ret i64 [[TMP2]]
+//
+// RV64-LABEL: define dso_local i64 @test_pabdsumau_u8x8_u64(
+// RV64-SAME: i64 noundef [[RD:%.*]], i64 noundef [[RS1_COERCE:%.*]], i64 
noundef [[RS2_COERCE:%.*]]) #[[ATTR0]] {
+// RV64-NEXT:  [[ENTRY:.*:]]
+// RV64-NEXT:    [[TMP0:%.*]] = bitcast i64 [[RS1_COERCE]] to <8 x i8>
+// RV64-NEXT:    [[TMP1:%.*]] = bitcast i64 [[RS2_COERCE]] to <8 x i8>
+// RV64-NEXT:    [[TMP2:%.*]] = call i64 @llvm.riscv.pabdsumau.i64.v8i8(i64 
[[RD]], <8 x i8> [[TMP0]], <8 x i8> [[TMP1]])
+// RV64-NEXT:    ret i64 [[TMP2]]
+//
+uint64_t test_pabdsumau_u8x8_u64(uint64_t rd, uint8x8_t rs1, uint8x8_t rs2) {
+  return __riscv_pabdsumau_u8x8_u64(rd, rs1, rs2);
+}
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 5460f1a4e65ba..f3e2f25629026 100644
--- a/cross-project-tests/intrinsic-header-tests/riscv_packed_simd.c
+++ b/cross-project-tests/intrinsic-header-tests/riscv_packed_simd.c
@@ -2289,3 +2289,50 @@ int32x2_t test_pmerge_mvm_i32x2(int32x2_t rs1, 
uint32x2_t rd, int32x2_t rs2) {
 int32x2_t test_pmerge_mvmn_i32x2(int32x2_t rs2, int32x2_t rs1, uint32x2_t rd) {
   return __riscv_pmerge_i32x2(rs1, rs2, rd);
 }
+
+// CHECK-LABEL: test_pabdsumu_u8x4_u32:
+// RV32:        pabdsumu.b
+// RV64:        zext.w
+// RV64:        pabdsumu.b
+uint32_t test_pabdsumu_u8x4_u32(uint8x4_t a, uint8x4_t b) {
+  return __riscv_pabdsumu_u8x4_u32(a, b);
+}
+
+// CHECK-LABEL: test_pabdsumau_u8x4_u32:
+// RV32:        pabdsumau.b
+// RV64:        zext.w
+// RV64:        pabdsumau.b
+uint32_t test_pabdsumau_u8x4_u32(uint32_t rd, uint8x4_t a, uint8x4_t b) {
+  return __riscv_pabdsumau_u8x4_u32(rd, a, b);
+}
+
+// CHECK-LABEL: test_pabdsumu_u8x8_u32:
+// RV32:        pabdsumu.b
+// RV32:        pabdsumau.b
+// RV64:        pabdsumu.b
+uint32_t test_pabdsumu_u8x8_u32(uint8x8_t a, uint8x8_t b) {
+  return __riscv_pabdsumu_u8x8_u32(a, b);
+}
+
+// CHECK-LABEL: test_pabdsumu_u8x8_u64:
+// RV32-COUNT-2: pabdsumu.b
+// RV32:        waddu
+// RV64:        pabdsumu.b
+uint64_t test_pabdsumu_u8x8_u64(uint8x8_t a, uint8x8_t b) {
+  return __riscv_pabdsumu_u8x8_u64(a, b);
+}
+
+// CHECK-LABEL: test_pabdsumau_u8x8_u32:
+// RV32-COUNT-2: pabdsumau.b
+// RV64:        pabdsumau.b
+uint32_t test_pabdsumau_u8x8_u32(uint32_t rd, uint8x8_t a, uint8x8_t b) {
+  return __riscv_pabdsumau_u8x8_u32(rd, a, b);
+}
+
+// CHECK-LABEL: test_pabdsumau_u8x8_u64:
+// RV32-COUNT-2: pabdsumu.b
+// RV32:        waddau
+// RV64:        pabdsumau.b
+uint64_t test_pabdsumau_u8x8_u64(uint64_t rd, uint8x8_t a, uint8x8_t b) {
+  return __riscv_pabdsumau_u8x8_u64(rd, a, b);
+}

_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to