[llvm] [RISCV] Recognize VLA shift pairs from shuffle masks (PR #127710)
Luke Lau via llvm-commits
llvm-commits at lists.llvm.org
Wed Feb 19 20:29:26 PST 2025
================
@@ -5651,6 +5695,73 @@ static SDValue lowerVECTOR_SHUFFLE(SDValue Op, SelectionDAG &DAG,
return getWideningInterleave(EvenV, OddV, DL, DAG, Subtarget);
}
+ // Recognize a pattern which can handled via a pair of vslideup/vslidedown
+ // instructions (in any combination) with masking on the second instruction.
+ // Avoid matching bit rotates as slide pairs. This is a performance
+ // heuristic, not a functional check.
+ // TODO: Generalize this slightly to allow single instruction cases, and
+ // prune the logic above which is mostly covered by this already.
+ std::pair<int, int> SrcInfo[2];
+ unsigned RotateAmt;
+ MVT RotateVT;
+ if (isMaskedSlidePair(Mask, SrcInfo) &&
+ !isLegalBitRotate(Mask, VT, Subtarget, RotateVT, RotateAmt)) {
+ SDValue Sources[2];
+ auto GetSourceFor = [&](const std::pair<int, int> &Info) {
+ int SrcIdx = Info.first;
+ assert(SrcIdx == 0 || SrcIdx == 1);
+ SDValue &Src = Sources[SrcIdx];
+ if (!Src) {
+ SDValue SrcV = SrcIdx == 0 ? V1 : V2;
+ Src = convertToScalableVector(ContainerVT, SrcV, DAG, Subtarget);
+ }
+ return Src;
+ };
+ auto GetSlide = [&](const std::pair<int, int> &Src, SDValue Mask,
+ SDValue Passthru) {
+ SDValue SrcV = GetSourceFor(Src);
+ int SlideAmt = Src.second;
+ if (SlideAmt == 0) {
+ // Should never be second operation
+ assert(Mask == TrueMask);
+ return SrcV;
+ }
+ if (SlideAmt < 0)
+ return getVSlidedown(DAG, Subtarget, DL, ContainerVT, Passthru, SrcV,
+ DAG.getConstant(-SlideAmt, DL, XLenVT), Mask, VL,
+ RISCVVType::TAIL_AGNOSTIC);
+ return getVSlideup(DAG, Subtarget, DL, ContainerVT, Passthru, SrcV,
+ DAG.getConstant(SlideAmt, DL, XLenVT), Mask, VL,
+ RISCVVType::TAIL_AGNOSTIC);
+ };
+
+ // Build the mask. Note that vslideup unconditionally preserves elements
+ // below the slide amount in the destination, and thus those elements are
+ // undefined in the mask. If the mask ends up all true (or undef), it
+ // will be folded away by general logic.
+ SmallVector<SDValue> MaskVals;
+ for (unsigned i = 0; i != Mask.size(); ++i) {
+ int M = Mask[i];
+ if (M < 0 || (SrcInfo[1].second > 0 && i < (unsigned)SrcInfo[1].second)) {
+ MaskVals.push_back(DAG.getUNDEF(XLenVT));
+ continue;
+ }
+ int Src = M >= (int)NumElts;
+ int Diff = (int)i - (M % NumElts);
+ bool C = Src == SrcInfo[1].first && Diff == SrcInfo[1].second;
+ MaskVals.push_back(DAG.getConstant(C, DL, XLenVT));
----------------
lukel97 wrote:
Just to check my understanding, at this point we'll also have the invariant `C || Src == SrcInfo[0].first && Diff == SrcInfo[0].second`? Is that worth an assert
https://github.com/llvm/llvm-project/pull/127710
More information about the llvm-commits
mailing list