forked from OSchip/llvm-project
[DAG] Refactor the shuffle combining logic in DAGCombiner. NFC.
This patch simplifies the logic that combines a pair of shuffle nodes into a single shuffle if there is a legal mask. Also added comments to better describe the algorithm. No functional change intended. llvm-svn: 222522
This commit is contained in:
parent
fd1731d876
commit
26e8f4d166
|
@ -11088,121 +11088,11 @@ SDValue DAGCombiner::visitVECTOR_SHUFFLE(SDNode *N) {
|
||||||
return V;
|
return V;
|
||||||
}
|
}
|
||||||
|
|
||||||
// If this shuffle node is simply a swizzle of another shuffle node,
|
|
||||||
// then try to simplify it.
|
|
||||||
if (N0.getOpcode() == ISD::VECTOR_SHUFFLE && Level < AfterLegalizeDAG &&
|
|
||||||
N1.getOpcode() == ISD::UNDEF) {
|
|
||||||
|
|
||||||
ShuffleVectorSDNode *OtherSV = cast<ShuffleVectorSDNode>(N0);
|
|
||||||
|
|
||||||
// The incoming shuffle must be of the same type as the result of the
|
|
||||||
// current shuffle.
|
|
||||||
assert(OtherSV->getOperand(0).getValueType() == VT &&
|
|
||||||
"Shuffle types don't match");
|
|
||||||
|
|
||||||
SmallVector<int, 4> Mask;
|
|
||||||
// Compute the combined shuffle mask.
|
|
||||||
for (unsigned i = 0; i != NumElts; ++i) {
|
|
||||||
int Idx = SVN->getMaskElt(i);
|
|
||||||
assert(Idx < (int)NumElts && "Index references undef operand");
|
|
||||||
// Next, this index comes from the first value, which is the incoming
|
|
||||||
// shuffle. Adopt the incoming index.
|
|
||||||
if (Idx >= 0)
|
|
||||||
Idx = OtherSV->getMaskElt(Idx);
|
|
||||||
Mask.push_back(Idx);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check if all indices in Mask are Undef. In case, propagate Undef.
|
|
||||||
bool isUndefMask = true;
|
|
||||||
for (unsigned i = 0; i != NumElts && isUndefMask; ++i)
|
|
||||||
isUndefMask &= Mask[i] < 0;
|
|
||||||
|
|
||||||
if (isUndefMask)
|
|
||||||
return DAG.getUNDEF(VT);
|
|
||||||
|
|
||||||
bool CommuteOperands = false;
|
|
||||||
if (N0.getOperand(1).getOpcode() != ISD::UNDEF) {
|
|
||||||
// To be valid, the combine shuffle mask should only reference elements
|
|
||||||
// from one of the two vectors in input to the inner shufflevector.
|
|
||||||
bool IsValidMask = true;
|
|
||||||
for (unsigned i = 0; i != NumElts && IsValidMask; ++i)
|
|
||||||
// See if the combined mask only reference undefs or elements coming
|
|
||||||
// from the first shufflevector operand.
|
|
||||||
IsValidMask = Mask[i] < 0 || (unsigned)Mask[i] < NumElts;
|
|
||||||
|
|
||||||
if (!IsValidMask) {
|
|
||||||
IsValidMask = true;
|
|
||||||
for (unsigned i = 0; i != NumElts && IsValidMask; ++i)
|
|
||||||
// Check that all the elements come from the second shuffle operand.
|
|
||||||
IsValidMask = Mask[i] < 0 || (unsigned)Mask[i] >= NumElts;
|
|
||||||
CommuteOperands = IsValidMask;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Early exit if the combined shuffle mask is not valid.
|
|
||||||
if (!IsValidMask)
|
|
||||||
return SDValue();
|
|
||||||
}
|
|
||||||
|
|
||||||
// See if this pair of shuffles can be safely folded according to either
|
|
||||||
// of the following rules:
|
|
||||||
// shuffle(shuffle(x, y), undef) -> x
|
|
||||||
// shuffle(shuffle(x, undef), undef) -> x
|
|
||||||
// shuffle(shuffle(x, y), undef) -> y
|
|
||||||
bool IsIdentityMask = true;
|
|
||||||
unsigned BaseMaskIndex = CommuteOperands ? NumElts : 0;
|
|
||||||
for (unsigned i = 0; i != NumElts && IsIdentityMask; ++i) {
|
|
||||||
// Skip Undefs.
|
|
||||||
if (Mask[i] < 0)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
// The combined shuffle must map each index to itself.
|
|
||||||
IsIdentityMask = (unsigned)Mask[i] == i + BaseMaskIndex;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (IsIdentityMask) {
|
|
||||||
if (CommuteOperands)
|
|
||||||
// optimize shuffle(shuffle(x, y), undef) -> y.
|
|
||||||
return OtherSV->getOperand(1);
|
|
||||||
|
|
||||||
// optimize shuffle(shuffle(x, undef), undef) -> x
|
|
||||||
// optimize shuffle(shuffle(x, y), undef) -> x
|
|
||||||
return OtherSV->getOperand(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
// It may still be beneficial to combine the two shuffles if the
|
|
||||||
// resulting shuffle is legal.
|
|
||||||
if (TLI.isTypeLegal(VT)) {
|
|
||||||
if (!CommuteOperands) {
|
|
||||||
if (TLI.isShuffleMaskLegal(Mask, VT))
|
|
||||||
// shuffle(shuffle(x, undef, M1), undef, M2) -> shuffle(x, undef, M3).
|
|
||||||
// shuffle(shuffle(x, y, M1), undef, M2) -> shuffle(x, undef, M3)
|
|
||||||
return DAG.getVectorShuffle(VT, SDLoc(N), N0->getOperand(0), N1,
|
|
||||||
&Mask[0]);
|
|
||||||
} else {
|
|
||||||
// Compute the commuted shuffle mask.
|
|
||||||
for (unsigned i = 0; i != NumElts; ++i) {
|
|
||||||
int idx = Mask[i];
|
|
||||||
if (idx < 0)
|
|
||||||
continue;
|
|
||||||
else if (idx < (int)NumElts)
|
|
||||||
Mask[i] = idx + NumElts;
|
|
||||||
else
|
|
||||||
Mask[i] = idx - NumElts;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (TLI.isShuffleMaskLegal(Mask, VT))
|
|
||||||
// shuffle(shuffle(x, y, M1), undef, M2) -> shuffle(y, undef, M3)
|
|
||||||
return DAG.getVectorShuffle(VT, SDLoc(N), N0->getOperand(1), N1,
|
|
||||||
&Mask[0]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Canonicalize shuffles according to rules:
|
// Canonicalize shuffles according to rules:
|
||||||
// shuffle(A, shuffle(A, B)) -> shuffle(shuffle(A,B), A)
|
// shuffle(A, shuffle(A, B)) -> shuffle(shuffle(A,B), A)
|
||||||
// shuffle(B, shuffle(A, B)) -> shuffle(shuffle(A,B), B)
|
// shuffle(B, shuffle(A, B)) -> shuffle(shuffle(A,B), B)
|
||||||
// shuffle(B, shuffle(A, Undef)) -> shuffle(shuffle(A, Undef), B)
|
// shuffle(B, shuffle(A, Undef)) -> shuffle(shuffle(A, Undef), B)
|
||||||
if (N1.getOpcode() == ISD::VECTOR_SHUFFLE && N0.getOpcode() != ISD::UNDEF &&
|
if (N1.getOpcode() == ISD::VECTOR_SHUFFLE &&
|
||||||
N0.getOpcode() != ISD::VECTOR_SHUFFLE && Level < AfterLegalizeDAG &&
|
N0.getOpcode() != ISD::VECTOR_SHUFFLE && Level < AfterLegalizeDAG &&
|
||||||
TLI.isTypeLegal(VT)) {
|
TLI.isTypeLegal(VT)) {
|
||||||
// The incoming shuffle must be of the same type as the result of the
|
// The incoming shuffle must be of the same type as the result of the
|
||||||
|
@ -11221,13 +11111,12 @@ SDValue DAGCombiner::visitVECTOR_SHUFFLE(SDNode *N) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Try to fold according to rules:
|
// Try to fold according to rules:
|
||||||
// shuffle(shuffle(A, B, M0), B, M1) -> shuffle(A, B, M2)
|
// shuffle(shuffle(A, B, M0), C, M1) -> shuffle(A, B, M2)
|
||||||
// shuffle(shuffle(A, B, M0), A, M1) -> shuffle(A, B, M2)
|
// shuffle(shuffle(A, B, M0), C, M1) -> shuffle(A, C, M2)
|
||||||
// shuffle(shuffle(A, Undef, M0), B, M1) -> shuffle(A, B, M2)
|
// shuffle(shuffle(A, B, M0), C, M1) -> shuffle(B, C, M2)
|
||||||
// shuffle(shuffle(A, Undef, M0), A, M1) -> shuffle(A, Undef, M2)
|
|
||||||
// Don't try to fold shuffles with illegal type.
|
// Don't try to fold shuffles with illegal type.
|
||||||
if (N0.getOpcode() == ISD::VECTOR_SHUFFLE && Level < AfterLegalizeDAG &&
|
if (N0.getOpcode() == ISD::VECTOR_SHUFFLE && Level < AfterLegalizeDAG &&
|
||||||
N1.getOpcode() != ISD::UNDEF && TLI.isTypeLegal(VT)) {
|
TLI.isTypeLegal(VT)) {
|
||||||
ShuffleVectorSDNode *OtherSV = cast<ShuffleVectorSDNode>(N0);
|
ShuffleVectorSDNode *OtherSV = cast<ShuffleVectorSDNode>(N0);
|
||||||
|
|
||||||
// The incoming shuffle must be of the same type as the result of the
|
// The incoming shuffle must be of the same type as the result of the
|
||||||
|
@ -11235,14 +11124,7 @@ SDValue DAGCombiner::visitVECTOR_SHUFFLE(SDNode *N) {
|
||||||
assert(OtherSV->getOperand(0).getValueType() == VT &&
|
assert(OtherSV->getOperand(0).getValueType() == VT &&
|
||||||
"Shuffle types don't match");
|
"Shuffle types don't match");
|
||||||
|
|
||||||
SDValue SV0 = OtherSV->getOperand(0);
|
SDValue SV0, SV1;
|
||||||
SDValue SV1 = OtherSV->getOperand(1);
|
|
||||||
bool HasSameOp0 = N1 == SV0;
|
|
||||||
bool IsSV1Undef = SV1.getOpcode() == ISD::UNDEF;
|
|
||||||
if (!HasSameOp0 && !IsSV1Undef && N1 != SV1)
|
|
||||||
// Early exit.
|
|
||||||
return SDValue();
|
|
||||||
|
|
||||||
SmallVector<int, 4> Mask;
|
SmallVector<int, 4> Mask;
|
||||||
// Compute the combined shuffle mask for a shuffle with SV0 as the first
|
// Compute the combined shuffle mask for a shuffle with SV0 as the first
|
||||||
// operand, and SV1 as the second operand.
|
// operand, and SV1 as the second operand.
|
||||||
|
@ -11254,14 +11136,49 @@ SDValue DAGCombiner::visitVECTOR_SHUFFLE(SDNode *N) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SDValue CurrentVec;
|
||||||
if (Idx < (int)NumElts) {
|
if (Idx < (int)NumElts) {
|
||||||
|
// This shuffle index refers to the inner shuffle N0. Lookup the inner
|
||||||
|
// shuffle mask to identify which vector is actually referenced.
|
||||||
Idx = OtherSV->getMaskElt(Idx);
|
Idx = OtherSV->getMaskElt(Idx);
|
||||||
if (IsSV1Undef && Idx >= (int) NumElts)
|
if (Idx < 0) {
|
||||||
Idx = -1; // Propagate Undef.
|
// Propagate Undef.
|
||||||
} else
|
|
||||||
Idx = HasSameOp0 ? Idx - NumElts : Idx;
|
|
||||||
|
|
||||||
Mask.push_back(Idx);
|
Mask.push_back(Idx);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
CurrentVec = (Idx < (int) NumElts) ? OtherSV->getOperand(0)
|
||||||
|
: OtherSV->getOperand(1);
|
||||||
|
} else {
|
||||||
|
// This shuffle index references an element within N1.
|
||||||
|
CurrentVec = N1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Simple case where 'CurrentVec' is UNDEF.
|
||||||
|
if (CurrentVec.getOpcode() == ISD::UNDEF) {
|
||||||
|
Mask.push_back(-1);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Canonicalize the shuffle index. We don't know yet if CurrentVec
|
||||||
|
// will be the first or second operand of the combined shuffle.
|
||||||
|
Idx = Idx % NumElts;
|
||||||
|
if (!SV0.getNode() || SV0 == CurrentVec) {
|
||||||
|
// Ok. CurrentVec is the left hand side.
|
||||||
|
// Update the mask accordingly.
|
||||||
|
SV0 = CurrentVec;
|
||||||
|
Mask.push_back(Idx);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Bail out if we cannot convert the shuffle pair into a single shuffle.
|
||||||
|
if (SV1.getNode() && SV1 != CurrentVec)
|
||||||
|
return SDValue();
|
||||||
|
|
||||||
|
// Ok. CurrentVec is the right hand side.
|
||||||
|
// Update the mask accordingly.
|
||||||
|
SV1 = CurrentVec;
|
||||||
|
Mask.push_back(Idx + NumElts);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if all indices in Mask are Undef. In case, propagate Undef.
|
// Check if all indices in Mask are Undef. In case, propagate Undef.
|
||||||
|
@ -11272,16 +11189,14 @@ SDValue DAGCombiner::visitVECTOR_SHUFFLE(SDNode *N) {
|
||||||
if (isUndefMask)
|
if (isUndefMask)
|
||||||
return DAG.getUNDEF(VT);
|
return DAG.getUNDEF(VT);
|
||||||
|
|
||||||
// Avoid introducing shuffles with illegal mask.
|
if (!SV0.getNode())
|
||||||
if (TLI.isShuffleMaskLegal(Mask, VT)) {
|
SV0 = DAG.getUNDEF(VT);
|
||||||
if (IsSV1Undef)
|
if (!SV1.getNode())
|
||||||
// shuffle(shuffle(A, Undef, M0), B, M1) -> shuffle(A, B, M2)
|
SV1 = DAG.getUNDEF(VT);
|
||||||
// shuffle(shuffle(A, Undef, M0), A, M1) -> shuffle(A, Undef, M2)
|
|
||||||
return DAG.getVectorShuffle(VT, SDLoc(N), SV0, N1, &Mask[0]);
|
|
||||||
return DAG.getVectorShuffle(VT, SDLoc(N), SV0, SV1, &Mask[0]);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Compute the commuted shuffle mask.
|
// Avoid introducing shuffles with illegal mask.
|
||||||
|
if (!TLI.isShuffleMaskLegal(Mask, VT)) {
|
||||||
|
// Compute the commuted shuffle mask and test again.
|
||||||
for (unsigned i = 0; i != NumElts; ++i) {
|
for (unsigned i = 0; i != NumElts; ++i) {
|
||||||
int idx = Mask[i];
|
int idx = Mask[i];
|
||||||
if (idx < 0)
|
if (idx < 0)
|
||||||
|
@ -11292,14 +11207,19 @@ SDValue DAGCombiner::visitVECTOR_SHUFFLE(SDNode *N) {
|
||||||
Mask[i] = idx - NumElts;
|
Mask[i] = idx - NumElts;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (TLI.isShuffleMaskLegal(Mask, VT)) {
|
if (!TLI.isShuffleMaskLegal(Mask, VT))
|
||||||
if (IsSV1Undef)
|
return SDValue();
|
||||||
// shuffle(shuffle(A, Undef, M0), B, M1) -> shuffle(B, A, M2)
|
|
||||||
return DAG.getVectorShuffle(VT, SDLoc(N), N1, SV0, &Mask[0]);
|
// shuffle(shuffle(A, B, M0), C, M1) -> shuffle(B, A, M2)
|
||||||
// shuffle(shuffle(A, B, M0), B, M1) -> shuffle(B, A, M2)
|
// shuffle(shuffle(A, B, M0), C, M1) -> shuffle(C, A, M2)
|
||||||
// shuffle(shuffle(A, B, M0), A, M1) -> shuffle(B, A, M2)
|
// shuffle(shuffle(A, B, M0), C, M1) -> shuffle(C, B, M2)
|
||||||
return DAG.getVectorShuffle(VT, SDLoc(N), SV1, SV0, &Mask[0]);
|
std::swap(SV0, SV1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// shuffle(shuffle(A, B, M0), C, M1) -> shuffle(A, B, M2)
|
||||||
|
// shuffle(shuffle(A, B, M0), C, M1) -> shuffle(A, C, M2)
|
||||||
|
// shuffle(shuffle(A, B, M0), C, M1) -> shuffle(B, C, M2)
|
||||||
|
return DAG.getVectorShuffle(VT, SDLoc(N), SV0, SV1, &Mask[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
return SDValue();
|
return SDValue();
|
||||||
|
|
Loading…
Reference in New Issue