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