[llvm] 8c22bbd - [RISCV][P-ext] Replace lowerBuildVectorAsRV32PNarrowingShift with shuffle lowering. (#209088)

via llvm-commits llvm-commits at lists.llvm.org
Thu Jul 16 08:04:51 PDT 2026


Author: Craig Topper
Date: 2026-07-16T08:04:47-07:00
New Revision: 8c22bbde747ce8c577318c3fb6cafaae6f1b8aec

URL: https://github.com/llvm/llvm-project/commit/8c22bbde747ce8c577318c3fb6cafaae6f1b8aec
DIFF: https://github.com/llvm/llvm-project/commit/8c22bbde747ce8c577318c3fb6cafaae6f1b8aec.diff

LOG: [RISCV][P-ext] Replace lowerBuildVectorAsRV32PNarrowingShift with shuffle lowering. (#209088)

Add an implementation of isExtractSubvectorCheap for extracting
v2i16/v4i8 from a v4i16/v8i8 vector on RV32. This allows the
build_vector+extract_elt pattern to be turned into
shuffle_vector+extract_subvectors.

Assisted-by: Claude

Added: 
    

Modified: 
    llvm/lib/Target/RISCV/RISCVISelLowering.cpp

Removed: 
    


################################################################################
diff  --git a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
index 2df58fc2ca9f0..0063b429f516e 100644
--- a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
+++ b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
@@ -2849,6 +2849,10 @@ bool RISCVTargetLowering::isFPImmLegal(const APFloat &Imm, EVT VT,
 // TODO: This is very conservative.
 bool RISCVTargetLowering::isExtractSubvectorCheap(EVT ResVT, EVT SrcVT,
                                                   unsigned Index) const {
+  if (Subtarget.hasStdExtP() && !Subtarget.is64Bit() &&
+      (ResVT == MVT::v4i8 || ResVT == MVT::v2i16))
+    return (Index % ResVT.getVectorNumElements()) == 0;
+
   if (!Subtarget.hasVInstructions())
     return false;
 
@@ -4740,49 +4744,6 @@ 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();
@@ -4794,9 +4755,6 @@ static SDValue lowerBUILD_VECTOR(SDValue Op, SelectionDAG &DAG,
   SDLoc DL(Op);
 
   if (Subtarget.isRV32() && Subtarget.hasStdExtP()) {
-    if (SDValue V = lowerBuildVectorAsRV32PNarrowingShift(Op, DAG))
-      return V;
-
     if (VT == MVT::v2i16) {
       SDValue Lo = DAG.getBitcast(
           MVT::v2i16,
@@ -6484,6 +6442,61 @@ 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.
+static SDValue
+lowerVECTOR_SHUFFLEAsRV32PNarrowingShift(ShuffleVectorSDNode *SVN,
+                                         const RISCVSubtarget &Subtarget,
+                                         SelectionDAG &DAG) {
+  MVT VT = SVN->getSimpleValueType(0);
+  if (Subtarget.is64Bit() || (VT != MVT::v4i8 && VT != MVT::v2i16))
+    return SDValue();
+
+  SDValue V1 = SVN->getOperand(0);
+  SDValue V2 = SVN->getOperand(1);
+
+  // 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();
+
+  // 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 
diff erent 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))
+    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));
+}
+
 SDValue RISCVTargetLowering::lowerVECTOR_SHUFFLE(SDValue Op,
                                                  SelectionDAG &DAG) const {
   SDValue V1 = Op.getOperand(0);
@@ -6572,6 +6585,9 @@ SDValue RISCVTargetLowering::lowerVECTOR_SHUFFLE(SDValue Op,
       return V;
     if (SDValue V = lowerVECTOR_SHUFFLEAsPZip(SVN, DAG))
       return V;
+    if (SDValue V =
+            lowerVECTOR_SHUFFLEAsRV32PNarrowingShift(SVN, Subtarget, DAG))
+      return V;
     return SDValue();
   }
 


        


More information about the llvm-commits mailing list