[clang] ac0c8eb - [Clang][RISCV] Add packed subvector extract intrinsics (#224429)
via cfe-commits
cfe-commits at lists.llvm.org
Thu Sep 17 20:09:10 PDT 2026
Author: SiHuaN
Date: 2026-09-18T11:09:04+08:00
New Revision: ac0c8eb5aa55af2387b6c925de26e159b7a8a271
URL: https://github.com/llvm/llvm-project/commit/ac0c8eb5aa55af2387b6c925de26e159b7a8a271
DIFF: https://github.com/llvm/llvm-project/commit/ac0c8eb5aa55af2387b6c925de26e159b7a8a271.diff
LOG: [Clang][RISCV] Add packed subvector extract intrinsics (#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.
Added:
Modified:
clang/lib/Headers/riscv_packed_simd.h
clang/test/CodeGen/RISCV/rvp-intrinsics.c
cross-project-tests/intrinsic-header-tests/riscv_packed_simd.c
Removed:
################################################################################
diff --git a/clang/lib/Headers/riscv_packed_simd.h b/clang/lib/Headers/riscv_packed_simd.h
index cfa673e365d9f..db6d0d37c2e8a 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) { \
@@ -1132,6 +1149,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)
@@ -1327,6 +1350,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 412c63a182b11..c6721dbeb5db8 100644
--- a/clang/test/CodeGen/RISCV/rvp-intrinsics.c
+++ b/clang/test/CodeGen/RISCV/rvp-intrinsics.c
@@ -11990,3 +11990,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 e68c9156311ba..14e64c3c3584b 100644
--- a/cross-project-tests/intrinsic-header-tests/riscv_packed_simd.c
+++ b/cross-project-tests/intrinsic-header-tests/riscv_packed_simd.c
@@ -4819,3 +4819,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 cfe-commits
mailing list