-
Notifications
You must be signed in to change notification settings - Fork 15.2k
[LV] Vectorize conditional scalar assignments #158088
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
base: main
Are you sure you want to change the base?
Changes from all commits
049428d
0c902a6
41bbf8d
e78b208
b937d1b
883a770
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 |
|---|---|---|
|
|
@@ -56,6 +56,8 @@ bool RecurrenceDescriptor::isIntegerRecurrenceKind(RecurKind Kind) { | |
| case RecurKind::FindFirstIVUMin: | ||
| case RecurKind::FindLastIVSMax: | ||
| case RecurKind::FindLastIVUMax: | ||
| // TODO: Make type-agnostic. | ||
| case RecurKind::FindLast: | ||
| return true; | ||
| } | ||
| return false; | ||
|
|
@@ -691,9 +693,9 @@ RecurrenceDescriptor::isAnyOfPattern(Loop *Loop, PHINode *OrigPhi, | |
| // value of the data type or a non-constant value by using mask and multiple | ||
| // reduction operations. | ||
| RecurrenceDescriptor::InstDesc | ||
| RecurrenceDescriptor::isFindIVPattern(RecurKind Kind, Loop *TheLoop, | ||
| PHINode *OrigPhi, Instruction *I, | ||
| ScalarEvolution &SE) { | ||
| RecurrenceDescriptor::isFindPattern(RecurKind Kind, Loop *TheLoop, | ||
| PHINode *OrigPhi, Instruction *I, | ||
| ScalarEvolution &SE) { | ||
| // TODO: Support the vectorization of FindLastIV when the reduction phi is | ||
| // used by more than one select instruction. This vectorization is only | ||
| // performed when the SCEV of each increasing induction variable used by the | ||
|
|
@@ -702,8 +704,10 @@ RecurrenceDescriptor::isFindIVPattern(RecurKind Kind, Loop *TheLoop, | |
| return InstDesc(false, I); | ||
|
|
||
| // We are looking for selects of the form: | ||
| // select(cmp(), phi, loop_induction) or | ||
| // select(cmp(), loop_induction, phi) | ||
| // select(cmp(), phi, value) or | ||
| // select(cmp(), value, phi) | ||
| // where 'value' is be a loop induction variable | ||
| // (for FindFirstIV/FindLastIV) or an arbitrary value (for FindLast). | ||
| // TODO: Match selects with multi-use cmp conditions. | ||
| Value *NonRdxPhi = nullptr; | ||
| if (!match(I, m_CombineOr(m_Select(m_OneUse(m_Cmp()), m_Value(NonRdxPhi), | ||
|
|
@@ -712,6 +716,17 @@ RecurrenceDescriptor::isFindIVPattern(RecurKind Kind, Loop *TheLoop, | |
| m_Value(NonRdxPhi))))) | ||
| return InstDesc(false, I); | ||
|
|
||
| if (isFindLastRecurrenceKind(Kind)) { | ||
|
Member
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. Above (not this line), this function is called
Member
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. There's also the comment above for |
||
| // Must be an integer scalar. | ||
MacDue marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| Type *Type = OrigPhi->getType(); | ||
| if (!Type->isIntegerTy()) | ||
| return InstDesc(false, I); | ||
|
|
||
| // FIXME: Support more complex patterns, including multiple selects. | ||
| // The Select must be used only outside the loop and by the PHI. | ||
| return InstDesc(I, RecurKind::FindLast); | ||
| } | ||
|
|
||
| // Returns either FindFirstIV/FindLastIV, if such a pattern is found, or | ||
| // std::nullopt. | ||
| auto GetRecurKind = [&](Value *V) -> std::optional<RecurKind> { | ||
|
|
@@ -920,8 +935,8 @@ RecurrenceDescriptor::InstDesc RecurrenceDescriptor::isRecurrenceInstr( | |
| Kind == RecurKind::Add || Kind == RecurKind::Mul || | ||
| Kind == RecurKind::Sub || Kind == RecurKind::AddChainWithSubs) | ||
| return isConditionalRdxPattern(I); | ||
| if (isFindIVRecurrenceKind(Kind) && SE) | ||
| return isFindIVPattern(Kind, L, OrigPhi, I, *SE); | ||
| if ((isFindIVRecurrenceKind(Kind) || isFindLastRecurrenceKind(Kind)) && SE) | ||
| return isFindPattern(Kind, L, OrigPhi, I, *SE); | ||
| [[fallthrough]]; | ||
| case Instruction::FCmp: | ||
| case Instruction::ICmp: | ||
|
|
@@ -1118,7 +1133,11 @@ bool RecurrenceDescriptor::isReductionPHI(PHINode *Phi, Loop *TheLoop, | |
| << "\n"); | ||
| return true; | ||
| } | ||
|
|
||
| if (AddReductionVar(Phi, RecurKind::FindLast, TheLoop, FMF, RedDes, DB, AC, | ||
| DT, SE)) { | ||
| LLVM_DEBUG(dbgs() << "Found a FindLast reduction PHI." << *Phi << "\n"); | ||
| return true; | ||
| } | ||
| // Not a reduction of known type. | ||
| return false; | ||
| } | ||
|
|
@@ -1248,6 +1267,8 @@ unsigned RecurrenceDescriptor::getOpcode(RecurKind Kind) { | |
| case RecurKind::FMaximumNum: | ||
| case RecurKind::FMinimumNum: | ||
| return Instruction::FCmp; | ||
| case RecurKind::FindLast: | ||
| return Instruction::Select; | ||
| default: | ||
| llvm_unreachable("Unknown recurrence operation"); | ||
| } | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -4045,6 +4045,7 @@ static bool willGenerateVectors(VPlan &Plan, ElementCount VF, | |
| continue; | ||
| case VPDef::VPReductionSC: | ||
| case VPDef::VPActiveLaneMaskPHISC: | ||
| case VPDef::VPLastActiveMaskPHISC: | ||
| case VPDef::VPWidenCallSC: | ||
| case VPDef::VPWidenCanonicalIVSC: | ||
| case VPDef::VPWidenCastSC: | ||
|
|
@@ -4265,11 +4266,15 @@ bool LoopVectorizationPlanner::isCandidateForEpilogueVectorization( | |
| ElementCount VF) const { | ||
| // Cross iteration phis such as fixed-order recurrences and FMaxNum/FMinNum | ||
| // reductions need special handling and are currently unsupported. | ||
| // FindLast reductions also require special handling for the synthesized | ||
| // mask PHI. | ||
| if (any_of(OrigLoop->getHeader()->phis(), [&](PHINode &Phi) { | ||
| if (!Legal->isReductionVariable(&Phi)) | ||
| return Legal->isFixedOrderRecurrence(&Phi); | ||
| return RecurrenceDescriptor::isFPMinMaxNumRecurrenceKind( | ||
| Legal->getRecurrenceDescriptor(&Phi).getRecurrenceKind()); | ||
| RecurKind Kind = | ||
| Legal->getRecurrenceDescriptor(&Phi).getRecurrenceKind(); | ||
| return RecurrenceDescriptor::isFindLastRecurrenceKind(Kind) || | ||
| RecurrenceDescriptor::isFPMinMaxNumRecurrenceKind(Kind); | ||
| })) | ||
| return false; | ||
|
|
||
|
|
@@ -4559,6 +4564,12 @@ LoopVectorizationPlanner::selectInterleaveCount(VPlan &Plan, ElementCount VF, | |
| any_of(Plan.getVectorLoopRegion()->getEntryBasicBlock()->phis(), | ||
| IsaPred<VPReductionPHIRecipe>); | ||
|
|
||
| // FIXME: implement interleaving for FindLast transform correctly. | ||
| for (auto &[_, RdxDesc] : Legal->getReductionVars()) | ||
| if (RecurrenceDescriptor::isFindLastRecurrenceKind( | ||
| RdxDesc.getRecurrenceKind())) | ||
| return 1; | ||
|
|
||
| // If we did not calculate the cost for VF (because the user selected the VF) | ||
| // then we calculate the cost of VF here. | ||
| if (LoopCost == 0) { | ||
|
|
@@ -8488,6 +8499,10 @@ VPlanPtr LoopVectorizationPlanner::tryToBuildVPlanWithVPRecipes( | |
| *Plan, Builder)) | ||
| return nullptr; | ||
|
|
||
| // Create whole-vector selects for find-last recurrences. | ||
| VPlanTransforms::runPass(VPlanTransforms::convertFindLastRecurrences, *Plan, | ||
| RecipeBuilder); | ||
|
|
||
| if (useActiveLaneMask(Style)) { | ||
| // TODO: Move checks to VPlanTransforms::addActiveLaneMask once | ||
| // TailFoldingStyle is visible there. | ||
|
|
@@ -8581,10 +8596,11 @@ void LoopVectorizationPlanner::adjustRecipesForReductions( | |
| continue; | ||
|
|
||
| RecurKind Kind = PhiR->getRecurrenceKind(); | ||
| assert( | ||
| !RecurrenceDescriptor::isAnyOfRecurrenceKind(Kind) && | ||
| !RecurrenceDescriptor::isFindIVRecurrenceKind(Kind) && | ||
| "AnyOf and FindIV reductions are not allowed for in-loop reductions"); | ||
| assert(!RecurrenceDescriptor::isFindLastRecurrenceKind(Kind) && | ||
| !RecurrenceDescriptor::isAnyOfRecurrenceKind(Kind) && | ||
| !RecurrenceDescriptor::isFindIVRecurrenceKind(Kind) && | ||
| "AnyOf, FindIV, and FindLast reductions are not allowed for in-loop " | ||
| "reductions"); | ||
|
|
||
| // Collect the chain of "link" recipes for the reduction starting at PhiR. | ||
| SetVector<VPSingleDefRecipe *> Worklist; | ||
|
|
@@ -8884,7 +8900,8 @@ void LoopVectorizationPlanner::adjustRecipesForReductions( | |
| RecurKind RK = RdxDesc.getRecurrenceKind(); | ||
| if ((!RecurrenceDescriptor::isAnyOfRecurrenceKind(RK) && | ||
| !RecurrenceDescriptor::isFindIVRecurrenceKind(RK) && | ||
| !RecurrenceDescriptor::isMinMaxRecurrenceKind(RK))) { | ||
| !RecurrenceDescriptor::isMinMaxRecurrenceKind(RK) && | ||
| !RecurrenceDescriptor::isFindLastRecurrenceKind(RK))) { | ||
| VPBuilder PHBuilder(Plan->getVectorPreheader()); | ||
| VPValue *Iden = Plan->getOrAddLiveIn( | ||
| getRecurrenceIdentity(RK, PhiTy, RdxDesc.getFastMathFlags())); | ||
|
|
@@ -10006,6 +10023,21 @@ bool LoopVectorizePass::processLoop(Loop *L) { | |
| // Override IC if user provided an interleave count. | ||
| IC = UserIC > 0 ? UserIC : IC; | ||
|
|
||
| // FIXME: Enable interleaving for last_active reductions. | ||
|
Collaborator
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 would be required to enable interleaving?
Collaborator
Author
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. Completing the final reduction outside of the loop, especially the mask phis. |
||
| if (any_of(make_second_range(LVL.getReductionVars()), [&](auto &RdxDesc) { | ||
| return RecurrenceDescriptor::isFindLastRecurrenceKind( | ||
| RdxDesc.getRecurrenceKind()); | ||
| })) { | ||
| LLVM_DEBUG(dbgs() << "LV: Not interleaving without vectorization due " | ||
| << "to conditional scalar assignments.\n"); | ||
| IntDiagMsg = { | ||
| "ConditionalAssignmentPreventsScalarInterleaving", | ||
| "Unable to interleave without vectorization due to conditional " | ||
| "assignments"}; | ||
| InterleaveLoop = false; | ||
| IC = 1; | ||
| } | ||
|
|
||
| // Emit diagnostic messages, if any. | ||
| const char *VAPassName = Hints.vectorizeAnalysisPassName(); | ||
| if (!VectorizeLoop && !InterleaveLoop) { | ||
|
|
||
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.
If this is not type-agnostic, should this be reflected in the name of the recurrence kind?
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.
It isn't for the other FindFirst/FindLast (though that might be inferred by U/S Min/Max) or AnyOf. I think it's just the fp-based reduction types that are prefixed with an extra
F.I did experiment with treating FindLast separately in
AddReductionVarwhen it checks the type and everything was fine, but decided to leave that out of the initial patch.