@@ -8748,10 +8748,9 @@ static void addCanonicalIVRecipes(VPlan &Plan, Type *IdxTy, bool HasNUW,
8748
8748
// / Create and return a ResumePhi for \p WideIV, unless it is truncated. If the
8749
8749
// / induction recipe is not canonical, creates a VPDerivedIVRecipe to compute
8750
8750
// / the end value of the induction.
8751
- static VPValue *addResumePhiRecipeForInduction (
8751
+ static VPInstruction *addResumePhiRecipeForInduction (
8752
8752
VPWidenInductionRecipe *WideIV, VPBuilder &VectorPHBuilder,
8753
- VPBuilder &ScalarPHBuilder, VPTypeAnalysis &TypeInfo, VPValue *VectorTC,
8754
- DenseMap<VPValue *, VPValue *> &EndValues) {
8753
+ VPBuilder &ScalarPHBuilder, VPTypeAnalysis &TypeInfo, VPValue *VectorTC) {
8755
8754
auto *WideIntOrFp = dyn_cast<VPWidenIntOrFpInductionRecipe>(WideIV);
8756
8755
// Truncated wide inductions resume from the last lane of their vector value
8757
8756
// in the last vector iteration which is handled elsewhere.
@@ -8776,7 +8775,6 @@ static VPValue *addResumePhiRecipeForInduction(
8776
8775
ScalarTypeOfWideIV);
8777
8776
}
8778
8777
8779
- EndValues[WideIV] = EndValue;
8780
8778
auto *ResumePhiRecipe =
8781
8779
ScalarPHBuilder.createNaryOp (VPInstruction::ResumePhi, {EndValue, Start},
8782
8780
WideIV->getDebugLoc (), " bc.resume.val" );
@@ -8785,10 +8783,10 @@ static VPValue *addResumePhiRecipeForInduction(
8785
8783
8786
8784
// / Create resume phis in the scalar preheader for first-order recurrences,
8787
8785
// / reductions and inductions, and update the VPIRInstructions wrapping the
8788
- // / original phis in the scalar header.
8786
+ // / original phis in the scalar header. End values for inductions are added to
8787
+ // / \p IVEndValues.
8789
8788
static void addScalarResumePhis (VPRecipeBuilder &Builder, VPlan &Plan,
8790
- Loop *OrigLoop,
8791
- DenseMap<VPValue *, VPValue *> &EndValues) {
8789
+ DenseMap<VPValue *, VPValue *> &IVEndValues) {
8792
8790
VPTypeAnalysis TypeInfo (Plan.getCanonicalIV ()->getScalarType ());
8793
8791
auto *ScalarPH = Plan.getScalarPreheader ();
8794
8792
auto *MiddleVPBB = cast<VPBasicBlock>(ScalarPH->getSinglePredecessor ());
@@ -8806,9 +8804,10 @@ static void addScalarResumePhis(VPRecipeBuilder &Builder, VPlan &Plan,
8806
8804
8807
8805
auto *VectorPhiR = cast<VPHeaderPHIRecipe>(Builder.getRecipe (ScalarPhiI));
8808
8806
if (auto *WideIVR = dyn_cast<VPWidenInductionRecipe>(VectorPhiR)) {
8809
- if (VPValue *ResumePhi = addResumePhiRecipeForInduction (
8807
+ if (VPInstruction *ResumePhi = addResumePhiRecipeForInduction (
8810
8808
WideIVR, VectorPHBuilder, ScalarPHBuilder, TypeInfo,
8811
- &Plan.getVectorTripCount (), EndValues)) {
8809
+ &Plan.getVectorTripCount ())) {
8810
+ IVEndValues[WideIVR] = ResumePhi->getOperand (0 );
8812
8811
ScalarPhiIRI->addOperand (ResumePhi);
8813
8812
continue ;
8814
8813
}
@@ -8837,57 +8836,6 @@ static void addScalarResumePhis(VPRecipeBuilder &Builder, VPlan &Plan,
8837
8836
}
8838
8837
}
8839
8838
8840
- static bool isIVUse (VPValue *Incoming) {
8841
- VPRecipeBase *IncomingDef = Incoming->getDefiningRecipe ();
8842
- if (!IncomingDef)
8843
- return false ;
8844
- auto *WideIV = dyn_cast<VPWidenInductionRecipe>(IncomingDef);
8845
- if (WideIV) {
8846
- return isa<VPWidenPointerInductionRecipe>(WideIV) || !cast<VPWidenIntOrFpInductionRecipe>(WideIV)->getTruncInst ();
8847
- }
8848
-
8849
- if (IncomingDef->getNumOperands () != 2 )
8850
- return false ;
8851
- WideIV = dyn_cast<VPWidenInductionRecipe>(IncomingDef->getOperand (0 ));
8852
- if (!WideIV)
8853
- WideIV = dyn_cast<VPWidenInductionRecipe>(IncomingDef->getOperand (1 ));
8854
- if (!WideIV)
8855
- return false ;
8856
-
8857
- using namespace VPlanPatternMatch ;
8858
- auto &ID = WideIV->getInductionDescriptor ();
8859
- switch (ID.getInductionOpcode ()) {
8860
- case Instruction::Add:
8861
- return match (Incoming,
8862
- m_c_Binary<Instruction::Add>(
8863
- m_VPValue (), m_Specific (WideIV->getStepValue ())));
8864
- case Instruction::FAdd:
8865
- return match (Incoming,
8866
- m_c_Binary<Instruction::FAdd>(
8867
- m_VPValue (), m_Specific (WideIV->getStepValue ())));
8868
- case Instruction::FSub:
8869
- return match (Incoming,
8870
- m_Binary<Instruction::FSub>(
8871
- m_VPValue (), m_Specific (WideIV->getStepValue ())));
8872
- case Instruction::Sub: {
8873
- VPValue *Step;
8874
- return match (Incoming,
8875
- m_Binary<Instruction::Sub>(m_VPValue (), m_VPValue (Step))) &&
8876
- Step->isLiveIn () && WideIV->getStepValue ()->isLiveIn () &&
8877
- (cast<ConstantInt>(Step->getLiveInIRValue ())->getValue () +
8878
- cast<ConstantInt>(WideIV->getStepValue ()->getLiveInIRValue ())
8879
- ->getValue ())
8880
- .isZero ();
8881
- }
8882
- default :
8883
- return ID.getKind () == InductionDescriptor::IK_PtrInduction &&
8884
- match (
8885
- Incoming,
8886
- m_GetElementPtr (m_VPValue (), m_Specific (WideIV->getStepValue ())));
8887
- }
8888
- llvm_unreachable (" should have been covered by switch above" );
8889
- }
8890
-
8891
8839
// Collect VPIRInstructions for phis in the exit blocks that are modeled
8892
8840
// in VPlan and add the exiting VPValue as operand. Some exiting values are not
8893
8841
// modeled explicitly yet and won't be included. Those are un-truncated
@@ -8925,80 +8873,13 @@ collectUsersInExitBlocks(Loop *OrigLoop, VPRecipeBuilder &Builder,
8925
8873
return ExitUsersToFix;
8926
8874
}
8927
8875
8928
- // / If \p Incoming is a user of a non-truncated induction, create recipes to
8929
- // / compute the final value and update the user \p ExitIRI.
8930
- static bool addInductionEndValue (
8931
- VPlan &Plan, VPIRInstruction *ExitIRI, VPValue *Incoming,
8932
- const MapVector<PHINode *, InductionDescriptor> &Inductions,
8933
- DenseMap<VPValue *, VPValue *> &EndValues, VPTypeAnalysis &TypeInfo) {
8934
- if ((isa<VPWidenIntOrFpInductionRecipe>(Incoming) &&
8935
- !cast<VPWidenIntOrFpInductionRecipe>(Incoming)->getTruncInst ()) ||
8936
- isa<VPWidenPointerInductionRecipe>(Incoming) ||
8937
- (isa<Instruction>(Incoming->getUnderlyingValue ()) &&
8938
- any_of (cast<Instruction>(Incoming->getUnderlyingValue ())->users (),
8939
- [&Inductions](User *U) {
8940
- auto *P = dyn_cast<PHINode>(U);
8941
- return P && Inductions.contains (P);
8942
- }))) {
8943
- VPValue *IV;
8944
- if (auto *WideIV =
8945
- dyn_cast<VPWidenInductionRecipe>(Incoming->getDefiningRecipe ()))
8946
- IV = WideIV;
8947
- else if (auto *WideIV =
8948
- dyn_cast<VPWidenInductionRecipe>(Incoming->getDefiningRecipe ()
8949
- ->getOperand (0 )
8950
- ->getDefiningRecipe ()))
8951
- IV = WideIV;
8952
- else
8953
- IV = Incoming->getDefiningRecipe ()->getOperand (1 );
8954
- // Skip phi nodes already updated. This can be the case if 2 induction
8955
- // phis chase each other.
8956
- VPValue *EndValue = EndValues[IV];
8957
- if (any_of (cast<VPRecipeBase>(Incoming->getDefiningRecipe ())->operands (),
8958
- IsaPred<VPWidenIntOrFpInductionRecipe,
8959
- VPWidenPointerInductionRecipe>)) {
8960
- ExitIRI->setOperand (0 , EndValue);
8961
- return true ;
8962
- }
8963
-
8964
- VPBuilder B (Plan.getMiddleBlock ()->getTerminator ());
8965
- VPValue *Escape = nullptr ;
8966
- auto *WideIV = cast<VPWidenInductionRecipe>(IV->getDefiningRecipe ());
8967
- VPValue *Step = WideIV->getStepValue ();
8968
- Type *ScalarTy = TypeInfo.inferScalarType (WideIV);
8969
- if (ScalarTy->isIntegerTy ())
8970
- Escape =
8971
- B.createNaryOp (Instruction::Sub, {EndValue, Step}, {}, " ind.escape" );
8972
- else if (ScalarTy->isPointerTy ())
8973
- Escape = B.createPtrAdd (
8974
- EndValue,
8975
- B.createNaryOp (Instruction::Sub,
8976
- {Plan.getOrAddLiveIn (ConstantInt::get (
8977
- Step->getLiveInIRValue ()->getType (), 0 )),
8978
- Step}),
8979
- {}, " ind.escape" );
8980
- else if (ScalarTy->isFloatingPointTy ()) {
8981
- const auto &ID = WideIV->getInductionDescriptor ();
8982
- Escape = B.createNaryOp (
8983
- ID.getInductionBinOp ()->getOpcode () == Instruction::FAdd
8984
- ? Instruction::FSub
8985
- : Instruction::FAdd,
8986
- {EndValue, Step}, {ID.getInductionBinOp ()->getFastMathFlags ()});
8987
- } else {
8988
- llvm_unreachable (" all possible induction types must be handled" );
8989
- }
8990
- ExitIRI->setOperand (0 , Escape);
8991
- return true ;
8992
- }
8993
- return false ;
8994
- }
8995
8876
// Add exit values to \p Plan. Extracts are added for each entry in \p
8996
8877
// ExitUsersToFix if needed and their operands are updated. Returns true if all
8997
8878
// exit users can be handled, otherwise return false.
8998
- static bool addUsersInExitBlocks (
8999
- VPlan &Plan, const SetVector<VPIRInstruction *> &ExitUsersToFix ,
9000
- const MapVector<PHINode *, InductionDescriptor > &Inductions ,
9001
- DenseMap<VPValue *, VPValue *> &EndValues ) {
8879
+ static bool
8880
+ addUsersInExitBlocks ( VPlan &Plan,
8881
+ const SetVector<VPIRInstruction * > &ExitUsersToFix ,
8882
+ DenseMap<VPValue *, VPValue *> &IVEndValues ) {
9002
8883
if (ExitUsersToFix.empty ())
9003
8884
return true ;
9004
8885
@@ -9020,16 +8901,11 @@ static bool addUsersInExitBlocks(
9020
8901
if (ExitIRI->getParent ()->getSinglePredecessor () != MiddleVPBB)
9021
8902
return false ;
9022
8903
9023
- VPValue *Incoming = ExitIRI->getOperand (0 );
9024
- if (addInductionEndValue (Plan, ExitIRI, Incoming, Inductions, EndValues,
9025
- TypeInfo))
9026
- continue ;
9027
-
9028
8904
LLVMContext &Ctx = ExitIRI->getInstruction ().getContext ();
9029
8905
VPValue *Ext = B.createNaryOp (VPInstruction::ExtractFromEnd,
9030
8906
{Op, Plan.getOrAddLiveIn (ConstantInt::get (
9031
8907
IntegerType::get (Ctx, 32 ), 1 ))});
9032
- ExitIRI->setOperand (0 , Ext);
8908
+ ExitIRI->setOperand (Idx , Ext);
9033
8909
}
9034
8910
}
9035
8911
return true ;
@@ -9324,13 +9200,12 @@ LoopVectorizationPlanner::tryToBuildVPlanWithVPRecipes(VFRange &Range) {
9324
9200
VPlanTransforms::handleUncountableEarlyExit (
9325
9201
*Plan, *PSE.getSE (), OrigLoop, UncountableExitingBlock, RecipeBuilder);
9326
9202
}
9327
- DenseMap<VPValue *, VPValue *> EndValues ;
9328
- addScalarResumePhis (RecipeBuilder, *Plan, OrigLoop, EndValues );
9203
+ DenseMap<VPValue *, VPValue *> IVEndValues ;
9204
+ addScalarResumePhis (RecipeBuilder, *Plan, IVEndValues );
9329
9205
SetVector<VPIRInstruction *> ExitUsersToFix =
9330
9206
collectUsersInExitBlocks (OrigLoop, RecipeBuilder, *Plan);
9331
9207
addExitUsersForFirstOrderRecurrences (*Plan, ExitUsersToFix);
9332
- if (!addUsersInExitBlocks (*Plan, ExitUsersToFix,
9333
- EndValues)) {
9208
+ if (!addUsersInExitBlocks (*Plan, ExitUsersToFix, IVEndValues)) {
9334
9209
reportVectorizationFailure (
9335
9210
" Some exit values in loop with uncountable exit not supported yet" ,
9336
9211
" UncountableEarlyExitLoopsUnsupportedExitValue" , ORE, OrigLoop);
@@ -9409,6 +9284,8 @@ LoopVectorizationPlanner::tryToBuildVPlanWithVPRecipes(VFRange &Range) {
9409
9284
VPlanTransforms::addActiveLaneMask (*Plan, ForControlFlow,
9410
9285
WithoutRuntimeCheck);
9411
9286
}
9287
+
9288
+ VPlanTransforms::optimizeInductionExitUsers (*Plan, IVEndValues);
9412
9289
return Plan;
9413
9290
}
9414
9291
@@ -9457,8 +9334,8 @@ VPlanPtr LoopVectorizationPlanner::buildVPlan(VFRange &Range) {
9457
9334
auto *HeaderR = cast<VPHeaderPHIRecipe>(&R);
9458
9335
RecipeBuilder.setRecipe (HeaderR->getUnderlyingInstr (), HeaderR);
9459
9336
}
9460
- DenseMap<VPValue *, VPValue *> EndValues ;
9461
- addScalarResumePhis (RecipeBuilder, *Plan, OrigLoop, EndValues );
9337
+ DenseMap<VPValue *, VPValue *> IVEndValues ;
9338
+ addScalarResumePhis (RecipeBuilder, *Plan, IVEndValues );
9462
9339
9463
9340
assert (verifyVPlanIsValid (*Plan) && " VPlan is invalid" );
9464
9341
return Plan;
0 commit comments