[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