[llvm] [RISCV] Lower disjoint shuffle of shuffles to MERGE-GATHER sequence (PR #178095)
Luke Lau via llvm-commits
llvm-commits at lists.llvm.org
Thu Jan 29 02:42:50 PST 2026
================
@@ -5439,6 +5439,113 @@ static SDValue lowerVECTOR_SHUFFLEAsVSlideup(const SDLoc &DL, MVT VT,
return convertFromScalableVector(VT, Res, DAG, Subtarget);
}
+// A shuffle of shuffles where:
+// - the first level of shuffles both only used data from a single input
+// - the final output doesn't use data from the same lane of both operands
+// This can be lowered to a MERGE followed by a GATHER
+static SDValue lowerVECTOR_SHUFFLEAsMergeGather(const SDLoc &DL, MVT VT,
+ SDValue V1, SDValue V2,
+ ArrayRef<int> Mask,
+ const RISCVSubtarget &Subtarget,
+ SelectionDAG &DAG) {
+ if (V1.getOpcode() != ISD::VECTOR_SHUFFLE ||
+ V2.getOpcode() != ISD::VECTOR_SHUFFLE)
+ return SDValue();
+
+ if (!V1.hasOneUse() || !V2.hasOneUse())
+ return SDValue();
+
+ // Can just be reduced into a single gather operation
+ if (V1.getOperand(0) == V2.getOperand(0))
+ return SDValue();
+
+ unsigned NumElts = VT.getVectorNumElements();
+ auto *SVN1 = cast<ShuffleVectorSDNode>(V1.getNode());
+ auto *SVN2 = cast<ShuffleVectorSDNode>(V2.getNode());
+ auto V1Mask = SVN1->getMask();
+ auto V2Mask = SVN2->getMask();
+ // 0: Not set, 1: Set by V1, 2: Set by V2
+ SmallVector<unsigned> ShuffleLaneUses(NumElts, 0);
+ for (unsigned Idx : seq<unsigned>(NumElts)) {
+ int Lane = Mask[Idx];
+ // Don't assign if poison
+ if (Lane == -1)
+ continue;
+ unsigned OpNum;
+ int OrigLane;
+ if ((unsigned)Lane < NumElts) {
+ OpNum = 1;
+ OrigLane = V1Mask[Lane];
+ } else {
+ OpNum = 2;
+ OrigLane = V2Mask[Lane - NumElts];
+ }
+ if (OrigLane == -1)
+ continue;
+ // Don't handle if shuffling from a second operand
+ if ((unsigned)OrigLane >= NumElts)
+ return SDValue();
+
+ const unsigned CurrLaneSrc = ShuffleLaneUses[OrigLane];
+ // Can't use the same lane from both operands in the merge
+ if (CurrLaneSrc != 0 && CurrLaneSrc != OpNum)
+ return SDValue();
+ ShuffleLaneUses[OrigLane] = OpNum;
+ }
+
+ MVT ContainerVT = getContainerForFixedLengthVector(DAG, VT, Subtarget);
+ auto [TrueMask, VL] = getDefaultVLOps(VT, ContainerVT, DL, DAG, Subtarget);
+
+ // Create the mask for the initial merge
+ auto XLenVT = Subtarget.getXLenVT();
----------------
lukel97 wrote:
Nit
```suggestion
MVT XLenVT = Subtarget.getXLenVT();
```
https://github.com/llvm/llvm-project/pull/178095
More information about the llvm-commits
mailing list