[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 21:56:15 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/6] [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/6] 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");

>From 5173782d23d6b89328347b119d832cbd3b6a7436 Mon Sep 17 00:00:00 2001
From: XChy <xxs_chy at outlook.com>
Date: Sat, 11 Jul 2026 01:12:27 +0800
Subject: [PATCH 3/6] resolve comments

---
 llvm/lib/Target/RISCV/RISCVISelLowering.cpp | 14 ++++++--------
 llvm/lib/Target/RISCV/RISCVInstrInfoP.td    | 19 +++++++------------
 2 files changed, 13 insertions(+), 20 deletions(-)

diff --git a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
index d3561183c8e1c..354b3d7d7c196 100644
--- a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
+++ b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
@@ -4741,8 +4741,7 @@ static SDValue lowerBUILD_VECTOR(SDValue Op, SelectionDAG &DAG,
       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));
+          MVT::v2i16, DAG.getNode(RISCVISD::PACK, DL, MVT::i32, Lo, Hi));
     }
 
     if (VT == MVT::v4i8) {
@@ -4762,12 +4761,11 @@ 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));
+          DAG.getNode(RISCVISD::PACK, DL, MVT::i32,
+                      DAG.getNode(ISD::BITCAST, DL, MVT::i32,
+                                  PPairDB.getValue(0)),
+                      DAG.getNode(ISD::BITCAST, DL, MVT::i32,
+                                  PPairDB.getValue(1))));
     }
 
     llvm_unreachable("Unexpected RV32 P BUILD_VECTOR type");
diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfoP.td b/llvm/lib/Target/RISCV/RISCVInstrInfoP.td
index 8facdcbb0e8c6..c63c6a344cd70 100644
--- a/llvm/lib/Target/RISCV/RISCVInstrInfoP.td
+++ b/llvm/lib/Target/RISCV/RISCVInstrInfoP.td
@@ -1866,6 +1866,11 @@ def shiftMask16 : ComplexPattern<XLenVT, 1, "selectShiftMask<16>", [], [], 0>;
 def BuildGPRPair : OutPatFrag<(ops node:$lo, node:$hi),
   (REG_SEQUENCE GPRPair, $lo, sub_gpr_even, $hi, sub_gpr_odd)>;
 
+def SDT_RISCVPack : SDTypeProfile<1, 2, [SDTCisVT<0, XLenVT>,
+                                          SDTCisSameAs<0, 1>,
+                                          SDTCisSameAs<0, 2>]>;
+def riscv_pack : RVSDNode<"PACK", SDT_RISCVPack>;
+
 // Averaging subtraction, (a - b) >> 2
 def riscv_asub : RVSDNode<"ASUB", SDTIntBinOp>;
 def riscv_asubu : RVSDNode<"ASUBU", SDTIntBinOp>;
@@ -2232,6 +2237,8 @@ let append Predicates = [IsRV32] in {
   def : Pat<(riscv_nsra GPR:$lo, GPR:$hi, shiftMask64:$shamt),
             (NSRA (BuildGPRPair GPR:$lo, GPR:$hi), shiftMask64:$shamt)>;
 
+  def : Pat<(riscv_pack GPR:$lo, GPR:$hi), (PACK GPR:$lo, GPR:$hi)>;
+
   // Match a pattern of 2 bytes being inserted into bits [31:16], with bits
   // bits [15:0] coming from a zero extended value. We can use pack with
   // ppaire.b for bits [31:16]. If bits [15:0] can also be a ppaire.b, it can be
@@ -2297,10 +2304,6 @@ let append Predicates = [IsRV32] in {
   def : Pat<(v4i16 (sext (v4i8 GPR:$rs))), (PWADD_B GPR:$rs, (v4i8 X0))>;
   def : Pat<(v2i32 (sext (v2i16 GPR:$rs))), (PWADD_H GPR:$rs, (v2i16 X0))>;
 
-  // Build vector patterns
-  def : Pat<(v2i16 (build_vector (XLenVT GPR:$a), (XLenVT GPR:$b))),
-            (PACK GPR:$a, GPR:$b)>;
-
   // Truncate patterns using pnsrli.
   // FIXME: Support general shift+trunc
   def : Pat<(v4i8 (trunc (v4i16 GPRPair:$rs))), (PNSRLI_B GPRPair:$rs, 0)>;
@@ -2784,14 +2787,6 @@ let append Predicates = [IsRV64] in {
   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))),

>From 229b69dc5076a6278171d9b915b03d044f3c6596 Mon Sep 17 00:00:00 2001
From: XChy <xxs_chy at outlook.com>
Date: Sat, 11 Jul 2026 02:21:35 +0800
Subject: [PATCH 4/6] use RISCVISD::PAIRE instead of RISCVISD::PACK

