@@ -8864,56 +8864,56 @@ static void addScalarResumePhis(VPRecipeBuilder &Builder, VPlan &Plan) {
8864
8864
}
8865
8865
}
8866
8866
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
8868
8868
// in VPlan and add the exiting VPValue as operand. Some exiting values are not
8869
8869
// modeled explicitly yet and won't be included. Those are un-truncated
8870
8870
// VPWidenIntOrFpInductionRecipe, VPWidenPointerInductionRecipe and induction
8871
8871
// increments.
8872
- static SetVector<VPIRInstruction *> collectUsersInExitBlock (
8872
+ static SetVector<VPIRInstruction *> collectUsersInExitBlocks (
8873
8873
Loop *OrigLoop, VPRecipeBuilder &Builder, VPlan &Plan,
8874
8874
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 {};
8881
8875
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
+ }
8908
8908
}
8909
8909
return ExitUsersToFix;
8910
8910
}
8911
8911
8912
8912
// Add exit values to \p Plan. Extracts are added for each entry in \p
8913
8913
// ExitUsersToFix if needed and their operands are updated.
8914
8914
static void
8915
- addUsersInExitBlock (VPlan &Plan,
8916
- const SetVector<VPIRInstruction *> &ExitUsersToFix) {
8915
+ addUsersInExitBlocks (VPlan &Plan,
8916
+ const SetVector<VPIRInstruction *> &ExitUsersToFix) {
8917
8917
if (ExitUsersToFix.empty ())
8918
8918
return ;
8919
8919
@@ -8929,6 +8929,8 @@ addUsersInExitBlock(VPlan &Plan,
8929
8929
if (V->isLiveIn ())
8930
8930
continue ;
8931
8931
8932
+ assert (ExitIRI->getParent ()->getSinglePredecessor () == MiddleVPBB &&
8933
+ " Exit value not handled yet for this edge." );
8932
8934
LLVMContext &Ctx = ExitIRI->getInstruction ().getContext ();
8933
8935
VPValue *Ext = B.createNaryOp (VPInstruction::ExtractFromEnd,
8934
8936
{V, Plan.getOrAddLiveIn (ConstantInt::get (
@@ -9206,10 +9208,10 @@ LoopVectorizationPlanner::tryToBuildVPlanWithVPRecipes(VFRange &Range) {
9206
9208
RecipeBuilder.fixHeaderPhis ();
9207
9209
9208
9210
addScalarResumePhis (RecipeBuilder, *Plan);
9209
- SetVector<VPIRInstruction *> ExitUsersToFix = collectUsersInExitBlock (
9211
+ SetVector<VPIRInstruction *> ExitUsersToFix = collectUsersInExitBlocks (
9210
9212
OrigLoop, RecipeBuilder, *Plan, Legal->getInductionVars ());
9211
9213
addExitUsersForFirstOrderRecurrences (*Plan, ExitUsersToFix);
9212
- addUsersInExitBlock (*Plan, ExitUsersToFix);
9214
+ addUsersInExitBlocks (*Plan, ExitUsersToFix);
9213
9215
// ---------------------------------------------------------------------------
9214
9216
// Transform initial VPlan: Apply previously taken decisions, in order, to
9215
9217
// bring the VPlan to its final state.
0 commit comments