@@ -607,10 +607,6 @@ class InnerLoopVectorizer {
607607 BasicBlock *MiddleBlock, BasicBlock *VectorHeader,
608608 VPlan &Plan, VPTransformState &State);
609609
610- // / Create the phi node for the resume value of first order recurrences in the
611- // / scalar preheader and update the users in the scalar loop.
612- void fixFixedOrderRecurrence (VPLiveOut *LO, VPTransformState &State);
613-
614610 // / Iteratively sink the scalarized operands of a predicated instruction into
615611 // / the block that was created for it.
616612 void sinkScalarOperands (Instruction *PredInst);
@@ -3339,8 +3335,6 @@ void InnerLoopVectorizer::fixVectorizedLoop(VPTransformState &State,
33393335 for (const auto &[_, LO] : to_vector (Plan.getLiveOuts ())) {
33403336 if (!Legal->isFixedOrderRecurrence (LO->getPhi ()))
33413337 continue ;
3342- fixFixedOrderRecurrence (LO, State);
3343- Plan.removeLiveOut (LO->getPhi ());
33443338 }
33453339
33463340 // Forget the original basic block.
@@ -3422,35 +3416,6 @@ static void reorderIncomingBlocks(SmallVectorImpl<BasicBlock *> &Blocks,
34223416 std::swap (Blocks[0 ], Blocks[1 ]);
34233417}
34243418
3425- void InnerLoopVectorizer::fixFixedOrderRecurrence (VPLiveOut *LO,
3426- VPTransformState &State) {
3427- // Extract the last vector element in the middle block. This will be the
3428- // initial value for the recurrence when jumping to the scalar loop.
3429- VPValue *VPExtract = LO->getOperand (0 );
3430- using namespace llvm ::VPlanPatternMatch;
3431- assert (match (VPExtract, m_VPInstruction<VPInstruction::ExtractFromEnd>(
3432- m_VPValue (), m_VPValue ())) &&
3433- " FOR LiveOut expects to use an extract from end." );
3434- Value *ResumeScalarFOR = State.get (VPExtract, UF - 1 , true );
3435-
3436- // Fix the initial value of the original recurrence in the scalar loop.
3437- PHINode *ScalarHeaderPhi = LO->getPhi ();
3438- auto *InitScalarFOR =
3439- ScalarHeaderPhi->getIncomingValueForBlock (LoopScalarPreHeader);
3440- Builder.SetInsertPoint (LoopScalarPreHeader, LoopScalarPreHeader->begin ());
3441- auto *ScalarPreheaderPhi =
3442- Builder.CreatePHI (ScalarHeaderPhi->getType (), 2 , " scalar.recur.init" );
3443- SmallVector<BasicBlock *> Blocks (predecessors (LoopScalarPreHeader));
3444- reorderIncomingBlocks (Blocks, LoopMiddleBlock);
3445- for (auto *BB : Blocks) {
3446- auto *Incoming = BB == LoopMiddleBlock ? ResumeScalarFOR : InitScalarFOR;
3447- ScalarPreheaderPhi->addIncoming (Incoming, BB);
3448- }
3449- ScalarHeaderPhi->setIncomingValueForBlock (LoopScalarPreHeader,
3450- ScalarPreheaderPhi);
3451- ScalarHeaderPhi->setName (" scalar.recur" );
3452- }
3453-
34543419void InnerLoopVectorizer::sinkScalarOperands (Instruction *PredInst) {
34553420 // The basic block and loop containing the predicated instruction.
34563421 auto *PredBB = PredInst->getParent ();
@@ -8501,7 +8466,9 @@ static void addUsersInExitBlock(VPBasicBlock *HeaderVPBB, Loop *OrigLoop,
85018466 Value *IncomingValue =
85028467 ExitPhi.getIncomingValueForBlock (ExitingBB);
85038468 VPValue *V = Builder.getVPValueOrAddLiveIn (IncomingValue, Plan);
8504- Plan.addLiveOut (&ExitPhi, V);
8469+ Plan.addLiveOut (
8470+ &ExitPhi, V,
8471+ cast<VPBasicBlock>(Plan.getVectorLoopRegion ()->getSingleSuccessor ()));
85058472 }
85068473}
85078474
@@ -8681,6 +8648,49 @@ LoopVectorizationPlanner::tryToBuildVPlanWithVPRecipes(VFRange &Range) {
86818648 " VPBasicBlock" );
86828649 RecipeBuilder.fixHeaderPhis ();
86838650
8651+ auto *MiddleVPBB =
8652+ cast<VPBasicBlock>(Plan->getVectorLoopRegion ()->getSingleSuccessor ());
8653+
8654+ VPBasicBlock *ScalarPH = nullptr ;
8655+ for (VPBlockBase *Succ : MiddleVPBB->getSuccessors ()) {
8656+ auto *VPIRBB = dyn_cast<VPIRBasicBlock>(Succ);
8657+ if (VPIRBB && VPIRBB->getIRBasicBlock () == OrigLoop->getHeader ()) {
8658+ ScalarPH = VPIRBB;
8659+ break ;
8660+ }
8661+ }
8662+
8663+ if (ScalarPH) {
8664+ for (auto &H : HeaderVPBB->phis ()) {
8665+ auto *FOR = dyn_cast<VPFirstOrderRecurrencePHIRecipe>(&H);
8666+ if (!FOR)
8667+ continue ;
8668+ VPBuilder B (ScalarPH);
8669+ VPBuilder MiddleBuilder;
8670+ // Set insert point so new recipes are inserted before terminator and
8671+ // condition, if there is either the former or both.
8672+ if (MiddleVPBB->getNumSuccessors () != 2 )
8673+ MiddleBuilder.setInsertPoint (MiddleVPBB);
8674+ else if (isa<VPInstruction>(MiddleVPBB->getTerminator ()->getOperand (0 )))
8675+ MiddleBuilder.setInsertPoint (
8676+ &*std::prev (MiddleVPBB->getTerminator ()->getIterator ()));
8677+ else
8678+ MiddleBuilder.setInsertPoint (MiddleVPBB->getTerminator ());
8679+
8680+ // Extract the resume value and create a new VPLiveOut for it.
8681+ auto *Resume = MiddleBuilder.createNaryOp (
8682+ VPInstruction::ExtractFromEnd,
8683+ {FOR->getBackedgeValue (),
8684+ Plan->getOrAddLiveIn (
8685+ ConstantInt::get (Plan->getCanonicalIV ()->getScalarType (), 1 ))},
8686+ {}, " vector.recur.extract" );
8687+ auto *R =
8688+ B.createNaryOp (VPInstruction::ExitPhi, {Resume, FOR->getStartValue ()},
8689+ {}, " scalar.recur.init" );
8690+ Plan->addLiveOut (cast<PHINode>(FOR->getUnderlyingInstr ()), R, ScalarPH);
8691+ }
8692+ }
8693+
86848694 // ---------------------------------------------------------------------------
86858695 // Transform initial VPlan: Apply previously taken decisions, in order, to
86868696 // bring the VPlan to its final state.
0 commit comments