---
 llvm/lib/Target/RISCV/RISCVISelLowering.cpp |  4 ++--
 llvm/lib/Target/RISCV/RISCVInstrInfoP.td    | 10 +++++-----
 2 files changed, 7 insertions(+), 7 deletions(-)

diff --git a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
index 354b3d7d7c196..70221884d9a8a 100644
--- a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
+++ b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
@@ -4741,7 +4741,7 @@ static SDValue lowerBUILD_VECTOR(SDValue Op, SelectionDAG &DAG,
       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, DAG.getNode(RISCVISD::PACK, DL, MVT::i32, Lo, Hi));
+          MVT::v2i16, DAG.getNode(RISCVISD::PAIRE, DL, MVT::i32, Lo, Hi));
     }
 
     if (VT == MVT::v4i8) {
@@ -4761,7 +4761,7 @@ static SDValue lowerBUILD_VECTOR(SDValue Op, SelectionDAG &DAG,
 
       return DAG.getNode(
           ISD::BITCAST, DL, MVT::v4i8,
-          DAG.getNode(RISCVISD::PACK, DL, MVT::i32,
+          DAG.getNode(RISCVISD::PAIRE, DL, MVT::i32,
                       DAG.getNode(ISD::BITCAST, DL, MVT::i32,
                                   PPairDB.getValue(0)),
                       DAG.getNode(ISD::BITCAST, DL, MVT::i32,
diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfoP.td b/llvm/lib/Target/RISCV/RISCVInstrInfoP.td
index c63c6a344cd70..b25fc746dfdba 100644
--- a/llvm/lib/Target/RISCV/RISCVInstrInfoP.td
+++ b/llvm/lib/Target/RISCV/RISCVInstrInfoP.td
@@ -1866,10 +1866,10 @@ def shiftMask16 : ComplexPattern<XLenVT, 1, "selectShiftMask<16>", [], [], 0>;
 def BuildGPRPair : OutPatFrag<(ops node:$lo, node:$hi),
   (REG_SEQUENCE GPRPair, $lo, sub_gpr_even, $hi, sub_gpr_odd)>;
 
-def SDT_RISCVPack : SDTypeProfile<1, 2, [SDTCisVT<0, XLenVT>,
-                                          SDTCisSameAs<0, 1>,
-                                          SDTCisSameAs<0, 2>]>;
-def riscv_pack : RVSDNode<"PACK", SDT_RISCVPack>;
+def SDT_RISCVPairEven : SDTypeProfile<1, 2, [SDTCisVT<0, XLenVT>,
+                                              SDTCisSameAs<0, 1>,
+                                              SDTCisSameAs<0, 2>]>;
+def riscv_paire : RVSDNode<"PAIRE", SDT_RISCVPairEven>;
 
 // Averaging subtraction, (a - b) >> 2
 def riscv_asub : RVSDNode<"ASUB", SDTIntBinOp>;
@@ -2237,7 +2237,7 @@ let append Predicates = [IsRV32] in {
   def : Pat<(riscv_nsra GPR:$lo, GPR:$hi, shiftMask64:$shamt),
             (NSRA (BuildGPRPair GPR:$lo, GPR:$hi), shiftMask64:$shamt)>;
 
-  def : Pat<(riscv_pack GPR:$lo, GPR:$hi), (PACK GPR:$lo, GPR:$hi)>;
+  def : Pat<(riscv_paire GPR:$lo, GPR:$hi), (PACK GPR:$lo, GPR:$hi)>;
 
   // Match a pattern of 2 bytes being inserted into bits [31:16], with bits
   // bits [15:0] coming from a zero extended value. We can use pack with

>From bf8c5b7ddaf7aa1d2b8aa578b2f234ca025be5d1 Mon Sep 17 00:00:00 2001
From: XChy <xxs_chy at outlook.com>
Date: Sat, 11 Jul 2026 02:42:44 +0800
Subject: [PATCH 5/6] add type constraint

---
 llvm/lib/Target/RISCV/RISCVInstrInfoP.td | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfoP.td b/llvm/lib/Target/RISCV/RISCVInstrInfoP.td
index b25fc746dfdba..f8aded51aadd9 100644
--- a/llvm/lib/Target/RISCV/RISCVInstrInfoP.td
+++ b/llvm/lib/Target/RISCV/RISCVInstrInfoP.td
@@ -2237,7 +2237,8 @@ let append Predicates = [IsRV32] in {
   def : Pat<(riscv_nsra GPR:$lo, GPR:$hi, shiftMask64:$shamt),
             (NSRA (BuildGPRPair GPR:$lo, GPR:$hi), shiftMask64:$shamt)>;
 
-  def : Pat<(riscv_paire GPR:$lo, GPR:$hi), (PACK GPR:$lo, GPR:$hi)>;
+  def : Pat<(XLenVT (riscv_paire GPR:$lo, GPR:$hi)),
+          (PACK GPR:$lo, GPR:$hi)>;
 
   // Match a pattern of 2 bytes being inserted into bits [31:16], with bits
   // bits [15:0] coming from a zero extended value. We can use pack with

>From 13ef29dd75486fc9f97a6f176fa9df50a47dcfbc Mon Sep 17 00:00:00 2001
From: XChy <xxs_chy at outlook.com>
Date: Sat, 11 Jul 2026 12:55:54 +0800
Subject: [PATCH 6/6] resolve comments

---
 llvm/lib/Target/RISCV/RISCVISelLowering.cpp | 23 +++++++++++----------
 llvm/lib/Target/RISCV/RISCVInstrInfoP.td    | 10 ++++-----
 2 files changed, 17 insertions(+), 16 deletions(-)

diff --git a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
index 70221884d9a8a..7e6e680699438 100644
--- a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
+++ b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
@@ -4738,10 +4738,13 @@ static SDValue lowerBUILD_VECTOR(SDValue Op, SelectionDAG &DAG,
       return V;
 
     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, DAG.getNode(RISCVISD::PAIRE, DL, MVT::i32, Lo, Hi));
+      SDValue Lo = DAG.getBitcast(
+          MVT::v2i16,
+          DAG.getAnyExtOrTrunc(Op->getOperand(0), DL, MVT::i32));
+      SDValue Hi = DAG.getBitcast(
+          MVT::v2i16,
+          DAG.getAnyExtOrTrunc(Op->getOperand(1), DL, MVT::i32));
+      return DAG.getNode(RISCVISD::PAIRE, DL, MVT::v2i16, Lo, Hi);
     }
 
     if (VT == MVT::v4i8) {
@@ -4759,13 +4762,11 @@ static SDValue lowerBUILD_VECTOR(SDValue Op, SelectionDAG &DAG,
           DAG.getNode(RISCVISD::PPAIRE_DB, DL, {MVT::v4i8, MVT::v4i8},
                       {Val0, Val2, Val1, Val3});
 
-      return DAG.getNode(
-          ISD::BITCAST, DL, MVT::v4i8,
-          DAG.getNode(RISCVISD::PAIRE, DL, MVT::i32,
-                      DAG.getNode(ISD::BITCAST, DL, MVT::i32,
-                                  PPairDB.getValue(0)),
-                      DAG.getNode(ISD::BITCAST, DL, MVT::i32,
-                                  PPairDB.getValue(1))));
+      return DAG.getBitcast(
+          MVT::v4i8,
+          DAG.getNode(RISCVISD::PAIRE, DL, MVT::v2i16,
+                      DAG.getBitcast(MVT::v2i16, PPairDB.getValue(0)),
+                      DAG.getBitcast(MVT::v2i16, PPairDB.getValue(1))));
     }
 
     llvm_unreachable("Unexpected RV32 P BUILD_VECTOR type");
diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfoP.td b/llvm/lib/Target/RISCV/RISCVInstrInfoP.td
index f8aded51aadd9..5f5b871422a85 100644
--- a/llvm/lib/Target/RISCV/RISCVInstrInfoP.td
+++ b/llvm/lib/Target/RISCV/RISCVInstrInfoP.td
@@ -1866,9 +1866,9 @@ def shiftMask16 : ComplexPattern<XLenVT, 1, "selectShiftMask<16>", [], [], 0>;
 def BuildGPRPair : OutPatFrag<(ops node:$lo, node:$hi),
   (REG_SEQUENCE GPRPair, $lo, sub_gpr_even, $hi, sub_gpr_odd)>;
 
-def SDT_RISCVPairEven : SDTypeProfile<1, 2, [SDTCisVT<0, XLenVT>,
-                                              SDTCisSameAs<0, 1>,
-                                              SDTCisSameAs<0, 2>]>;
+def SDT_RISCVPairEven : SDTypeProfile<1, 2, [SDTCisVec<0>,
+                                             SDTCisSameAs<0, 1>,
+                                             SDTCisSameAs<0, 2>]>;
 def riscv_paire : RVSDNode<"PAIRE", SDT_RISCVPairEven>;
 
 // Averaging subtraction, (a - b) >> 2
@@ -2237,8 +2237,8 @@ let append Predicates = [IsRV32] in {
   def : Pat<(riscv_nsra GPR:$lo, GPR:$hi, shiftMask64:$shamt),
             (NSRA (BuildGPRPair GPR:$lo, GPR:$hi), shiftMask64:$shamt)>;
 
-  def : Pat<(XLenVT (riscv_paire GPR:$lo, GPR:$hi)),
-          (PACK GPR:$lo, GPR:$hi)>;
+  def : Pat<(v2i16 (riscv_paire (v2i16 GPR:$lo), (v2i16 GPR:$hi))),
+            (PACK GPR:$lo, GPR:$hi)>;
 
   // Match a pattern of 2 bytes being inserted into bits [31:16], with bits
   // bits [15:0] coming from a zero extended value. We can use pack with



More information about the llvm-commits mailing list