Skip to content

Commit 115672f

Browse files
authored
[RISCV] Remove now redundant isElementRotate shuffle lowering [NFCI] (#128064)
This is the first cleanup following the introduction of the new isMaskedSlidePair lowering in 43f2968. As mentioned in that review, the new code is a generalization of the existing isElementRotate, but was staged to make diffs manageable. This change removes isElementRotate. The tricky bit is making sure that a) the same shuffles hit the same lowering paths (in particular, two element shuffles can match multiple ways) and 2) avoiding DAG canonicalization changes.
1 parent ab098a7 commit 115672f

File tree

1 file changed

+27
-117
lines changed

1 file changed

+27
-117
lines changed

llvm/lib/Target/RISCV/RISCVISelLowering.cpp

Lines changed: 27 additions & 117 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)