https://github.com/sihuan created https://github.com/llvm/llvm-project/pull/224429
Add the Packed Subvector Extract intrinsics: - `__riscv_pget_i8x8_i8x4` - `__riscv_pget_u8x8_u8x4` - `__riscv_pget_i16x4_i16x2` - `__riscv_pget_u16x4_u16x2` Each extracts the 32-bit packed subvector selected by a constant index (0 = low, 1 = high) from a 64-bit packed vector. The index is range-checked with `__enable_if__`, as for the element extract intrinsics. This is header-only: the shuffle is selected without backend changes, so no new IR intrinsics or builtins are required. >From b727b977cb268de1f2145c7e5ff49d39f18eb0a8 Mon Sep 17 00:00:00 2001 From: SiHuaN <[email protected]> Date: Thu, 17 Sep 2026 20:16:50 +0000 Subject: [PATCH] [Clang][RISCV] Add packed subvector extract intrinsics Add __riscv_pget_i8x8_i8x4, __riscv_pget_u8x8_u8x4, __riscv_pget_i16x4_i16x2 and __riscv_pget_u16x4_u16x2, which extract a 32-bit packed subvector from a 64-bit packed vector. The index selects the low or high half and must be a constant, enforced with __enable_if__ as for the element extract intrinsics. --- clang/lib/Headers/riscv_packed_simd.h | 25 ++ clang/test/CodeGen/RISCV/rvp-intrinsics.c | 250 ++++++++++++++++++ .../riscv_packed_simd.c | 54 ++++ 3 files changed, 329 insertions(+) diff --git a/clang/lib/Headers/riscv_packed_simd.h b/clang/lib/Headers/riscv_packed_simd.h index 8c20d00e68652..7571cbe284f6b 100644 --- a/clang/lib/Headers/riscv_packed_simd.h +++ b/clang/lib/Headers/riscv_packed_simd.h @@ -75,6 +75,23 @@ typedef uint32_t uint32x2_t __attribute__((__vector_size__(8))); return __v[__idx]; \ } +#define __packed_subvector_extract8(name, rty, ty) \ + static __inline__ rty __DEFAULT_FN_ATTRS __riscv_##name(ty __v, \ + unsigned __idx) \ + __attribute__((__enable_if__( \ + __idx <= 1, "index must be a constant integer from 0 to 1"))) { \ + return __idx ? __builtin_shufflevector(__v, __v, 4, 5, 6, 7) \ + : __builtin_shufflevector(__v, __v, 0, 1, 2, 3); \ + } +#define __packed_subvector_extract4(name, rty, ty) \ + static __inline__ rty __DEFAULT_FN_ATTRS __riscv_##name(ty __v, \ + unsigned __idx) \ + __attribute__((__enable_if__( \ + __idx <= 1, "index must be a constant integer from 0 to 1"))) { \ + return __idx ? __builtin_shufflevector(__v, __v, 2, 3) \ + : __builtin_shufflevector(__v, __v, 0, 1); \ + } + #define __packed_store(name, ty, elt_ty) \ static __inline__ void __DEFAULT_FN_ATTRS __riscv_##name(elt_ty *__p, \ ty __v) { \ @@ -1114,6 +1131,12 @@ __packed_concat4(pjoin2_u8x8, uint8x8_t, uint8x4_t) __packed_concat2(pjoin2_i16x4, int16x4_t, int16x2_t) __packed_concat2(pjoin2_u16x4, uint16x4_t, uint16x2_t) +/* Packed Subvector Extract */ +__packed_subvector_extract8(pget_i8x8_i8x4, int8x4_t, int8x8_t) +__packed_subvector_extract8(pget_u8x8_u8x4, uint8x4_t, uint8x8_t) +__packed_subvector_extract4(pget_i16x4_i16x2, int16x2_t, int16x4_t) +__packed_subvector_extract4(pget_u16x4_u16x2, uint16x2_t, uint16x4_t) + /* Packed Store (32-bit) */ __packed_store(pst_i8x4, int8x4_t, int8_t) __packed_store(pst_u8x4, uint8x4_t, uint8_t) @@ -1309,6 +1332,8 @@ __packed_reinterpret(u32x2_i32x2, int32x2_t, uint32x2_t) #undef __packed_abdsum #undef __packed_ternary_builtin_cast #undef __packed_extract +#undef __packed_subvector_extract8 +#undef __packed_subvector_extract4 #undef __packed_insert #undef __packed_join2 #undef __packed_join4 diff --git a/clang/test/CodeGen/RISCV/rvp-intrinsics.c b/clang/test/CodeGen/RISCV/rvp-intrinsics.c index b2b2b1b9a777b..edf15f7b5a408 100644 --- a/clang/test/CodeGen/RISCV/rvp-intrinsics.c +++ b/clang/test/CodeGen/RISCV/rvp-intrinsics.c @@ -11864,3 +11864,253 @@ int16x4_t test_pjoin2_i16x4(int16x2_t lo, int16x2_t hi) { uint16x4_t test_pjoin2_u16x4(uint16x2_t lo, uint16x2_t hi) { return __riscv_pjoin2_u16x4(lo, hi); } + +/* Packed Subvector Extract */ + +// RV32-LABEL: define dso_local i32 @test_pget_i8x8_i8x4( +// RV32-SAME: i64 noundef [[V_COERCE:%.*]]) #[[ATTR0]] { +// RV32-NEXT: [[ENTRY:.*:]] +// RV32-NEXT: br i1 false, label %[[COND_TRUE_I:.*]], label %[[COND_FALSE_I:.*]] +// RV32: [[COND_TRUE_I]]: +// RV32-NEXT: br label %[[__RISCV_PGET_I8X8_I8X4_EXIT:.*]] +// RV32: [[COND_FALSE_I]]: +// RV32-NEXT: [[SHUFFLE2_I_EXTRACT:%.*]] = trunc i64 [[V_COERCE]] to i32 +// RV32-NEXT: br label %[[__RISCV_PGET_I8X8_I8X4_EXIT]] +// RV32: [[__RISCV_PGET_I8X8_I8X4_EXIT]]: +// RV32-NEXT: [[TMP0:%.*]] = phi i32 [ poison, %[[COND_TRUE_I]] ], [ [[SHUFFLE2_I_EXTRACT]], %[[COND_FALSE_I]] ] +// RV32-NEXT: ret i32 [[TMP0]] +// +// RV64-LABEL: define dso_local i32 @test_pget_i8x8_i8x4( +// RV64-SAME: i64 noundef [[V_COERCE:%.*]]) #[[ATTR0]] { +// RV64-NEXT: [[ENTRY:.*:]] +// RV64-NEXT: br i1 false, label %[[COND_TRUE_I:.*]], label %[[COND_FALSE_I:.*]] +// RV64: [[COND_TRUE_I]]: +// RV64-NEXT: br label %[[__RISCV_PGET_I8X8_I8X4_EXIT:.*]] +// RV64: [[COND_FALSE_I]]: +// RV64-NEXT: [[SHUFFLE2_I_EXTRACT:%.*]] = trunc i64 [[V_COERCE]] to i32 +// RV64-NEXT: br label %[[__RISCV_PGET_I8X8_I8X4_EXIT]] +// RV64: [[__RISCV_PGET_I8X8_I8X4_EXIT]]: +// RV64-NEXT: [[TMP0:%.*]] = phi i32 [ poison, %[[COND_TRUE_I]] ], [ [[SHUFFLE2_I_EXTRACT]], %[[COND_FALSE_I]] ] +// RV64-NEXT: ret i32 [[TMP0]] +// +int8x4_t test_pget_i8x8_i8x4(int8x8_t v) { + return __riscv_pget_i8x8_i8x4(v, 0); +} + +// RV32-LABEL: define dso_local i32 @test_pget_i8x8_i8x4_idx1( +// RV32-SAME: i64 noundef [[V_COERCE:%.*]]) #[[ATTR0]] { +// RV32-NEXT: [[ENTRY:.*:]] +// RV32-NEXT: br i1 true, label %[[COND_TRUE_I:.*]], label %[[COND_FALSE_I:.*]] +// RV32: [[COND_TRUE_I]]: +// RV32-NEXT: [[SHUFFLE_I_BC:%.*]] = bitcast i64 [[V_COERCE]] to <2 x i32> +// RV32-NEXT: [[SHUFFLE_I_EXTRACT:%.*]] = extractelement <2 x i32> [[SHUFFLE_I_BC]], i64 1 +// RV32-NEXT: br label %[[__RISCV_PGET_I8X8_I8X4_EXIT:.*]] +// RV32: [[COND_FALSE_I]]: +// RV32-NEXT: br label %[[__RISCV_PGET_I8X8_I8X4_EXIT]] +// RV32: [[__RISCV_PGET_I8X8_I8X4_EXIT]]: +// RV32-NEXT: [[TMP0:%.*]] = phi i32 [ [[SHUFFLE_I_EXTRACT]], %[[COND_TRUE_I]] ], [ poison, %[[COND_FALSE_I]] ] +// RV32-NEXT: ret i32 [[TMP0]] +// +// RV64-LABEL: define dso_local i32 @test_pget_i8x8_i8x4_idx1( +// RV64-SAME: i64 noundef [[V_COERCE:%.*]]) #[[ATTR0]] { +// RV64-NEXT: [[ENTRY:.*:]] +// RV64-NEXT: br i1 true, label %[[COND_TRUE_I:.*]], label %[[COND_FALSE_I:.*]] +// RV64: [[COND_TRUE_I]]: +// RV64-NEXT: [[EXTELT_OFFSET:%.*]] = lshr i64 [[V_COERCE]], 32 +// RV64-NEXT: [[SHUFFLE_I_EXTRACT:%.*]] = trunc nuw i64 [[EXTELT_OFFSET]] to i32 +// RV64-NEXT: br label %[[__RISCV_PGET_I8X8_I8X4_EXIT:.*]] +// RV64: [[COND_FALSE_I]]: +// RV64-NEXT: br label %[[__RISCV_PGET_I8X8_I8X4_EXIT]] +// RV64: [[__RISCV_PGET_I8X8_I8X4_EXIT]]: +// RV64-NEXT: [[TMP0:%.*]] = phi i32 [ [[SHUFFLE_I_EXTRACT]], %[[COND_TRUE_I]] ], [ poison, %[[COND_FALSE_I]] ] +// RV64-NEXT: ret i32 [[TMP0]] +// +int8x4_t test_pget_i8x8_i8x4_idx1(int8x8_t v) { + return __riscv_pget_i8x8_i8x4(v, 1); +} + +// RV32-LABEL: define dso_local i32 @test_pget_u8x8_u8x4( +// RV32-SAME: i64 noundef [[V_COERCE:%.*]]) #[[ATTR0]] { +// RV32-NEXT: [[ENTRY:.*:]] +// RV32-NEXT: br i1 false, label %[[COND_TRUE_I:.*]], label %[[COND_FALSE_I:.*]] +// RV32: [[COND_TRUE_I]]: +// RV32-NEXT: br label %[[__RISCV_PGET_U8X8_U8X4_EXIT:.*]] +// RV32: [[COND_FALSE_I]]: +// RV32-NEXT: [[SHUFFLE2_I_EXTRACT:%.*]] = trunc i64 [[V_COERCE]] to i32 +// RV32-NEXT: br label %[[__RISCV_PGET_U8X8_U8X4_EXIT]] +// RV32: [[__RISCV_PGET_U8X8_U8X4_EXIT]]: +// RV32-NEXT: [[TMP0:%.*]] = phi i32 [ poison, %[[COND_TRUE_I]] ], [ [[SHUFFLE2_I_EXTRACT]], %[[COND_FALSE_I]] ] +// RV32-NEXT: ret i32 [[TMP0]] +// +// RV64-LABEL: define dso_local i32 @test_pget_u8x8_u8x4( +// RV64-SAME: i64 noundef [[V_COERCE:%.*]]) #[[ATTR0]] { +// RV64-NEXT: [[ENTRY:.*:]] +// RV64-NEXT: br i1 false, label %[[COND_TRUE_I:.*]], label %[[COND_FALSE_I:.*]] +// RV64: [[COND_TRUE_I]]: +// RV64-NEXT: br label %[[__RISCV_PGET_U8X8_U8X4_EXIT:.*]] +// RV64: [[COND_FALSE_I]]: +// RV64-NEXT: [[SHUFFLE2_I_EXTRACT:%.*]] = trunc i64 [[V_COERCE]] to i32 +// RV64-NEXT: br label %[[__RISCV_PGET_U8X8_U8X4_EXIT]] +// RV64: [[__RISCV_PGET_U8X8_U8X4_EXIT]]: +// RV64-NEXT: [[TMP0:%.*]] = phi i32 [ poison, %[[COND_TRUE_I]] ], [ [[SHUFFLE2_I_EXTRACT]], %[[COND_FALSE_I]] ] +// RV64-NEXT: ret i32 [[TMP0]] +// +uint8x4_t test_pget_u8x8_u8x4(uint8x8_t v) { + return __riscv_pget_u8x8_u8x4(v, 0); +} + +// RV32-LABEL: define dso_local i32 @test_pget_u8x8_u8x4_idx1( +// RV32-SAME: i64 noundef [[V_COERCE:%.*]]) #[[ATTR0]] { +// RV32-NEXT: [[ENTRY:.*:]] +// RV32-NEXT: br i1 true, label %[[COND_TRUE_I:.*]], label %[[COND_FALSE_I:.*]] +// RV32: [[COND_TRUE_I]]: +// RV32-NEXT: [[SHUFFLE_I_BC:%.*]] = bitcast i64 [[V_COERCE]] to <2 x i32> +// RV32-NEXT: [[SHUFFLE_I_EXTRACT:%.*]] = extractelement <2 x i32> [[SHUFFLE_I_BC]], i64 1 +// RV32-NEXT: br label %[[__RISCV_PGET_U8X8_U8X4_EXIT:.*]] +// RV32: [[COND_FALSE_I]]: +// RV32-NEXT: br label %[[__RISCV_PGET_U8X8_U8X4_EXIT]] +// RV32: [[__RISCV_PGET_U8X8_U8X4_EXIT]]: +// RV32-NEXT: [[TMP0:%.*]] = phi i32 [ [[SHUFFLE_I_EXTRACT]], %[[COND_TRUE_I]] ], [ poison, %[[COND_FALSE_I]] ] +// RV32-NEXT: ret i32 [[TMP0]] +// +// RV64-LABEL: define dso_local i32 @test_pget_u8x8_u8x4_idx1( +// RV64-SAME: i64 noundef [[V_COERCE:%.*]]) #[[ATTR0]] { +// RV64-NEXT: [[ENTRY:.*:]] +// RV64-NEXT: br i1 true, label %[[COND_TRUE_I:.*]], label %[[COND_FALSE_I:.*]] +// RV64: [[COND_TRUE_I]]: +// RV64-NEXT: [[EXTELT_OFFSET:%.*]] = lshr i64 [[V_COERCE]], 32 +// RV64-NEXT: [[SHUFFLE_I_EXTRACT:%.*]] = trunc nuw i64 [[EXTELT_OFFSET]] to i32 +// RV64-NEXT: br label %[[__RISCV_PGET_U8X8_U8X4_EXIT:.*]] +// RV64: [[COND_FALSE_I]]: +// RV64-NEXT: br label %[[__RISCV_PGET_U8X8_U8X4_EXIT]] +// RV64: [[__RISCV_PGET_U8X8_U8X4_EXIT]]: +// RV64-NEXT: [[TMP0:%.*]] = phi i32 [ [[SHUFFLE_I_EXTRACT]], %[[COND_TRUE_I]] ], [ poison, %[[COND_FALSE_I]] ] +// RV64-NEXT: ret i32 [[TMP0]] +// +uint8x4_t test_pget_u8x8_u8x4_idx1(uint8x8_t v) { + return __riscv_pget_u8x8_u8x4(v, 1); +} + +// RV32-LABEL: define dso_local i32 @test_pget_i16x4_i16x2( +// RV32-SAME: i64 noundef [[V_COERCE:%.*]]) #[[ATTR0]] { +// RV32-NEXT: [[ENTRY:.*:]] +// RV32-NEXT: br i1 false, label %[[COND_TRUE_I:.*]], label %[[COND_FALSE_I:.*]] +// RV32: [[COND_TRUE_I]]: +// RV32-NEXT: br label %[[__RISCV_PGET_I16X4_I16X2_EXIT:.*]] +// RV32: [[COND_FALSE_I]]: +// RV32-NEXT: [[SHUFFLE2_I_EXTRACT:%.*]] = trunc i64 [[V_COERCE]] to i32 +// RV32-NEXT: br label %[[__RISCV_PGET_I16X4_I16X2_EXIT]] +// RV32: [[__RISCV_PGET_I16X4_I16X2_EXIT]]: +// RV32-NEXT: [[TMP0:%.*]] = phi i32 [ poison, %[[COND_TRUE_I]] ], [ [[SHUFFLE2_I_EXTRACT]], %[[COND_FALSE_I]] ] +// RV32-NEXT: ret i32 [[TMP0]] +// +// RV64-LABEL: define dso_local i32 @test_pget_i16x4_i16x2( +// RV64-SAME: i64 noundef [[V_COERCE:%.*]]) #[[ATTR0]] { +// RV64-NEXT: [[ENTRY:.*:]] +// RV64-NEXT: br i1 false, label %[[COND_TRUE_I:.*]], label %[[COND_FALSE_I:.*]] +// RV64: [[COND_TRUE_I]]: +// RV64-NEXT: br label %[[__RISCV_PGET_I16X4_I16X2_EXIT:.*]] +// RV64: [[COND_FALSE_I]]: +// RV64-NEXT: [[SHUFFLE2_I_EXTRACT:%.*]] = trunc i64 [[V_COERCE]] to i32 +// RV64-NEXT: br label %[[__RISCV_PGET_I16X4_I16X2_EXIT]] +// RV64: [[__RISCV_PGET_I16X4_I16X2_EXIT]]: +// RV64-NEXT: [[TMP0:%.*]] = phi i32 [ poison, %[[COND_TRUE_I]] ], [ [[SHUFFLE2_I_EXTRACT]], %[[COND_FALSE_I]] ] +// RV64-NEXT: ret i32 [[TMP0]] +// +int16x2_t test_pget_i16x4_i16x2(int16x4_t v) { + return __riscv_pget_i16x4_i16x2(v, 0); +} + +// RV32-LABEL: define dso_local i32 @test_pget_i16x4_i16x2_idx1( +// RV32-SAME: i64 noundef [[V_COERCE:%.*]]) #[[ATTR0]] { +// RV32-NEXT: [[ENTRY:.*:]] +// RV32-NEXT: br i1 true, label %[[COND_TRUE_I:.*]], label %[[COND_FALSE_I:.*]] +// RV32: [[COND_TRUE_I]]: +// RV32-NEXT: [[SHUFFLE_I_BC:%.*]] = bitcast i64 [[V_COERCE]] to <2 x i32> +// RV32-NEXT: [[SHUFFLE_I_EXTRACT:%.*]] = extractelement <2 x i32> [[SHUFFLE_I_BC]], i64 1 +// RV32-NEXT: br label %[[__RISCV_PGET_I16X4_I16X2_EXIT:.*]] +// RV32: [[COND_FALSE_I]]: +// RV32-NEXT: br label %[[__RISCV_PGET_I16X4_I16X2_EXIT]] +// RV32: [[__RISCV_PGET_I16X4_I16X2_EXIT]]: +// RV32-NEXT: [[TMP0:%.*]] = phi i32 [ [[SHUFFLE_I_EXTRACT]], %[[COND_TRUE_I]] ], [ poison, %[[COND_FALSE_I]] ] +// RV32-NEXT: ret i32 [[TMP0]] +// +// RV64-LABEL: define dso_local i32 @test_pget_i16x4_i16x2_idx1( +// RV64-SAME: i64 noundef [[V_COERCE:%.*]]) #[[ATTR0]] { +// RV64-NEXT: [[ENTRY:.*:]] +// RV64-NEXT: br i1 true, label %[[COND_TRUE_I:.*]], label %[[COND_FALSE_I:.*]] +// RV64: [[COND_TRUE_I]]: +// RV64-NEXT: [[EXTELT_OFFSET:%.*]] = lshr i64 [[V_COERCE]], 32 +// RV64-NEXT: [[SHUFFLE_I_EXTRACT:%.*]] = trunc nuw i64 [[EXTELT_OFFSET]] to i32 +// RV64-NEXT: br label %[[__RISCV_PGET_I16X4_I16X2_EXIT:.*]] +// RV64: [[COND_FALSE_I]]: +// RV64-NEXT: br label %[[__RISCV_PGET_I16X4_I16X2_EXIT]] +// RV64: [[__RISCV_PGET_I16X4_I16X2_EXIT]]: +// RV64-NEXT: [[TMP0:%.*]] = phi i32 [ [[SHUFFLE_I_EXTRACT]], %[[COND_TRUE_I]] ], [ poison, %[[COND_FALSE_I]] ] +// RV64-NEXT: ret i32 [[TMP0]] +// +int16x2_t test_pget_i16x4_i16x2_idx1(int16x4_t v) { + return __riscv_pget_i16x4_i16x2(v, 1); +} + +// RV32-LABEL: define dso_local i32 @test_pget_u16x4_u16x2( +// RV32-SAME: i64 noundef [[V_COERCE:%.*]]) #[[ATTR0]] { +// RV32-NEXT: [[ENTRY:.*:]] +// RV32-NEXT: br i1 false, label %[[COND_TRUE_I:.*]], label %[[COND_FALSE_I:.*]] +// RV32: [[COND_TRUE_I]]: +// RV32-NEXT: br label %[[__RISCV_PGET_U16X4_U16X2_EXIT:.*]] +// RV32: [[COND_FALSE_I]]: +// RV32-NEXT: [[SHUFFLE2_I_EXTRACT:%.*]] = trunc i64 [[V_COERCE]] to i32 +// RV32-NEXT: br label %[[__RISCV_PGET_U16X4_U16X2_EXIT]] +// RV32: [[__RISCV_PGET_U16X4_U16X2_EXIT]]: +// RV32-NEXT: [[TMP0:%.*]] = phi i32 [ poison, %[[COND_TRUE_I]] ], [ [[SHUFFLE2_I_EXTRACT]], %[[COND_FALSE_I]] ] +// RV32-NEXT: ret i32 [[TMP0]] +// +// RV64-LABEL: define dso_local i32 @test_pget_u16x4_u16x2( +// RV64-SAME: i64 noundef [[V_COERCE:%.*]]) #[[ATTR0]] { +// RV64-NEXT: [[ENTRY:.*:]] +// RV64-NEXT: br i1 false, label %[[COND_TRUE_I:.*]], label %[[COND_FALSE_I:.*]] +// RV64: [[COND_TRUE_I]]: +// RV64-NEXT: br label %[[__RISCV_PGET_U16X4_U16X2_EXIT:.*]] +// RV64: [[COND_FALSE_I]]: +// RV64-NEXT: [[SHUFFLE2_I_EXTRACT:%.*]] = trunc i64 [[V_COERCE]] to i32 +// RV64-NEXT: br label %[[__RISCV_PGET_U16X4_U16X2_EXIT]] +// RV64: [[__RISCV_PGET_U16X4_U16X2_EXIT]]: +// RV64-NEXT: [[TMP0:%.*]] = phi i32 [ poison, %[[COND_TRUE_I]] ], [ [[SHUFFLE2_I_EXTRACT]], %[[COND_FALSE_I]] ] +// RV64-NEXT: ret i32 [[TMP0]] +// +uint16x2_t test_pget_u16x4_u16x2(uint16x4_t v) { + return __riscv_pget_u16x4_u16x2(v, 0); +} + +// RV32-LABEL: define dso_local i32 @test_pget_u16x4_u16x2_idx1( +// RV32-SAME: i64 noundef [[V_COERCE:%.*]]) #[[ATTR0]] { +// RV32-NEXT: [[ENTRY:.*:]] +// RV32-NEXT: br i1 true, label %[[COND_TRUE_I:.*]], label %[[COND_FALSE_I:.*]] +// RV32: [[COND_TRUE_I]]: +// RV32-NEXT: [[SHUFFLE_I_BC:%.*]] = bitcast i64 [[V_COERCE]] to <2 x i32> +// RV32-NEXT: [[SHUFFLE_I_EXTRACT:%.*]] = extractelement <2 x i32> [[SHUFFLE_I_BC]], i64 1 +// RV32-NEXT: br label %[[__RISCV_PGET_U16X4_U16X2_EXIT:.*]] +// RV32: [[COND_FALSE_I]]: +// RV32-NEXT: br label %[[__RISCV_PGET_U16X4_U16X2_EXIT]] +// RV32: [[__RISCV_PGET_U16X4_U16X2_EXIT]]: +// RV32-NEXT: [[TMP0:%.*]] = phi i32 [ [[SHUFFLE_I_EXTRACT]], %[[COND_TRUE_I]] ], [ poison, %[[COND_FALSE_I]] ] +// RV32-NEXT: ret i32 [[TMP0]] +// +// RV64-LABEL: define dso_local i32 @test_pget_u16x4_u16x2_idx1( +// RV64-SAME: i64 noundef [[V_COERCE:%.*]]) #[[ATTR0]] { +// RV64-NEXT: [[ENTRY:.*:]] +// RV64-NEXT: br i1 true, label %[[COND_TRUE_I:.*]], label %[[COND_FALSE_I:.*]] +// RV64: [[COND_TRUE_I]]: +// RV64-NEXT: [[EXTELT_OFFSET:%.*]] = lshr i64 [[V_COERCE]], 32 +// RV64-NEXT: [[SHUFFLE_I_EXTRACT:%.*]] = trunc nuw i64 [[EXTELT_OFFSET]] to i32 +// RV64-NEXT: br label %[[__RISCV_PGET_U16X4_U16X2_EXIT:.*]] +// RV64: [[COND_FALSE_I]]: +// RV64-NEXT: br label %[[__RISCV_PGET_U16X4_U16X2_EXIT]] +// RV64: [[__RISCV_PGET_U16X4_U16X2_EXIT]]: +// RV64-NEXT: [[TMP0:%.*]] = phi i32 [ [[SHUFFLE_I_EXTRACT]], %[[COND_TRUE_I]] ], [ poison, %[[COND_FALSE_I]] ] +// RV64-NEXT: ret i32 [[TMP0]] +// +uint16x2_t test_pget_u16x4_u16x2_idx1(uint16x4_t v) { + return __riscv_pget_u16x4_u16x2(v, 1); +} 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 f3857cedc3b5a..70b6124eb48fd 100644 --- a/cross-project-tests/intrinsic-header-tests/riscv_packed_simd.c +++ b/cross-project-tests/intrinsic-header-tests/riscv_packed_simd.c @@ -4771,3 +4771,57 @@ int16x4_t test_pjoin2_i16x4(int16x2_t lo, int16x2_t hi) { uint16x4_t test_pjoin2_u16x4(uint16x2_t lo, uint16x2_t hi) { return __riscv_pjoin2_u16x4(lo, hi); } + +/* Packed Subvector Extract */ + +// CHECK-LABEL: test_pget_i8x8_i8x4: +// CHECK: ret +int8x4_t test_pget_i8x8_i8x4(int8x8_t v) { + return __riscv_pget_i8x8_i8x4(v, 0); +} + +// CHECK-LABEL: test_pget_i8x8_i8x4_idx1: +// RV32: mv{{[[:space:]]}} +// RV64: srli{{[[:space:]]}} +int8x4_t test_pget_i8x8_i8x4_idx1(int8x8_t v) { + return __riscv_pget_i8x8_i8x4(v, 1); +} + +// CHECK-LABEL: test_pget_u8x8_u8x4: +// CHECK: ret +uint8x4_t test_pget_u8x8_u8x4(uint8x8_t v) { + return __riscv_pget_u8x8_u8x4(v, 0); +} + +// CHECK-LABEL: test_pget_u8x8_u8x4_idx1: +// RV32: mv{{[[:space:]]}} +// RV64: srli{{[[:space:]]}} +uint8x4_t test_pget_u8x8_u8x4_idx1(uint8x8_t v) { + return __riscv_pget_u8x8_u8x4(v, 1); +} + +// CHECK-LABEL: test_pget_i16x4_i16x2: +// CHECK: ret +int16x2_t test_pget_i16x4_i16x2(int16x4_t v) { + return __riscv_pget_i16x4_i16x2(v, 0); +} + +// CHECK-LABEL: test_pget_i16x4_i16x2_idx1: +// RV32: mv{{[[:space:]]}} +// RV64: srli{{[[:space:]]}} +int16x2_t test_pget_i16x4_i16x2_idx1(int16x4_t v) { + return __riscv_pget_i16x4_i16x2(v, 1); +} + +// CHECK-LABEL: test_pget_u16x4_u16x2: +// CHECK: ret +uint16x2_t test_pget_u16x4_u16x2(uint16x4_t v) { + return __riscv_pget_u16x4_u16x2(v, 0); +} + +// CHECK-LABEL: test_pget_u16x4_u16x2_idx1: +// RV32: mv{{[[:space:]]}} +// RV64: srli{{[[:space:]]}} +uint16x2_t test_pget_u16x4_u16x2_idx1(uint16x4_t v) { + return __riscv_pget_u16x4_u16x2(v, 1); +} _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
