https://github.com/XChy updated https://github.com/llvm/llvm-project/pull/223619
>From 7810c2edb98d55ab17662396dcfa4cbea01fb6d2 Mon Sep 17 00:00:00 2001 From: XChy <[email protected]> Date: Tue, 15 Sep 2026 15:48:39 +0800 Subject: [PATCH] [RISCV][P-ext] Support Packed Store --- clang/lib/Headers/riscv_packed_simd.h | 22 +++ clang/test/CodeGen/RISCV/rvp-intrinsics.c | 183 ++++++++++++++++++ clang/test/Sema/riscv-pst-pointer-types.c | 41 ++++ .../riscv_packed_simd.c | 66 +++++++ 4 files changed, 312 insertions(+) create mode 100644 clang/test/Sema/riscv-pst-pointer-types.c diff --git a/clang/lib/Headers/riscv_packed_simd.h b/clang/lib/Headers/riscv_packed_simd.h index e04c51b3208f9..dc057d8ef2608 100644 --- a/clang/lib/Headers/riscv_packed_simd.h +++ b/clang/lib/Headers/riscv_packed_simd.h @@ -75,6 +75,13 @@ typedef uint32_t uint32x2_t __attribute__((__vector_size__(8))); return __v[__idx]; \ } +#define __packed_store(name, ty, elt_ty) \ + static __inline__ void __DEFAULT_FN_ATTRS __riscv_##name(elt_ty *__p, \ + ty __v) { \ + typedef ty __attribute__((__aligned__(1))) ua_ty; \ + *(ua_ty *)__p = __v; \ + } + #define __packed_binary_builtin(name, ty, builtin) \ static __inline__ ty __DEFAULT_FN_ATTRS __riscv_##name(ty __rs1, ty __rs2) { \ return builtin(__rs1, __rs2); \ @@ -1038,6 +1045,20 @@ __packed_binary_builtin_cast(pnclipup_u16x4, uint32x2_t, uint16x4_t, __builtin_r __packed_binary_builtin_cast(pnclipp_i32x2, int64_t, int32x2_t, __builtin_riscv_pnclipp_i32x2) __packed_binary_builtin_cast(pnclipup_u32x2, uint64_t, uint32x2_t, __builtin_riscv_pnclipup_u32x2) +/* Packed Store (32-bit) */ +__packed_store(pst_i8x4, int8x4_t, int8_t) +__packed_store(pst_u8x4, uint8x4_t, uint8_t) +__packed_store(pst_i16x2, int16x2_t, int16_t) +__packed_store(pst_u16x2, uint16x2_t, uint16_t) + +/* Packed Store (64-bit) */ +__packed_store(pst_i8x8, int8x8_t, int8_t) +__packed_store(pst_u8x8, uint8x8_t, uint8_t) +__packed_store(pst_i16x4, int16x4_t, int16_t) +__packed_store(pst_u16x4, uint16x4_t, uint16_t) +__packed_store(pst_i32x2, int32x2_t, int32_t) +__packed_store(pst_u32x2, uint32x2_t, uint32_t) + /* Packed Element Extract (32-bit) */ __packed_extract(pget_i8x4_i8, int8_t, int8x4_t, 3) __packed_extract(pget_u8x4_u8, uint8_t, uint8x4_t, 3) @@ -1155,6 +1176,7 @@ __packed_reinterpret(u32x2_i32x2, int32x2_t, uint32x2_t) #undef __packed_scalar_binary_op #undef __packed_binary_op #undef __packed_unary_op +#undef __packed_store #undef __packed_binary_builtin #undef __packed_binary_builtin_mixed #undef __packed_ternary_builtin diff --git a/clang/test/CodeGen/RISCV/rvp-intrinsics.c b/clang/test/CodeGen/RISCV/rvp-intrinsics.c index 954e8eb77e41e..41d23d2d6bcff 100644 --- a/clang/test/CodeGen/RISCV/rvp-intrinsics.c +++ b/clang/test/CodeGen/RISCV/rvp-intrinsics.c @@ -11005,3 +11005,186 @@ int32_t test_pget_i32x2_i32(int32x2_t v) { uint32_t test_pget_u32x2_u32(uint32x2_t v) { return __riscv_pget_u32x2_u32(v, 1); } + +/* Packed Store (32-bit) */ + +// RV32-LABEL: define dso_local void @test_pst_i8x4( +// RV32-SAME: ptr noundef [[P:%.*]], i32 noundef [[V_COERCE:%.*]]) #[[ATTR0]] { +// RV32-NEXT: [[ENTRY:.*:]] +// RV32-NEXT: store i32 [[V_COERCE]], ptr [[P]], align 1 +// RV32-NEXT: ret void +// +// RV64-LABEL: define dso_local void @test_pst_i8x4( +// RV64-SAME: ptr noundef [[P:%.*]], i32 noundef [[V_COERCE:%.*]]) #[[ATTR0]] { +// RV64-NEXT: [[ENTRY:.*:]] +// RV64-NEXT: store i32 [[V_COERCE]], ptr [[P]], align 1 +// RV64-NEXT: ret void +// +void test_pst_i8x4(int8_t *p, int8x4_t v) { __riscv_pst_i8x4(p, v); } + +// RV32-LABEL: define dso_local void @test_pst_u8x4( +// RV32-SAME: ptr noundef [[P:%.*]], i32 noundef [[V_COERCE:%.*]]) #[[ATTR0]] { +// RV32-NEXT: [[ENTRY:.*:]] +// RV32-NEXT: store i32 [[V_COERCE]], ptr [[P]], align 1 +// RV32-NEXT: ret void +// +// RV64-LABEL: define dso_local void @test_pst_u8x4( +// RV64-SAME: ptr noundef [[P:%.*]], i32 noundef [[V_COERCE:%.*]]) #[[ATTR0]] { +// RV64-NEXT: [[ENTRY:.*:]] +// RV64-NEXT: store i32 [[V_COERCE]], ptr [[P]], align 1 +// RV64-NEXT: ret void +// +void test_pst_u8x4(uint8_t *p, uint8x4_t v) { __riscv_pst_u8x4(p, v); } + +// RV32-LABEL: define dso_local void @test_pst_i16x2( +// RV32-SAME: ptr noundef [[P:%.*]], i32 noundef [[V_COERCE:%.*]]) #[[ATTR0]] { +// RV32-NEXT: [[ENTRY:.*:]] +// RV32-NEXT: store i32 [[V_COERCE]], ptr [[P]], align 1 +// RV32-NEXT: ret void +// +// RV64-LABEL: define dso_local void @test_pst_i16x2( +// RV64-SAME: ptr noundef [[P:%.*]], i32 noundef [[V_COERCE:%.*]]) #[[ATTR0]] { +// RV64-NEXT: [[ENTRY:.*:]] +// RV64-NEXT: store i32 [[V_COERCE]], ptr [[P]], align 1 +// RV64-NEXT: ret void +// +void test_pst_i16x2(int16_t *p, int16x2_t v) { __riscv_pst_i16x2(p, v); } + +// RV32-LABEL: define dso_local void @test_pst_u16x2( +// RV32-SAME: ptr noundef [[P:%.*]], i32 noundef [[V_COERCE:%.*]]) #[[ATTR0]] { +// RV32-NEXT: [[ENTRY:.*:]] +// RV32-NEXT: store i32 [[V_COERCE]], ptr [[P]], align 1 +// RV32-NEXT: ret void +// +// RV64-LABEL: define dso_local void @test_pst_u16x2( +// RV64-SAME: ptr noundef [[P:%.*]], i32 noundef [[V_COERCE:%.*]]) #[[ATTR0]] { +// RV64-NEXT: [[ENTRY:.*:]] +// RV64-NEXT: store i32 [[V_COERCE]], ptr [[P]], align 1 +// RV64-NEXT: ret void +// +void test_pst_u16x2(uint16_t *p, uint16x2_t v) { __riscv_pst_u16x2(p, v); } + +/* Packed Store (64-bit) */ + +// RV32-LABEL: define dso_local void @test_pst_i8x8( +// RV32-SAME: ptr noundef [[P:%.*]], i64 noundef [[V_COERCE:%.*]]) #[[ATTR0]] { +// RV32-NEXT: [[ENTRY:.*:]] +// RV32-NEXT: store i64 [[V_COERCE]], ptr [[P]], align 1 +// RV32-NEXT: ret void +// +// RV64-LABEL: define dso_local void @test_pst_i8x8( +// RV64-SAME: ptr noundef [[P:%.*]], i64 noundef [[V_COERCE:%.*]]) #[[ATTR0]] { +// RV64-NEXT: [[ENTRY:.*:]] +// RV64-NEXT: store i64 [[V_COERCE]], ptr [[P]], align 1 +// RV64-NEXT: ret void +// +void test_pst_i8x8(int8_t *p, int8x8_t v) { __riscv_pst_i8x8(p, v); } + +// RV32-LABEL: define dso_local void @test_pst_u8x8( +// RV32-SAME: ptr noundef [[P:%.*]], i64 noundef [[V_COERCE:%.*]]) #[[ATTR0]] { +// RV32-NEXT: [[ENTRY:.*:]] +// RV32-NEXT: store i64 [[V_COERCE]], ptr [[P]], align 1 +// RV32-NEXT: ret void +// +// RV64-LABEL: define dso_local void @test_pst_u8x8( +// RV64-SAME: ptr noundef [[P:%.*]], i64 noundef [[V_COERCE:%.*]]) #[[ATTR0]] { +// RV64-NEXT: [[ENTRY:.*:]] +// RV64-NEXT: store i64 [[V_COERCE]], ptr [[P]], align 1 +// RV64-NEXT: ret void +// +void test_pst_u8x8(uint8_t *p, uint8x8_t v) { __riscv_pst_u8x8(p, v); } + +// RV32-LABEL: define dso_local void @test_pst_i16x4( +// RV32-SAME: ptr noundef [[P:%.*]], i64 noundef [[V_COERCE:%.*]]) #[[ATTR0]] { +// RV32-NEXT: [[ENTRY:.*:]] +// RV32-NEXT: store i64 [[V_COERCE]], ptr [[P]], align 1 +// RV32-NEXT: ret void +// +// RV64-LABEL: define dso_local void @test_pst_i16x4( +// RV64-SAME: ptr noundef [[P:%.*]], i64 noundef [[V_COERCE:%.*]]) #[[ATTR0]] { +// RV64-NEXT: [[ENTRY:.*:]] +// RV64-NEXT: store i64 [[V_COERCE]], ptr [[P]], align 1 +// RV64-NEXT: ret void +// +void test_pst_i16x4(int16_t *p, int16x4_t v) { __riscv_pst_i16x4(p, v); } + +// RV32-LABEL: define dso_local void @test_pst_u16x4( +// RV32-SAME: ptr noundef [[P:%.*]], i64 noundef [[V_COERCE:%.*]]) #[[ATTR0]] { +// RV32-NEXT: [[ENTRY:.*:]] +// RV32-NEXT: store i64 [[V_COERCE]], ptr [[P]], align 1 +// RV32-NEXT: ret void +// +// RV64-LABEL: define dso_local void @test_pst_u16x4( +// RV64-SAME: ptr noundef [[P:%.*]], i64 noundef [[V_COERCE:%.*]]) #[[ATTR0]] { +// RV64-NEXT: [[ENTRY:.*:]] +// RV64-NEXT: store i64 [[V_COERCE]], ptr [[P]], align 1 +// RV64-NEXT: ret void +// +void test_pst_u16x4(uint16_t *p, uint16x4_t v) { __riscv_pst_u16x4(p, v); } + +// RV32-LABEL: define dso_local void @test_pst_i32x2( +// RV32-SAME: ptr noundef [[P:%.*]], i64 noundef [[V_COERCE:%.*]]) #[[ATTR0]] { +// RV32-NEXT: [[ENTRY:.*:]] +// RV32-NEXT: store i64 [[V_COERCE]], ptr [[P]], align 1 +// RV32-NEXT: ret void +// +// RV64-LABEL: define dso_local void @test_pst_i32x2( +// RV64-SAME: ptr noundef [[P:%.*]], i64 noundef [[V_COERCE:%.*]]) #[[ATTR0]] { +// RV64-NEXT: [[ENTRY:.*:]] +// RV64-NEXT: store i64 [[V_COERCE]], ptr [[P]], align 1 +// RV64-NEXT: ret void +// +void test_pst_i32x2(int32_t *p, int32x2_t v) { __riscv_pst_i32x2(p, v); } + +// RV32-LABEL: define dso_local void @test_pst_u32x2( +// RV32-SAME: ptr noundef [[P:%.*]], i64 noundef [[V_COERCE:%.*]]) #[[ATTR0]] { +// RV32-NEXT: [[ENTRY:.*:]] +// RV32-NEXT: store i64 [[V_COERCE]], ptr [[P]], align 1 +// RV32-NEXT: ret void +// +// RV64-LABEL: define dso_local void @test_pst_u32x2( +// RV64-SAME: ptr noundef [[P:%.*]], i64 noundef [[V_COERCE:%.*]]) #[[ATTR0]] { +// RV64-NEXT: [[ENTRY:.*:]] +// RV64-NEXT: store i64 [[V_COERCE]], ptr [[P]], align 1 +// RV64-NEXT: ret void +// +void test_pst_u32x2(uint32_t *p, uint32x2_t v) { __riscv_pst_u32x2(p, v); } + +/* Packed Store with provable alignment (cf. the P-ext spec's note on + * __builtin_assume_aligned) */ + +// RV32-LABEL: define dso_local void @test_pst_i8x4_aligned( +// RV32-SAME: ptr noundef [[P:%.*]], i32 noundef [[V_COERCE:%.*]]) #[[ATTR0]] { +// RV32-NEXT: [[ENTRY:.*:]] +// RV32-NEXT: call void @llvm.assume(i1 true) [ "align"(ptr [[P]], i32 4) ] +// RV32-NEXT: store i32 [[V_COERCE]], ptr [[P]], align 1 +// RV32-NEXT: ret void +// +// RV64-LABEL: define dso_local void @test_pst_i8x4_aligned( +// RV64-SAME: ptr noundef [[P:%.*]], i32 noundef [[V_COERCE:%.*]]) #[[ATTR0]] { +// RV64-NEXT: [[ENTRY:.*:]] +// RV64-NEXT: call void @llvm.assume(i1 true) [ "align"(ptr [[P]], i64 4) ] +// RV64-NEXT: store i32 [[V_COERCE]], ptr [[P]], align 1 +// RV64-NEXT: ret void +// +void test_pst_i8x4_aligned(int8_t *p, int8x4_t v) { + __riscv_pst_i8x4(__builtin_assume_aligned(p, 4), v); +} + +// RV32-LABEL: define dso_local void @test_pst_i32x2_aligned( +// RV32-SAME: ptr noundef [[P:%.*]], i64 noundef [[V_COERCE:%.*]]) #[[ATTR0]] { +// RV32-NEXT: [[ENTRY:.*:]] +// RV32-NEXT: call void @llvm.assume(i1 true) [ "align"(ptr [[P]], i32 8) ] +// RV32-NEXT: store i64 [[V_COERCE]], ptr [[P]], align 1 +// RV32-NEXT: ret void +// +// RV64-LABEL: define dso_local void @test_pst_i32x2_aligned( +// RV64-SAME: ptr noundef [[P:%.*]], i64 noundef [[V_COERCE:%.*]]) #[[ATTR0]] { +// RV64-NEXT: [[ENTRY:.*:]] +// RV64-NEXT: call void @llvm.assume(i1 true) [ "align"(ptr [[P]], i64 8) ] +// RV64-NEXT: store i64 [[V_COERCE]], ptr [[P]], align 1 +// RV64-NEXT: ret void +// +void test_pst_i32x2_aligned(int32_t *p, int32x2_t v) { + __riscv_pst_i32x2(__builtin_assume_aligned(p, 8), v); +} diff --git a/clang/test/Sema/riscv-pst-pointer-types.c b/clang/test/Sema/riscv-pst-pointer-types.c new file mode 100644 index 0000000000000..48e82b5710188 --- /dev/null +++ b/clang/test/Sema/riscv-pst-pointer-types.c @@ -0,0 +1,41 @@ +// RUN: %clang_cc1 -triple riscv32 -target-feature +experimental-p \ +// RUN: -fsyntax-only -verify -verify-ignore-unexpected=note %s +// RUN: %clang_cc1 -triple riscv64 -target-feature +experimental-p \ +// RUN: -fsyntax-only -verify -verify-ignore-unexpected=note %s + +#include <riscv_packed_simd.h> + +// The __riscv_pst_* intrinsics take a pointer to the element type; passing a +// pointer to an unrelated type is ill-formed. + +void test_pst_i8x4_ok(int8_t *p, int8x4_t v) { __riscv_pst_i8x4(p, v); } + +void test_pst_i8x4_void_ptr(void *p, int8x4_t v) { + __riscv_pst_i8x4(p, v); +} + +void test_pst_i8x4_array(int8x4_t v) { + int8_t a[4]; + __riscv_pst_i8x4(a, v); +} + +void test_pst_i8x4_wrong_pointer_type(float *p, int8x4_t v) { + // expected-error@+1 {{incompatible pointer types passing 'float *' to parameter of type 'int8_t *' (aka 'signed char *')}} + __riscv_pst_i8x4(p, v); +} + +void test_pst_u16x2_wrong_pointer_type(uint32_t *p, uint16x2_t v) { + // expected-error@+1 {{incompatible pointer types passing 'uint32_t *' (aka 'unsigned int *') to parameter of type 'uint16_t *' (aka 'unsigned short *')}} + __riscv_pst_u16x2(p, v); +} + +void test_pst_i32x2_wrong_pointer_type(int8x4_t *p, int32x2_t v) { + // expected-error@+1 {{incompatible pointer types passing 'int8x4_t *' to parameter of type 'int32_t *' (aka 'int *')}} + __riscv_pst_i32x2(p, v); +} + +void test_pst_i16x4_const_discards_qualifiers(const int16_t *p, + int16x4_t v) { + // expected-warning@+1 {{passing 'const int16_t *' (aka 'const short *') to parameter of type 'int16_t *' (aka 'short *') discards qualifiers}} + __riscv_pst_i16x4(p, v); +} 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 f222e66ff1dd5..7fc08120e93ad 100644 --- a/cross-project-tests/intrinsic-header-tests/riscv_packed_simd.c +++ b/cross-project-tests/intrinsic-header-tests/riscv_packed_simd.c @@ -4459,3 +4459,69 @@ int64_t test_maccsu_w00_i64(int64_t rd, int32x2_t a, uint32x2_t b) { int64_t test_maccsu_w11_i64(int64_t rd, int32x2_t a, uint32x2_t b) { return __riscv_maccsu_w11_i64(rd, a, b); } + +// CHECK-LABEL: test_pst_i8x4: +// CHECK-COUNT-4: sb{{[[:space:]]}} +void test_pst_i8x4(int8_t *p, int8x4_t v) { __riscv_pst_i8x4(p, v); } + +// CHECK-LABEL: test_pst_u8x4: +// CHECK-COUNT-4: sb{{[[:space:]]}} +void test_pst_u8x4(uint8_t *p, uint8x4_t v) { __riscv_pst_u8x4(p, v); } + +// CHECK-LABEL: test_pst_i16x2: +// CHECK-COUNT-4: sb{{[[:space:]]}} +void test_pst_i16x2(int16_t *p, int16x2_t v) { __riscv_pst_i16x2(p, v); } + +// CHECK-LABEL: test_pst_u16x2: +// CHECK-COUNT-4: sb{{[[:space:]]}} +void test_pst_u16x2(uint16_t *p, uint16x2_t v) { __riscv_pst_u16x2(p, v); } + +// CHECK-LABEL: test_pst_i8x8: +// CHECK-COUNT-8: sb{{[[:space:]]}} +void test_pst_i8x8(int8_t *p, int8x8_t v) { __riscv_pst_i8x8(p, v); } + +// CHECK-LABEL: test_pst_u8x8: +// CHECK-COUNT-8: sb{{[[:space:]]}} +void test_pst_u8x8(uint8_t *p, uint8x8_t v) { __riscv_pst_u8x8(p, v); } + +// CHECK-LABEL: test_pst_i16x4: +// CHECK-COUNT-8: sb{{[[:space:]]}} +void test_pst_i16x4(int16_t *p, int16x4_t v) { __riscv_pst_i16x4(p, v); } + +// CHECK-LABEL: test_pst_u16x4: +// CHECK-COUNT-8: sb{{[[:space:]]}} +void test_pst_u16x4(uint16_t *p, uint16x4_t v) { __riscv_pst_u16x4(p, v); } + +// CHECK-LABEL: test_pst_i32x2: +// CHECK-COUNT-8: sb{{[[:space:]]}} +void test_pst_i32x2(int32_t *p, int32x2_t v) { __riscv_pst_i32x2(p, v); } + +// CHECK-LABEL: test_pst_u32x2: +// CHECK-COUNT-8: sb{{[[:space:]]}} +void test_pst_u32x2(uint32_t *p, uint32x2_t v) { __riscv_pst_u32x2(p, v); } + +// CHECK-LABEL: test_pst_i8x4_aligned: +// CHECK: sw +void test_pst_i8x4_aligned(int8_t *p, int8x4_t v) { + __riscv_pst_i8x4(__builtin_assume_aligned(p, 4), v); +} + +// CHECK-LABEL: test_pst_u16x2_aligned: +// CHECK: sw +void test_pst_u16x2_aligned(uint16_t *p, uint16x2_t v) { + __riscv_pst_u16x2(__builtin_assume_aligned(p, 4), v); +} + +// CHECK-LABEL: test_pst_i8x8_aligned: +// RV32-COUNT-2: sw +// RV64: sd +void test_pst_i8x8_aligned(int8_t *p, int8x8_t v) { + __riscv_pst_i8x8(__builtin_assume_aligned(p, 8), v); +} + +// CHECK-LABEL: test_pst_u32x2_aligned: +// RV32-COUNT-2: sw +// RV64: sd +void test_pst_u32x2_aligned(uint32_t *p, uint32x2_t v) { + __riscv_pst_u32x2(__builtin_assume_aligned(p, 8), v); +} _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
