@@ -8864,56 +8864,56 @@ static void addScalarResumePhis(VPRecipeBuilder &Builder, VPlan &Plan) {
88648864 }
88658865}
88668866
8867- // Collect VPIRInstructions for phis in the original exit block that are modeled
8867+ // Collect VPIRInstructions for phis in the exit blocks that are modeled
88688868// in VPlan and add the exiting VPValue as operand. Some exiting values are not
88698869// modeled explicitly yet and won't be included. Those are un-truncated
88708870// VPWidenIntOrFpInductionRecipe, VPWidenPointerInductionRecipe and induction
88718871// increments.
8872- static SetVector<VPIRInstruction *> collectUsersInExitBlock (
8872+ static SetVector<VPIRInstruction *> collectUsersInExitBlocks (
88738873 Loop *OrigLoop, VPRecipeBuilder &Builder, VPlan &Plan,
88748874 const MapVector<PHINode *, InductionDescriptor> &Inductions) {
8875- auto *MiddleVPBB = Plan.getMiddleBlock ();
8876- // No edge from the middle block to the unique exit block has been inserted
8877- // and there is nothing to fix from vector loop; phis should have incoming
8878- // from scalar loop only.
8879- if (MiddleVPBB->getNumSuccessors () != 2 )
8880- return {};
88818875 SetVector<VPIRInstruction *> ExitUsersToFix;
8882- VPBasicBlock *ExitVPBB = cast<VPIRBasicBlock>(MiddleVPBB->getSuccessors ()[0 ]);
8883- BasicBlock *ExitingBB = OrigLoop->getExitingBlock ();
8884- for (VPRecipeBase &R : *ExitVPBB) {
8885- auto *ExitIRI = dyn_cast<VPIRInstruction>(&R);
8886- if (!ExitIRI)
8887- continue ;
8888- auto *ExitPhi = dyn_cast<PHINode>(&ExitIRI->getInstruction ());
8889- if (!ExitPhi)
8890- break ;
8891- Value *IncomingValue = ExitPhi->getIncomingValueForBlock (ExitingBB);
8892- VPValue *V = Builder.getVPValueOrAddLiveIn (IncomingValue);
8893- // Exit values for inductions are computed and updated outside of VPlan and
8894- // independent of induction recipes.
8895- // TODO: Compute induction exit values in VPlan.
8896- if ((isa<VPWidenIntOrFpInductionRecipe>(V) &&
8897- !cast<VPWidenIntOrFpInductionRecipe>(V)->getTruncInst ()) ||
8898- isa<VPWidenPointerInductionRecipe>(V) ||
8899- (isa<Instruction>(IncomingValue) &&
8900- OrigLoop->contains (cast<Instruction>(IncomingValue)) &&
8901- any_of (IncomingValue->users (), [&Inductions](User *U) {
8902- auto *P = dyn_cast<PHINode>(U);
8903- return P && Inductions.contains (P);
8904- })))
8905- continue ;
8906- ExitUsersToFix.insert (ExitIRI);
8907- ExitIRI->addOperand (V);
8876+ for (VPIRBasicBlock *ExitVPBB : Plan.getExitBlocks ()) {
8877+ BasicBlock *ExitBB = ExitVPBB->getIRBasicBlock ();
8878+ BasicBlock *ExitingBB = find_singleton<BasicBlock>(
8879+ to_vector (predecessors (ExitBB)),
8880+ [OrigLoop](BasicBlock *Pred, bool AllowRepeats) {
8881+ return OrigLoop->contains (Pred) ? Pred : nullptr ;
8882+ });
8883+ for (VPRecipeBase &R : *ExitVPBB) {
8884+ auto *ExitIRI = dyn_cast<VPIRInstruction>(&R);
8885+ if (!ExitIRI)
8886+ continue ;
8887+ auto *ExitPhi = dyn_cast<PHINode>(&ExitIRI->getInstruction ());
8888+ if (!ExitPhi)
8889+ break ;
8890+ Value *IncomingValue = ExitPhi->getIncomingValueForBlock (ExitingBB);
8891+ VPValue *V = Builder.getVPValueOrAddLiveIn (IncomingValue);
8892+ // Exit values for inductions are computed and updated outside of VPlan
8893+ // and independent of induction recipes.
8894+ // TODO: Compute induction exit values in VPlan.
8895+ if ((isa<VPWidenIntOrFpInductionRecipe>(V) &&
8896+ !cast<VPWidenIntOrFpInductionRecipe>(V)->getTruncInst ()) ||
8897+ isa<VPWidenPointerInductionRecipe>(V) ||
8898+ (isa<Instruction>(IncomingValue) &&
8899+ OrigLoop->contains (cast<Instruction>(IncomingValue)) &&
8900+ any_of (IncomingValue->users (), [&Inductions](User *U) {
8901+ auto *P = dyn_cast<PHINode>(U);
8902+ return P && Inductions.contains (P);
8903+ })))
8904+ continue ;
8905+ ExitUsersToFix.insert (ExitIRI);
8906+ ExitIRI->addOperand (V);
8907+ }
89088908 }
89098909 return ExitUsersToFix;
89108910}
89118911
89128912// Add exit values to \p Plan. Extracts are added for each entry in \p
89138913// ExitUsersToFix if needed and their operands are updated.
89148914static void
8915- addUsersInExitBlock (VPlan &Plan,
8916- const SetVector<VPIRInstruction *> &ExitUsersToFix) {
8915+ addUsersInExitBlocks (VPlan &Plan,
8916+ const SetVector<VPIRInstruction *> &ExitUsersToFix) {
89178917 if (ExitUsersToFix.empty ())
89188918 return ;
89198919
@@ -8929,6 +8929,8 @@ addUsersInExitBlock(VPlan &Plan,
89298929 if (V->isLiveIn ())
89308930 continue ;
89318931
8932+ assert (ExitIRI->getParent ()->getSinglePredecessor () == MiddleVPBB &&
8933+ " Exit value not handled yet for this edge." );
89328934 LLVMContext &Ctx = ExitIRI->getInstruction ().getContext ();
89338935 VPValue *Ext = B.createNaryOp (VPInstruction::ExtractFromEnd,
89348936 {V, Plan.getOrAddLiveIn (ConstantInt::get (
@@ -9206,10 +9208,10 @@ LoopVectorizationPlanner::tryToBuildVPlanWithVPRecipes(VFRange &Range) {
92069208 RecipeBuilder.fixHeaderPhis ();
92079209
92089210 addScalarResumePhis (RecipeBuilder, *Plan);
9209- SetVector<VPIRInstruction *> ExitUsersToFix = collectUsersInExitBlock (
9211+ SetVector<VPIRInstruction *> ExitUsersToFix = collectUsersInExitBlocks (
92109212 OrigLoop, RecipeBuilder, *Plan, Legal->getInductionVars ());
92119213 addExitUsersForFirstOrderRecurrences (*Plan, ExitUsersToFix);
9212- addUsersInExitBlock (*Plan, ExitUsersToFix);
9214+ addUsersInExitBlocks (*Plan, ExitUsersToFix);
92139215 // ---------------------------------------------------------------------------
92149216 // Transform initial VPlan: Apply previously taken decisions, in order, to
92159217 // bring the VPlan to its final state.
0 commit comments