[llvm] [RISCV] Lower disjoint shuffle of shuffles to MERGE-GATHER sequence (PR #178095)
Ryan Buchner via llvm-commits
llvm-commits at lists.llvm.org
Tue Jan 27 08:35:51 PST 2026
================
@@ -5439,6 +5439,107 @@ 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];
+ auto LanePoisonOrOOB = [](int Lane, unsigned NumElts) -> bool {
+ return Lane < 0 || Lane > (int)NumElts;
+ };
+ // Don't handle if the index is poison or out of bounds
+ if (LanePoisonOrOOB(Lane, 2 * NumElts))
+ return SDValue();
----------------
bababuck wrote:
Thanks for the explanation!
https://github.com/llvm/llvm-project/pull/178095
More information about the llvm-commits
mailing list