@@ -3290,17 +3290,6 @@ void InnerLoopVectorizer::fixVectorizedLoop(VPTransformState &State,
3290
3290
if (EnableVPlanNativePath)
3291
3291
fixNonInductionPHIs (Plan, State);
3292
3292
3293
- // At this point every instruction in the original loop is widened to a
3294
- // vector form. Note that fixing reduction phis, as well as extracting the
3295
- // exit and resume values for fixed-order recurrences are already modeled in
3296
- // VPlan. All that remains to do here is to create a phi in the scalar
3297
- // pre-header for each fixed-order recurrence resume value.
3298
- // TODO: Also model creating phis in the scalar pre-header in VPlan.
3299
- for (const auto &[_, LO] : to_vector (Plan.getLiveOuts ())) {
3300
- if (!Legal->isFixedOrderRecurrence (LO->getPhi ()))
3301
- continue ;
3302
- }
3303
-
3304
3293
// Forget the original basic block.
3305
3294
PSE.getSE ()->forgetLoop (OrigLoop);
3306
3295
PSE.getSE ()->forgetBlockAndLoopDispositions ();
@@ -3337,8 +3326,6 @@ void InnerLoopVectorizer::fixVectorizedLoop(VPTransformState &State,
3337
3326
VectorLoop->getHeader (), Plan, State);
3338
3327
}
3339
3328
3340
- // Fix LCSSA phis not already fixed earlier. Extracts may need to be generated
3341
- // in the exit block, so update the builder.
3342
3329
State.Builder .SetInsertPoint (State.CFG .ExitBB ,
3343
3330
State.CFG .ExitBB ->getFirstNonPHIIt ());
3344
3331
for (const auto &KV : Plan.getLiveOuts ())
@@ -8485,9 +8472,59 @@ static void addUsersInExitBlock(VPBasicBlock *HeaderVPBB, Loop *OrigLoop,
8485
8472
Value *IncomingValue =
8486
8473
ExitPhi.getIncomingValueForBlock (ExitingBB);
8487
8474
VPValue *V = Builder.getVPValueOrAddLiveIn (IncomingValue, Plan);
8488
- Plan.addLiveOut (
8489
- &ExitPhi, V,
8490
- cast<VPBasicBlock>(Plan.getVectorLoopRegion ()->getSingleSuccessor ()));
8475
+ Plan.addLiveOut (&ExitPhi, V);
8476
+ }
8477
+ }
8478
+
8479
+ // / Feed a resume value for every FOR from the vector loop to the scalar loop,
8480
+ // / if middle block branches to scalar preheader, by introducing ExtractFromEnd
8481
+ // / and ResumePhi recipes in each, respectively, and a VPLiveOut which uses the
8482
+ // / latter and corresponds to the scalar header.
8483
+ static void addLiveOutsForFirstOrderRecurrences (VPlan &Plan) {
8484
+ VPRegionBlock *VectorRegion = Plan.getVectorLoopRegion ();
8485
+
8486
+ // Start by finding out if middle block branches to scalar preheader.
8487
+ // TODO: Should be replaced by
8488
+ // Plan->getScalarLoopRegion()->getSinglePredecessor() in the future once the
8489
+ // scalar region is modeled as well.
8490
+ VPBasicBlock *ScalarPHVPBB = nullptr ;
8491
+ auto *MiddleVPBB = cast<VPBasicBlock>(VectorRegion->getSingleSuccessor ());
8492
+ for (VPBlockBase *Succ : MiddleVPBB->getSuccessors ()) {
8493
+ if (isa<VPIRBasicBlock>(Succ))
8494
+ continue ;
8495
+ assert (!ScalarPHVPBB && " Two candidates for ScalarPHVPBB?" );
8496
+ ScalarPHVPBB = cast<VPBasicBlock>(Succ);
8497
+ }
8498
+ if (!ScalarPHVPBB)
8499
+ return ;
8500
+
8501
+ for (auto &H : VectorRegion->getEntryBasicBlock ()->phis ()) {
8502
+ auto *FOR = dyn_cast<VPFirstOrderRecurrencePHIRecipe>(&H);
8503
+ if (!FOR)
8504
+ continue ;
8505
+
8506
+ VPBuilder B (ScalarPHVPBB);
8507
+ VPBuilder MiddleBuilder (MiddleVPBB);
8508
+ // Reset insert point so new recipes are inserted before terminator and
8509
+ // condition, if there is either the former or both.
8510
+ if (auto *Terminator = MiddleVPBB->getTerminator ()) {
8511
+ auto *Condition = dyn_cast<VPInstruction>(Terminator->getOperand (0 ));
8512
+ assert ((!Condition || Condition->getParent () == MiddleVPBB) &&
8513
+ " Condition expected in MiddleVPBB" );
8514
+ MiddleBuilder.setInsertPoint (Condition ? Condition : Terminator);
8515
+ }
8516
+
8517
+ // Extract the resume value and create a new VPLiveOut for it.
8518
+ auto *Resume = MiddleBuilder.createNaryOp (
8519
+ VPInstruction::ExtractFromEnd,
8520
+ {FOR->getBackedgeValue (),
8521
+ Plan.getOrAddLiveIn (
8522
+ ConstantInt::get (Plan.getCanonicalIV ()->getScalarType (), 1 ))},
8523
+ {}, " vector.recur.extract" );
8524
+ auto *ResumePhiRecipe =
8525
+ B.createNaryOp (VPInstruction::ResumePhi, {Resume, FOR->getStartValue ()},
8526
+ {}, " scalar.recur.init" );
8527
+ Plan.addLiveOut (cast<PHINode>(FOR->getUnderlyingInstr ()), ResumePhiRecipe);
8491
8528
}
8492
8529
}
8493
8530
@@ -8655,48 +8692,7 @@ LoopVectorizationPlanner::tryToBuildVPlanWithVPRecipes(VFRange &Range) {
8655
8692
" VPBasicBlock" );
8656
8693
RecipeBuilder.fixHeaderPhis ();
8657
8694
8658
- auto *MiddleVPBB =
8659
- cast<VPBasicBlock>(Plan->getVectorLoopRegion ()->getSingleSuccessor ());
8660
-
8661
- VPBasicBlock *ScalarPH = nullptr ;
8662
- for (VPBlockBase *Succ : MiddleVPBB->getSuccessors ()) {
8663
- auto *VPBB = dyn_cast<VPBasicBlock>(Succ);
8664
- if (VPBB && !isa<VPIRBasicBlock>(VPBB)) {
8665
- ScalarPH = VPBB;
8666
- break ;
8667
- }
8668
- }
8669
-
8670
- if (ScalarPH) {
8671
- for (auto &H : HeaderVPBB->phis ()) {
8672
- auto *FOR = dyn_cast<VPFirstOrderRecurrencePHIRecipe>(&H);
8673
- if (!FOR)
8674
- continue ;
8675
- VPBuilder B (ScalarPH);
8676
- VPBuilder MiddleBuilder;
8677
- // Set insert point so new recipes are inserted before terminator and
8678
- // condition, if there is either the former or both.
8679
- if (MiddleVPBB->getNumSuccessors () != 2 )
8680
- MiddleBuilder.setInsertPoint (MiddleVPBB);
8681
- else if (isa<VPInstruction>(MiddleVPBB->getTerminator ()->getOperand (0 )))
8682
- MiddleBuilder.setInsertPoint (
8683
- &*std::prev (MiddleVPBB->getTerminator ()->getIterator ()));
8684
- else
8685
- MiddleBuilder.setInsertPoint (MiddleVPBB->getTerminator ());
8686
-
8687
- // Extract the resume value and create a new VPLiveOut for it.
8688
- auto *Resume = MiddleBuilder.createNaryOp (
8689
- VPInstruction::ExtractFromEnd,
8690
- {FOR->getBackedgeValue (),
8691
- Plan->getOrAddLiveIn (
8692
- ConstantInt::get (Plan->getCanonicalIV ()->getScalarType (), 1 ))},
8693
- {}, " vector.recur.extract" );
8694
- auto *R =
8695
- B.createNaryOp (VPInstruction::ExitPhi, {Resume, FOR->getStartValue ()},
8696
- {}, " scalar.recur.init" );
8697
- Plan->addLiveOut (cast<PHINode>(FOR->getUnderlyingInstr ()), R, ScalarPH);
8698
- }
8699
- }
8695
+ addLiveOutsForFirstOrderRecurrences (*Plan);
8700
8696
8701
8697
// ---------------------------------------------------------------------------
8702
8698
// Transform initial VPlan: Apply previously taken decisions, in order, to
0 commit comments