[llvm] [RISCV][P-ext] Improve the codegen for unzip-like shuffle and buildvector (PR #208763)
Hongyu Chen via llvm-commits
llvm-commits at lists.llvm.org
Fri Jul 10 09:26:01 PDT 2026
https://github.com/XChy updated https://github.com/llvm/llvm-project/pull/208763
>From 8ec9f361c5514f6db3985205098a1d1c75a4f79e Mon Sep 17 00:00:00 2001
From: XChy <xxs_chy at outlook.com>
Date: Fri, 10 Jul 2026 23:38:51 +0800
Subject: [PATCH 1/2] [RISCV][P-ext] Improve the codegen for unzip-like shuffle
and buildvector
---
llvm/lib/Target/RISCV/RISCVISelLowering.cpp | 126 +++++++++--
llvm/lib/Target/RISCV/RISCVInstrInfoP.td | 36 +++
llvm/test/CodeGen/RISCV/rvp-srl-bitcast-bv.ll | 6 +-
llvm/test/CodeGen/RISCV/rvp-zip.ll | 205 +++++++++++++++---
4 files changed, 315 insertions(+), 58 deletions(-)
diff --git a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
index fda994a04b00f..dca57ce4ea388 100644
--- a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
+++ b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
@@ -612,7 +612,7 @@ RISCVTargetLowering::RISCVTargetLowering(const TargetMachine &TM,
setCondCodeAction({ISD::SETNE, ISD::SETGT}, VTs, Custom);
if (!Subtarget.is64Bit())
- setOperationAction(ISD::BUILD_VECTOR, MVT::v4i8, Custom);
+ setOperationAction(ISD::BUILD_VECTOR, {MVT::v2i16, MVT::v4i8}, Custom);
// P extension vector comparisons produce all 1s for true, all 0s for false
setBooleanVectorContents(ZeroOrNegativeOneBooleanContent);
@@ -4680,6 +4680,49 @@ static SDValue lowerBuildVectorViaPacking(SDValue Op, SelectionDAG &DAG,
DAG.getBuildVector(WideVecVT, DL, NewOperands));
}
+static SDValue lowerBuildVectorAsRV32PNarrowingShift(SDValue Op,
+ SelectionDAG &DAG) {
+ // Match a legalized single-source deinterleave shuffle:
+ // BUILD_VECTOR extractelt(src, 0), extractelt(src, 2), ...
+ // BUILD_VECTOR extractelt(src, 1), extractelt(src, 3), ...
+ // and lower it to an RV32 P narrowing shift.
+ MVT VT = Op.getSimpleValueType();
+ if (VT != MVT::v4i8 && VT != MVT::v2i16)
+ return SDValue();
+
+ using namespace SDPatternMatch;
+ MVT SrcVT = VT == MVT::v4i8 ? MVT::v8i8 : MVT::v4i16;
+ unsigned EltBits = VT.getVectorElementType().getSizeInBits();
+ SDValue Src;
+ SmallVector<int, 4> ExtractIndices;
+ for (SDValue Lane : Op->op_values()) {
+ if (Lane.isUndef()) {
+ ExtractIndices.push_back(-1);
+ continue;
+ }
+
+ SDValue LaneSrc;
+ int64_t Idx;
+ if (!sd_match(Lane, m_ExtractElt(m_Value(LaneSrc), m_ConstInt(Idx))))
+ return SDValue();
+
+ if (LaneSrc.getSimpleValueType() != SrcVT || (Src && Src != LaneSrc))
+ return SDValue();
+
+ Src = LaneSrc;
+ ExtractIndices.push_back(Idx);
+ }
+
+ unsigned Index = 0;
+ if (!Src ||
+ !ShuffleVectorInst::isDeInterleaveMaskOfFactor(ExtractIndices, 2, Index))
+ return SDValue();
+
+ SDLoc DL(Op);
+ return DAG.getNode(RISCVISD::PNSRL, DL, VT, Src,
+ DAG.getConstant(Index * EltBits, DL, MVT::i32));
+}
+
static SDValue lowerBUILD_VECTOR(SDValue Op, SelectionDAG &DAG,
const RISCVSubtarget &Subtarget) {
MVT VT = Op.getSimpleValueType();
@@ -4691,30 +4734,43 @@ static SDValue lowerBUILD_VECTOR(SDValue Op, SelectionDAG &DAG,
SDLoc DL(Op);
if (Subtarget.isRV32() && Subtarget.hasStdExtP()) {
- if (VT != MVT::v4i8)
- return SDValue();
+ if (SDValue V = lowerBuildVectorAsRV32PNarrowingShift(Op, DAG))
+ return V;
- // <4 x i8> BUILD_VECTOR a, b, c, d -> PACK(PPACK.DH pair(a, c), pair(b, d))
- SDValue Val0 =
- DAG.getNode(ISD::SCALAR_TO_VECTOR, DL, MVT::v4i8, Op->getOperand(0));
- SDValue Val1 =
- DAG.getNode(ISD::SCALAR_TO_VECTOR, DL, MVT::v4i8, Op->getOperand(1));
- SDValue Val2 =
- DAG.getNode(ISD::SCALAR_TO_VECTOR, DL, MVT::v4i8, Op->getOperand(2));
- SDValue Val3 =
- DAG.getNode(ISD::SCALAR_TO_VECTOR, DL, MVT::v4i8, Op->getOperand(3));
- SDValue PPairDB =
- DAG.getNode(RISCVISD::PPAIRE_DB, DL, {MVT::v4i8, MVT::v4i8},
- {Val0, Val2, Val1, Val3});
+ if (VT == MVT::v2i16) {
+ SDValue Lo = DAG.getAnyExtOrTrunc(Op->getOperand(0), DL, MVT::i32);
+ SDValue Hi = DAG.getAnyExtOrTrunc(Op->getOperand(1), DL, MVT::i32);
+ return DAG.getBitcast(
+ MVT::v2i16,
+ SDValue(DAG.getMachineNode(RISCV::PACK, DL, MVT::i32, {Lo, Hi}), 0));
+ }
+
+ if (VT == MVT::v4i8) {
+ // <4 x i8> BUILD_VECTOR a, b, c, d -> PACK(PPACK.DH pair(a, c), pair(b, d))
+ SDValue Val0 =
+ DAG.getNode(ISD::SCALAR_TO_VECTOR, DL, MVT::v4i8, Op->getOperand(0));
+ SDValue Val1 =
+ DAG.getNode(ISD::SCALAR_TO_VECTOR, DL, MVT::v4i8, Op->getOperand(1));
+ SDValue Val2 =
+ DAG.getNode(ISD::SCALAR_TO_VECTOR, DL, MVT::v4i8, Op->getOperand(2));
+ SDValue Val3 =
+ DAG.getNode(ISD::SCALAR_TO_VECTOR, DL, MVT::v4i8, Op->getOperand(3));
+ SDValue PPairDB =
+ DAG.getNode(RISCVISD::PPAIRE_DB, DL, {MVT::v4i8, MVT::v4i8},
+ {Val0, Val2, Val1, Val3});
- return DAG.getNode(
- ISD::BITCAST, DL, MVT::v4i8,
- SDValue(
- DAG.getMachineNode(
- RISCV::PACK, DL, MVT::i32,
- {DAG.getNode(ISD::BITCAST, DL, MVT::i32, PPairDB.getValue(0)),
- DAG.getNode(ISD::BITCAST, DL, MVT::i32, PPairDB.getValue(1))}),
- 0));
+ return DAG.getNode(
+ ISD::BITCAST, DL, MVT::v4i8,
+ SDValue(
+ DAG.getMachineNode(RISCV::PACK, DL, MVT::i32,
+ {DAG.getNode(ISD::BITCAST, DL, MVT::i32,
+ PPairDB.getValue(0)),
+ DAG.getNode(ISD::BITCAST, DL, MVT::i32,
+ PPairDB.getValue(1))}),
+ 0));
+ }
+
+ llvm_unreachable("Unexpected RV32 P BUILD_VECTOR type");
}
// Proper support for f16 requires Zvfh. bf16 always requires special
@@ -6342,6 +6398,28 @@ static SDValue lowerVECTOR_SHUFFLEAsPZip(ShuffleVectorSDNode *SVN,
return SDValue();
}
+// Match a deinterleave shuffle that forms a P-extension packed unzip:
+// <a0, a2, ..., b0, b2, ...> -> unzip*p
+// <a1, a3, ..., b1, b3, ...> -> unzip*hp
+static SDValue lowerVECTOR_SHUFFLEAsPUnzip(ShuffleVectorSDNode *SVN,
+ SelectionDAG &DAG, bool IsRV64) {
+ MVT VT = SVN->getSimpleValueType(0);
+ if (!IsRV64 || (VT != MVT::v8i8 && VT != MVT::v4i16))
+ return SDValue();
+
+ SDValue V1 = SVN->getOperand(0);
+ SDValue V2 = SVN->getOperand(1);
+ SDLoc DL(SVN);
+ ArrayRef<int> Mask = SVN->getMask();
+
+ unsigned Index = 0;
+ if (!ShuffleVectorInst::isDeInterleaveMaskOfFactor(Mask, 2, Index))
+ return SDValue();
+
+ unsigned Opc = Index == 0 ? RISCVISD::PUNZIPE : RISCVISD::PUNZIPO;
+ return DAG.getNode(Opc, DL, VT, V1, V2);
+}
+
SDValue RISCVTargetLowering::lowerVECTOR_SHUFFLE(SDValue Op,
SelectionDAG &DAG) const {
SDValue V1 = Op.getOperand(0);
@@ -6377,6 +6455,8 @@ SDValue RISCVTargetLowering::lowerVECTOR_SHUFFLE(SDValue Op,
return DAG.getBitcast(VT, Srl);
}
+ if (SDValue V = lowerVECTOR_SHUFFLEAsPUnzip(SVN, DAG, Subtarget.is64Bit()))
+ return V;
if (SDValue V = lowerVECTOR_SHUFFLEAsPZip(SVN, DAG))
return V;
return SDValue();
diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfoP.td b/llvm/lib/Target/RISCV/RISCVInstrInfoP.td
index 7fa7c96ca99ca..8facdcbb0e8c6 100644
--- a/llvm/lib/Target/RISCV/RISCVInstrInfoP.td
+++ b/llvm/lib/Target/RISCV/RISCVInstrInfoP.td
@@ -1883,6 +1883,12 @@ def riscv_psrl : RVSDNode<"PSRL", SDT_RISCVPackedShift>;
def riscv_psra : RVSDNode<"PSRA", SDT_RISCVPackedShift>;
def riscv_pssha : RVSDNode<"PSSHA", SDT_RISCVPackedShift>;
+// RV32 packed narrowing shift.
+def SDT_RISCVPackedNarrowingShift
+ : SDTypeProfile<1, 2, [SDTCisVec<0>, SDTCisVec<1>,
+ SDTCisVT<2, XLenVT>]>;
+def riscv_pnsrl : RVSDNode<"PNSRL", SDT_RISCVPackedNarrowingShift>;
+
// The immediate for these is the number of trailing ones in the max value.
def riscv_sati : RVSDNode<"SATI", SDTIntBinOp>;
def riscv_usati : RVSDNode<"USATI", SDTIntBinOp>;
@@ -1914,6 +1920,13 @@ def SDT_RISCVPZip : SDTypeProfile<1, 2, [SDTCisVec<0>,
SDTCisSameAs<0, 2>]>;
def riscv_pzip : RVSDNode<"PZIP", SDT_RISCVPZip>;
+// Deinterleave the even/odd lanes of two packed vectors.
+def SDT_RISCVPUnzip : SDTypeProfile<1, 2, [SDTCisVec<0>,
+ SDTCisSameAs<0, 1>,
+ SDTCisSameAs<0, 2>]>;
+def riscv_punzipe : RVSDNode<"PUNZIPE", SDT_RISCVPUnzip>;
+def riscv_punzipo : RVSDNode<"PUNZIPO", SDT_RISCVPUnzip>;
+
// Add one to the immediate. Used by RISCVISD::SATI.
def IncImm : SDNodeXForm<imm, [{
return CurDAG->getTargetConstant(N->getZExtValue() + 1, SDLoc(N),
@@ -2293,6 +2306,11 @@ let append Predicates = [IsRV32] in {
def : Pat<(v4i8 (trunc (v4i16 GPRPair:$rs))), (PNSRLI_B GPRPair:$rs, 0)>;
def : Pat<(v2i16 (trunc (v2i32 GPRPair:$rs))), (PNSRLI_H GPRPair:$rs, 0)>;
+ def : Pat<(v4i8 (riscv_pnsrl (v8i8 GPRPair:$rs1), uimm4:$imm)),
+ (PNSRLI_B GPRPair:$rs1, uimm4:$imm)>;
+ def : Pat<(v2i16 (riscv_pnsrl (v4i16 GPRPair:$rs1), uimm5:$imm)),
+ (PNSRLI_H GPRPair:$rs1, uimm5:$imm)>;
+
def : Pat<(v4i8 (trunc (v4i16 (riscv_psrl GPRPair:$rs1, uimm4:$imm)))),
(PNSRLI_B GPRPair:$rs1, uimm4:$imm)>;
def : Pat<(v2i16 (trunc (v2i32 (riscv_psrl GPRPair:$rs1, uimm5:$imm)))),
@@ -2765,6 +2783,24 @@ let append Predicates = [IsRV64] in {
def : Pat<(v4i16 (zext_invec (v8i8 GPR:$rs))), (ZIP8P GPR:$rs, (v8i8 X0))>;
def : Pat<(v2i32 (zext_invec (v4i16 GPR:$rs))), (ZIP16P GPR:$rs, (v4i16 X0))>;
+ // Packed unzip.
+ def : Pat<(v8i8 (riscv_punzipe (v8i8 GPR:$rs), (v8i8 undef))),
+ (UNZIP8P GPR:$rs, (v8i8 X0))>;
+ def : Pat<(v8i8 (riscv_punzipo (v8i8 GPR:$rs), (v8i8 undef))),
+ (UNZIP8HP GPR:$rs, (v8i8 X0))>;
+ def : Pat<(v4i16 (riscv_punzipe (v4i16 GPR:$rs), (v4i16 undef))),
+ (UNZIP16P GPR:$rs, (v4i16 X0))>;
+ def : Pat<(v4i16 (riscv_punzipo (v4i16 GPR:$rs), (v4i16 undef))),
+ (UNZIP16HP GPR:$rs, (v4i16 X0))>;
+ def : Pat<(v8i8 (riscv_punzipe (v8i8 GPR:$rs1), (v8i8 GPR:$rs2))),
+ (UNZIP8P GPR:$rs1, GPR:$rs2)>;
+ def : Pat<(v8i8 (riscv_punzipo (v8i8 GPR:$rs1), (v8i8 GPR:$rs2))),
+ (UNZIP8HP GPR:$rs1, GPR:$rs2)>;
+ def : Pat<(v4i16 (riscv_punzipe (v4i16 GPR:$rs1), (v4i16 GPR:$rs2))),
+ (UNZIP16P GPR:$rs1, GPR:$rs2)>;
+ def : Pat<(v4i16 (riscv_punzipo (v4i16 GPR:$rs1), (v4i16 GPR:$rs2))),
+ (UNZIP16HP GPR:$rs1, GPR:$rs2)>;
+
// Packed zip.
def : Pat<(v8i8 (riscv_pzip (v8i8 GPR:$rs1), (v8i8 GPR:$rs2))),
(ZIP8P GPR:$rs1, GPR:$rs2)>;
diff --git a/llvm/test/CodeGen/RISCV/rvp-srl-bitcast-bv.ll b/llvm/test/CodeGen/RISCV/rvp-srl-bitcast-bv.ll
index 0a9b3ff7c5505..4692dbb7fdc1b 100644
--- a/llvm/test/CodeGen/RISCV/rvp-srl-bitcast-bv.ll
+++ b/llvm/test/CodeGen/RISCV/rvp-srl-bitcast-bv.ll
@@ -11,9 +11,9 @@ define i16 @srl_bitcast_buildvector_extract_last(<2 x i16> %v, ptr %p) {
; CHECK-RV32-NEXT: srai a3, a0, 16
; CHECK-RV32-NEXT: div a3, a2, a3
; CHECK-RV32-NEXT: sext.h a0, a0
-; CHECK-RV32-NEXT: div a2, a2, a0
-; CHECK-RV32-NEXT: zext.h a0, a3
-; CHECK-RV32-NEXT: pack a2, a2, a3
+; CHECK-RV32-NEXT: div a0, a2, a0
+; CHECK-RV32-NEXT: pack a2, a0, a3
+; CHECK-RV32-NEXT: srli a0, a2, 16
; CHECK-RV32-NEXT: sw a2, 0(a1)
; CHECK-RV32-NEXT: ret
;
diff --git a/llvm/test/CodeGen/RISCV/rvp-zip.ll b/llvm/test/CodeGen/RISCV/rvp-zip.ll
index 2f146afc23427..766db01267521 100644
--- a/llvm/test/CodeGen/RISCV/rvp-zip.ll
+++ b/llvm/test/CodeGen/RISCV/rvp-zip.ll
@@ -37,20 +37,12 @@ define <4 x i16> @test_pzip_v4i16(<2 x i16> %a, <2 x i16> %b) {
define <4 x i8> @test_punzipe_v4i8(<8 x i8> %a) {
; RV32-LABEL: test_punzipe_v4i8:
; RV32: # %bb.0:
-; RV32-NEXT: srli a3, a1, 16
-; RV32-NEXT: srli a2, a0, 16
-; RV32-NEXT: ppaire.db a0, a0, a2
-; RV32-NEXT: pack a0, a0, a1
+; RV32-NEXT: pncvt.b a0, a0
; RV32-NEXT: ret
;
; RV64-LABEL: test_punzipe_v4i8:
; RV64: # %bb.0:
-; RV64-NEXT: srli a1, a0, 48
-; RV64-NEXT: srli a2, a0, 32
-; RV64-NEXT: srli a3, a0, 16
-; RV64-NEXT: ppaire.b a1, a2, a1
-; RV64-NEXT: ppaire.b a0, a0, a3
-; RV64-NEXT: ppaire.h a0, a0, a1
+; RV64-NEXT: pncvt.wb a0, a0
; RV64-NEXT: ret
%r = shufflevector <8 x i8> %a, <8 x i8> poison, <4 x i32> <i32 0, i32 2, i32 4, i32 6>
ret <4 x i8> %r
@@ -59,23 +51,12 @@ define <4 x i8> @test_punzipe_v4i8(<8 x i8> %a) {
define <4 x i8> @test_punzipo_v4i8(<8 x i8> %a) {
; RV32-LABEL: test_punzipo_v4i8:
; RV32: # %bb.0:
-; RV32-NEXT: srli a3, a1, 24
-; RV32-NEXT: srli a1, a1, 8
-; RV32-NEXT: srli a2, a0, 24
-; RV32-NEXT: srli a0, a0, 8
-; RV32-NEXT: ppaire.db a0, a0, a2
-; RV32-NEXT: pack a0, a0, a1
+; RV32-NEXT: pncvth.b a0, a0
; RV32-NEXT: ret
;
; RV64-LABEL: test_punzipo_v4i8:
; RV64: # %bb.0:
-; RV64-NEXT: srli a1, a0, 56
-; RV64-NEXT: srli a2, a0, 40
-; RV64-NEXT: srli a3, a0, 24
-; RV64-NEXT: srli a0, a0, 8
-; RV64-NEXT: ppaire.b a1, a2, a1
-; RV64-NEXT: ppaire.b a0, a0, a3
-; RV64-NEXT: ppaire.h a0, a0, a1
+; RV64-NEXT: pncvth.wb a0, a0
; RV64-NEXT: ret
%r = shufflevector <8 x i8> %a, <8 x i8> poison, <4 x i32> <i32 1, i32 3, i32 5, i32 7>
ret <4 x i8> %r
@@ -84,13 +65,12 @@ define <4 x i8> @test_punzipo_v4i8(<8 x i8> %a) {
define <2 x i16> @test_punzipe_v2i16(<4 x i16> %a) {
; RV32-LABEL: test_punzipe_v2i16:
; RV32: # %bb.0:
-; RV32-NEXT: pack a0, a0, a1
+; RV32-NEXT: pncvt.h a0, a0
; RV32-NEXT: ret
;
; RV64-LABEL: test_punzipe_v2i16:
; RV64: # %bb.0:
-; RV64-NEXT: srli a1, a0, 32
-; RV64-NEXT: ppaire.h a0, a0, a1
+; RV64-NEXT: pncvt.wh a0, a0
; RV64-NEXT: ret
%r = shufflevector <4 x i16> %a, <4 x i16> poison, <2 x i32> <i32 0, i32 2>
ret <2 x i16> %r
@@ -99,19 +79,180 @@ define <2 x i16> @test_punzipe_v2i16(<4 x i16> %a) {
define <2 x i16> @test_punzipo_v2i16(<4 x i16> %a) {
; RV32-LABEL: test_punzipo_v2i16:
; RV32: # %bb.0:
-; RV32-NEXT: srli a1, a1, 16
-; RV32-NEXT: srli a0, a0, 16
-; RV32-NEXT: pack a0, a0, a1
+; RV32-NEXT: pncvth.h a0, a0
; RV32-NEXT: ret
;
; RV64-LABEL: test_punzipo_v2i16:
; RV64: # %bb.0:
-; RV64-NEXT: srli a1, a0, 48
-; RV64-NEXT: srli a0, a0, 16
-; RV64-NEXT: ppaire.h a0, a0, a1
+; RV64-NEXT: pncvth.wh a0, a0
; RV64-NEXT: ret
%r = shufflevector <4 x i16> %a, <4 x i16> poison, <2 x i32> <i32 1, i32 3>
ret <2 x i16> %r
}
+
+define <8 x i8> @test_unzip8p_v8i8(<8 x i8> %a, <8 x i8> %b) {
+; RV32-LABEL: test_unzip8p_v8i8:
+; RV32: # %bb.0:
+; RV32-NEXT: srli a4, a3, 16
+; RV32-NEXT: srli a5, a2, 16
+; RV32-NEXT: ppaire.b a3, a3, a4
+; RV32-NEXT: ppaire.b a2, a2, a5
+; RV32-NEXT: srli a4, a1, 16
+; RV32-NEXT: srli a5, a0, 16
+; RV32-NEXT: ppaire.b a4, a1, a4
+; RV32-NEXT: ppaire.b a0, a0, a5
+; RV32-NEXT: pack a1, a2, a3
+; RV32-NEXT: pack a0, a0, a4
+; RV32-NEXT: ret
+;
+; RV64-LABEL: test_unzip8p_v8i8:
+; RV64: # %bb.0:
+; RV64-NEXT: unzip8p a0, a0, a1
+; RV64-NEXT: ret
+ %r = shufflevector <8 x i8> %a, <8 x i8> %b, <8 x i32> <i32 0, i32 2, i32 4, i32 6, i32 8, i32 10, i32 12, i32 14>
+ ret <8 x i8> %r
+}
+
+define <8 x i8> @test_unzip8hp_v8i8(<8 x i8> %a, <8 x i8> %b) {
+; RV32-LABEL: test_unzip8hp_v8i8:
+; RV32: # %bb.0:
+; RV32-NEXT: srli a4, a3, 24
+; RV32-NEXT: srli a3, a3, 8
+; RV32-NEXT: srli a5, a2, 24
+; RV32-NEXT: srli a2, a2, 8
+; RV32-NEXT: ppaire.b a3, a3, a4
+; RV32-NEXT: ppaire.b a2, a2, a5
+; RV32-NEXT: srli a4, a1, 24
+; RV32-NEXT: srli a1, a1, 8
+; RV32-NEXT: srli a5, a0, 24
+; RV32-NEXT: srli a0, a0, 8
+; RV32-NEXT: ppaire.b a4, a1, a4
+; RV32-NEXT: ppaire.b a0, a0, a5
+; RV32-NEXT: pack a1, a2, a3
+; RV32-NEXT: pack a0, a0, a4
+; RV32-NEXT: ret
+;
+; RV64-LABEL: test_unzip8hp_v8i8:
+; RV64: # %bb.0:
+; RV64-NEXT: unzip8hp a0, a0, a1
+; RV64-NEXT: ret
+ %r = shufflevector <8 x i8> %a, <8 x i8> %b, <8 x i32> <i32 1, i32 3, i32 5, i32 7, i32 9, i32 11, i32 13, i32 15>
+ ret <8 x i8> %r
+}
+
+define <4 x i16> @test_unzip16p_v4i16(<4 x i16> %a, <4 x i16> %b) {
+; RV32-LABEL: test_unzip16p_v4i16:
+; RV32: # %bb.0:
+; RV32-NEXT: pack a2, a2, a3
+; RV32-NEXT: pack a0, a0, a1
+; RV32-NEXT: mv a1, a2
+; RV32-NEXT: ret
+;
+; RV64-LABEL: test_unzip16p_v4i16:
+; RV64: # %bb.0:
+; RV64-NEXT: unzip16p a0, a0, a1
+; RV64-NEXT: ret
+ %r = shufflevector <4 x i16> %a, <4 x i16> %b, <4 x i32> <i32 0, i32 2, i32 4, i32 6>
+ ret <4 x i16> %r
+}
+
+define <4 x i16> @test_unzip16hp_v4i16(<4 x i16> %a, <4 x i16> %b) {
+; RV32-LABEL: test_unzip16hp_v4i16:
+; RV32: # %bb.0:
+; RV32-NEXT: srli a3, a3, 16
+; RV32-NEXT: srli a2, a2, 16
+; RV32-NEXT: srli a4, a1, 16
+; RV32-NEXT: srli a0, a0, 16
+; RV32-NEXT: pack a1, a2, a3
+; RV32-NEXT: pack a0, a0, a4
+; RV32-NEXT: ret
+;
+; RV64-LABEL: test_unzip16hp_v4i16:
+; RV64: # %bb.0:
+; RV64-NEXT: unzip16hp a0, a0, a1
+; RV64-NEXT: ret
+ %r = shufflevector <4 x i16> %a, <4 x i16> %b, <4 x i32> <i32 1, i32 3, i32 5, i32 7>
+ ret <4 x i16> %r
+}
+
+define <8 x i8> @test_unzip8p_v8i8_partial_poison(<8 x i8> %a, <8 x i8> %b) {
+; RV32-LABEL: test_unzip8p_v8i8_partial_poison:
+; RV32: # %bb.0:
+; RV32-NEXT: srli a4, a2, 16
+; RV32-NEXT: ppaire.b a2, a2, a4
+; RV32-NEXT: srli a3, a3, 16
+; RV32-NEXT: ppaire.b a3, a0, a3
+; RV32-NEXT: srli a4, a1, 16
+; RV32-NEXT: ppaire.b a4, a1, a4
+; RV32-NEXT: ppaire.b a0, a0, a0
+; RV32-NEXT: pack a1, a2, a3
+; RV32-NEXT: pack a0, a0, a4
+; RV32-NEXT: ret
+;
+; RV64-LABEL: test_unzip8p_v8i8_partial_poison:
+; RV64: # %bb.0:
+; RV64-NEXT: unzip8p a0, a0, a1
+; RV64-NEXT: ret
+ %r = shufflevector <8 x i8> %a, <8 x i8> %b, <8 x i32> <i32 0, i32 poison, i32 4, i32 6, i32 8, i32 10, i32 poison, i32 14>
+ ret <8 x i8> %r
+}
+
+define <8 x i8> @test_unzip8hp_v8i8_partial_poison(<8 x i8> %a, <8 x i8> %b) {
+; RV32-LABEL: test_unzip8hp_v8i8_partial_poison:
+; RV32: # %bb.0:
+; RV32-NEXT: srli a4, a2, 24
+; RV32-NEXT: srli a2, a2, 8
+; RV32-NEXT: ppaire.b a2, a2, a4
+; RV32-NEXT: srli a3, a3, 8
+; RV32-NEXT: ppaire.b a3, a3, a0
+; RV32-NEXT: srli a4, a0, 24
+; RV32-NEXT: srli a0, a0, 8
+; RV32-NEXT: srli a1, a1, 24
+; RV32-NEXT: ppaire.b a0, a0, a4
+; RV32-NEXT: ppaire.b a4, a0, a1
+; RV32-NEXT: pack a1, a2, a3
+; RV32-NEXT: pack a0, a0, a4
+; RV32-NEXT: ret
+;
+; RV64-LABEL: test_unzip8hp_v8i8_partial_poison:
+; RV64: # %bb.0:
+; RV64-NEXT: unzip8hp a0, a0, a1
+; RV64-NEXT: ret
+ %r = shufflevector <8 x i8> %a, <8 x i8> %b, <8 x i32> <i32 1, i32 3, i32 poison, i32 7, i32 9, i32 11, i32 13, i32 poison>
+ ret <8 x i8> %r
+}
+
+define <4 x i16> @test_unzip16p_v4i16_partial_poison(<4 x i16> %a, <4 x i16> %b) {
+; RV32-LABEL: test_unzip16p_v4i16_partial_poison:
+; RV32: # %bb.0:
+; RV32-NEXT: pack a1, a2, a3
+; RV32-NEXT: pack a0, a0, a0
+; RV32-NEXT: ret
+;
+; RV64-LABEL: test_unzip16p_v4i16_partial_poison:
+; RV64: # %bb.0:
+; RV64-NEXT: unzip16p a0, a0, a1
+; RV64-NEXT: ret
+ %r = shufflevector <4 x i16> %a, <4 x i16> %b, <4 x i32> <i32 0, i32 poison, i32 4, i32 6>
+ ret <4 x i16> %r
+}
+
+define <4 x i16> @test_unzip16hp_v4i16_partial_poison(<4 x i16> %a, <4 x i16> %b) {
+; RV32-LABEL: test_unzip16hp_v4i16_partial_poison:
+; RV32: # %bb.0:
+; RV32-NEXT: srli a1, a1, 16
+; RV32-NEXT: srli a0, a0, 16
+; RV32-NEXT: srli a3, a3, 16
+; RV32-NEXT: pack a0, a0, a1
+; RV32-NEXT: pack a1, a0, a3
+; RV32-NEXT: ret
+;
+; RV64-LABEL: test_unzip16hp_v4i16_partial_poison:
+; RV64: # %bb.0:
+; RV64-NEXT: unzip16hp a0, a0, a1
+; RV64-NEXT: ret
+ %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
+}
;; NOTE: These prefixes are unused and the list is autogenerated. Do not add tests below this line:
; CHECK: {{.*}}
>From 6880a68a11a2561b3649c69835661d930668d2af Mon Sep 17 00:00:00 2001
From: XChy <xxs_chy at outlook.com>
Date: Sat, 11 Jul 2026 00:25:41 +0800
Subject: [PATCH 2/2] format
---
llvm/lib/Target/RISCV/RISCVISelLowering.cpp | 16 ++++++++--------
1 file changed, 8 insertions(+), 8 deletions(-)
diff --git a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
index dca57ce4ea388..d3561183c8e1c 100644
--- a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
+++ b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
@@ -4746,7 +4746,8 @@ static SDValue lowerBUILD_VECTOR(SDValue Op, SelectionDAG &DAG,
}
if (VT == MVT::v4i8) {
- // <4 x i8> BUILD_VECTOR a, b, c, d -> PACK(PPACK.DH pair(a, c), pair(b, d))
+ // <4 x i8> BUILD_VECTOR a, b, c, d -> PACK(PPACK.DH pair(a, c), pair(b,
+ // d))
SDValue Val0 =
DAG.getNode(ISD::SCALAR_TO_VECTOR, DL, MVT::v4i8, Op->getOperand(0));
SDValue Val1 =
@@ -4761,13 +4762,12 @@ static SDValue lowerBUILD_VECTOR(SDValue Op, SelectionDAG &DAG,
return DAG.getNode(
ISD::BITCAST, DL, MVT::v4i8,
- SDValue(
- DAG.getMachineNode(RISCV::PACK, DL, MVT::i32,
- {DAG.getNode(ISD::BITCAST, DL, MVT::i32,
- PPairDB.getValue(0)),
- DAG.getNode(ISD::BITCAST, DL, MVT::i32,
- PPairDB.getValue(1))}),
- 0));
+ SDValue(DAG.getMachineNode(RISCV::PACK, DL, MVT::i32,
+ {DAG.getNode(ISD::BITCAST, DL, MVT::i32,
+ PPairDB.getValue(0)),
+ DAG.getNode(ISD::BITCAST, DL, MVT::i32,
+ PPairDB.getValue(1))}),
+ 0));
}
llvm_unreachable("Unexpected RV32 P BUILD_VECTOR type");
More information about the llvm-commits
mailing list