Skip to content

Commit 4fd8dbc

Browse files
committed
[LV] Move code to prepare VPlan for epilogue vector loop to helper (NFC)
Move code to prepare the VPlan for the epilogue vector loop to a helper to reduce size and complexity of processLoop.
1 parent a92e3df commit 4fd8dbc

File tree

1 file changed

+72
-65
lines changed

1 file changed

+72
-65
lines changed

llvm/lib/Transforms/Vectorize/LoopVectorize.cpp

Lines changed: 72 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -9989,6 +9989,77 @@ LoopVectorizePass::LoopVectorizePass(LoopVectorizeOptions Opts)
99899989
VectorizeOnlyWhenForced(Opts.VectorizeOnlyWhenForced ||
99909990
!EnableLoopVectorization) {}
99919991

9992+
/// Prepare \p Plan for vectorizing the epilogue loop. That is, re-use expanded
9993+
/// SCEVs from \p ExpandedSCEVs and set resume values for header recipes.
9994+
static void
9995+
preparePlanForEpilogueVectorLoop(VPlan &Plan, Loop *L,
9996+
const SCEV2ValueTy &ExpandedSCEVs) {
9997+
VPRegionBlock *VectorLoop = Plan.getVectorLoopRegion();
9998+
VPBasicBlock *Header = VectorLoop->getEntryBasicBlock();
9999+
Header->setName("vec.epilog.vector.body");
10000+
10001+
// Re-use the trip count and steps expanded for the main loop, as
10002+
// skeleton creation needs it as a value that dominates both the scalar
10003+
// and vector epilogue loops
10004+
// TODO: This is a workaround needed for epilogue vectorization and it
10005+
// should be removed once induction resume value creation is done
10006+
// directly in VPlan.
10007+
for (auto &R : make_early_inc_range(*Plan.getPreheader())) {
10008+
auto *ExpandR = dyn_cast<VPExpandSCEVRecipe>(&R);
10009+
if (!ExpandR)
10010+
continue;
10011+
auto *ExpandedVal =
10012+
Plan.getOrAddLiveIn(ExpandedSCEVs.find(ExpandR->getSCEV())->second);
10013+
ExpandR->replaceAllUsesWith(ExpandedVal);
10014+
if (Plan.getTripCount() == ExpandR)
10015+
Plan.resetTripCount(ExpandedVal);
10016+
ExpandR->eraseFromParent();
10017+
}
10018+
10019+
// Ensure that the start values for any VPWidenIntOrFpInductionRecipe,
10020+
// VPWidenPointerInductionRecipe and VPReductionPHIRecipes are updated
10021+
// before vectorizing the epilogue loop.
10022+
for (VPRecipeBase &R : Header->phis()) {
10023+
if (isa<VPCanonicalIVPHIRecipe>(&R))
10024+
continue;
10025+
10026+
Value *ResumeV = nullptr;
10027+
// TODO: Move setting of resume values to prepareToExecute.
10028+
if (auto *ReductionPhi = dyn_cast<VPReductionPHIRecipe>(&R)) {
10029+
ResumeV = cast<PHINode>(ReductionPhi->getUnderlyingInstr())
10030+
->getIncomingValueForBlock(L->getLoopPreheader());
10031+
const RecurrenceDescriptor &RdxDesc =
10032+
ReductionPhi->getRecurrenceDescriptor();
10033+
RecurKind RK = RdxDesc.getRecurrenceKind();
10034+
if (RecurrenceDescriptor::isAnyOfRecurrenceKind(RK)) {
10035+
// VPReductionPHIRecipes for AnyOf reductions expect a boolean as
10036+
// start value; compare the final value from the main vector loop
10037+
// to the start value.
10038+
IRBuilder<> Builder(
10039+
cast<Instruction>(ResumeV)->getParent()->getFirstNonPHI());
10040+
ResumeV =
10041+
Builder.CreateICmpNE(ResumeV, RdxDesc.getRecurrenceStartValue());
10042+
}
10043+
} else {
10044+
// Retrieve the induction resume values for wide inductions from
10045+
// their original phi nodes in the scalar loop.
10046+
PHINode *IndPhi = nullptr;
10047+
if (auto *Ind = dyn_cast<VPWidenPointerInductionRecipe>(&R)) {
10048+
IndPhi = cast<PHINode>(Ind->getUnderlyingValue());
10049+
} else {
10050+
auto *WidenInd = cast<VPWidenIntOrFpInductionRecipe>(&R);
10051+
IndPhi = WidenInd->getPHINode();
10052+
}
10053+
// Hook up to the PHINode generated by a ResumePhi recipe of main
10054+
// loop VPlan, which feeds the scalar loop.
10055+
ResumeV = IndPhi->getIncomingValueForBlock(L->getLoopPreheader());
10056+
}
10057+
assert(ResumeV && "Must have a resume value");
10058+
VPValue *StartVal = Plan.getOrAddLiveIn(ResumeV);
10059+
cast<VPHeaderPHIRecipe>(&R)->setStartValue(StartVal);
10060+
}
10061+
}
10062+
999210063
bool LoopVectorizePass::processLoop(Loop *L) {
999310064
assert((EnableVPlanNativePath || L->isInnermost()) &&
999410065
"VPlan-native path is not enabled. Only process inner loops.");
@@ -10353,72 +10424,8 @@ bool LoopVectorizePass::processLoop(Loop *L) {
1035310424
EpilogueVectorizerEpilogueLoop EpilogILV(L, PSE, LI, DT, TLI, TTI, AC,
1035410425
ORE, EPI, &LVL, &CM, BFI, PSI,
1035510426
Checks, BestEpiPlan);
10356-
10357-
VPRegionBlock *VectorLoop = BestEpiPlan.getVectorLoopRegion();
10358-
VPBasicBlock *Header = VectorLoop->getEntryBasicBlock();
10359-
Header->setName("vec.epilog.vector.body");
10360-
10361-
// Re-use the trip count and steps expanded for the main loop, as
10362-
// skeleton creation needs it as a value that dominates both the scalar
10363-
// and vector epilogue loops
10364-
// TODO: This is a workaround needed for epilogue vectorization and it
10365-
// should be removed once induction resume value creation is done
10366-
// directly in VPlan.
1036710427
EpilogILV.setTripCount(MainILV.getTripCount());
10368-
for (auto &R : make_early_inc_range(*BestEpiPlan.getPreheader())) {
10369-
auto *ExpandR = dyn_cast<VPExpandSCEVRecipe>(&R);
10370-
if (!ExpandR)
10371-
continue;
10372-
auto *ExpandedVal = BestEpiPlan.getOrAddLiveIn(
10373-
ExpandedSCEVs.find(ExpandR->getSCEV())->second);
10374-
ExpandR->replaceAllUsesWith(ExpandedVal);
10375-
if (BestEpiPlan.getTripCount() == ExpandR)
10376-
BestEpiPlan.resetTripCount(ExpandedVal);
10377-
ExpandR->eraseFromParent();
10378-
}
10379-
10380-
// Ensure that the start values for any VPWidenIntOrFpInductionRecipe,
10381-
// VPWidenPointerInductionRecipe and VPReductionPHIRecipes are updated
10382-
// before vectorizing the epilogue loop.
10383-
for (VPRecipeBase &R : Header->phis()) {
10384-
if (isa<VPCanonicalIVPHIRecipe>(&R))
10385-
continue;
10386-
10387-
Value *ResumeV = nullptr;
10388-
// TODO: Move setting of resume values to prepareToExecute.
10389-
if (auto *ReductionPhi = dyn_cast<VPReductionPHIRecipe>(&R)) {
10390-
ResumeV = cast<PHINode>(ReductionPhi->getUnderlyingInstr())
10391-
->getIncomingValueForBlock(L->getLoopPreheader());
10392-
const RecurrenceDescriptor &RdxDesc =
10393-
ReductionPhi->getRecurrenceDescriptor();
10394-
RecurKind RK = RdxDesc.getRecurrenceKind();
10395-
if (RecurrenceDescriptor::isAnyOfRecurrenceKind(RK)) {
10396-
// VPReductionPHIRecipes for AnyOf reductions expect a boolean as
10397-
// start value; compare the final value from the main vector loop
10398-
// to the start value.
10399-
IRBuilder<> Builder(
10400-
cast<Instruction>(ResumeV)->getParent()->getFirstNonPHI());
10401-
ResumeV = Builder.CreateICmpNE(ResumeV,
10402-
RdxDesc.getRecurrenceStartValue());
10403-
}
10404-
} else {
10405-
// Retrieve the induction resume values for wide inductions from
10406-
// their original phi nodes in the scalar loop.
10407-
PHINode *IndPhi = nullptr;
10408-
if (auto *Ind = dyn_cast<VPWidenPointerInductionRecipe>(&R)) {
10409-
IndPhi = cast<PHINode>(Ind->getUnderlyingValue());
10410-
} else {
10411-
auto *WidenInd = cast<VPWidenIntOrFpInductionRecipe>(&R);
10412-
IndPhi = WidenInd->getPHINode();
10413-
}
10414-
// Hook up to the PHINode generated by a ResumePhi recipe of main
10415-
// loop VPlan, which feeds the scalar loop.
10416-
ResumeV = IndPhi->getIncomingValueForBlock(L->getLoopPreheader());
10417-
}
10418-
assert(ResumeV && "Must have a resume value");
10419-
VPValue *StartVal = BestEpiPlan.getOrAddLiveIn(ResumeV);
10420-
cast<VPHeaderPHIRecipe>(&R)->setStartValue(StartVal);
10421-
}
10428+
preparePlanForEpilogueVectorLoop(BestEpiPlan, L, ExpandedSCEVs);
1042210429

1042310430
assert(DT->verify(DominatorTree::VerificationLevel::Fast) &&
1042410431
"DT not preserved correctly");

0 commit comments

Comments
 (0)