@@ -2777,6 +2777,23 @@ BasicBlock *InnerLoopVectorizer::createVectorizedLoopSkeleton(
27772777 return LoopVectorPreHeader;
27782778}
27792779
2780+ static bool isValueIncomingFromBlock (BasicBlock *ExitingBB, Value *V,
2781+ Instruction *UI) {
2782+ PHINode *PHI = dyn_cast<PHINode>(UI);
2783+ assert (PHI && " Expected LCSSA form" );
2784+
2785+ // If this loop has an uncountable early exit then there could be
2786+ // different users of OrigPhi with either:
2787+ // 1. Multiple users, because each exiting block (countable or
2788+ // uncountable) jumps to the same exit block, or ..
2789+ // 2. A single user with an incoming value from a countable or
2790+ // uncountable exiting block.
2791+ // In both cases there is no guarantee this came from a countable exiting
2792+ // block, i.e. the latch.
2793+ int Index = PHI->getBasicBlockIndex (ExitingBB);
2794+ return Index != -1 && PHI->getIncomingValue (Index) == V;
2795+ }
2796+
27802797// Fix up external users of the induction variable. At this point, we are
27812798// in LCSSA form, with all external PHIs that use the IV having one input value,
27822799// coming from the remainder loop. We need those PHIs to also have a correct
@@ -2799,12 +2816,13 @@ void InnerLoopVectorizer::fixupIVUsers(PHINode *OrigPhi,
27992816
28002817 // An external user of the last iteration's value should see the value that
28012818 // the remainder loop uses to initialize its own IV.
2802- Value *PostInc = OrigPhi->getIncomingValueForBlock (OrigLoop->getLoopLatch ());
2819+ BasicBlock *OrigLoopLatch = OrigLoop->getLoopLatch ();
2820+ Value *PostInc = OrigPhi->getIncomingValueForBlock (OrigLoopLatch);
28032821 for (User *U : PostInc->users ()) {
28042822 Instruction *UI = cast<Instruction>(U);
28052823 if (!OrigLoop->contains (UI)) {
2806- assert (isa<PHINode>(UI) && " Expected LCSSA form " );
2807- MissingVals[UI ] = EndValue;
2824+ if ( isValueIncomingFromBlock (OrigLoopLatch, PostInc, UI))
2825+ MissingVals[cast<PHINode>(UI) ] = EndValue;
28082826 }
28092827 }
28102828
@@ -2814,7 +2832,8 @@ void InnerLoopVectorizer::fixupIVUsers(PHINode *OrigPhi,
28142832 for (User *U : OrigPhi->users ()) {
28152833 auto *UI = cast<Instruction>(U);
28162834 if (!OrigLoop->contains (UI)) {
2817- assert (isa<PHINode>(UI) && " Expected LCSSA form" );
2835+ if (!isValueIncomingFromBlock (OrigLoopLatch, OrigPhi, UI))
2836+ continue ;
28182837 IRBuilder<> B (MiddleBlock->getTerminator ());
28192838
28202839 // Fast-math-flags propagate from the original induction instruction.
@@ -2844,18 +2863,6 @@ void InnerLoopVectorizer::fixupIVUsers(PHINode *OrigPhi,
28442863 }
28452864 }
28462865
2847- assert ((MissingVals.empty () ||
2848- all_of (MissingVals,
2849- [MiddleBlock, this ](const std::pair<Value *, Value *> &P) {
2850- return all_of (
2851- predecessors (cast<Instruction>(P.first )->getParent ()),
2852- [MiddleBlock, this ](BasicBlock *Pred) {
2853- return Pred == MiddleBlock ||
2854- Pred == OrigLoop->getLoopLatch ();
2855- });
2856- })) &&
2857- " Expected escaping values from latch/middle.block only" );
2858-
28592866 for (auto &I : MissingVals) {
28602867 PHINode *PHI = cast<PHINode>(I.first );
28612868 // One corner case we have to handle is two IVs "chasing" each-other,
@@ -7811,6 +7818,9 @@ DenseMap<const SCEV *, Value *> LoopVectorizationPlanner::executePlan(
78117818 State.LVer ->prepareNoAliasMetadata ();
78127819 }
78137820
7821+ // Set the uncountable early exit block in the VPTransformState.
7822+ State.CFG .UncountableEarlyExitBB = ILV.Legal ->getUncountableEarlyExitBlock ();
7823+
78147824 ILV.printDebugTracesAtStart ();
78157825
78167826 // ===------------------------------------------------===//
@@ -9237,14 +9247,20 @@ collectUsersInExitBlocks(Loop *OrigLoop, VPRecipeBuilder &Builder,
92379247// Add exit values to \p Plan. Extracts are added for each entry in \p
92389248// ExitUsersToFix if needed and their operands are updated. Returns true if all
92399249// exit users can be handled, otherwise return false.
9240- static bool
9250+ static void
92419251addUsersInExitBlocks (VPlan &Plan,
92429252 const SetVector<VPIRInstruction *> &ExitUsersToFix) {
92439253 if (ExitUsersToFix.empty ())
9244- return true ;
9254+ return ;
92459255
92469256 auto *MiddleVPBB = Plan.getMiddleBlock ();
9247- VPBuilder B (MiddleVPBB, MiddleVPBB->getFirstNonPhi ());
9257+ VPBuilder MiddleB (MiddleVPBB, MiddleVPBB->getFirstNonPhi ());
9258+ VPBuilder EarlyExitB;
9259+ VPBasicBlock *VectorEarlyExitVPBB = Plan.getEarlyExit ();
9260+ VPValue *EarlyExitMask = nullptr ;
9261+ if (VectorEarlyExitVPBB)
9262+ EarlyExitB.setInsertPoint (VectorEarlyExitVPBB,
9263+ VectorEarlyExitVPBB->getFirstNonPhi ());
92489264
92499265 // Introduce extract for exiting values and update the VPIRInstructions
92509266 // modeling the corresponding LCSSA phis.
@@ -9255,19 +9271,38 @@ addUsersInExitBlocks(VPlan &Plan,
92559271 if (Op->isLiveIn ())
92569272 continue ;
92579273
9258- // Currently only live-ins can be used by exit values from blocks not
9259- // exiting via the vector latch through to the middle block.
9260- if (ExitIRI->getParent ()->getSinglePredecessor () != MiddleVPBB)
9261- return false ;
9262-
92639274 LLVMContext &Ctx = ExitIRI->getInstruction ().getContext ();
9264- VPValue *Ext = B.createNaryOp (VPInstruction::ExtractFromEnd,
9265- {Op, Plan.getOrAddLiveIn (ConstantInt::get (
9266- IntegerType::get (Ctx, 32 ), 1 ))});
9275+ VPValue *Ext;
9276+ VPBasicBlock *PredVPBB =
9277+ cast<VPBasicBlock>(ExitIRI->getParent ()->getPredecessors ()[Idx]);
9278+ if (PredVPBB != MiddleVPBB) {
9279+ assert (ExitIRI->getParent ()->getNumPredecessors () <= 2 );
9280+
9281+ // Cache the early exit mask
9282+ if (!EarlyExitMask) {
9283+ VPBasicBlock *MiddleSplitVPBB =
9284+ cast<VPBasicBlock>(VectorEarlyExitVPBB->getSinglePredecessor ());
9285+ VPInstruction *PredTerm =
9286+ cast<VPInstruction>(MiddleSplitVPBB->getTerminator ());
9287+ assert (PredTerm->getOpcode () == VPInstruction::BranchOnCond &&
9288+ " Unexpected middle split block terminator" );
9289+ VPInstruction *ScalarCond =
9290+ cast<VPInstruction>(PredTerm->getOperand (0 ));
9291+ assert (
9292+ ScalarCond->getOpcode () == VPInstruction::AnyOf &&
9293+ " Unexpected condition for middle split block terminator branch" );
9294+ EarlyExitMask = ScalarCond->getOperand (0 );
9295+ }
9296+ Ext = EarlyExitB.createNaryOp (VPInstruction::ExtractFirstActive,
9297+ {Op, EarlyExitMask});
9298+ } else {
9299+ Ext = MiddleB.createNaryOp (VPInstruction::ExtractFromEnd,
9300+ {Op, Plan.getOrAddLiveIn (ConstantInt::get (
9301+ IntegerType::get (Ctx, 32 ), 1 ))});
9302+ }
92679303 ExitIRI->setOperand (Idx, Ext);
92689304 }
92699305 }
9270- return true ;
92719306}
92729307
92739308// / Handle users in the exit block for first order reductions in the original
@@ -9570,12 +9605,7 @@ LoopVectorizationPlanner::tryToBuildVPlanWithVPRecipes(VFRange &Range) {
95709605 SetVector<VPIRInstruction *> ExitUsersToFix =
95719606 collectUsersInExitBlocks (OrigLoop, RecipeBuilder, *Plan);
95729607 addExitUsersForFirstOrderRecurrences (*Plan, ExitUsersToFix);
9573- if (!addUsersInExitBlocks (*Plan, ExitUsersToFix)) {
9574- reportVectorizationFailure (
9575- " Some exit values in loop with uncountable exit not supported yet" ,
9576- " UncountableEarlyExitLoopsUnsupportedExitValue" , ORE, OrigLoop);
9577- return nullptr ;
9578- }
9608+ addUsersInExitBlocks (*Plan, ExitUsersToFix);
95799609
95809610 // ---------------------------------------------------------------------------
95819611 // Transform initial VPlan: Apply previously taken decisions, in order, to
0 commit comments