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
