From 33c7ef4a631db53440f569f048660474e0a46bd6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=99=88=E5=AD=90=E6=98=82?= <2802328816@qq.com> Date: Thu, 30 Jul 2026 02:24:02 +0800 Subject: [PATCH] [Clang][RISCV] Add packed pair byte intrinsics (#212589) Add the 32-bit byte forms and the 64-bit byte/halfword forms of the P-extension packed pair intrinsics to riscv_packed_simd.h using generic shufflevector IR. Extend the existing packed pair shuffle lowering to recognize the mixed even/odd forms and select ppaireo/ppairoe in addition to ppaire/ppairo. Add Clang CodeGen, LLVM CodeGen, and intrinsic header tests for the new forms. --- clang/lib/Headers/riscv_packed_simd.h | 69 +++ clang/test/CodeGen/RISCV/rvp-intrinsics.c | 530 ++++++++++++++++++ .../riscv_packed_simd.c | 161 ++++++ llvm/lib/Target/RISCV/RISCVISelLowering.cpp | 31 +- llvm/lib/Target/RISCV/RISCVInstrInfoP.td | 32 +- llvm/test/CodeGen/RISCV/rvp-simd-32.ll | 36 ++ llvm/test/CodeGen/RISCV/rvp-simd-64.ll | 56 ++ 7 files changed, 898 insertions(+), 17 deletions(-) diff --git a/clang/lib/Headers/riscv_packed_simd.h b/clang/lib/Headers/riscv_packed_simd.h index e63585fb99e3..ded18175b745 100644 --- a/clang/lib/Headers/riscv_packed_simd.h +++ b/clang/lib/Headers/riscv_packed_simd.h @@ -193,6 +193,39 @@ typedef uint32_t uint32x2_t __attribute__((__vector_size__(8))); return __builtin_shufflevector(__rs1, __rs1, 1, 3, 5, 7); \ } +#define __packed_pair_ee4(name, ty) \ + static __inline__ ty __DEFAULT_FN_ATTRS __riscv_##name(ty __rs1, ty __rs2) { \ + return __builtin_shufflevector(__rs1, __rs2, 0, 4, 2, 6); \ + } +#define __packed_pair_eo4(name, ty) \ + static __inline__ ty __DEFAULT_FN_ATTRS __riscv_##name(ty __rs1, ty __rs2) { \ + return __builtin_shufflevector(__rs1, __rs2, 0, 5, 2, 7); \ + } +#define __packed_pair_oe4(name, ty) \ + static __inline__ ty __DEFAULT_FN_ATTRS __riscv_##name(ty __rs1, ty __rs2) { \ + return __builtin_shufflevector(__rs1, __rs2, 1, 4, 3, 6); \ + } +#define __packed_pair_oo4(name, ty) \ + static __inline__ ty __DEFAULT_FN_ATTRS __riscv_##name(ty __rs1, ty __rs2) { \ + return __builtin_shufflevector(__rs1, __rs2, 1, 5, 3, 7); \ + } +#define __packed_pair_ee8(name, ty) \ + static __inline__ ty __DEFAULT_FN_ATTRS __riscv_##name(ty __rs1, ty __rs2) { \ + return __builtin_shufflevector(__rs1, __rs2, 0, 8, 2, 10, 4, 12, 6, 14); \ + } +#define __packed_pair_eo8(name, ty) \ + static __inline__ ty __DEFAULT_FN_ATTRS __riscv_##name(ty __rs1, ty __rs2) { \ + return __builtin_shufflevector(__rs1, __rs2, 0, 9, 2, 11, 4, 13, 6, 15); \ + } +#define __packed_pair_oe8(name, ty) \ + static __inline__ ty __DEFAULT_FN_ATTRS __riscv_##name(ty __rs1, ty __rs2) { \ + return __builtin_shufflevector(__rs1, __rs2, 1, 8, 3, 10, 5, 12, 7, 14); \ + } +#define __packed_pair_oo8(name, ty) \ + static __inline__ ty __DEFAULT_FN_ATTRS __riscv_##name(ty __rs1, ty __rs2) { \ + return __builtin_shufflevector(__rs1, __rs2, 1, 9, 3, 11, 5, 13, 7, 15); \ + } + #define __packed_nzip2(name, rty, ty) \ static __inline__ rty __DEFAULT_FN_ATTRS __riscv_##name(ty __rs1, \ ty __rs2) { \ @@ -565,6 +598,34 @@ __packed_unzipo2(punzipo_i16x2, int16x2_t, int16x4_t) __packed_unzipe2(punzipe_u16x2, uint16x2_t, uint16x4_t) __packed_unzipo2(punzipo_u16x2, uint16x2_t, uint16x4_t) +/* Packed Pair (32-bit byte forms) */ +__packed_pair_ee4(ppaire_i8x4, int8x4_t) +__packed_pair_ee4(ppaire_u8x4, uint8x4_t) +__packed_pair_eo4(ppaireo_i8x4, int8x4_t) +__packed_pair_eo4(ppaireo_u8x4, uint8x4_t) +__packed_pair_oe4(ppairoe_i8x4, int8x4_t) +__packed_pair_oe4(ppairoe_u8x4, uint8x4_t) +__packed_pair_oo4(ppairo_i8x4, int8x4_t) +__packed_pair_oo4(ppairo_u8x4, uint8x4_t) + +/* Packed Pair (64-bit byte and halfword forms) */ +__packed_pair_ee8(ppaire_i8x8, int8x8_t) +__packed_pair_ee8(ppaire_u8x8, uint8x8_t) +__packed_pair_eo8(ppaireo_i8x8, int8x8_t) +__packed_pair_eo8(ppaireo_u8x8, uint8x8_t) +__packed_pair_oe8(ppairoe_i8x8, int8x8_t) +__packed_pair_oe8(ppairoe_u8x8, uint8x8_t) +__packed_pair_oo8(ppairo_i8x8, int8x8_t) +__packed_pair_oo8(ppairo_u8x8, uint8x8_t) +__packed_pair_ee4(ppaire_i16x4, int16x4_t) +__packed_pair_ee4(ppaire_u16x4, uint16x4_t) +__packed_pair_eo4(ppaireo_i16x4, int16x4_t) +__packed_pair_eo4(ppaireo_u16x4, uint16x4_t) +__packed_pair_oe4(ppairoe_i16x4, int16x4_t) +__packed_pair_oe4(ppairoe_u16x4, uint16x4_t) +__packed_pair_oo4(ppairo_i16x4, int16x4_t) +__packed_pair_oo4(ppairo_u16x4, uint16x4_t) + /* Packed Narrowing Zip (32-bit) */ __packed_nzip2(pnzip_i8x4, int8x4_t, int16x2_t) __packed_nzip2(pnzip_u8x4, uint8x4_t, uint16x2_t) @@ -809,6 +870,14 @@ __packed_reinterpret(u32x2_i32x2, int32x2_t, uint32x2_t) #undef __packed_unzipe4 #undef __packed_unzipo2 #undef __packed_unzipo4 +#undef __packed_pair_ee4 +#undef __packed_pair_eo4 +#undef __packed_pair_oe4 +#undef __packed_pair_oo4 +#undef __packed_pair_ee8 +#undef __packed_pair_eo8 +#undef __packed_pair_oe8 +#undef __packed_pair_oo8 #undef __packed_nzip2 #undef __packed_nzip4 #undef __packed_nziph2 diff --git a/clang/test/CodeGen/RISCV/rvp-intrinsics.c b/clang/test/CodeGen/RISCV/rvp-intrinsics.c index 7e3f5b3d1de2..9ba0428e192f 100644 --- a/clang/test/CodeGen/RISCV/rvp-intrinsics.c +++ b/clang/test/CodeGen/RISCV/rvp-intrinsics.c @@ -6826,6 +6826,536 @@ uint16x2_t test_punzipo_u16x2(uint16x4_t rs1) { return __riscv_punzipo_u16x2(rs1); } +/* Packed Pair */ + +// RV32-LABEL: define dso_local i32 @test_ppaire_i8x4( +// RV32-SAME: i32 noundef [[RS1_COERCE:%.*]], i32 noundef [[RS2_COERCE:%.*]]) #[[ATTR0]] { +// RV32-NEXT: [[ENTRY:.*:]] +// RV32-NEXT: [[TMP0:%.*]] = bitcast i32 [[RS1_COERCE]] to <4 x i8> +// RV32-NEXT: [[TMP1:%.*]] = bitcast i32 [[RS2_COERCE]] to <4 x i8> +// RV32-NEXT: [[SHUFFLE_I:%.*]] = shufflevector <4 x i8> [[TMP0]], <4 x i8> [[TMP1]], <4 x i32> +// RV32-NEXT: [[TMP2:%.*]] = bitcast <4 x i8> [[SHUFFLE_I]] to i32 +// RV32-NEXT: ret i32 [[TMP2]] +// +// RV64-LABEL: define dso_local i32 @test_ppaire_i8x4( +// RV64-SAME: i32 noundef [[RS1_COERCE:%.*]], i32 noundef [[RS2_COERCE:%.*]]) #[[ATTR0]] { +// RV64-NEXT: [[ENTRY:.*:]] +// RV64-NEXT: [[TMP0:%.*]] = bitcast i32 [[RS1_COERCE]] to <4 x i8> +// RV64-NEXT: [[TMP1:%.*]] = bitcast i32 [[RS2_COERCE]] to <4 x i8> +// RV64-NEXT: [[SHUFFLE_I:%.*]] = shufflevector <4 x i8> [[TMP0]], <4 x i8> [[TMP1]], <4 x i32> +// RV64-NEXT: [[TMP2:%.*]] = bitcast <4 x i8> [[SHUFFLE_I]] to i32 +// RV64-NEXT: ret i32 [[TMP2]] +// +int8x4_t test_ppaire_i8x4(int8x4_t rs1, int8x4_t rs2) { + return __riscv_ppaire_i8x4(rs1, rs2); +} + +// RV32-LABEL: define dso_local i32 @test_ppaire_u8x4( +// RV32-SAME: i32 noundef [[RS1_COERCE:%.*]], i32 noundef [[RS2_COERCE:%.*]]) #[[ATTR0]] { +// RV32-NEXT: [[ENTRY:.*:]] +// RV32-NEXT: [[TMP0:%.*]] = bitcast i32 [[RS1_COERCE]] to <4 x i8> +// RV32-NEXT: [[TMP1:%.*]] = bitcast i32 [[RS2_COERCE]] to <4 x i8> +// RV32-NEXT: [[SHUFFLE_I:%.*]] = shufflevector <4 x i8> [[TMP0]], <4 x i8> [[TMP1]], <4 x i32> +// RV32-NEXT: [[TMP2:%.*]] = bitcast <4 x i8> [[SHUFFLE_I]] to i32 +// RV32-NEXT: ret i32 [[TMP2]] +// +// RV64-LABEL: define dso_local i32 @test_ppaire_u8x4( +// RV64-SAME: i32 noundef [[RS1_COERCE:%.*]], i32 noundef [[RS2_COERCE:%.*]]) #[[ATTR0]] { +// RV64-NEXT: [[ENTRY:.*:]] +// RV64-NEXT: [[TMP0:%.*]] = bitcast i32 [[RS1_COERCE]] to <4 x i8> +// RV64-NEXT: [[TMP1:%.*]] = bitcast i32 [[RS2_COERCE]] to <4 x i8> +// RV64-NEXT: [[SHUFFLE_I:%.*]] = shufflevector <4 x i8> [[TMP0]], <4 x i8> [[TMP1]], <4 x i32> +// RV64-NEXT: [[TMP2:%.*]] = bitcast <4 x i8> [[SHUFFLE_I]] to i32 +// RV64-NEXT: ret i32 [[TMP2]] +// +uint8x4_t test_ppaire_u8x4(uint8x4_t rs1, uint8x4_t rs2) { + return __riscv_ppaire_u8x4(rs1, rs2); +} + +// RV32-LABEL: define dso_local i32 @test_ppaireo_i8x4( +// RV32-SAME: i32 noundef [[RS1_COERCE:%.*]], i32 noundef [[RS2_COERCE:%.*]]) #[[ATTR0]] { +// RV32-NEXT: [[ENTRY:.*:]] +// RV32-NEXT: [[TMP0:%.*]] = bitcast i32 [[RS1_COERCE]] to <4 x i8> +// RV32-NEXT: [[TMP1:%.*]] = bitcast i32 [[RS2_COERCE]] to <4 x i8> +// RV32-NEXT: [[SHUFFLE_I:%.*]] = shufflevector <4 x i8> [[TMP0]], <4 x i8> [[TMP1]], <4 x i32> +// RV32-NEXT: [[TMP2:%.*]] = bitcast <4 x i8> [[SHUFFLE_I]] to i32 +// RV32-NEXT: ret i32 [[TMP2]] +// +// RV64-LABEL: define dso_local i32 @test_ppaireo_i8x4( +// RV64-SAME: i32 noundef [[RS1_COERCE:%.*]], i32 noundef [[RS2_COERCE:%.*]]) #[[ATTR0]] { +// RV64-NEXT: [[ENTRY:.*:]] +// RV64-NEXT: [[TMP0:%.*]] = bitcast i32 [[RS1_COERCE]] to <4 x i8> +// RV64-NEXT: [[TMP1:%.*]] = bitcast i32 [[RS2_COERCE]] to <4 x i8> +// RV64-NEXT: [[SHUFFLE_I:%.*]] = shufflevector <4 x i8> [[TMP0]], <4 x i8> [[TMP1]], <4 x i32> +// RV64-NEXT: [[TMP2:%.*]] = bitcast <4 x i8> [[SHUFFLE_I]] to i32 +// RV64-NEXT: ret i32 [[TMP2]] +// +int8x4_t test_ppaireo_i8x4(int8x4_t rs1, int8x4_t rs2) { + return __riscv_ppaireo_i8x4(rs1, rs2); +} + +// RV32-LABEL: define dso_local i32 @test_ppaireo_u8x4( +// RV32-SAME: i32 noundef [[RS1_COERCE:%.*]], i32 noundef [[RS2_COERCE:%.*]]) #[[ATTR0]] { +// RV32-NEXT: [[ENTRY:.*:]] +// RV32-NEXT: [[TMP0:%.*]] = bitcast i32 [[RS1_COERCE]] to <4 x i8> +// RV32-NEXT: [[TMP1:%.*]] = bitcast i32 [[RS2_COERCE]] to <4 x i8> +// RV32-NEXT: [[SHUFFLE_I:%.*]] = shufflevector <4 x i8> [[TMP0]], <4 x i8> [[TMP1]], <4 x i32> +// RV32-NEXT: [[TMP2:%.*]] = bitcast <4 x i8> [[SHUFFLE_I]] to i32 +// RV32-NEXT: ret i32 [[TMP2]] +// +// RV64-LABEL: define dso_local i32 @test_ppaireo_u8x4( +// RV64-SAME: i32 noundef [[RS1_COERCE:%.*]], i32 noundef [[RS2_COERCE:%.*]]) #[[ATTR0]] { +// RV64-NEXT: [[ENTRY:.*:]] +// RV64-NEXT: [[TMP0:%.*]] = bitcast i32 [[RS1_COERCE]] to <4 x i8> +// RV64-NEXT: [[TMP1:%.*]] = bitcast i32 [[RS2_COERCE]] to <4 x i8> +// RV64-NEXT: [[SHUFFLE_I:%.*]] = shufflevector <4 x i8> [[TMP0]], <4 x i8> [[TMP1]], <4 x i32> +// RV64-NEXT: [[TMP2:%.*]] = bitcast <4 x i8> [[SHUFFLE_I]] to i32 +// RV64-NEXT: ret i32 [[TMP2]] +// +uint8x4_t test_ppaireo_u8x4(uint8x4_t rs1, uint8x4_t rs2) { + return __riscv_ppaireo_u8x4(rs1, rs2); +} + +// RV32-LABEL: define dso_local i32 @test_ppairoe_i8x4( +// RV32-SAME: i32 noundef [[RS1_COERCE:%.*]], i32 noundef [[RS2_COERCE:%.*]]) #[[ATTR0]] { +// RV32-NEXT: [[ENTRY:.*:]] +// RV32-NEXT: [[TMP0:%.*]] = bitcast i32 [[RS1_COERCE]] to <4 x i8> +// RV32-NEXT: [[TMP1:%.*]] = bitcast i32 [[RS2_COERCE]] to <4 x i8> +// RV32-NEXT: [[SHUFFLE_I:%.*]] = shufflevector <4 x i8> [[TMP0]], <4 x i8> [[TMP1]], <4 x i32> +// RV32-NEXT: [[TMP2:%.*]] = bitcast <4 x i8> [[SHUFFLE_I]] to i32 +// RV32-NEXT: ret i32 [[TMP2]] +// +// RV64-LABEL: define dso_local i32 @test_ppairoe_i8x4( +// RV64-SAME: i32 noundef [[RS1_COERCE:%.*]], i32 noundef [[RS2_COERCE:%.*]]) #[[ATTR0]] { +// RV64-NEXT: [[ENTRY:.*:]] +// RV64-NEXT: [[TMP0:%.*]] = bitcast i32 [[RS1_COERCE]] to <4 x i8> +// RV64-NEXT: [[TMP1:%.*]] = bitcast i32 [[RS2_COERCE]] to <4 x i8> +// RV64-NEXT: [[SHUFFLE_I:%.*]] = shufflevector <4 x i8> [[TMP0]], <4 x i8> [[TMP1]], <4 x i32> +// RV64-NEXT: [[TMP2:%.*]] = bitcast <4 x i8> [[SHUFFLE_I]] to i32 +// RV64-NEXT: ret i32 [[TMP2]] +// +int8x4_t test_ppairoe_i8x4(int8x4_t rs1, int8x4_t rs2) { + return __riscv_ppairoe_i8x4(rs1, rs2); +} + +// RV32-LABEL: define dso_local i32 @test_ppairoe_u8x4( +// RV32-SAME: i32 noundef [[RS1_COERCE:%.*]], i32 noundef [[RS2_COERCE:%.*]]) #[[ATTR0]] { +// RV32-NEXT: [[ENTRY:.*:]] +// RV32-NEXT: [[TMP0:%.*]] = bitcast i32 [[RS1_COERCE]] to <4 x i8> +// RV32-NEXT: [[TMP1:%.*]] = bitcast i32 [[RS2_COERCE]] to <4 x i8> +// RV32-NEXT: [[SHUFFLE_I:%.*]] = shufflevector <4 x i8> [[TMP0]], <4 x i8> [[TMP1]], <4 x i32> +// RV32-NEXT: [[TMP2:%.*]] = bitcast <4 x i8> [[SHUFFLE_I]] to i32 +// RV32-NEXT: ret i32 [[TMP2]] +// +// RV64-LABEL: define dso_local i32 @test_ppairoe_u8x4( +// RV64-SAME: i32 noundef [[RS1_COERCE:%.*]], i32 noundef [[RS2_COERCE:%.*]]) #[[ATTR0]] { +// RV64-NEXT: [[ENTRY:.*:]] +// RV64-NEXT: [[TMP0:%.*]] = bitcast i32 [[RS1_COERCE]] to <4 x i8> +// RV64-NEXT: [[TMP1:%.*]] = bitcast i32 [[RS2_COERCE]] to <4 x i8> +// RV64-NEXT: [[SHUFFLE_I:%.*]] = shufflevector <4 x i8> [[TMP0]], <4 x i8> [[TMP1]], <4 x i32> +// RV64-NEXT: [[TMP2:%.*]] = bitcast <4 x i8> [[SHUFFLE_I]] to i32 +// RV64-NEXT: ret i32 [[TMP2]] +// +uint8x4_t test_ppairoe_u8x4(uint8x4_t rs1, uint8x4_t rs2) { + return __riscv_ppairoe_u8x4(rs1, rs2); +} + +// RV32-LABEL: define dso_local i32 @test_ppairo_i8x4( +// RV32-SAME: i32 noundef [[RS1_COERCE:%.*]], i32 noundef [[RS2_COERCE:%.*]]) #[[ATTR0]] { +// RV32-NEXT: [[ENTRY:.*:]] +// RV32-NEXT: [[TMP0:%.*]] = bitcast i32 [[RS1_COERCE]] to <4 x i8> +// RV32-NEXT: [[TMP1:%.*]] = bitcast i32 [[RS2_COERCE]] to <4 x i8> +// RV32-NEXT: [[SHUFFLE_I:%.*]] = shufflevector <4 x i8> [[TMP0]], <4 x i8> [[TMP1]], <4 x i32> +// RV32-NEXT: [[TMP2:%.*]] = bitcast <4 x i8> [[SHUFFLE_I]] to i32 +// RV32-NEXT: ret i32 [[TMP2]] +// +// RV64-LABEL: define dso_local i32 @test_ppairo_i8x4( +// RV64-SAME: i32 noundef [[RS1_COERCE:%.*]], i32 noundef [[RS2_COERCE:%.*]]) #[[ATTR0]] { +// RV64-NEXT: [[ENTRY:.*:]] +// RV64-NEXT: [[TMP0:%.*]] = bitcast i32 [[RS1_COERCE]] to <4 x i8> +// RV64-NEXT: [[TMP1:%.*]] = bitcast i32 [[RS2_COERCE]] to <4 x i8> +// RV64-NEXT: [[SHUFFLE_I:%.*]] = shufflevector <4 x i8> [[TMP0]], <4 x i8> [[TMP1]], <4 x i32> +// RV64-NEXT: [[TMP2:%.*]] = bitcast <4 x i8> [[SHUFFLE_I]] to i32 +// RV64-NEXT: ret i32 [[TMP2]] +// +int8x4_t test_ppairo_i8x4(int8x4_t rs1, int8x4_t rs2) { + return __riscv_ppairo_i8x4(rs1, rs2); +} + +// RV32-LABEL: define dso_local i32 @test_ppairo_u8x4( +// RV32-SAME: i32 noundef [[RS1_COERCE:%.*]], i32 noundef [[RS2_COERCE:%.*]]) #[[ATTR0]] { +// RV32-NEXT: [[ENTRY:.*:]] +// RV32-NEXT: [[TMP0:%.*]] = bitcast i32 [[RS1_COERCE]] to <4 x i8> +// RV32-NEXT: [[TMP1:%.*]] = bitcast i32 [[RS2_COERCE]] to <4 x i8> +// RV32-NEXT: [[SHUFFLE_I:%.*]] = shufflevector <4 x i8> [[TMP0]], <4 x i8> [[TMP1]], <4 x i32> +// RV32-NEXT: [[TMP2:%.*]] = bitcast <4 x i8> [[SHUFFLE_I]] to i32 +// RV32-NEXT: ret i32 [[TMP2]] +// +// RV64-LABEL: define dso_local i32 @test_ppairo_u8x4( +// RV64-SAME: i32 noundef [[RS1_COERCE:%.*]], i32 noundef [[RS2_COERCE:%.*]]) #[[ATTR0]] { +// RV64-NEXT: [[ENTRY:.*:]] +// RV64-NEXT: [[TMP0:%.*]] = bitcast i32 [[RS1_COERCE]] to <4 x i8> +// RV64-NEXT: [[TMP1:%.*]] = bitcast i32 [[RS2_COERCE]] to <4 x i8> +// RV64-NEXT: [[SHUFFLE_I:%.*]] = shufflevector <4 x i8> [[TMP0]], <4 x i8> [[TMP1]], <4 x i32> +// RV64-NEXT: [[TMP2:%.*]] = bitcast <4 x i8> [[SHUFFLE_I]] to i32 +// RV64-NEXT: ret i32 [[TMP2]] +// +uint8x4_t test_ppairo_u8x4(uint8x4_t rs1, uint8x4_t rs2) { + return __riscv_ppairo_u8x4(rs1, rs2); +} + +// RV32-LABEL: define dso_local i64 @test_ppaire_i8x8( +// RV32-SAME: i64 noundef [[RS1_COERCE:%.*]], i64 noundef [[RS2_COERCE:%.*]]) #[[ATTR0]] { +// RV32-NEXT: [[ENTRY:.*:]] +// RV32-NEXT: [[TMP0:%.*]] = bitcast i64 [[RS1_COERCE]] to <8 x i8> +// RV32-NEXT: [[TMP1:%.*]] = bitcast i64 [[RS2_COERCE]] to <8 x i8> +// RV32-NEXT: [[SHUFFLE_I:%.*]] = shufflevector <8 x i8> [[TMP0]], <8 x i8> [[TMP1]], <8 x i32> +// RV32-NEXT: [[TMP2:%.*]] = bitcast <8 x i8> [[SHUFFLE_I]] to i64 +// RV32-NEXT: ret i64 [[TMP2]] +// +// RV64-LABEL: define dso_local i64 @test_ppaire_i8x8( +// RV64-SAME: i64 noundef [[RS1_COERCE:%.*]], i64 noundef [[RS2_COERCE:%.*]]) #[[ATTR0]] { +// RV64-NEXT: [[ENTRY:.*:]] +// RV64-NEXT: [[TMP0:%.*]] = bitcast i64 [[RS1_COERCE]] to <8 x i8> +// RV64-NEXT: [[TMP1:%.*]] = bitcast i64 [[RS2_COERCE]] to <8 x i8> +// RV64-NEXT: [[SHUFFLE_I:%.*]] = shufflevector <8 x i8> [[TMP0]], <8 x i8> [[TMP1]], <8 x i32> +// RV64-NEXT: [[TMP2:%.*]] = bitcast <8 x i8> [[SHUFFLE_I]] to i64 +// RV64-NEXT: ret i64 [[TMP2]] +// +int8x8_t test_ppaire_i8x8(int8x8_t rs1, int8x8_t rs2) { + return __riscv_ppaire_i8x8(rs1, rs2); +} + +// RV32-LABEL: define dso_local i64 @test_ppaire_u8x8( +// RV32-SAME: i64 noundef [[RS1_COERCE:%.*]], i64 noundef [[RS2_COERCE:%.*]]) #[[ATTR0]] { +// RV32-NEXT: [[ENTRY:.*:]] +// RV32-NEXT: [[TMP0:%.*]] = bitcast i64 [[RS1_COERCE]] to <8 x i8> +// RV32-NEXT: [[TMP1:%.*]] = bitcast i64 [[RS2_COERCE]] to <8 x i8> +// RV32-NEXT: [[SHUFFLE_I:%.*]] = shufflevector <8 x i8> [[TMP0]], <8 x i8> [[TMP1]], <8 x i32> +// RV32-NEXT: [[TMP2:%.*]] = bitcast <8 x i8> [[SHUFFLE_I]] to i64 +// RV32-NEXT: ret i64 [[TMP2]] +// +// RV64-LABEL: define dso_local i64 @test_ppaire_u8x8( +// RV64-SAME: i64 noundef [[RS1_COERCE:%.*]], i64 noundef [[RS2_COERCE:%.*]]) #[[ATTR0]] { +// RV64-NEXT: [[ENTRY:.*:]] +// RV64-NEXT: [[TMP0:%.*]] = bitcast i64 [[RS1_COERCE]] to <8 x i8> +// RV64-NEXT: [[TMP1:%.*]] = bitcast i64 [[RS2_COERCE]] to <8 x i8> +// RV64-NEXT: [[SHUFFLE_I:%.*]] = shufflevector <8 x i8> [[TMP0]], <8 x i8> [[TMP1]], <8 x i32> +// RV64-NEXT: [[TMP2:%.*]] = bitcast <8 x i8> [[SHUFFLE_I]] to i64 +// RV64-NEXT: ret i64 [[TMP2]] +// +uint8x8_t test_ppaire_u8x8(uint8x8_t rs1, uint8x8_t rs2) { + return __riscv_ppaire_u8x8(rs1, rs2); +} + +// RV32-LABEL: define dso_local i64 @test_ppaireo_i8x8( +// RV32-SAME: i64 noundef [[RS1_COERCE:%.*]], i64 noundef [[RS2_COERCE:%.*]]) #[[ATTR0]] { +// RV32-NEXT: [[ENTRY:.*:]] +// RV32-NEXT: [[TMP0:%.*]] = bitcast i64 [[RS1_COERCE]] to <8 x i8> +// RV32-NEXT: [[TMP1:%.*]] = bitcast i64 [[RS2_COERCE]] to <8 x i8> +// RV32-NEXT: [[SHUFFLE_I:%.*]] = shufflevector <8 x i8> [[TMP0]], <8 x i8> [[TMP1]], <8 x i32> +// RV32-NEXT: [[TMP2:%.*]] = bitcast <8 x i8> [[SHUFFLE_I]] to i64 +// RV32-NEXT: ret i64 [[TMP2]] +// +// RV64-LABEL: define dso_local i64 @test_ppaireo_i8x8( +// RV64-SAME: i64 noundef [[RS1_COERCE:%.*]], i64 noundef [[RS2_COERCE:%.*]]) #[[ATTR0]] { +// RV64-NEXT: [[ENTRY:.*:]] +// RV64-NEXT: [[TMP0:%.*]] = bitcast i64 [[RS1_COERCE]] to <8 x i8> +// RV64-NEXT: [[TMP1:%.*]] = bitcast i64 [[RS2_COERCE]] to <8 x i8> +// RV64-NEXT: [[SHUFFLE_I:%.*]] = shufflevector <8 x i8> [[TMP0]], <8 x i8> [[TMP1]], <8 x i32> +// RV64-NEXT: [[TMP2:%.*]] = bitcast <8 x i8> [[SHUFFLE_I]] to i64 +// RV64-NEXT: ret i64 [[TMP2]] +// +int8x8_t test_ppaireo_i8x8(int8x8_t rs1, int8x8_t rs2) { + return __riscv_ppaireo_i8x8(rs1, rs2); +} + +// RV32-LABEL: define dso_local i64 @test_ppaireo_u8x8( +// RV32-SAME: i64 noundef [[RS1_COERCE:%.*]], i64 noundef [[RS2_COERCE:%.*]]) #[[ATTR0]] { +// RV32-NEXT: [[ENTRY:.*:]] +// RV32-NEXT: [[TMP0:%.*]] = bitcast i64 [[RS1_COERCE]] to <8 x i8> +// RV32-NEXT: [[TMP1:%.*]] = bitcast i64 [[RS2_COERCE]] to <8 x i8> +// RV32-NEXT: [[SHUFFLE_I:%.*]] = shufflevector <8 x i8> [[TMP0]], <8 x i8> [[TMP1]], <8 x i32> +// RV32-NEXT: [[TMP2:%.*]] = bitcast <8 x i8> [[SHUFFLE_I]] to i64 +// RV32-NEXT: ret i64 [[TMP2]] +// +// RV64-LABEL: define dso_local i64 @test_ppaireo_u8x8( +// RV64-SAME: i64 noundef [[RS1_COERCE:%.*]], i64 noundef [[RS2_COERCE:%.*]]) #[[ATTR0]] { +// RV64-NEXT: [[ENTRY:.*:]] +// RV64-NEXT: [[TMP0:%.*]] = bitcast i64 [[RS1_COERCE]] to <8 x i8> +// RV64-NEXT: [[TMP1:%.*]] = bitcast i64 [[RS2_COERCE]] to <8 x i8> +// RV64-NEXT: [[SHUFFLE_I:%.*]] = shufflevector <8 x i8> [[TMP0]], <8 x i8> [[TMP1]], <8 x i32> +// RV64-NEXT: [[TMP2:%.*]] = bitcast <8 x i8> [[SHUFFLE_I]] to i64 +// RV64-NEXT: ret i64 [[TMP2]] +// +uint8x8_t test_ppaireo_u8x8(uint8x8_t rs1, uint8x8_t rs2) { + return __riscv_ppaireo_u8x8(rs1, rs2); +} + +// RV32-LABEL: define dso_local i64 @test_ppairoe_i8x8( +// RV32-SAME: i64 noundef [[RS1_COERCE:%.*]], i64 noundef [[RS2_COERCE:%.*]]) #[[ATTR0]] { +// RV32-NEXT: [[ENTRY:.*:]] +// RV32-NEXT: [[TMP0:%.*]] = bitcast i64 [[RS1_COERCE]] to <8 x i8> +// RV32-NEXT: [[TMP1:%.*]] = bitcast i64 [[RS2_COERCE]] to <8 x i8> +// RV32-NEXT: [[SHUFFLE_I:%.*]] = shufflevector <8 x i8> [[TMP0]], <8 x i8> [[TMP1]], <8 x i32> +// RV32-NEXT: [[TMP2:%.*]] = bitcast <8 x i8> [[SHUFFLE_I]] to i64 +// RV32-NEXT: ret i64 [[TMP2]] +// +// RV64-LABEL: define dso_local i64 @test_ppairoe_i8x8( +// RV64-SAME: i64 noundef [[RS1_COERCE:%.*]], i64 noundef [[RS2_COERCE:%.*]]) #[[ATTR0]] { +// RV64-NEXT: [[ENTRY:.*:]] +// RV64-NEXT: [[TMP0:%.*]] = bitcast i64 [[RS1_COERCE]] to <8 x i8> +// RV64-NEXT: [[TMP1:%.*]] = bitcast i64 [[RS2_COERCE]] to <8 x i8> +// RV64-NEXT: [[SHUFFLE_I:%.*]] = shufflevector <8 x i8> [[TMP0]], <8 x i8> [[TMP1]], <8 x i32> +// RV64-NEXT: [[TMP2:%.*]] = bitcast <8 x i8> [[SHUFFLE_I]] to i64 +// RV64-NEXT: ret i64 [[TMP2]] +// +int8x8_t test_ppairoe_i8x8(int8x8_t rs1, int8x8_t rs2) { + return __riscv_ppairoe_i8x8(rs1, rs2); +} + +// RV32-LABEL: define dso_local i64 @test_ppairoe_u8x8( +// RV32-SAME: i64 noundef [[RS1_COERCE:%.*]], i64 noundef [[RS2_COERCE:%.*]]) #[[ATTR0]] { +// RV32-NEXT: [[ENTRY:.*:]] +// RV32-NEXT: [[TMP0:%.*]] = bitcast i64 [[RS1_COERCE]] to <8 x i8> +// RV32-NEXT: [[TMP1:%.*]] = bitcast i64 [[RS2_COERCE]] to <8 x i8> +// RV32-NEXT: [[SHUFFLE_I:%.*]] = shufflevector <8 x i8> [[TMP0]], <8 x i8> [[TMP1]], <8 x i32> +// RV32-NEXT: [[TMP2:%.*]] = bitcast <8 x i8> [[SHUFFLE_I]] to i64 +// RV32-NEXT: ret i64 [[TMP2]] +// +// RV64-LABEL: define dso_local i64 @test_ppairoe_u8x8( +// RV64-SAME: i64 noundef [[RS1_COERCE:%.*]], i64 noundef [[RS2_COERCE:%.*]]) #[[ATTR0]] { +// RV64-NEXT: [[ENTRY:.*:]] +// RV64-NEXT: [[TMP0:%.*]] = bitcast i64 [[RS1_COERCE]] to <8 x i8> +// RV64-NEXT: [[TMP1:%.*]] = bitcast i64 [[RS2_COERCE]] to <8 x i8> +// RV64-NEXT: [[SHUFFLE_I:%.*]] = shufflevector <8 x i8> [[TMP0]], <8 x i8> [[TMP1]], <8 x i32> +// RV64-NEXT: [[TMP2:%.*]] = bitcast <8 x i8> [[SHUFFLE_I]] to i64 +// RV64-NEXT: ret i64 [[TMP2]] +// +uint8x8_t test_ppairoe_u8x8(uint8x8_t rs1, uint8x8_t rs2) { + return __riscv_ppairoe_u8x8(rs1, rs2); +} + +// RV32-LABEL: define dso_local i64 @test_ppairo_i8x8( +// RV32-SAME: i64 noundef [[RS1_COERCE:%.*]], i64 noundef [[RS2_COERCE:%.*]]) #[[ATTR0]] { +// RV32-NEXT: [[ENTRY:.*:]] +// RV32-NEXT: [[TMP0:%.*]] = bitcast i64 [[RS1_COERCE]] to <8 x i8> +// RV32-NEXT: [[TMP1:%.*]] = bitcast i64 [[RS2_COERCE]] to <8 x i8> +// RV32-NEXT: [[SHUFFLE_I:%.*]] = shufflevector <8 x i8> [[TMP0]], <8 x i8> [[TMP1]], <8 x i32> +// RV32-NEXT: [[TMP2:%.*]] = bitcast <8 x i8> [[SHUFFLE_I]] to i64 +// RV32-NEXT: ret i64 [[TMP2]] +// +// RV64-LABEL: define dso_local i64 @test_ppairo_i8x8( +// RV64-SAME: i64 noundef [[RS1_COERCE:%.*]], i64 noundef [[RS2_COERCE:%.*]]) #[[ATTR0]] { +// RV64-NEXT: [[ENTRY:.*:]] +// RV64-NEXT: [[TMP0:%.*]] = bitcast i64 [[RS1_COERCE]] to <8 x i8> +// RV64-NEXT: [[TMP1:%.*]] = bitcast i64 [[RS2_COERCE]] to <8 x i8> +// RV64-NEXT: [[SHUFFLE_I:%.*]] = shufflevector <8 x i8> [[TMP0]], <8 x i8> [[TMP1]], <8 x i32> +// RV64-NEXT: [[TMP2:%.*]] = bitcast <8 x i8> [[SHUFFLE_I]] to i64 +// RV64-NEXT: ret i64 [[TMP2]] +// +int8x8_t test_ppairo_i8x8(int8x8_t rs1, int8x8_t rs2) { + return __riscv_ppairo_i8x8(rs1, rs2); +} + +// RV32-LABEL: define dso_local i64 @test_ppairo_u8x8( +// RV32-SAME: i64 noundef [[RS1_COERCE:%.*]], i64 noundef [[RS2_COERCE:%.*]]) #[[ATTR0]] { +// RV32-NEXT: [[ENTRY:.*:]] +// RV32-NEXT: [[TMP0:%.*]] = bitcast i64 [[RS1_COERCE]] to <8 x i8> +// RV32-NEXT: [[TMP1:%.*]] = bitcast i64 [[RS2_COERCE]] to <8 x i8> +// RV32-NEXT: [[SHUFFLE_I:%.*]] = shufflevector <8 x i8> [[TMP0]], <8 x i8> [[TMP1]], <8 x i32> +// RV32-NEXT: [[TMP2:%.*]] = bitcast <8 x i8> [[SHUFFLE_I]] to i64 +// RV32-NEXT: ret i64 [[TMP2]] +// +// RV64-LABEL: define dso_local i64 @test_ppairo_u8x8( +// RV64-SAME: i64 noundef [[RS1_COERCE:%.*]], i64 noundef [[RS2_COERCE:%.*]]) #[[ATTR0]] { +// RV64-NEXT: [[ENTRY:.*:]] +// RV64-NEXT: [[TMP0:%.*]] = bitcast i64 [[RS1_COERCE]] to <8 x i8> +// RV64-NEXT: [[TMP1:%.*]] = bitcast i64 [[RS2_COERCE]] to <8 x i8> +// RV64-NEXT: [[SHUFFLE_I:%.*]] = shufflevector <8 x i8> [[TMP0]], <8 x i8> [[TMP1]], <8 x i32> +// RV64-NEXT: [[TMP2:%.*]] = bitcast <8 x i8> [[SHUFFLE_I]] to i64 +// RV64-NEXT: ret i64 [[TMP2]] +// +uint8x8_t test_ppairo_u8x8(uint8x8_t rs1, uint8x8_t rs2) { + return __riscv_ppairo_u8x8(rs1, rs2); +} + +// RV32-LABEL: define dso_local i64 @test_ppaire_i16x4( +// RV32-SAME: i64 noundef [[RS1_COERCE:%.*]], i64 noundef [[RS2_COERCE:%.*]]) #[[ATTR0]] { +// RV32-NEXT: [[ENTRY:.*:]] +// RV32-NEXT: [[TMP0:%.*]] = bitcast i64 [[RS1_COERCE]] to <4 x i16> +// RV32-NEXT: [[TMP1:%.*]] = bitcast i64 [[RS2_COERCE]] to <4 x i16> +// RV32-NEXT: [[SHUFFLE_I:%.*]] = shufflevector <4 x i16> [[TMP0]], <4 x i16> [[TMP1]], <4 x i32> +// RV32-NEXT: [[TMP2:%.*]] = bitcast <4 x i16> [[SHUFFLE_I]] to i64 +// RV32-NEXT: ret i64 [[TMP2]] +// +// RV64-LABEL: define dso_local i64 @test_ppaire_i16x4( +// RV64-SAME: i64 noundef [[RS1_COERCE:%.*]], i64 noundef [[RS2_COERCE:%.*]]) #[[ATTR0]] { +// RV64-NEXT: [[ENTRY:.*:]] +// RV64-NEXT: [[TMP0:%.*]] = bitcast i64 [[RS1_COERCE]] to <4 x i16> +// RV64-NEXT: [[TMP1:%.*]] = bitcast i64 [[RS2_COERCE]] to <4 x i16> +// RV64-NEXT: [[SHUFFLE_I:%.*]] = shufflevector <4 x i16> [[TMP0]], <4 x i16> [[TMP1]], <4 x i32> +// RV64-NEXT: [[TMP2:%.*]] = bitcast <4 x i16> [[SHUFFLE_I]] to i64 +// RV64-NEXT: ret i64 [[TMP2]] +// +int16x4_t test_ppaire_i16x4(int16x4_t rs1, int16x4_t rs2) { + return __riscv_ppaire_i16x4(rs1, rs2); +} + +// RV32-LABEL: define dso_local i64 @test_ppaire_u16x4( +// RV32-SAME: i64 noundef [[RS1_COERCE:%.*]], i64 noundef [[RS2_COERCE:%.*]]) #[[ATTR0]] { +// RV32-NEXT: [[ENTRY:.*:]] +// RV32-NEXT: [[TMP0:%.*]] = bitcast i64 [[RS1_COERCE]] to <4 x i16> +// RV32-NEXT: [[TMP1:%.*]] = bitcast i64 [[RS2_COERCE]] to <4 x i16> +// RV32-NEXT: [[SHUFFLE_I:%.*]] = shufflevector <4 x i16> [[TMP0]], <4 x i16> [[TMP1]], <4 x i32> +// RV32-NEXT: [[TMP2:%.*]] = bitcast <4 x i16> [[SHUFFLE_I]] to i64 +// RV32-NEXT: ret i64 [[TMP2]] +// +// RV64-LABEL: define dso_local i64 @test_ppaire_u16x4( +// RV64-SAME: i64 noundef [[RS1_COERCE:%.*]], i64 noundef [[RS2_COERCE:%.*]]) #[[ATTR0]] { +// RV64-NEXT: [[ENTRY:.*:]] +// RV64-NEXT: [[TMP0:%.*]] = bitcast i64 [[RS1_COERCE]] to <4 x i16> +// RV64-NEXT: [[TMP1:%.*]] = bitcast i64 [[RS2_COERCE]] to <4 x i16> +// RV64-NEXT: [[SHUFFLE_I:%.*]] = shufflevector <4 x i16> [[TMP0]], <4 x i16> [[TMP1]], <4 x i32> +// RV64-NEXT: [[TMP2:%.*]] = bitcast <4 x i16> [[SHUFFLE_I]] to i64 +// RV64-NEXT: ret i64 [[TMP2]] +// +uint16x4_t test_ppaire_u16x4(uint16x4_t rs1, uint16x4_t rs2) { + return __riscv_ppaire_u16x4(rs1, rs2); +} + +// RV32-LABEL: define dso_local i64 @test_ppaireo_i16x4( +// RV32-SAME: i64 noundef [[RS1_COERCE:%.*]], i64 noundef [[RS2_COERCE:%.*]]) #[[ATTR0]] { +// RV32-NEXT: [[ENTRY:.*:]] +// RV32-NEXT: [[TMP0:%.*]] = bitcast i64 [[RS1_COERCE]] to <4 x i16> +// RV32-NEXT: [[TMP1:%.*]] = bitcast i64 [[RS2_COERCE]] to <4 x i16> +// RV32-NEXT: [[SHUFFLE_I:%.*]] = shufflevector <4 x i16> [[TMP0]], <4 x i16> [[TMP1]], <4 x i32> +// RV32-NEXT: [[TMP2:%.*]] = bitcast <4 x i16> [[SHUFFLE_I]] to i64 +// RV32-NEXT: ret i64 [[TMP2]] +// +// RV64-LABEL: define dso_local i64 @test_ppaireo_i16x4( +// RV64-SAME: i64 noundef [[RS1_COERCE:%.*]], i64 noundef [[RS2_COERCE:%.*]]) #[[ATTR0]] { +// RV64-NEXT: [[ENTRY:.*:]] +// RV64-NEXT: [[TMP0:%.*]] = bitcast i64 [[RS1_COERCE]] to <4 x i16> +// RV64-NEXT: [[TMP1:%.*]] = bitcast i64 [[RS2_COERCE]] to <4 x i16> +// RV64-NEXT: [[SHUFFLE_I:%.*]] = shufflevector <4 x i16> [[TMP0]], <4 x i16> [[TMP1]], <4 x i32> +// RV64-NEXT: [[TMP2:%.*]] = bitcast <4 x i16> [[SHUFFLE_I]] to i64 +// RV64-NEXT: ret i64 [[TMP2]] +// +int16x4_t test_ppaireo_i16x4(int16x4_t rs1, int16x4_t rs2) { + return __riscv_ppaireo_i16x4(rs1, rs2); +} + +// RV32-LABEL: define dso_local i64 @test_ppaireo_u16x4( +// RV32-SAME: i64 noundef [[RS1_COERCE:%.*]], i64 noundef [[RS2_COERCE:%.*]]) #[[ATTR0]] { +// RV32-NEXT: [[ENTRY:.*:]] +// RV32-NEXT: [[TMP0:%.*]] = bitcast i64 [[RS1_COERCE]] to <4 x i16> +// RV32-NEXT: [[TMP1:%.*]] = bitcast i64 [[RS2_COERCE]] to <4 x i16> +// RV32-NEXT: [[SHUFFLE_I:%.*]] = shufflevector <4 x i16> [[TMP0]], <4 x i16> [[TMP1]], <4 x i32> +// RV32-NEXT: [[TMP2:%.*]] = bitcast <4 x i16> [[SHUFFLE_I]] to i64 +// RV32-NEXT: ret i64 [[TMP2]] +// +// RV64-LABEL: define dso_local i64 @test_ppaireo_u16x4( +// RV64-SAME: i64 noundef [[RS1_COERCE:%.*]], i64 noundef [[RS2_COERCE:%.*]]) #[[ATTR0]] { +// RV64-NEXT: [[ENTRY:.*:]] +// RV64-NEXT: [[TMP0:%.*]] = bitcast i64 [[RS1_COERCE]] to <4 x i16> +// RV64-NEXT: [[TMP1:%.*]] = bitcast i64 [[RS2_COERCE]] to <4 x i16> +// RV64-NEXT: [[SHUFFLE_I:%.*]] = shufflevector <4 x i16> [[TMP0]], <4 x i16> [[TMP1]], <4 x i32> +// RV64-NEXT: [[TMP2:%.*]] = bitcast <4 x i16> [[SHUFFLE_I]] to i64 +// RV64-NEXT: ret i64 [[TMP2]] +// +uint16x4_t test_ppaireo_u16x4(uint16x4_t rs1, uint16x4_t rs2) { + return __riscv_ppaireo_u16x4(rs1, rs2); +} + +// RV32-LABEL: define dso_local i64 @test_ppairoe_i16x4( +// RV32-SAME: i64 noundef [[RS1_COERCE:%.*]], i64 noundef [[RS2_COERCE:%.*]]) #[[ATTR0]] { +// RV32-NEXT: [[ENTRY:.*:]] +// RV32-NEXT: [[TMP0:%.*]] = bitcast i64 [[RS1_COERCE]] to <4 x i16> +// RV32-NEXT: [[TMP1:%.*]] = bitcast i64 [[RS2_COERCE]] to <4 x i16> +// RV32-NEXT: [[SHUFFLE_I:%.*]] = shufflevector <4 x i16> [[TMP0]], <4 x i16> [[TMP1]], <4 x i32> +// RV32-NEXT: [[TMP2:%.*]] = bitcast <4 x i16> [[SHUFFLE_I]] to i64 +// RV32-NEXT: ret i64 [[TMP2]] +// +// RV64-LABEL: define dso_local i64 @test_ppairoe_i16x4( +// RV64-SAME: i64 noundef [[RS1_COERCE:%.*]], i64 noundef [[RS2_COERCE:%.*]]) #[[ATTR0]] { +// RV64-NEXT: [[ENTRY:.*:]] +// RV64-NEXT: [[TMP0:%.*]] = bitcast i64 [[RS1_COERCE]] to <4 x i16> +// RV64-NEXT: [[TMP1:%.*]] = bitcast i64 [[RS2_COERCE]] to <4 x i16> +// RV64-NEXT: [[SHUFFLE_I:%.*]] = shufflevector <4 x i16> [[TMP0]], <4 x i16> [[TMP1]], <4 x i32> +// RV64-NEXT: [[TMP2:%.*]] = bitcast <4 x i16> [[SHUFFLE_I]] to i64 +// RV64-NEXT: ret i64 [[TMP2]] +// +int16x4_t test_ppairoe_i16x4(int16x4_t rs1, int16x4_t rs2) { + return __riscv_ppairoe_i16x4(rs1, rs2); +} + +// RV32-LABEL: define dso_local i64 @test_ppairoe_u16x4( +// RV32-SAME: i64 noundef [[RS1_COERCE:%.*]], i64 noundef [[RS2_COERCE:%.*]]) #[[ATTR0]] { +// RV32-NEXT: [[ENTRY:.*:]] +// RV32-NEXT: [[TMP0:%.*]] = bitcast i64 [[RS1_COERCE]] to <4 x i16> +// RV32-NEXT: [[TMP1:%.*]] = bitcast i64 [[RS2_COERCE]] to <4 x i16> +// RV32-NEXT: [[SHUFFLE_I:%.*]] = shufflevector <4 x i16> [[TMP0]], <4 x i16> [[TMP1]], <4 x i32> +// RV32-NEXT: [[TMP2:%.*]] = bitcast <4 x i16> [[SHUFFLE_I]] to i64 +// RV32-NEXT: ret i64 [[TMP2]] +// +// RV64-LABEL: define dso_local i64 @test_ppairoe_u16x4( +// RV64-SAME: i64 noundef [[RS1_COERCE:%.*]], i64 noundef [[RS2_COERCE:%.*]]) #[[ATTR0]] { +// RV64-NEXT: [[ENTRY:.*:]] +// RV64-NEXT: [[TMP0:%.*]] = bitcast i64 [[RS1_COERCE]] to <4 x i16> +// RV64-NEXT: [[TMP1:%.*]] = bitcast i64 [[RS2_COERCE]] to <4 x i16> +// RV64-NEXT: [[SHUFFLE_I:%.*]] = shufflevector <4 x i16> [[TMP0]], <4 x i16> [[TMP1]], <4 x i32> +// RV64-NEXT: [[TMP2:%.*]] = bitcast <4 x i16> [[SHUFFLE_I]] to i64 +// RV64-NEXT: ret i64 [[TMP2]] +// +uint16x4_t test_ppairoe_u16x4(uint16x4_t rs1, uint16x4_t rs2) { + return __riscv_ppairoe_u16x4(rs1, rs2); +} + +// RV32-LABEL: define dso_local i64 @test_ppairo_i16x4( +// RV32-SAME: i64 noundef [[RS1_COERCE:%.*]], i64 noundef [[RS2_COERCE:%.*]]) #[[ATTR0]] { +// RV32-NEXT: [[ENTRY:.*:]] +// RV32-NEXT: [[TMP0:%.*]] = bitcast i64 [[RS1_COERCE]] to <4 x i16> +// RV32-NEXT: [[TMP1:%.*]] = bitcast i64 [[RS2_COERCE]] to <4 x i16> +// RV32-NEXT: [[SHUFFLE_I:%.*]] = shufflevector <4 x i16> [[TMP0]], <4 x i16> [[TMP1]], <4 x i32> +// RV32-NEXT: [[TMP2:%.*]] = bitcast <4 x i16> [[SHUFFLE_I]] to i64 +// RV32-NEXT: ret i64 [[TMP2]] +// +// RV64-LABEL: define dso_local i64 @test_ppairo_i16x4( +// RV64-SAME: i64 noundef [[RS1_COERCE:%.*]], i64 noundef [[RS2_COERCE:%.*]]) #[[ATTR0]] { +// RV64-NEXT: [[ENTRY:.*:]] +// RV64-NEXT: [[TMP0:%.*]] = bitcast i64 [[RS1_COERCE]] to <4 x i16> +// RV64-NEXT: [[TMP1:%.*]] = bitcast i64 [[RS2_COERCE]] to <4 x i16> +// RV64-NEXT: [[SHUFFLE_I:%.*]] = shufflevector <4 x i16> [[TMP0]], <4 x i16> [[TMP1]], <4 x i32> +// RV64-NEXT: [[TMP2:%.*]] = bitcast <4 x i16> [[SHUFFLE_I]] to i64 +// RV64-NEXT: ret i64 [[TMP2]] +// +int16x4_t test_ppairo_i16x4(int16x4_t rs1, int16x4_t rs2) { + return __riscv_ppairo_i16x4(rs1, rs2); +} + +// RV32-LABEL: define dso_local i64 @test_ppairo_u16x4( +// RV32-SAME: i64 noundef [[RS1_COERCE:%.*]], i64 noundef [[RS2_COERCE:%.*]]) #[[ATTR0]] { +// RV32-NEXT: [[ENTRY:.*:]] +// RV32-NEXT: [[TMP0:%.*]] = bitcast i64 [[RS1_COERCE]] to <4 x i16> +// RV32-NEXT: [[TMP1:%.*]] = bitcast i64 [[RS2_COERCE]] to <4 x i16> +// RV32-NEXT: [[SHUFFLE_I:%.*]] = shufflevector <4 x i16> [[TMP0]], <4 x i16> [[TMP1]], <4 x i32> +// RV32-NEXT: [[TMP2:%.*]] = bitcast <4 x i16> [[SHUFFLE_I]] to i64 +// RV32-NEXT: ret i64 [[TMP2]] +// +// RV64-LABEL: define dso_local i64 @test_ppairo_u16x4( +// RV64-SAME: i64 noundef [[RS1_COERCE:%.*]], i64 noundef [[RS2_COERCE:%.*]]) #[[ATTR0]] { +// RV64-NEXT: [[ENTRY:.*:]] +// RV64-NEXT: [[TMP0:%.*]] = bitcast i64 [[RS1_COERCE]] to <4 x i16> +// RV64-NEXT: [[TMP1:%.*]] = bitcast i64 [[RS2_COERCE]] to <4 x i16> +// RV64-NEXT: [[SHUFFLE_I:%.*]] = shufflevector <4 x i16> [[TMP0]], <4 x i16> [[TMP1]], <4 x i32> +// RV64-NEXT: [[TMP2:%.*]] = bitcast <4 x i16> [[SHUFFLE_I]] to i64 +// RV64-NEXT: ret i64 [[TMP2]] +// +uint16x4_t test_ppairo_u16x4(uint16x4_t rs1, uint16x4_t rs2) { + return __riscv_ppairo_u16x4(rs1, rs2); +} + /* Packed Absolute Difference Sum (32-bit) */ // RV32-LABEL: define dso_local i32 @test_pabdsumu_u8x4_u32( // RV32-SAME: i32 noundef [[RS1_COERCE:%.*]], i32 noundef [[RS2_COERCE:%.*]]) #[[ATTR0]] { 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 ee3bc75e3a72..874ae879ae48 100644 --- a/cross-project-tests/intrinsic-header-tests/riscv_packed_simd.c +++ b/cross-project-tests/intrinsic-header-tests/riscv_packed_simd.c @@ -2539,6 +2539,167 @@ int32x2_t test_pmulq_i32x2(int32x2_t a, int32x2_t b) { int32x2_t test_pmulqr_i32x2(int32x2_t a, int32x2_t b) { return __riscv_pmulqr_i32x2(a, b); } + +// CHECK-LABEL: test_ppaire_i8x4: +// CHECK: ppaire.b +int8x4_t test_ppaire_i8x4(int8x4_t rs1, int8x4_t rs2) { + return __riscv_ppaire_i8x4(rs1, rs2); +} + +// CHECK-LABEL: test_ppaire_u8x4: +// CHECK: ppaire.b +uint8x4_t test_ppaire_u8x4(uint8x4_t rs1, uint8x4_t rs2) { + return __riscv_ppaire_u8x4(rs1, rs2); +} + +// CHECK-LABEL: test_ppaireo_i8x4: +// CHECK: ppaireo.b +int8x4_t test_ppaireo_i8x4(int8x4_t rs1, int8x4_t rs2) { + return __riscv_ppaireo_i8x4(rs1, rs2); +} + +// CHECK-LABEL: test_ppaireo_u8x4: +// CHECK: ppaireo.b +uint8x4_t test_ppaireo_u8x4(uint8x4_t rs1, uint8x4_t rs2) { + return __riscv_ppaireo_u8x4(rs1, rs2); +} + +// CHECK-LABEL: test_ppairoe_i8x4: +// CHECK: ppairoe.b +int8x4_t test_ppairoe_i8x4(int8x4_t rs1, int8x4_t rs2) { + return __riscv_ppairoe_i8x4(rs1, rs2); +} + +// CHECK-LABEL: test_ppairoe_u8x4: +// CHECK: ppairoe.b +uint8x4_t test_ppairoe_u8x4(uint8x4_t rs1, uint8x4_t rs2) { + return __riscv_ppairoe_u8x4(rs1, rs2); +} + +// CHECK-LABEL: test_ppairo_i8x4: +// CHECK: ppairo.b +int8x4_t test_ppairo_i8x4(int8x4_t rs1, int8x4_t rs2) { + return __riscv_ppairo_i8x4(rs1, rs2); +} + +// CHECK-LABEL: test_ppairo_u8x4: +// CHECK: ppairo.b +uint8x4_t test_ppairo_u8x4(uint8x4_t rs1, uint8x4_t rs2) { + return __riscv_ppairo_u8x4(rs1, rs2); +} + +// CHECK-LABEL: test_ppaire_i8x8: +// RV32: ppaire.db +// RV64: ppaire.b +int8x8_t test_ppaire_i8x8(int8x8_t rs1, int8x8_t rs2) { + return __riscv_ppaire_i8x8(rs1, rs2); +} + +// CHECK-LABEL: test_ppaire_u8x8: +// RV32: ppaire.db +// RV64: ppaire.b +uint8x8_t test_ppaire_u8x8(uint8x8_t rs1, uint8x8_t rs2) { + return __riscv_ppaire_u8x8(rs1, rs2); +} + +// CHECK-LABEL: test_ppaireo_i8x8: +// RV32: ppaireo.db +// RV64: ppaireo.b +int8x8_t test_ppaireo_i8x8(int8x8_t rs1, int8x8_t rs2) { + return __riscv_ppaireo_i8x8(rs1, rs2); +} + +// CHECK-LABEL: test_ppaireo_u8x8: +// RV32: ppaireo.db +// RV64: ppaireo.b +uint8x8_t test_ppaireo_u8x8(uint8x8_t rs1, uint8x8_t rs2) { + return __riscv_ppaireo_u8x8(rs1, rs2); +} + +// CHECK-LABEL: test_ppairoe_i8x8: +// RV32: ppairoe.db +// RV64: ppairoe.b +int8x8_t test_ppairoe_i8x8(int8x8_t rs1, int8x8_t rs2) { + return __riscv_ppairoe_i8x8(rs1, rs2); +} + +// CHECK-LABEL: test_ppairoe_u8x8: +// RV32: ppairoe.db +// RV64: ppairoe.b +uint8x8_t test_ppairoe_u8x8(uint8x8_t rs1, uint8x8_t rs2) { + return __riscv_ppairoe_u8x8(rs1, rs2); +} + +// CHECK-LABEL: test_ppairo_i8x8: +// RV32: ppairo.db +// RV64: ppairo.b +int8x8_t test_ppairo_i8x8(int8x8_t rs1, int8x8_t rs2) { + return __riscv_ppairo_i8x8(rs1, rs2); +} + +// CHECK-LABEL: test_ppairo_u8x8: +// RV32: ppairo.db +// RV64: ppairo.b +uint8x8_t test_ppairo_u8x8(uint8x8_t rs1, uint8x8_t rs2) { + return __riscv_ppairo_u8x8(rs1, rs2); +} + +// CHECK-LABEL: test_ppaire_i16x4: +// RV32: ppaire.dh +// RV64: ppaire.h +int16x4_t test_ppaire_i16x4(int16x4_t rs1, int16x4_t rs2) { + return __riscv_ppaire_i16x4(rs1, rs2); +} + +// CHECK-LABEL: test_ppaire_u16x4: +// RV32: ppaire.dh +// RV64: ppaire.h +uint16x4_t test_ppaire_u16x4(uint16x4_t rs1, uint16x4_t rs2) { + return __riscv_ppaire_u16x4(rs1, rs2); +} + +// CHECK-LABEL: test_ppaireo_i16x4: +// RV32: ppaireo.dh +// RV64: ppaireo.h +int16x4_t test_ppaireo_i16x4(int16x4_t rs1, int16x4_t rs2) { + return __riscv_ppaireo_i16x4(rs1, rs2); +} + +// CHECK-LABEL: test_ppaireo_u16x4: +// RV32: ppaireo.dh +// RV64: ppaireo.h +uint16x4_t test_ppaireo_u16x4(uint16x4_t rs1, uint16x4_t rs2) { + return __riscv_ppaireo_u16x4(rs1, rs2); +} + +// CHECK-LABEL: test_ppairoe_i16x4: +// RV32: ppairoe.dh +// RV64: ppairoe.h +int16x4_t test_ppairoe_i16x4(int16x4_t rs1, int16x4_t rs2) { + return __riscv_ppairoe_i16x4(rs1, rs2); +} + +// CHECK-LABEL: test_ppairoe_u16x4: +// RV32: ppairoe.dh +// RV64: ppairoe.h +uint16x4_t test_ppairoe_u16x4(uint16x4_t rs1, uint16x4_t rs2) { + return __riscv_ppairoe_u16x4(rs1, rs2); +} + +// CHECK-LABEL: test_ppairo_i16x4: +// RV32: ppairo.dh +// RV64: ppairo.h +int16x4_t test_ppairo_i16x4(int16x4_t rs1, int16x4_t rs2) { + return __riscv_ppairo_i16x4(rs1, rs2); +} + +// CHECK-LABEL: test_ppairo_u16x4: +// RV32: ppairo.dh +// RV64: ppairo.h +uint16x4_t test_ppairo_u16x4(uint16x4_t rs1, uint16x4_t rs2) { + return __riscv_ppairo_u16x4(rs1, rs2); +} + // CHECK-LABEL: test_pnzip_i8x4: // CHECK: ppaire.b int8x4_t test_pnzip_i8x4(int16x2_t rs1, int16x2_t rs2) { diff --git a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp index 37505a5b187f..b546a21e1c43 100644 --- a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp +++ b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp @@ -6527,6 +6527,8 @@ lowerVECTOR_SHUFFLEAsRV32PNarrowingShift(ShuffleVectorSDNode *SVN, // Match a strided-interleave shuffle that forms a P-extension packed pair: // -> ppaire.* +// -> ppaireo.* +// -> ppairoe.* // -> ppairo.* static SDValue lowerVECTOR_SHUFFLEAsPPair(ShuffleVectorSDNode *SVN, SelectionDAG &DAG) { @@ -6549,32 +6551,37 @@ static SDValue lowerVECTOR_SHUFFLEAsPPair(ShuffleVectorSDNode *SVN, bool V1IsSplat = DAG.isSplatValue(V1); bool V2IsSplat = DAG.isSplatValue(V2); - // Match : even lanes come from V1 - // and odd lanes from V2 (start=0, ppaire) or vice versa (start=1, ppairo). - // Trailing lanes may be undef when a 4-byte source was widened to v8i8. - auto IsStrided = [&](unsigned Start) { + // Match the packed pair shuffle forms: + // + // where each start is 0 for even lanes or 1 for odd lanes. This covers all + // four PPAIRE/PPAIREO/PPAIROE/PPAIRO combinations. Trailing lanes may be + // undef when a 4-byte source was widened to v8i8. + auto IsStrided = [&](unsigned V1Start, unsigned V2Start) { for (unsigned I = 0; I != NumElts / 2; ++I) { int M0 = Mask[2 * I]; int M1 = Mask[2 * I + 1]; if (M0 >= 0 && - (V1IsSplat ? M0 >= (int)NumElts : M0 != (int)(Start + 2 * I))) + (V1IsSplat ? M0 >= (int)NumElts : M0 != (int)(V1Start + 2 * I))) return false; if (M1 >= 0 && (V2IsSplat ? M1 < (int)NumElts - : M1 != (int)(NumElts + Start + 2 * I))) + : M1 != (int)(NumElts + V2Start + 2 * I))) return false; } return true; }; - bool IsOdd; - if (IsStrided(0)) - IsOdd = false; - else if (IsStrided(1)) - IsOdd = true; + unsigned Opc; + if (IsStrided(0, 0)) + Opc = RISCVISD::PPAIRE; + else if (IsStrided(1, 1)) + Opc = RISCVISD::PPAIRO; + else if (IsStrided(0, 1)) + Opc = RISCVISD::PPAIREO; + else if (IsStrided(1, 0)) + Opc = RISCVISD::PPAIROE; else return SDValue(); - unsigned Opc = IsOdd ? RISCVISD::PPAIRO : RISCVISD::PPAIRE; return DAG.getNode(Opc, DL, VT, V1, V2); } diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfoP.td b/llvm/lib/Target/RISCV/RISCVInstrInfoP.td index e1e23b67af1b..b5cd4c1aad19 100644 --- a/llvm/lib/Target/RISCV/RISCVInstrInfoP.td +++ b/llvm/lib/Target/RISCV/RISCVInstrInfoP.td @@ -1866,11 +1866,13 @@ def shiftMask64 : ComplexPattern", [], [], 0>; def BuildGPRPair : OutPatFrag<(ops node:$lo, node:$hi), (REG_SEQUENCE GPRPair, $lo, sub_gpr_even, $hi, sub_gpr_odd)>; -def SDT_RISCVPPairEven : SDTypeProfile<1, 2, [SDTCisVec<0>, - SDTCisSameAs<0, 1>, - SDTCisSameAs<0, 2>]>; -def riscv_ppaire : RVSDNode<"PPAIRE", SDT_RISCVPPairEven>; -def riscv_ppairo : RVSDNode<"PPAIRO", SDT_RISCVPPairEven>; +def SDT_RISCVPPair : SDTypeProfile<1, 2, [SDTCisVec<0>, + SDTCisSameAs<0, 1>, + SDTCisSameAs<0, 2>]>; +def riscv_ppaire : RVSDNode<"PPAIRE", SDT_RISCVPPair>; +def riscv_ppaireo : RVSDNode<"PPAIREO", SDT_RISCVPPair>; +def riscv_ppairoe : RVSDNode<"PPAIROE", SDT_RISCVPPair>; +def riscv_ppairo : RVSDNode<"PPAIRO", SDT_RISCVPPair>; def SDT_RISCVPackedBinary : SDTypeProfile<1, 2, [SDTCisVec<0>, SDTCisSameAs<0, 1>, SDTCisSameAs<0, 2>]>; @@ -2321,14 +2323,26 @@ let append Predicates = [IsRV32] in { // Packed pair: pair the even/odd-position elements of rs1 and rs2. def : Pat<(v4i8 (riscv_ppaire (v4i8 GPR:$rs1), (v4i8 GPR:$rs2))), (PPAIRE_B GPR:$rs1, GPR:$rs2)>; + def : Pat<(v4i8 (riscv_ppaireo (v4i8 GPR:$rs1), (v4i8 GPR:$rs2))), + (PPAIREO_B GPR:$rs1, GPR:$rs2)>; + def : Pat<(v4i8 (riscv_ppairoe (v4i8 GPR:$rs1), (v4i8 GPR:$rs2))), + (PPAIROE_B GPR:$rs1, GPR:$rs2)>; def : Pat<(v4i8 (riscv_ppairo (v4i8 GPR:$rs1), (v4i8 GPR:$rs2))), (PPAIRO_B GPR:$rs1, GPR:$rs2)>; def : Pat<(v8i8 (riscv_ppaire GPRPair:$rs1, GPRPair:$rs2)), (PPAIRE_DB GPRPair:$rs1, GPRPair:$rs2)>; + def : Pat<(v8i8 (riscv_ppaireo GPRPair:$rs1, GPRPair:$rs2)), + (PPAIREO_DB GPRPair:$rs1, GPRPair:$rs2)>; + def : Pat<(v8i8 (riscv_ppairoe GPRPair:$rs1, GPRPair:$rs2)), + (PPAIROE_DB GPRPair:$rs1, GPRPair:$rs2)>; def : Pat<(v8i8 (riscv_ppairo GPRPair:$rs1, GPRPair:$rs2)), (PPAIRO_DB GPRPair:$rs1, GPRPair:$rs2)>; def : Pat<(v4i16 (riscv_ppaire GPRPair:$rs1, GPRPair:$rs2)), (PPAIRE_DH GPRPair:$rs1, GPRPair:$rs2)>; + def : Pat<(v4i16 (riscv_ppaireo GPRPair:$rs1, GPRPair:$rs2)), + (PPAIREO_DH GPRPair:$rs1, GPRPair:$rs2)>; + def : Pat<(v4i16 (riscv_ppairoe GPRPair:$rs1, GPRPair:$rs2)), + (PPAIROE_DH GPRPair:$rs1, GPRPair:$rs2)>; def : Pat<(v4i16 (riscv_ppairo GPRPair:$rs1, GPRPair:$rs2)), (PPAIRO_DH GPRPair:$rs1, GPRPair:$rs2)>; @@ -2888,10 +2902,18 @@ let append Predicates = [IsRV64] in { // Packed pair: pair the even/odd-position elements of rs1 and rs2. def : Pat<(v8i8 (riscv_ppaire (v8i8 GPR:$rs1), (v8i8 GPR:$rs2))), (PPAIRE_B GPR:$rs1, GPR:$rs2)>; + def : Pat<(v8i8 (riscv_ppaireo (v8i8 GPR:$rs1), (v8i8 GPR:$rs2))), + (PPAIREO_B GPR:$rs1, GPR:$rs2)>; + def : Pat<(v8i8 (riscv_ppairoe (v8i8 GPR:$rs1), (v8i8 GPR:$rs2))), + (PPAIROE_B GPR:$rs1, GPR:$rs2)>; def : Pat<(v8i8 (riscv_ppairo (v8i8 GPR:$rs1), (v8i8 GPR:$rs2))), (PPAIRO_B GPR:$rs1, GPR:$rs2)>; def : Pat<(v4i16 (riscv_ppaire (v4i16 GPR:$rs1), (v4i16 GPR:$rs2))), (PPAIRE_H GPR:$rs1, GPR:$rs2)>; + def : Pat<(v4i16 (riscv_ppaireo (v4i16 GPR:$rs1), (v4i16 GPR:$rs2))), + (PPAIREO_H GPR:$rs1, GPR:$rs2)>; + def : Pat<(v4i16 (riscv_ppairoe (v4i16 GPR:$rs1), (v4i16 GPR:$rs2))), + (PPAIROE_H GPR:$rs1, GPR:$rs2)>; def : Pat<(v4i16 (riscv_ppairo (v4i16 GPR:$rs1), (v4i16 GPR:$rs2))), (PPAIRO_H GPR:$rs1, GPR:$rs2)>; } // append Predicates = [IsRV64] diff --git a/llvm/test/CodeGen/RISCV/rvp-simd-32.ll b/llvm/test/CodeGen/RISCV/rvp-simd-32.ll index 42a20b2b89af..c85b0091de48 100644 --- a/llvm/test/CodeGen/RISCV/rvp-simd-32.ll +++ b/llvm/test/CodeGen/RISCV/rvp-simd-32.ll @@ -2304,6 +2304,42 @@ define <4 x i8> @test_vselect_v4i8(<4 x i8> %a, <4 x i8> %b, <4 x i8> %c) { ret <4 x i8> %res } +define <4 x i8> @test_ppaire_v4i8(<4 x i8> %a, <4 x i8> %b) { +; CHECK-LABEL: test_ppaire_v4i8: +; CHECK: # %bb.0: +; CHECK-NEXT: ppaire.b a0, a0, a1 +; CHECK-NEXT: ret + %res = shufflevector <4 x i8> %a, <4 x i8> %b, <4 x i32> + ret <4 x i8> %res +} + +define <4 x i8> @test_ppaireo_v4i8(<4 x i8> %a, <4 x i8> %b) { +; CHECK-LABEL: test_ppaireo_v4i8: +; CHECK: # %bb.0: +; CHECK-NEXT: ppaireo.b a0, a0, a1 +; CHECK-NEXT: ret + %res = shufflevector <4 x i8> %a, <4 x i8> %b, <4 x i32> + ret <4 x i8> %res +} + +define <4 x i8> @test_ppairoe_v4i8(<4 x i8> %a, <4 x i8> %b) { +; CHECK-LABEL: test_ppairoe_v4i8: +; CHECK: # %bb.0: +; CHECK-NEXT: ppairoe.b a0, a0, a1 +; CHECK-NEXT: ret + %res = shufflevector <4 x i8> %a, <4 x i8> %b, <4 x i32> + ret <4 x i8> %res +} + +define <4 x i8> @test_ppairo_v4i8(<4 x i8> %a, <4 x i8> %b) { +; CHECK-LABEL: test_ppairo_v4i8: +; CHECK: # %bb.0: +; CHECK-NEXT: ppairo.b a0, a0, a1 +; CHECK-NEXT: ret + %res = shufflevector <4 x i8> %a, <4 x i8> %b, <4 x i32> + ret <4 x i8> %res +} + define <2 x i16> @test_bswap_v2i16(<2 x i16> %a) { ; CHECK-LABEL: test_bswap_v2i16: ; CHECK: # %bb.0: diff --git a/llvm/test/CodeGen/RISCV/rvp-simd-64.ll b/llvm/test/CodeGen/RISCV/rvp-simd-64.ll index 21b2f96b6727..a6e01ab13a39 100644 --- a/llvm/test/CodeGen/RISCV/rvp-simd-64.ll +++ b/llvm/test/CodeGen/RISCV/rvp-simd-64.ll @@ -6168,3 +6168,59 @@ define <2 x i32> @test_undef_v2i32() { ; CHECK-NEXT: ret ret <2 x i32> undef } + +define <8 x i8> @test_ppaireo_v8i8(<8 x i8> %a, <8 x i8> %b) { +; RV32-LABEL: test_ppaireo_v8i8: +; RV32: # %bb.0: +; RV32-NEXT: ppaireo.db a0, a0, a2 +; RV32-NEXT: ret +; +; RV64-LABEL: test_ppaireo_v8i8: +; RV64: # %bb.0: +; RV64-NEXT: ppaireo.b a0, a0, a1 +; RV64-NEXT: ret + %res = shufflevector <8 x i8> %a, <8 x i8> %b, <8 x i32> + ret <8 x i8> %res +} + +define <8 x i8> @test_ppairoe_v8i8(<8 x i8> %a, <8 x i8> %b) { +; RV32-LABEL: test_ppairoe_v8i8: +; RV32: # %bb.0: +; RV32-NEXT: ppairoe.db a0, a0, a2 +; RV32-NEXT: ret +; +; RV64-LABEL: test_ppairoe_v8i8: +; RV64: # %bb.0: +; RV64-NEXT: ppairoe.b a0, a0, a1 +; RV64-NEXT: ret + %res = shufflevector <8 x i8> %a, <8 x i8> %b, <8 x i32> + ret <8 x i8> %res +} + +define <4 x i16> @test_ppaireo_v4i16(<4 x i16> %a, <4 x i16> %b) { +; RV32-LABEL: test_ppaireo_v4i16: +; RV32: # %bb.0: +; RV32-NEXT: ppaireo.dh a0, a0, a2 +; RV32-NEXT: ret +; +; RV64-LABEL: test_ppaireo_v4i16: +; RV64: # %bb.0: +; RV64-NEXT: ppaireo.h a0, a0, a1 +; RV64-NEXT: ret + %res = shufflevector <4 x i16> %a, <4 x i16> %b, <4 x i32> + ret <4 x i16> %res +} + +define <4 x i16> @test_ppairoe_v4i16(<4 x i16> %a, <4 x i16> %b) { +; RV32-LABEL: test_ppairoe_v4i16: +; RV32: # %bb.0: +; RV32-NEXT: ppairoe.dh a0, a0, a2 +; RV32-NEXT: ret +; +; RV64-LABEL: test_ppairoe_v4i16: +; RV64: # %bb.0: +; RV64-NEXT: ppairoe.h a0, a0, a1 +; RV64-NEXT: ret + %res = shufflevector <4 x i16> %a, <4 x i16> %b, <4 x i32> + ret <4 x i16> %res +}