@@ -8819,55 +8819,59 @@ static void addScalarResumePhis(VPRecipeBuilder &Builder, VPlan &Plan) {
88198819 }
88208820}
88218821
8822- // Collect VPIRInstructions for phis in the original exit block that are modeled
8822+ // Collect VPIRInstructions for phis in the exit blocks that are modeled
88238823// in VPlan and add the exiting VPValue as operand. Some exiting values are not
88248824// modeled explicitly yet and won't be included. Those are un-truncated
88258825// VPWidenIntOrFpInductionRecipe, VPWidenPointerInductionRecipe and induction
88268826// increments.
8827- static SetVector<VPIRInstruction *> collectUsersInExitBlock (
8827+ static SetVector<VPIRInstruction *> collectUsersInExitBlocks (
88288828 Loop *OrigLoop, VPRecipeBuilder &Builder, VPlan &Plan,
88298829 const MapVector<PHINode *, InductionDescriptor> &Inductions) {
8830- auto *MiddleVPBB = Plan.getMiddleBlock ();
8831- // No edge from the middle block to the unique exit block has been inserted
8832- // and there is nothing to fix from vector loop; phis should have incoming
8833- // from scalar loop only.
8834- if (MiddleVPBB->getNumSuccessors () != 2 )
8835- return {};
88368830 SetVector<VPIRInstruction *> ExitUsersToFix;
8837- VPBasicBlock *ExitVPBB = cast<VPIRBasicBlock>(MiddleVPBB->getSuccessors ()[0 ]);
8838- BasicBlock *ExitingBB = OrigLoop->getExitingBlock ();
8839- for (VPRecipeBase &R : *ExitVPBB) {
8840- auto *ExitIRI = dyn_cast<VPIRInstruction>(&R);
8841- if (!ExitIRI)
8842- continue ;
8843- auto *ExitPhi = dyn_cast<PHINode>(&ExitIRI->getInstruction ());
8844- if (!ExitPhi)
8845- break ;
8846- Value *IncomingValue = ExitPhi->getIncomingValueForBlock (ExitingBB);
8847- VPValue *V = Builder.getVPValueOrAddLiveIn (IncomingValue);
8848- // Exit values for inductions are computed and updated outside of VPlan and
8849- // independent of induction recipes.
8850- // TODO: Compute induction exit values in VPlan.
8851- if ((isa<VPWidenIntOrFpInductionRecipe>(V) &&
8852- !cast<VPWidenIntOrFpInductionRecipe>(V)->getTruncInst ()) ||
8853- isa<VPWidenPointerInductionRecipe>(V) ||
8854- (isa<Instruction>(IncomingValue) &&
8855- OrigLoop->contains (cast<Instruction>(IncomingValue)) &&
8856- any_of (IncomingValue->users (), [&Inductions](User *U) {
8857- auto *P = dyn_cast<PHINode>(U);
8858- return P && Inductions.contains (P);
8859- })))
8831+ for (VPBlockBase *VPB : vp_depth_first_shallow (
8832+ Plan.getVectorLoopRegion ()->getSingleSuccessor ())) {
8833+ if (VPB->getNumSuccessors () != 0 || VPB == Plan.getScalarHeader ())
88608834 continue ;
8861- ExitUsersToFix.insert (ExitIRI);
8862- ExitIRI->addOperand (V);
8835+ auto *ExitVPBB = cast<VPIRBasicBlock>(VPB);
8836+ BasicBlock *ExitBB = ExitVPBB->getIRBasicBlock ();
8837+ BasicBlock *ExitingBB = find_singleton<BasicBlock>(
8838+ to_vector (predecessors (ExitBB)),
8839+ [OrigLoop](BasicBlock *Pred, bool AllowRepeats) {
8840+ return OrigLoop->contains (Pred) ? Pred : nullptr ;
8841+ });
8842+ for (VPRecipeBase &R : *ExitVPBB) {
8843+ auto *ExitIRI = dyn_cast<VPIRInstruction>(&R);
8844+ if (!ExitIRI)
8845+ continue ;
8846+ auto *ExitPhi = dyn_cast<PHINode>(&ExitIRI->getInstruction ());
8847+ if (!ExitPhi)
8848+ break ;
8849+ Value *IncomingValue = ExitPhi->getIncomingValueForBlock (ExitingBB);
8850+ VPValue *V = Builder.getVPValueOrAddLiveIn (IncomingValue);
8851+ // Exit values for inductions are computed and updated outside of VPlan
8852+ // and independent of induction recipes.
8853+ // TODO: Compute induction exit values in VPlan.
8854+ if ((isa<VPWidenIntOrFpInductionRecipe>(V) &&
8855+ !cast<VPWidenIntOrFpInductionRecipe>(V)->getTruncInst ()) ||
8856+ isa<VPWidenPointerInductionRecipe>(V) ||
8857+ (isa<Instruction>(IncomingValue) &&
8858+ OrigLoop->contains (cast<Instruction>(IncomingValue)) &&
8859+ any_of (IncomingValue->users (), [&Inductions](User *U) {
8860+ auto *P = dyn_cast<PHINode>(U);
8861+ return P && Inductions.contains (P);
8862+ })))
8863+ continue ;
8864+ ExitUsersToFix.insert (ExitIRI);
8865+ ExitIRI->addOperand (V);
8866+ }
88638867 }
88648868 return ExitUsersToFix;
88658869}
88668870
88678871// Add exit values to \p Plan. Extracts are added for each entry in \p
88688872// ExitUsersToFix if needed and their operands are updated.
88698873static void
8870- addUsersInExitBlock (VPlan &Plan,
8874+ addUsersInExitBlocks (VPlan &Plan,
88718875 const SetVector<VPIRInstruction *> &ExitUsersToFix) {
88728876 if (ExitUsersToFix.empty ())
88738877 return ;
@@ -9161,10 +9165,10 @@ LoopVectorizationPlanner::tryToBuildVPlanWithVPRecipes(VFRange &Range) {
91619165 RecipeBuilder.fixHeaderPhis ();
91629166
91639167 addScalarResumePhis (RecipeBuilder, *Plan);
9164- SetVector<VPIRInstruction *> ExitUsersToFix = collectUsersInExitBlock (
9168+ SetVector<VPIRInstruction *> ExitUsersToFix = collectUsersInExitBlocks (
91659169 OrigLoop, RecipeBuilder, *Plan, Legal->getInductionVars ());
91669170 addExitUsersForFirstOrderRecurrences (*Plan, ExitUsersToFix);
9167- addUsersInExitBlock (*Plan, ExitUsersToFix);
9171+ addUsersInExitBlocks (*Plan, ExitUsersToFix);
91689172 // ---------------------------------------------------------------------------
91699173 // Transform initial VPlan: Apply previously taken decisions, in order, to
91709174 // bring the VPlan to its final state.
0 commit comments