@@ -8953,14 +8953,65 @@ static void addScalarResumePhis(VPRecipeBuilder &Builder, VPlan &Plan) {
89538953 }
89548954}
89558955
8956+ static bool isIVUse (VPValue *Incoming) {
8957+ VPRecipeBase *IncomingDef = Incoming->getDefiningRecipe ();
8958+ if (!IncomingDef)
8959+ return false ;
8960+ auto *WideIV = dyn_cast<VPWidenInductionRecipe>(IncomingDef);
8961+ if (WideIV) {
8962+ return isa<VPWidenPointerInductionRecipe>(WideIV) || !cast<VPWidenIntOrFpInductionRecipe>(WideIV)->getTruncInst ();
8963+ }
8964+
8965+ if (IncomingDef->getNumOperands () != 2 )
8966+ return false ;
8967+ WideIV = dyn_cast<VPWidenInductionRecipe>(IncomingDef->getOperand (0 ));
8968+ if (!WideIV)
8969+ WideIV = dyn_cast<VPWidenInductionRecipe>(IncomingDef->getOperand (1 ));
8970+ if (!WideIV)
8971+ return false ;
8972+
8973+ using namespace VPlanPatternMatch ;
8974+ auto &ID = WideIV->getInductionDescriptor ();
8975+ switch (ID.getInductionOpcode ()) {
8976+ case Instruction::Add:
8977+ return match (Incoming,
8978+ m_c_Binary<Instruction::Add>(
8979+ m_VPValue (), m_Specific (WideIV->getStepValue ())));
8980+ case Instruction::FAdd:
8981+ return match (Incoming,
8982+ m_c_Binary<Instruction::FAdd>(
8983+ m_VPValue (), m_Specific (WideIV->getStepValue ())));
8984+ case Instruction::FSub:
8985+ return match (Incoming,
8986+ m_Binary<Instruction::FSub>(
8987+ m_VPValue (), m_Specific (WideIV->getStepValue ())));
8988+ case Instruction::Sub: {
8989+ VPValue *Step;
8990+ return match (Incoming,
8991+ m_Binary<Instruction::Sub>(m_VPValue (), m_VPValue (Step))) &&
8992+ Step->isLiveIn () && WideIV->getStepValue ()->isLiveIn () &&
8993+ (cast<ConstantInt>(Step->getLiveInIRValue ())->getValue () +
8994+ cast<ConstantInt>(WideIV->getStepValue ()->getLiveInIRValue ())
8995+ ->getValue ())
8996+ .isZero ();
8997+ }
8998+ default :
8999+ return ID.getKind () == InductionDescriptor::IK_PtrInduction &&
9000+ match (
9001+ Incoming,
9002+ m_GetElementPtr (m_VPValue (), m_Specific (WideIV->getStepValue ())));
9003+ }
9004+ llvm_unreachable (" should have been covered by switch above" );
9005+ }
9006+
89569007// Collect VPIRInstructions for phis in the exit blocks that are modeled
89579008// in VPlan and add the exiting VPValue as operand. Some exiting values are not
89589009// modeled explicitly yet and won't be included. Those are un-truncated
89599010// VPWidenIntOrFpInductionRecipe, VPWidenPointerInductionRecipe and induction
89609011// increments.
89619012static SetVector<VPIRInstruction *> collectUsersInExitBlocks (
8962- Loop *OrigLoop, VPRecipeBuilder &Builder, VPlan &Plan,
8963- const MapVector<PHINode *, InductionDescriptor> &Inductions ) {
9013+ Loop *OrigLoop, VPRecipeBuilder &Builder, VPlan &Plan
9014+ ) {
89649015 auto *MiddleVPBB = Plan.getMiddleBlock ();
89659016 SetVector<VPIRInstruction *> ExitUsersToFix;
89669017 for (VPIRBasicBlock *ExitVPBB : Plan.getExitBlocks ()) {
@@ -8985,18 +9036,8 @@ static SetVector<VPIRInstruction *> collectUsersInExitBlocks(
89859036 // Exit values for inductions are computed and updated outside of VPlan
89869037 // and independent of induction recipes.
89879038 // TODO: Compute induction exit values in VPlan.
8988- if ((isa<VPWidenIntOrFpInductionRecipe>(V) &&
8989- !cast<VPWidenIntOrFpInductionRecipe>(V)->getTruncInst ()) ||
8990- isa<VPWidenPointerInductionRecipe>(V) ||
8991- (isa<Instruction>(IncomingValue) &&
8992- OrigLoop->contains (cast<Instruction>(IncomingValue)) &&
8993- any_of (IncomingValue->users (), [&Inductions](User *U) {
8994- auto *P = dyn_cast<PHINode>(U);
8995- return P && Inductions.contains (P);
8996- }))) {
8997- if (ExitVPBB->getSinglePredecessor () == MiddleVPBB)
8998- continue ;
8999- }
9039+ if (isIVUse (V) && ExitVPBB->getSinglePredecessor () == MiddleVPBB)
9040+ continue ;
90009041 ExitUsersToFix.insert (ExitIRI);
90019042 ExitIRI->addOperand (V);
90029043 }
@@ -9332,7 +9373,7 @@ LoopVectorizationPlanner::tryToBuildVPlanWithVPRecipes(VFRange &Range) {
93329373 }
93339374 addScalarResumePhis (RecipeBuilder, *Plan);
93349375 SetVector<VPIRInstruction *> ExitUsersToFix = collectUsersInExitBlocks (
9335- OrigLoop, RecipeBuilder, *Plan, Legal-> getInductionVars () );
9376+ OrigLoop, RecipeBuilder, *Plan);
93369377 addExitUsersForFirstOrderRecurrences (*Plan, ExitUsersToFix);
93379378 if (!addUsersInExitBlocks (*Plan, ExitUsersToFix)) {
93389379 reportVectorizationFailure (
0 commit comments