@@ -4589,10 +4589,6 @@ static bool isMaskedSlidePair(ArrayRef<int> Mask,
45894589 return false;
45904590 }
45914591
4592- // Avoid matching unconditional slides for now. This is reasonably
4593- // covered by existing matchers.
4594- if (SrcInfo[0].first == -1 || SrcInfo[1].first == -1)
4595- return false;
45964592 // Avoid matching vselect idioms
45974593 if (SrcInfo[0].second == 0 && SrcInfo[1].second == 0)
45984594 return false;
@@ -4601,80 +4597,17 @@ static bool isMaskedSlidePair(ArrayRef<int> Mask,
46014597 if ((SrcInfo[0].second > 0 && SrcInfo[1].second < 0) ||
46024598 SrcInfo[1].second == 0)
46034599 std::swap(SrcInfo[0], SrcInfo[1]);
4600+ assert(SrcInfo[0].first != -1 && "Must find one slide");
46044601 return true;
46054602}
46064603
4607- /// Match shuffles that concatenate two vectors, rotate the concatenation,
4608- /// and then extract the original number of elements from the rotated result.
4609- /// This is equivalent to vector.splice or X86's PALIGNR instruction. The
4610- /// returned rotation amount is for a rotate right, where elements move from
4611- /// higher elements to lower elements. \p LoSrc indicates the first source
4612- /// vector of the rotate or -1 for undef. \p HiSrc indicates the second vector
4613- /// of the rotate or -1 for undef. At least one of \p LoSrc and \p HiSrc will be
4614- /// 0 or 1 if a rotation is found.
4615- ///
4616- /// NOTE: We talk about rotate to the right which matches how bit shift and
4617- /// rotate instructions are described where LSBs are on the right, but LLVM IR
4618- /// and the table below write vectors with the lowest elements on the left.
4619- static int isElementRotate(int &LoSrc, int &HiSrc, ArrayRef<int> Mask) {
4620- int Size = Mask.size();
4621-
4622- // We need to detect various ways of spelling a rotation:
4623- // [11, 12, 13, 14, 15, 0, 1, 2]
4624- // [-1, 12, 13, 14, -1, -1, 1, -1]
4625- // [-1, -1, -1, -1, -1, -1, 1, 2]
4626- // [ 3, 4, 5, 6, 7, 8, 9, 10]
4627- // [-1, 4, 5, 6, -1, -1, 9, -1]
4628- // [-1, 4, 5, 6, -1, -1, -1, -1]
4629- int Rotation = 0;
4630- LoSrc = -1;
4631- HiSrc = -1;
4632- for (int i = 0; i != Size; ++i) {
4633- int M = Mask[i];
4634- if (M < 0)
4635- continue;
4636-
4637- // Determine where a rotate vector would have started.
4638- int StartIdx = i - (M % Size);
4639- // The identity rotation isn't interesting, stop.
4640- if (StartIdx == 0)
4641- return -1;
4642-
4643- // If we found the tail of a vector the rotation must be the missing
4644- // front. If we found the head of a vector, it must be how much of the
4645- // head.
4646- int CandidateRotation = StartIdx < 0 ? -StartIdx : Size - StartIdx;
4647-
4648- if (Rotation == 0)
4649- Rotation = CandidateRotation;
4650- else if (Rotation != CandidateRotation)
4651- // The rotations don't match, so we can't match this mask.
4652- return -1;
4653-
4654- // Compute which value this mask is pointing at.
4655- int MaskSrc = M < Size ? 0 : 1;
4656-
4657- // Compute which of the two target values this index should be assigned to.
4658- // This reflects whether the high elements are remaining or the low elements
4659- // are remaining.
4660- int &TargetSrc = StartIdx < 0 ? HiSrc : LoSrc;
4661-
4662- // Either set up this value if we've not encountered it before, or check
4663- // that it remains consistent.
4664- if (TargetSrc < 0)
4665- TargetSrc = MaskSrc;
4666- else if (TargetSrc != MaskSrc)
4667- // This may be a rotation, but it pulls from the inputs in some
4668- // unsupported interleaving.
4669- return -1;
4670- }
4671-
4672- // Check that we successfully analyzed the mask, and normalize the results.
4673- assert(Rotation != 0 && "Failed to locate a viable rotation!");
4674- assert((LoSrc >= 0 || HiSrc >= 0) &&
4675- "Failed to find a rotated input vector!");
4676-
4677- return Rotation;
4604+ // Exactly matches the semantics of a previously existing custom matcher
4605+ // to allow migration to new matcher without changing output.
4606+ static bool isElementRotate(std::pair<int, int> SrcInfo[2], unsigned NumElts) {
4607+ if (SrcInfo[1].first == -1)
4608+ return true;
4609+ return SrcInfo[0].second < 0 && SrcInfo[1].second > 0 &&
4610+ SrcInfo[1].second - SrcInfo[0].second == (int)NumElts;
46784611}
46794612
46804613// Lower a deinterleave shuffle to SRL and TRUNC. Factor must be
@@ -5585,41 +5518,8 @@ static SDValue lowerVECTOR_SHUFFLE(SDValue Op, SelectionDAG &DAG,
55855518 if (SDValue V = lowerVECTOR_SHUFFLEAsRotate(SVN, DAG, Subtarget))
55865519 return V;
55875520
5588- // Lower rotations to a SLIDEDOWN and a SLIDEUP. One of the source vectors may
5589- // be undef which can be handled with a single SLIDEDOWN/UP.
5590- int LoSrc, HiSrc;
5591- int Rotation = isElementRotate(LoSrc, HiSrc, Mask);
5592- if (Rotation > 0) {
5593- SDValue LoV, HiV;
5594- if (LoSrc >= 0) {
5595- LoV = LoSrc == 0 ? V1 : V2;
5596- LoV = convertToScalableVector(ContainerVT, LoV, DAG, Subtarget);
5597- }
5598- if (HiSrc >= 0) {
5599- HiV = HiSrc == 0 ? V1 : V2;
5600- HiV = convertToScalableVector(ContainerVT, HiV, DAG, Subtarget);
5601- }
5602-
5603- // We found a rotation. We need to slide HiV down by Rotation. Then we need
5604- // to slide LoV up by (NumElts - Rotation).
5605- unsigned InvRotate = NumElts - Rotation;
5606-
5607- SDValue Res = DAG.getUNDEF(ContainerVT);
5608- if (HiV) {
5609- // Even though we could use a smaller VL, don't to avoid a vsetivli
5610- // toggle.
5611- Res = getVSlidedown(DAG, Subtarget, DL, ContainerVT, Res, HiV,
5612- DAG.getConstant(Rotation, DL, XLenVT), TrueMask, VL);
5613- }
5614- if (LoV)
5615- Res = getVSlideup(DAG, Subtarget, DL, ContainerVT, Res, LoV,
5616- DAG.getConstant(InvRotate, DL, XLenVT), TrueMask, VL,
5617- RISCVVType::TAIL_AGNOSTIC);
5618-
5619- return convertFromScalableVector(VT, Res, DAG, Subtarget);
5620- }
5621-
5622- if (ShuffleVectorInst::isReverseMask(Mask, NumElts) && V2.isUndef())
5521+ if (ShuffleVectorInst::isReverseMask(Mask, NumElts) && V2.isUndef() &&
5522+ NumElts != 2)
56235523 return DAG.getNode(ISD::VECTOR_REVERSE, DL, VT, V1);
56245524
56255525 // If this is a deinterleave(2,4,8) and we can widen the vector, then we can
@@ -5662,7 +5562,9 @@ static SDValue lowerVECTOR_SHUFFLE(SDValue Op, SelectionDAG &DAG,
56625562 // Detect an interleave shuffle and lower to
56635563 // (vmaccu.vx (vwaddu.vx lohalf(V1), lohalf(V2)), lohalf(V2), (2^eltbits - 1))
56645564 int EvenSrc, OddSrc;
5665- if (isInterleaveShuffle(Mask, VT, EvenSrc, OddSrc, Subtarget)) {
5565+ if (isInterleaveShuffle(Mask, VT, EvenSrc, OddSrc, Subtarget) &&
5566+ !(NumElts == 2 &&
5567+ ShuffleVectorInst::isSingleSourceMask(Mask, Mask.size()))) {
56665568 // Extract the halves of the vectors.
56675569 MVT HalfVT = VT.getHalfNumVectorElementsVT();
56685570
@@ -5698,15 +5600,16 @@ static SDValue lowerVECTOR_SHUFFLE(SDValue Op, SelectionDAG &DAG,
56985600
56995601 // Recognize a pattern which can handled via a pair of vslideup/vslidedown
57005602 // instructions (in any combination) with masking on the second instruction.
5701- // Avoid matching bit rotates as slide pairs. This is a performance
5702- // heuristic, not a functional check.
5703- // TODO: Generalize this slightly to allow single instruction cases, and
5704- // prune the logic above which is mostly covered by this already .
5603+ // Also handles masked slides into an identity source, and single slides
5604+ // without masking. Avoid matching bit rotates (which are not also element
5605+ // rotates) as slide pairs. This is a performance heuristic, not a
5606+ // functional check .
57055607 std::pair<int, int> SrcInfo[2];
57065608 unsigned RotateAmt;
57075609 MVT RotateVT;
57085610 if (isMaskedSlidePair(Mask, SrcInfo) &&
5709- !isLegalBitRotate(Mask, VT, Subtarget, RotateVT, RotateAmt)) {
5611+ (isElementRotate(SrcInfo, NumElts) ||
5612+ !isLegalBitRotate(Mask, VT, Subtarget, RotateVT, RotateAmt))) {
57105613 SDValue Sources[2];
57115614 auto GetSourceFor = [&](const std::pair<int, int> &Info) {
57125615 int SrcIdx = Info.first;
@@ -5737,6 +5640,12 @@ static SDValue lowerVECTOR_SHUFFLE(SDValue Op, SelectionDAG &DAG,
57375640 RISCVVType::TAIL_AGNOSTIC);
57385641 };
57395642
5643+ if (SrcInfo[1].first == -1) {
5644+ SDValue Res = DAG.getUNDEF(ContainerVT);
5645+ Res = GetSlide(SrcInfo[0], TrueMask, Res);
5646+ return convertFromScalableVector(VT, Res, DAG, Subtarget);
5647+ }
5648+
57405649 // Build the mask. Note that vslideup unconditionally preserves elements
57415650 // below the slide amount in the destination, and thus those elements are
57425651 // undefined in the mask. If the mask ends up all true (or undef), it
@@ -6055,9 +5964,10 @@ bool RISCVTargetLowering::isShuffleMaskLegal(ArrayRef<int> M, EVT VT) const {
60555964 if (SVT.getScalarType() == MVT::i1)
60565965 return false;
60575966
5967+ std::pair<int, int> SrcInfo[2];
60585968 int Dummy1, Dummy2;
60595969 return ShuffleVectorInst::isReverseMask(M, NumElts) ||
6060- (isElementRotate(Dummy1, Dummy2, M) > 0 ) ||
5970+ (isMaskedSlidePair(M, SrcInfo) && isElementRotate(SrcInfo, NumElts) ) ||
60615971 isInterleaveShuffle(M, SVT, Dummy1, Dummy2, Subtarget);
60625972}
60635973
0 commit comments