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); +} _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
