@@ -9989,6 +9989,77 @@ LoopVectorizePass::LoopVectorizePass(LoopVectorizeOptions Opts)
9989
9989
VectorizeOnlyWhenForced(Opts.VectorizeOnlyWhenForced ||
9990
9990
!EnableLoopVectorization) {}
9991
9991
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
+
9992
10063
bool LoopVectorizePass::processLoop (Loop *L) {
9993
10064
assert ((EnableVPlanNativePath || L->isInnermost ()) &&
9994
10065
" VPlan-native path is not enabled. Only process inner loops." );
@@ -10353,72 +10424,8 @@ bool LoopVectorizePass::processLoop(Loop *L) {
10353
10424
EpilogueVectorizerEpilogueLoop EpilogILV (L, PSE, LI, DT, TLI, TTI, AC,
10354
10425
ORE, EPI, &LVL, &CM, BFI, PSI,
10355
10426
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.
10367
10427
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);
10422
10429
10423
10430
assert (DT->verify (DominatorTree::VerificationLevel::Fast) &&
10424
10431
" DT not preserved correctly" );
0 commit comments