@@ -8953,14 +8953,65 @@ static void addScalarResumePhis(VPRecipeBuilder &Builder, VPlan &Plan) {
8953
8953
}
8954
8954
}
8955
8955
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
+
8956
9007
// Collect VPIRInstructions for phis in the exit blocks that are modeled
8957
9008
// in VPlan and add the exiting VPValue as operand. Some exiting values are not
8958
9009
// modeled explicitly yet and won't be included. Those are un-truncated
8959
9010
// VPWidenIntOrFpInductionRecipe, VPWidenPointerInductionRecipe and induction
8960
9011
// increments.
8961
9012
static SetVector<VPIRInstruction *> collectUsersInExitBlocks(
8962
- Loop *OrigLoop, VPRecipeBuilder &Builder, VPlan &Plan,
8963
- const MapVector<PHINode *, InductionDescriptor> &Inductions ) {
9013
+ Loop *OrigLoop, VPRecipeBuilder &Builder, VPlan &Plan
9014
+ ) {
8964
9015
auto *MiddleVPBB = Plan.getMiddleBlock();
8965
9016
SetVector<VPIRInstruction *> ExitUsersToFix;
8966
9017
for (VPIRBasicBlock *ExitVPBB : Plan.getExitBlocks()) {
@@ -8985,18 +9036,8 @@ static SetVector<VPIRInstruction *> collectUsersInExitBlocks(
8985
9036
// Exit values for inductions are computed and updated outside of VPlan
8986
9037
// and independent of induction recipes.
8987
9038
// 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;
9000
9041
ExitUsersToFix.insert(ExitIRI);
9001
9042
ExitIRI->addOperand(V);
9002
9043
}
@@ -9332,7 +9373,7 @@ LoopVectorizationPlanner::tryToBuildVPlanWithVPRecipes(VFRange &Range) {
9332
9373
}
9333
9374
addScalarResumePhis(RecipeBuilder, *Plan);
9334
9375
SetVector<VPIRInstruction *> ExitUsersToFix = collectUsersInExitBlocks(
9335
- OrigLoop, RecipeBuilder, *Plan, Legal->getInductionVars() );
9376
+ OrigLoop, RecipeBuilder, *Plan);
9336
9377
addExitUsersForFirstOrderRecurrences(*Plan, ExitUsersToFix);
9337
9378
if (!addUsersInExitBlocks(*Plan, ExitUsersToFix)) {
9338
9379
reportVectorizationFailure(
0 commit comments