@@ -7783,7 +7783,6 @@ DenseMap<const SCEV *, Value *> LoopVectorizationPlanner::executePlan(
77837783 LoopVectorizeHints Hints (L, true , *ORE);
77847784 Hints.setAlreadyVectorized ();
77857785 }
7786-
77877786 TargetTransformInfo::UnrollingPreferences UP;
77887787 TTI.getUnrollingPreferences (L, *PSE.getSE (), UP, ORE);
77897788 if (!UP.UnrollVectorizedLoop || CanonicalIVStartValue)
@@ -8882,61 +8881,73 @@ static void addScalarResumePhis(VPRecipeBuilder &Builder, VPlan &Plan) {
88828881static SetVector<VPIRInstruction *> collectUsersInExitBlocks (
88838882 Loop *OrigLoop, VPRecipeBuilder &Builder, VPlan &Plan,
88848883 const MapVector<PHINode *, InductionDescriptor> &Inductions) {
8884+ auto *MiddleVPBB = Plan.getMiddleBlock ();
88858885 SetVector<VPIRInstruction *> ExitUsersToFix;
88868886 for (VPIRBasicBlock *ExitVPBB : Plan.getExitBlocks ()) {
8887- BasicBlock *ExitBB = ExitVPBB->getIRBasicBlock ();
88888887 for (VPRecipeBase &R : *ExitVPBB) {
88898888 auto *ExitIRI = dyn_cast<VPIRInstruction>(&R);
88908889 if (!ExitIRI)
88918890 continue ;
88928891 auto *ExitPhi = dyn_cast<PHINode>(&ExitIRI->getInstruction ());
88938892 if (!ExitPhi)
88948893 break ;
8895- for (BasicBlock *ExitingBB : predecessors (ExitBB)) {
8896- if (!OrigLoop->contains (ExitingBB))
8897- continue ;
8898- Value *IncomingValue = ExitPhi->getIncomingValueForBlock (ExitingBB);
8899- VPValue *V = Builder.getVPValueOrAddLiveIn (IncomingValue);
8900- // Exit values for inductions are computed and updated outside of VPlan
8901- // and independent of induction recipes.
8902- // TODO: Compute induction exit values in VPlan.
8903- if ((isa<VPWidenIntOrFpInductionRecipe>(V) &&
8904- !cast<VPWidenIntOrFpInductionRecipe>(V)->getTruncInst ()) ||
8905- isa<VPWidenPointerInductionRecipe>(V) ||
8906- (isa<Instruction>(IncomingValue) &&
8907- OrigLoop->contains (cast<Instruction>(IncomingValue)) &&
8908- any_of (IncomingValue->users (), [&Inductions](User *U) {
8909- auto *P = dyn_cast<PHINode>(U);
8910- return P && Inductions.contains (P);
8911- })))
8912- continue ;
8913- ExitUsersToFix.insert (ExitIRI);
8914- ExitIRI->addOperand (V);
8894+ for (VPBlockBase *PredVPBB : ExitVPBB->getPredecessors ()) {
8895+ BasicBlock *ExitingBB = OrigLoop->getLoopLatch ();
8896+ if (PredVPBB != MiddleVPBB) {
8897+ SmallVector<BasicBlock *> ExitingBlocks;
8898+ OrigLoop->getExitingBlocks (ExitingBlocks);
8899+ assert (ExitingBlocks.size () == 2 && " only support 2 exiting blocks" );
8900+ ExitingBB = ExitingBB == ExitingBlocks[0 ] ? ExitingBlocks[1 ]
8901+ : ExitingBlocks[0 ];
8902+ }
8903+ Value *IncomingValue = ExitPhi->getIncomingValueForBlock (ExitingBB);
8904+ VPValue *V = Builder.getVPValueOrAddLiveIn (IncomingValue);
8905+ // Exit values for inductions are computed and updated outside of VPlan
8906+ // and independent of induction recipes.
8907+ // TODO: Compute induction exit values in VPlan.
8908+ if ((isa<VPWidenIntOrFpInductionRecipe>(V) &&
8909+ !cast<VPWidenIntOrFpInductionRecipe>(V)->getTruncInst ()) ||
8910+ isa<VPWidenPointerInductionRecipe>(V) ||
8911+ (isa<Instruction>(IncomingValue) &&
8912+ OrigLoop->contains (cast<Instruction>(IncomingValue)) &&
8913+ any_of (IncomingValue->users (), [&Inductions](User *U) {
8914+ auto *P = dyn_cast<PHINode>(U);
8915+ return P && Inductions.contains (P);
8916+ }))) {
8917+ if (ExitVPBB->getSinglePredecessor () == MiddleVPBB)
8918+ continue ;
8919+ }
8920+ ExitUsersToFix.insert (ExitIRI);
8921+ ExitIRI->addOperand (V);
89158922 }
89168923 }
89178924 }
89188925 return ExitUsersToFix;
89198926}
89208927
89218928// Add exit values to \p Plan. Extracts are added for each entry in \p
8922- // ExitUsersToFix if needed and their operands are updated.
8923- static void
8929+ // ExitUsersToFix if needed and their operands are updated. Returns true if all
8930+ // exit users can be handled, otherwise return false.
8931+ static bool
89248932addUsersInExitBlocks (VPlan &Plan,
89258933 const SetVector<VPIRInstruction *> &ExitUsersToFix) {
89268934 if (ExitUsersToFix.empty ())
8927- return ;
8935+ return true ;
8936+
8937+ auto *MiddleVPBB = Plan.getMiddleBlock ();
8938+ VPBuilder B (MiddleVPBB, MiddleVPBB->getFirstNonPhi ());
89288939
89298940 // Introduce extract for exiting values and update the VPIRInstructions
89308941 // modeling the corresponding LCSSA phis.
89318942 for (VPIRInstruction *ExitIRI : ExitUsersToFix) {
8932-
89338943 VPValue *V = ExitIRI->getOperand (0 );
89348944 // Pass live-in values used by exit phis directly through to their users in
89358945 // the exit block.
89368946 if (V->isLiveIn ())
89378947 continue ;
89388948
8939- // Currently only live-ins can be used by exit values from blocks not exiting via the vector latch through to the middle block.
8949+ // Currently only live-ins can be used by exit values from blocks not
8950+ // exiting via the vector latch through to the middle block.
89408951 if (ExitIRI->getParent ()->getSinglePredecessor () != MiddleVPBB)
89418952 return false ;
89428953
@@ -9218,31 +9229,19 @@ LoopVectorizationPlanner::tryToBuildVPlanWithVPRecipes(VFRange &Range) {
92189229 RecipeBuilder.fixHeaderPhis ();
92199230
92209231 if (Legal->hasUncountableEarlyExit ()) {
9232+ assert (Legal->getUncountableExitingBlocks ().size () == 1 &&
9233+ " Only single uncountable exiting bock supported" );
92219234 VPlanTransforms::handleUncountableEarlyExit (
9222- *Plan, *PSE.getSE (), OrigLoop, Legal->getUncountableExitingBlocks (),
9235+ *Plan, *PSE.getSE (), OrigLoop, Legal->getUncountableExitingBlocks ()[ 0 ] ,
92239236 RecipeBuilder);
92249237 }
92259238 addScalarResumePhis (RecipeBuilder, *Plan);
92269239 SetVector<VPIRInstruction *> ExitUsersToFix = collectUsersInExitBlocks (
92279240 OrigLoop, RecipeBuilder, *Plan, Legal->getInductionVars ());
92289241 addExitUsersForFirstOrderRecurrences (*Plan, ExitUsersToFix);
9229- if (!addUsersInExitBlocks (*Plan, ExitUsersToFix))
9230- <<<<<<< HEAD
9231-
9232- if (Legal->hasUncountableEarlyExit ()) {
9233- if (any_of (Plan->getExitBlocks (), [](VPIRBasicBlock *ExitBB) {
9234- return any_of (*ExitBB, [](VPRecipeBase &R) {
9235- auto VPIRI = cast<VPIRInstruction>(&R);
9236- return VPIRI->getNumOperands () == 0 ||
9237- any_of (VPIRI->operands (),
9238- [](VPValue *Op) { return !Op->isLiveIn (); });
9239- });
9240- }))
9241- return nullptr ;
9242- }
9242+ if (!addUsersInExitBlocks (*Plan, ExitUsersToFix))
9243+ return nullptr ;
92439244
9244- =======
9245- >>>>>>> origin/main
92469245 // ---------------------------------------------------------------------------
92479246 // Transform initial VPlan: Apply previously taken decisions, in order, to
92489247 // bring the VPlan to its final state.
@@ -9998,11 +9997,10 @@ bool LoopVectorizePass::processLoop(Loop *L) {
99989997 if (LVL.hasUncountableEarlyExit ()) {
99999998 if (!EnableEarlyExitVectorization) {
100009999 reportVectorizationFailure (" Auto-vectorization of loops with uncountable "
10001- " early exit is not yet supported " ,
10000+ " early exit is not enabled " ,
1000210001 " Auto-vectorization of loops with uncountable "
10003- " early exit is not yet supported" ,
10004- " UncountableEarlyExitLoopsUnsupported" , ORE,
10005- L);
10002+ " early exit is no enabled" ,
10003+ " UncountableEarlyExitLoopsDisabled" , ORE, L);
1000610004 return false ;
1000710005 }
1000810006 }
0 commit comments