-
Notifications
You must be signed in to change notification settings - Fork 14.4k
[SLP][REVEC] Support more mask pattern usage in shufflevector. #106212
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 5 commits
f093918
7e5e17f
ffb2e4c
cf61edf
5c8f656
3e35ab7
25b9018
8949d6b
43f419e
d2dabc8
6fa9b11
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -272,8 +272,7 @@ static void transformScalarShuffleIndiciesToVector(unsigned VecTyNumElements, | |
/// A group has the following features | ||
/// 1. All of value in a group are shufflevector. | ||
/// 2. The mask of all shufflevector is isExtractSubvectorMask. | ||
/// 3. The mask of all shufflevector uses all of the elements of the source (and | ||
/// the elements are used in order). | ||
/// 3. The mask of all shufflevector uses all of the elements of the source. | ||
/// e.g., it is 1 group (%0) | ||
/// %1 = shufflevector <16 x i8> %0, <16 x i8> poison, | ||
/// <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7> | ||
|
@@ -309,7 +308,7 @@ static unsigned getShufflevectorNumGroups(ArrayRef<Value *> VL) { | |
auto *SV = cast<ShuffleVectorInst>(VL[I]); | ||
Value *Src = SV->getOperand(0); | ||
ArrayRef<Value *> Group = VL.slice(I, GroupSize); | ||
SmallVector<int> ExtractionIndex(SVNumElements); | ||
SmallBitVector UsedIndex(SVNumElements); | ||
if (!all_of(Group, [&](Value *V) { | ||
auto *SV = cast<ShuffleVectorInst>(V); | ||
// From the same source. | ||
|
@@ -318,12 +317,11 @@ static unsigned getShufflevectorNumGroups(ArrayRef<Value *> VL) { | |
int Index; | ||
if (!SV->isExtractSubvectorMask(Index)) | ||
return false; | ||
for (int I : seq<int>(Index, Index + SV->getShuffleMask().size())) | ||
ExtractionIndex.push_back(I); | ||
UsedIndex.set(Index, Index + SV->getShuffleMask().size()); | ||
return true; | ||
})) | ||
return 0; | ||
if (!is_sorted(ExtractionIndex)) | ||
if (!UsedIndex.all()) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What if we just reuse the same group several times but some other group do not use at all? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Do you have an example? I am not sure what you mean. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I mean, <0,1> extracted several time, while <2,3> is not extracted at all There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Cannot. We had a
to make sure each elements will be accessed. |
||
return 0; | ||
++NumGroup; | ||
} | ||
|
@@ -10195,12 +10193,38 @@ BoUpSLP::getEntryCost(const TreeEntry *E, ArrayRef<Value *> VectorizedVals, | |
return VecCost; | ||
}; | ||
if (SLPReVec && !E->isAltShuffle()) | ||
return GetCostDiff(GetScalarCost, [](InstructionCost) { | ||
// shufflevector will be eliminated by instcombine because the | ||
// shufflevector masks are used in order (guaranteed by | ||
// getShufflevectorNumGroups). The vector cost is 0. | ||
return TTI::TCC_Free; | ||
}); | ||
return GetCostDiff( | ||
GetScalarCost, [&](InstructionCost) -> InstructionCost { | ||
// If a group uses mask in order, the shufflevector can be | ||
// eliminated by instcombine. Then the cost is 0. | ||
bool IsIdentity = true; | ||
auto *SV = cast<ShuffleVectorInst>(VL.front()); | ||
unsigned SVNumElements = | ||
cast<FixedVectorType>(SV->getOperand(0)->getType()) | ||
->getNumElements(); | ||
unsigned GroupSize = SVNumElements / SV->getShuffleMask().size(); | ||
for (size_t I = 0, E = VL.size(); I != E; I += GroupSize) { | ||
ArrayRef<Value *> Group = VL.slice(I, GroupSize); | ||
SmallVector<int> ExtractionIndex(SVNumElements); | ||
for_each(Group, [&](Value *V) { | ||
auto *SV = cast<ShuffleVectorInst>(V); | ||
int Index; | ||
SV->isExtractSubvectorMask(Index); | ||
for (int I : | ||
seq<int>(Index, Index + SV->getShuffleMask().size())) | ||
ExtractionIndex.push_back(I); | ||
}); | ||
if (!is_sorted(ExtractionIndex)) { | ||
IsIdentity = false; | ||
break; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Do a return here, no need to modify IsIdentity There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Good catch. |
||
} | ||
} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I rather doubt you need all this, just a heck for identity should be enough There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We can vectorize the following instructions and eliminate shufflevector.
But this cannot.
We need to check all shufflevector and know whether there is an identity mask. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. But you don't need to check for sorted array, just need to check that each next extract mask starting index > than the previous one There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You are right. Fixed. |
||
return IsIdentity | ||
? TTI::TCC_Free | ||
: ::getShuffleCost( | ||
*TTI, TargetTransformInfo::SK_PermuteSingleSrc, | ||
VecTy, calculateShufflevectorMask(E->Scalars)); | ||
}); | ||
return GetCostDiff(GetScalarCost, GetVectorCost); | ||
} | ||
case Instruction::Freeze: | ||
|
@@ -13971,9 +13995,16 @@ Value *BoUpSLP::vectorizeTree(TreeEntry *E, bool PostponedPHIs) { | |
LLVM_DEBUG(dbgs() << "SLP: Diamond merged for " << *VL0 << ".\n"); | ||
return E->VectorizedValue; | ||
} | ||
// The current shufflevector usage always duplicate the source. | ||
V = Builder.CreateShuffleVector(Src, | ||
calculateShufflevectorMask(E->Scalars)); | ||
assert(isa<ShuffleVectorInst>(Src) && | ||
"Not supported shufflevector usage."); | ||
auto *SVSrc = cast<ShuffleVectorInst>(Src); | ||
assert(isa<PoisonValue>(SVSrc->getOperand(1)) && | ||
"Not supported shufflevector usage."); | ||
SmallVector<int> ThisMask(calculateShufflevectorMask(E->Scalars)); | ||
SmallVector<int> NewMask(ThisMask.size()); | ||
transform(ThisMask, NewMask.begin(), | ||
[&SVSrc](int Mask) { return SVSrc->getShuffleMask()[Mask]; }); | ||
V = Builder.CreateShuffleVector(SVSrc->getOperand(0), NewMask); | ||
propagateIRFlags(V, E->Scalars, VL0); | ||
} else { | ||
assert(E->isAltShuffle() && | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You don't need to account all elements here, just group indices should be enough, no?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Right. I will fix it.