[llvm] [RISCV][P-ext] Generalize lowerVECTOR_SHUFFLEAsRV32PNarrowingShift (PR #210522)
Hongyu Chen via llvm-commits
llvm-commits at lists.llvm.org
Mon Jul 20 01:12:11 PDT 2026
https://github.com/XChy updated https://github.com/llvm/llvm-project/pull/210522
>From 595bef1bb8aa58e270b2224ba5f40ec8c0321dda Mon Sep 17 00:00:00 2001
From: XChy <xxs_chy at outlook.com>
Date: Sat, 18 Jul 2026 23:59:48 +0800
Subject: [PATCH 1/2] [RISCV][P-ext] Generalize
lowerVECTOR_SHUFFLEAsRV32PNarrowingShift
---
.../riscv_packed_simd.c | 84 +++++++++++++++++++
llvm/lib/Target/RISCV/RISCVISelLowering.cpp | 41 +++------
llvm/test/CodeGen/RISCV/rvp-zip.ll | 64 ++++++++++++++
3 files changed, 158 insertions(+), 31 deletions(-)
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 6aa08d6a58c00..b2990531e0257 100644
--- a/cross-project-tests/intrinsic-header-tests/riscv_packed_simd.c
+++ b/cross-project-tests/intrinsic-header-tests/riscv_packed_simd.c
@@ -2574,3 +2574,87 @@ int16x4_t test_pnziph_i16x4(int32x2_t rs1, int32x2_t rs2) {
uint16x4_t test_pnziph_u16x4(uint32x2_t rs1, uint32x2_t rs2) {
return __riscv_pnziph_u16x4(rs1, rs2);
}
+
+// CHECK-LABEL: test_pzip_i8x8:
+// RV32: wzip8p
+// RV64: zip8p
+int8x8_t test_pzip_i8x8(int8x4_t a, int8x4_t b) {
+ return __riscv_pzip_i8x8(a, b);
+}
+
+// CHECK-LABEL: test_pzip_u8x8:
+// RV32: wzip8p
+// RV64: zip8p
+uint8x8_t test_pzip_u8x8(uint8x4_t a, uint8x4_t b) {
+ return __riscv_pzip_u8x8(a, b);
+}
+
+// CHECK-LABEL: test_pzip_i16x4:
+// RV32: wzip16p
+// RV64: zip16p
+int16x4_t test_pzip_i16x4(int16x2_t a, int16x2_t b) {
+ return __riscv_pzip_i16x4(a, b);
+}
+
+// CHECK-LABEL: test_pzip_u16x4:
+// RV32: wzip16p
+// RV64: zip16p
+uint16x4_t test_pzip_u16x4(uint16x2_t a, uint16x2_t b) {
+ return __riscv_pzip_u16x4(a, b);
+}
+
+// CHECK-LABEL: test_punzipe_i8x4:
+// RV32: pncvt.b
+// RV64: pncvt.wb
+int8x4_t test_punzipe_i8x4(int8x8_t a) {
+ return __riscv_punzipe_i8x4(a);
+}
+
+// CHECK-LABEL: test_punzipo_i8x4:
+// RV32: pncvth.b
+// RV64: pncvth.wb
+int8x4_t test_punzipo_i8x4(int8x8_t a) {
+ return __riscv_punzipo_i8x4(a);
+}
+
+// CHECK-LABEL: test_punzipe_u8x4:
+// RV32: pncvt.b
+// RV64: pncvt.wb
+uint8x4_t test_punzipe_u8x4(uint8x8_t a) {
+ return __riscv_punzipe_u8x4(a);
+}
+
+// CHECK-LABEL: test_punzipo_u8x4:
+// RV32: pncvth.b
+// RV64: pncvth.wb
+uint8x4_t test_punzipo_u8x4(uint8x8_t a) {
+ return __riscv_punzipo_u8x4(a);
+}
+
+// CHECK-LABEL: test_punzipe_i16x2:
+// RV32: pncvt.h
+// RV64: pncvt.wh
+int16x2_t test_punzipe_i16x2(int16x4_t a) {
+ return __riscv_punzipe_i16x2(a);
+}
+
+// CHECK-LABEL: test_punzipo_i16x2:
+// RV32: pncvth.h
+// RV64: pncvth.wh
+int16x2_t test_punzipo_i16x2(int16x4_t a) {
+ return __riscv_punzipo_i16x2(a);
+}
+
+// CHECK-LABEL: test_punzipe_u16x2:
+// RV32: pncvt.h
+// RV64: pncvt.wh
+uint16x2_t test_punzipe_u16x2(uint16x4_t a) {
+ return __riscv_punzipe_u16x2(a);
+}
+
+// CHECK-LABEL: test_punzipo_u16x2:
+// RV32: pncvth.h
+// RV64: pncvth.wh
+uint16x2_t test_punzipo_u16x2(uint16x4_t a) {
+ return __riscv_punzipo_u16x2(a);
+}
\ No newline at end of file
diff --git a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
index 9aaee1e47eab3..0e33e140aaa72 100644
--- a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
+++ b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
@@ -6457,12 +6457,8 @@ static SDValue lowerVECTOR_SHUFFLEAsPUnzip(ShuffleVectorSDNode *SVN,
return DAG.getNode(Opc, DL, VT, V1, V2);
}
-// Match a legalized single-source deinterleave shuffle where the source
-// vector was split into two extract_subvectors of the same vector, e.g.
-// t20: v4i8 = extract_subvector t5, 0
-// t19: v4i8 = extract_subvector t5, 4
-// t21: v4i8 = vector_shuffle<0,2,4,6> t20, t19
-// and lower it to an RV32 P narrowing shift on the original source.
+// Match a legalized deinterleave shuffle on two RV32 vector halves and lower
+// it to an RV32 P narrowing shift on the concatenated source.
static SDValue
lowerVECTOR_SHUFFLEAsRV32PNarrowingShift(ShuffleVectorSDNode *SVN,
const RISCVSubtarget &Subtarget,
@@ -6473,41 +6469,24 @@ lowerVECTOR_SHUFFLEAsRV32PNarrowingShift(ShuffleVectorSDNode *SVN,
SDValue V1 = SVN->getOperand(0);
SDValue V2 = SVN->getOperand(1);
+ SDLoc DL(SVN);
+ unsigned NumElts = VT.getVectorNumElements();
- // The inputs should be two extract_subvectors from the same source.
- using namespace llvm::SDPatternMatch;
- SDValue Src;
- int64_t V1Index, V2Index;
- if (!sd_match(V1, m_ExtractSubvector(m_Value(Src), m_ConstInt(V1Index))) ||
- !sd_match(V2, m_ExtractSubvector(m_Specific(Src), m_ConstInt(V2Index))))
- return SDValue();
+ SDValue Src = foldConcatVector(V1, V2);
+ if (!Src) {
+ MVT SrcVT = VT == MVT::v4i8 ? MVT::v8i8 : MVT::v4i16;
+ Src = DAG.getNode(ISD::CONCAT_VECTORS, DL, SrcVT, V1, V2);
+ }
// The source vector should be twice the size.
- unsigned NumElts = VT.getVectorNumElements();
if (Src.getValueType().getVectorNumElements() != 2 * NumElts)
return SDValue();
- // The two extract_subvectors should be from different halves.
- if ((V1Index != 0 || V2Index != NumElts) &&
- (V1Index != NumElts || V2Index != 0))
- return SDValue();
-
- // Translate the shuffle mask, which indexes into the concatenation of V1
- // and V2, into indices into Src.
- SmallVector<int, 4> Indices(NumElts, -1);
- for (auto [I, M] : enumerate(SVN->getMask())) {
- if (M < 0)
- continue;
- int64_t Base = static_cast<unsigned>(M) < NumElts ? V1Index : V2Index;
- Indices[I] = Base + (M % NumElts);
- }
-
unsigned Index = 0;
- if (!ShuffleVectorInst::isDeInterleaveMaskOfFactor(Indices, 2, Index))
+ if (!ShuffleVectorInst::isDeInterleaveMaskOfFactor(SVN->getMask(), 2, Index))
return SDValue();
unsigned EltBits = VT.getVectorElementType().getSizeInBits();
- SDLoc DL(SVN);
return DAG.getNode(RISCVISD::PNSRL, DL, VT, Src,
DAG.getConstant(Index * EltBits, DL, MVT::i32));
}
diff --git a/llvm/test/CodeGen/RISCV/rvp-zip.ll b/llvm/test/CodeGen/RISCV/rvp-zip.ll
index 766db01267521..ecb2fc8f01be6 100644
--- a/llvm/test/CodeGen/RISCV/rvp-zip.ll
+++ b/llvm/test/CodeGen/RISCV/rvp-zip.ll
@@ -254,5 +254,69 @@ define <4 x i16> @test_unzip16hp_v4i16_partial_poison(<4 x i16> %a, <4 x i16> %b
%r = shufflevector <4 x i16> %a, <4 x i16> %b, <4 x i32> <i32 1, i32 3, i32 poison, i32 7>
ret <4 x i16> %r
}
+
+define i32 @test_punzipe_v4i8_coerce(i64 %a.coerce) {
+; RV32-LABEL: test_punzipe_v4i8_coerce:
+; RV32: # %bb.0:
+; RV32-NEXT: pncvt.b a0, a0
+; RV32-NEXT: ret
+;
+; RV64-LABEL: test_punzipe_v4i8_coerce:
+; RV64: # %bb.0:
+; RV64-NEXT: pncvt.wb a0, a0
+; RV64-NEXT: ret
+ %a = bitcast i64 %a.coerce to <8 x i8>
+ %r = shufflevector <8 x i8> %a, <8 x i8> poison, <4 x i32> <i32 0, i32 2, i32 4, i32 6>
+ %ret = bitcast <4 x i8> %r to i32
+ ret i32 %ret
+}
+
+define i32 @test_punzipo_v4i8_coerce(i64 %a.coerce) {
+; RV32-LABEL: test_punzipo_v4i8_coerce:
+; RV32: # %bb.0:
+; RV32-NEXT: pncvth.b a0, a0
+; RV32-NEXT: ret
+;
+; RV64-LABEL: test_punzipo_v4i8_coerce:
+; RV64: # %bb.0:
+; RV64-NEXT: pncvth.wb a0, a0
+; RV64-NEXT: ret
+ %a = bitcast i64 %a.coerce to <8 x i8>
+ %r = shufflevector <8 x i8> %a, <8 x i8> poison, <4 x i32> <i32 1, i32 3, i32 5, i32 7>
+ %ret = bitcast <4 x i8> %r to i32
+ ret i32 %ret
+}
+
+define i32 @test_punzipe_v2i16_coerce(i64 %a.coerce) {
+; RV32-LABEL: test_punzipe_v2i16_coerce:
+; RV32: # %bb.0:
+; RV32-NEXT: pncvt.h a0, a0
+; RV32-NEXT: ret
+;
+; RV64-LABEL: test_punzipe_v2i16_coerce:
+; RV64: # %bb.0:
+; RV64-NEXT: pncvt.wh a0, a0
+; RV64-NEXT: ret
+ %a = bitcast i64 %a.coerce to <4 x i16>
+ %r = shufflevector <4 x i16> %a, <4 x i16> poison, <2 x i32> <i32 0, i32 2>
+ %ret = bitcast <2 x i16> %r to i32
+ ret i32 %ret
+}
+
+define i32 @test_punzipo_v2i16_coerce(i64 %a.coerce) {
+; RV32-LABEL: test_punzipo_v2i16_coerce:
+; RV32: # %bb.0:
+; RV32-NEXT: pncvth.h a0, a0
+; RV32-NEXT: ret
+;
+; RV64-LABEL: test_punzipo_v2i16_coerce:
+; RV64: # %bb.0:
+; RV64-NEXT: pncvth.wh a0, a0
+; RV64-NEXT: ret
+ %a = bitcast i64 %a.coerce to <4 x i16>
+ %r = shufflevector <4 x i16> %a, <4 x i16> poison, <2 x i32> <i32 1, i32 3>
+ %ret = bitcast <2 x i16> %r to i32
+ ret i32 %ret
+}
;; NOTE: These prefixes are unused and the list is autogenerated. Do not add tests below this line:
; CHECK: {{.*}}
>From c940ef70d9f99fb4313996a6cc25db45f6e6fef1 Mon Sep 17 00:00:00 2001
From: XChy <xxs_chy at outlook.com>
Date: Sun, 19 Jul 2026 00:17:46 +0800
Subject: [PATCH 2/2] format
---
.../riscv_packed_simd.c | 32 +++++--------------
1 file changed, 8 insertions(+), 24 deletions(-)
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 b2990531e0257..2af196cdaadc0 100644
--- a/cross-project-tests/intrinsic-header-tests/riscv_packed_simd.c
+++ b/cross-project-tests/intrinsic-header-tests/riscv_packed_simd.c
@@ -2606,55 +2606,39 @@ uint16x4_t test_pzip_u16x4(uint16x2_t a, uint16x2_t b) {
// CHECK-LABEL: test_punzipe_i8x4:
// RV32: pncvt.b
// RV64: pncvt.wb
-int8x4_t test_punzipe_i8x4(int8x8_t a) {
- return __riscv_punzipe_i8x4(a);
-}
+int8x4_t test_punzipe_i8x4(int8x8_t a) { return __riscv_punzipe_i8x4(a); }
// CHECK-LABEL: test_punzipo_i8x4:
// RV32: pncvth.b
// RV64: pncvth.wb
-int8x4_t test_punzipo_i8x4(int8x8_t a) {
- return __riscv_punzipo_i8x4(a);
-}
+int8x4_t test_punzipo_i8x4(int8x8_t a) { return __riscv_punzipo_i8x4(a); }
// CHECK-LABEL: test_punzipe_u8x4:
// RV32: pncvt.b
// RV64: pncvt.wb
-uint8x4_t test_punzipe_u8x4(uint8x8_t a) {
- return __riscv_punzipe_u8x4(a);
-}
+uint8x4_t test_punzipe_u8x4(uint8x8_t a) { return __riscv_punzipe_u8x4(a); }
// CHECK-LABEL: test_punzipo_u8x4:
// RV32: pncvth.b
// RV64: pncvth.wb
-uint8x4_t test_punzipo_u8x4(uint8x8_t a) {
- return __riscv_punzipo_u8x4(a);
-}
+uint8x4_t test_punzipo_u8x4(uint8x8_t a) { return __riscv_punzipo_u8x4(a); }
// CHECK-LABEL: test_punzipe_i16x2:
// RV32: pncvt.h
// RV64: pncvt.wh
-int16x2_t test_punzipe_i16x2(int16x4_t a) {
- return __riscv_punzipe_i16x2(a);
-}
+int16x2_t test_punzipe_i16x2(int16x4_t a) { return __riscv_punzipe_i16x2(a); }
// CHECK-LABEL: test_punzipo_i16x2:
// RV32: pncvth.h
// RV64: pncvth.wh
-int16x2_t test_punzipo_i16x2(int16x4_t a) {
- return __riscv_punzipo_i16x2(a);
-}
+int16x2_t test_punzipo_i16x2(int16x4_t a) { return __riscv_punzipo_i16x2(a); }
// CHECK-LABEL: test_punzipe_u16x2:
// RV32: pncvt.h
// RV64: pncvt.wh
-uint16x2_t test_punzipe_u16x2(uint16x4_t a) {
- return __riscv_punzipe_u16x2(a);
-}
+uint16x2_t test_punzipe_u16x2(uint16x4_t a) { return __riscv_punzipe_u16x2(a); }
// CHECK-LABEL: test_punzipo_u16x2:
// RV32: pncvth.h
// RV64: pncvth.wh
-uint16x2_t test_punzipo_u16x2(uint16x4_t a) {
- return __riscv_punzipo_u16x2(a);
-}
\ No newline at end of file
+uint16x2_t test_punzipo_u16x2(uint16x4_t a) { return __riscv_punzipo_u16x2(a); }
More information about the llvm-commits
mailing list