@@ -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