[clang] [llvm] [Clang][RISCV] Add packed subvector extract intrinsics (PR #224429)
via llvm-commits
llvm-commits at lists.llvm.org
Thu Sep 17 14:04:52 PDT 2026
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 <liyongtai at iscas.ac.cn>
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);
+}
More information about the llvm-commits
mailing list