@@ -4589,10 +4589,6 @@ static bool isMaskedSlidePair(ArrayRef<int> Mask,
4589
4589
return false;
4590
4590
}
4591
4591
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;
4596
4592
// Avoid matching vselect idioms
4597
4593
if (SrcInfo[0].second == 0 && SrcInfo[1].second == 0)
4598
4594
return false;
@@ -4601,80 +4597,17 @@ static bool isMaskedSlidePair(ArrayRef<int> Mask,
4601
4597
if ((SrcInfo[0].second > 0 && SrcInfo[1].second < 0) ||
4602
4598
SrcInfo[1].second == 0)
4603
4599
std::swap(SrcInfo[0], SrcInfo[1]);
4600
+ assert(SrcInfo[0].first != -1 && "Must find one slide");
4604
4601
return true;
4605
4602
}
4606
4603
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;
4678
4611
}
4679
4612
4680
4613
// Lower a deinterleave shuffle to SRL and TRUNC. Factor must be
@@ -5585,41 +5518,8 @@ static SDValue lowerVECTOR_SHUFFLE(SDValue Op, SelectionDAG &DAG,
5585
5518
if (SDValue V = lowerVECTOR_SHUFFLEAsRotate(SVN, DAG, Subtarget))
5586
5519
return V;
5587
5520
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)
5623
5523
return DAG.getNode(ISD::VECTOR_REVERSE, DL, VT, V1);
5624
5524
5625
5525
// 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,
5662
5562
// Detect an interleave shuffle and lower to
5663
5563
// (vmaccu.vx (vwaddu.vx lohalf(V1), lohalf(V2)), lohalf(V2), (2^eltbits - 1))
5664
5564
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()))) {
5666
5568
// Extract the halves of the vectors.
5667
5569
MVT HalfVT = VT.getHalfNumVectorElementsVT();
5668
5570
@@ -5698,15 +5600,16 @@ static SDValue lowerVECTOR_SHUFFLE(SDValue Op, SelectionDAG &DAG,
5698
5600
5699
5601
// Recognize a pattern which can handled via a pair of vslideup/vslidedown
5700
5602
// 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 .
5705
5607
std::pair<int, int> SrcInfo[2];
5706
5608
unsigned RotateAmt;
5707
5609
MVT RotateVT;
5708
5610
if (isMaskedSlidePair(Mask, SrcInfo) &&
5709
- !isLegalBitRotate(Mask, VT, Subtarget, RotateVT, RotateAmt)) {
5611
+ (isElementRotate(SrcInfo, NumElts) ||
5612
+ !isLegalBitRotate(Mask, VT, Subtarget, RotateVT, RotateAmt))) {
5710
5613
SDValue Sources[2];
5711
5614
auto GetSourceFor = [&](const std::pair<int, int> &Info) {
5712
5615
int SrcIdx = Info.first;
@@ -5737,6 +5640,12 @@ static SDValue lowerVECTOR_SHUFFLE(SDValue Op, SelectionDAG &DAG,
5737
5640
RISCVVType::TAIL_AGNOSTIC);
5738
5641
};
5739
5642
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
+
5740
5649
// Build the mask. Note that vslideup unconditionally preserves elements
5741
5650
// below the slide amount in the destination, and thus those elements are
5742
5651
// 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 {
6055
5964
if (SVT.getScalarType() == MVT::i1)
6056
5965
return false;
6057
5966
5967
+ std::pair<int, int> SrcInfo[2];
6058
5968
int Dummy1, Dummy2;
6059
5969
return ShuffleVectorInst::isReverseMask(M, NumElts) ||
6060
- (isElementRotate(Dummy1, Dummy2, M) > 0 ) ||
5970
+ (isMaskedSlidePair(M, SrcInfo) && isElementRotate(SrcInfo, NumElts) ) ||
6061
5971
isInterleaveShuffle(M, SVT, Dummy1, Dummy2, Subtarget);
6062
5972
}
6063
5973
0 commit comments