[Clang][RISCV] packed absolute difference sum intrinsics (#207936)

Add the __riscv_pabdsumu/pabdsumau_* header wrappers over new
__builtin_riscv_* builtins, lowering to the
llvm.riscv.pabdsumu/pabdsumau intrinsics.
This commit is contained in:
SiHuaN 2026-07-08 16:40:13 +08:00 committed by GitHub
parent 62907d4a3b
commit 35678db1b4
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 231 additions and 0 deletions

View file

@ -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"
//===----------------------------------------------------------------------===//

View file

@ -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

View file

@ -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)

View file

@ -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);
}

View file

@ -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);
}