@@ -523,7 +523,7 @@ class InnerLoopVectorizer {
523
523
// / and the resume values can come from an additional bypass block, the \p
524
524
// / AdditionalBypass pair provides information about the bypass block and the
525
525
// / end value on the edge from bypass to this loop.
526
- PHINode * createInductionResumeValue (
526
+ void createInductionResumeValue (
527
527
PHINode *OrigPhi, const InductionDescriptor &ID, Value *Step,
528
528
ArrayRef<BasicBlock *> BypassBlocks,
529
529
std::pair<BasicBlock *, Value *> AdditionalBypass = {nullptr , nullptr });
@@ -536,6 +536,11 @@ class InnerLoopVectorizer {
536
536
// / count of the original loop for both main loop and epilogue vectorization.
537
537
void setTripCount (Value *TC) { TripCount = TC; }
538
538
539
+ std::pair<BasicBlock *, Value *>
540
+ getInductionBypassValue (PHINode *OrigPhi) const {
541
+ return InductionBypassValues.find (OrigPhi)->second ;
542
+ }
543
+
539
544
protected:
540
545
friend class LoopVectorizationPlanner ;
541
546
@@ -675,6 +680,9 @@ class InnerLoopVectorizer {
675
680
// / for cleaning the checks, if vectorization turns out unprofitable.
676
681
GeneratedRTChecks &RTChecks;
677
682
683
+ // / Mapping of induction phis to their bypass values and bypass blocks.
684
+ DenseMap<PHINode *, std::pair<BasicBlock *, Value *>> InductionBypassValues;
685
+
678
686
VPlan &Plan;
679
687
};
680
688
@@ -2588,7 +2596,18 @@ void InnerLoopVectorizer::createVectorLoopSkeleton(StringRef Prefix) {
2588
2596
nullptr , Twine (Prefix) + " scalar.ph" );
2589
2597
}
2590
2598
2591
- PHINode *InnerLoopVectorizer::createInductionResumeValue (
2599
+ static void addOperandToPhiInVPIRBasicBlock (VPIRBasicBlock *VPBB, PHINode *P,
2600
+ VPValue *Op) {
2601
+ for (VPRecipeBase &R : *VPBB) {
2602
+ auto *IRI = cast<VPIRInstruction>(&R);
2603
+ if (&IRI->getInstruction () == P) {
2604
+ IRI->addOperand (Op);
2605
+ break ;
2606
+ }
2607
+ }
2608
+ }
2609
+
2610
+ void InnerLoopVectorizer::createInductionResumeValue (
2592
2611
PHINode *OrigPhi, const InductionDescriptor &II, Value *Step,
2593
2612
ArrayRef<BasicBlock *> BypassBlocks,
2594
2613
std::pair<BasicBlock *, Value *> AdditionalBypass) {
@@ -2623,27 +2642,28 @@ PHINode *InnerLoopVectorizer::createInductionResumeValue(
2623
2642
}
2624
2643
}
2625
2644
2626
- // Create phi nodes to merge from the backedge-taken check block.
2627
- PHINode *BCResumeVal =
2628
- PHINode::Create (OrigPhi->getType (), 3 , " bc.resume.val" ,
2629
- LoopScalarPreHeader->getFirstNonPHIIt ());
2630
- // Copy original phi DL over to the new one.
2631
- BCResumeVal->setDebugLoc (OrigPhi->getDebugLoc ());
2645
+ VPBasicBlock *MiddleVPBB =
2646
+ cast<VPBasicBlock>(Plan.getVectorLoopRegion ()->getSingleSuccessor ());
2632
2647
2633
- // The new PHI merges the original incoming value, in case of a bypass,
2634
- // or the value at the end of the vectorized loop.
2635
- BCResumeVal->addIncoming (EndValue, LoopMiddleBlock);
2648
+ VPBasicBlock *ScalarPHVPBB = nullptr ;
2649
+ if (MiddleVPBB->getNumSuccessors () == 2 ) {
2650
+ // Order is strict: first is the exit block, second is the scalar preheader.
2651
+ ScalarPHVPBB = cast<VPBasicBlock>(MiddleVPBB->getSuccessors ()[1 ]);
2652
+ } else {
2653
+ ScalarPHVPBB = cast<VPBasicBlock>(MiddleVPBB->getSingleSuccessor ());
2654
+ }
2636
2655
2637
- // Fix the scalar body counter (PHI node).
2638
- // The old induction's phi node in the scalar body needs the truncated
2639
- // value.
2640
- for (BasicBlock *BB : BypassBlocks)
2641
- BCResumeVal-> addIncoming (II. getStartValue ( ), BB );
2656
+ VPBuilder ScalarPHBuilder (ScalarPHVPBB);
2657
+ auto *ResumePhiRecipe = ScalarPHBuilder. createNaryOp (
2658
+ VPInstruction::ResumePhi,
2659
+ {Plan. getOrAddLiveIn (EndValue), Plan. getOrAddLiveIn (II. getStartValue ())},
2660
+ OrigPhi-> getDebugLoc ( ), " bc.resume.val " );
2642
2661
2643
- if (AdditionalBypass.first )
2644
- BCResumeVal->setIncomingValueForBlock (AdditionalBypass.first ,
2645
- EndValueFromAdditionalBypass);
2646
- return BCResumeVal;
2662
+ auto *ScalarLoopHeader =
2663
+ cast<VPIRBasicBlock>(ScalarPHVPBB->getSingleSuccessor ());
2664
+ addOperandToPhiInVPIRBasicBlock (ScalarLoopHeader, OrigPhi, ResumePhiRecipe);
2665
+ InductionBypassValues[OrigPhi] = {AdditionalBypass.first ,
2666
+ EndValueFromAdditionalBypass};
2647
2667
}
2648
2668
2649
2669
// / Return the expanded step for \p ID using \p ExpandedSCEVs to look up SCEV
@@ -2676,10 +2696,8 @@ void InnerLoopVectorizer::createInductionResumeValues(
2676
2696
for (const auto &InductionEntry : Legal->getInductionVars ()) {
2677
2697
PHINode *OrigPhi = InductionEntry.first ;
2678
2698
const InductionDescriptor &II = InductionEntry.second ;
2679
- PHINode *BCResumeVal = createInductionResumeValue (
2680
- OrigPhi, II, getExpandedStep (II, ExpandedSCEVs), LoopBypassBlocks,
2681
- AdditionalBypass);
2682
- OrigPhi->setIncomingValueForBlock (LoopScalarPreHeader, BCResumeVal);
2699
+ createInductionResumeValue (OrigPhi, II, getExpandedStep (II, ExpandedSCEVs),
2700
+ LoopBypassBlocks, AdditionalBypass);
2683
2701
}
2684
2702
}
2685
2703
@@ -7803,6 +7821,25 @@ EpilogueVectorizerMainLoop::createEpilogueVectorizedLoopSkeleton(
7803
7821
// the second pass for the scalar loop. The induction resume values for the
7804
7822
// inductions in the epilogue loop are created before executing the plan for
7805
7823
// the epilogue loop.
7824
+ for (VPRecipeBase &R :
7825
+ Plan.getVectorLoopRegion ()->getEntryBasicBlock ()->phis ()) {
7826
+ // Create induction resume values for both widened pointer and
7827
+ // integer/fp inductions and update the start value of the induction
7828
+ // recipes to use the resume value.
7829
+ PHINode *IndPhi = nullptr ;
7830
+ const InductionDescriptor *ID;
7831
+ if (auto *Ind = dyn_cast<VPWidenPointerInductionRecipe>(&R)) {
7832
+ IndPhi = cast<PHINode>(Ind->getUnderlyingValue ());
7833
+ ID = &Ind->getInductionDescriptor ();
7834
+ } else if (auto *WidenInd = dyn_cast<VPWidenIntOrFpInductionRecipe>(&R)) {
7835
+ IndPhi = WidenInd->getPHINode ();
7836
+ ID = &WidenInd->getInductionDescriptor ();
7837
+ } else
7838
+ continue ;
7839
+
7840
+ createInductionResumeValue (IndPhi, *ID, getExpandedStep (*ID, ExpandedSCEVs),
7841
+ LoopBypassBlocks);
7842
+ }
7806
7843
7807
7844
return {LoopVectorPreHeader, nullptr };
7808
7845
}
@@ -10293,23 +10330,16 @@ bool LoopVectorizePass::processLoop(Loop *L) {
10293
10330
RdxDesc.getRecurrenceStartValue ());
10294
10331
}
10295
10332
} else {
10296
- // Create induction resume values for both widened pointer and
10297
- // integer/fp inductions and update the start value of the induction
10298
- // recipes to use the resume value.
10333
+ // Retrive the induction resume values for wide inductions from
10334
+ // their original phi nodes in the scalar loop
10299
10335
PHINode *IndPhi = nullptr ;
10300
- const InductionDescriptor *ID;
10301
10336
if (auto *Ind = dyn_cast<VPWidenPointerInductionRecipe>(&R)) {
10302
10337
IndPhi = cast<PHINode>(Ind->getUnderlyingValue ());
10303
- ID = &Ind->getInductionDescriptor ();
10304
10338
} else {
10305
10339
auto *WidenInd = cast<VPWidenIntOrFpInductionRecipe>(&R);
10306
10340
IndPhi = WidenInd->getPHINode ();
10307
- ID = &WidenInd->getInductionDescriptor ();
10308
10341
}
10309
-
10310
- ResumeV = MainILV.createInductionResumeValue (
10311
- IndPhi, *ID, getExpandedStep (*ID, ExpandedSCEVs),
10312
- {EPI.MainLoopIterationCountCheck });
10342
+ ResumeV = IndPhi->getIncomingValueForBlock (L->getLoopPreheader ());
10313
10343
}
10314
10344
assert (ResumeV && " Must have a resume value" );
10315
10345
VPValue *StartVal = BestEpiPlan.getOrAddLiveIn (ResumeV);
@@ -10321,7 +10351,13 @@ bool LoopVectorizePass::processLoop(Loop *L) {
10321
10351
LVP.executePlan (EPI.EpilogueVF , EPI.EpilogueUF , BestEpiPlan, EpilogILV,
10322
10352
DT, true , &ExpandedSCEVs);
10323
10353
++LoopsEpilogueVectorized;
10354
+ BasicBlock *PH = L->getLoopPreheader ();
10324
10355
10356
+ for (const auto &[IVPhi, _] : LVL.getInductionVars ()) {
10357
+ auto *Inc = cast<PHINode>(IVPhi->getIncomingValueForBlock (PH));
10358
+ const auto &[BB, V] = EpilogILV.getInductionBypassValue (IVPhi);
10359
+ Inc->setIncomingValueForBlock (BB, V);
10360
+ }
10325
10361
if (!MainILV.areSafetyChecksAdded ())
10326
10362
DisableRuntimeUnroll = true ;
10327
10363
} else {
0 commit comments