@@ -574,7 +574,7 @@ class InnerLoopVectorizer {
574
574
575
575
// / Create the exit value of first order recurrences in the middle block and
576
576
// / update their users.
577
- void fixFirstOrderRecurrence (VPFirstOrderRecurrencePHIRecipe *PhiR,
577
+ void fixFixedOrderRecurrence (VPFirstOrderRecurrencePHIRecipe *PhiR,
578
578
VPTransformState &State);
579
579
580
580
// / Create code for the loop exit value of the reduction.
@@ -3722,11 +3722,11 @@ void InnerLoopVectorizer::fixCrossIterationPHIs(VPTransformState &State) {
3722
3722
if (auto *ReductionPhi = dyn_cast<VPReductionPHIRecipe>(&R))
3723
3723
fixReduction (ReductionPhi, State);
3724
3724
else if (auto *FOR = dyn_cast<VPFirstOrderRecurrencePHIRecipe>(&R))
3725
- fixFirstOrderRecurrence (FOR, State);
3725
+ fixFixedOrderRecurrence (FOR, State);
3726
3726
}
3727
3727
}
3728
3728
3729
- void InnerLoopVectorizer::fixFirstOrderRecurrence (
3729
+ void InnerLoopVectorizer::fixFixedOrderRecurrence (
3730
3730
VPFirstOrderRecurrencePHIRecipe *PhiR, VPTransformState &State) {
3731
3731
// This is the second phase of vectorizing first-order recurrences. An
3732
3732
// overview of the transformation is described below. Suppose we have the
@@ -4003,7 +4003,7 @@ void InnerLoopVectorizer::fixReduction(VPReductionPHIRecipe *PhiR,
4003
4003
4004
4004
// We know that the loop is in LCSSA form. We need to update the PHI nodes
4005
4005
// in the exit blocks. See comment on analogous loop in
4006
- // fixFirstOrderRecurrence for a more complete explaination of the logic.
4006
+ // fixFixedOrderRecurrence for a more complete explaination of the logic.
4007
4007
if (!Cost->requiresScalarEpilogue (VF))
4008
4008
for (PHINode &LCSSAPhi : LoopExitBlock->phis ())
4009
4009
if (llvm::is_contained (LCSSAPhi.incoming_values (), LoopExitInst))
@@ -4752,7 +4752,7 @@ void LoopVectorizationCostModel::collectLoopUniforms(ElementCount VF) {
4752
4752
// First order recurrence Phi's should typically be considered
4753
4753
// non-uniform.
4754
4754
auto *OP = dyn_cast<PHINode>(OV);
4755
- if (OP && Legal->isFirstOrderRecurrence (OP))
4755
+ if (OP && Legal->isFixedOrderRecurrence (OP))
4756
4756
continue ;
4757
4757
// If all the users of the operand are uniform, then add the
4758
4758
// operand into the uniform worklist.
@@ -5445,7 +5445,7 @@ bool LoopVectorizationCostModel::isCandidateForEpilogueVectorization(
5445
5445
// Cross iteration phis such as reductions need special handling and are
5446
5446
// currently unsupported.
5447
5447
if (any_of (L.getHeader ()->phis (),
5448
- [&](PHINode &Phi) { return Legal->isFirstOrderRecurrence (&Phi); }))
5448
+ [&](PHINode &Phi) { return Legal->isFixedOrderRecurrence (&Phi); }))
5449
5449
return false ;
5450
5450
5451
5451
// Phis with uses outside of the loop require special handling and are
@@ -7028,7 +7028,7 @@ LoopVectorizationCostModel::getInstructionCost(Instruction *I, ElementCount VF,
7028
7028
7029
7029
// First-order recurrences are replaced by vector shuffles inside the loop.
7030
7030
// NOTE: Don't use ToVectorTy as SK_ExtractSubvector expects a vector type.
7031
- if (VF.isVector () && Legal->isFirstOrderRecurrence (Phi))
7031
+ if (VF.isVector () && Legal->isFixedOrderRecurrence (Phi))
7032
7032
return TTI.getShuffleCost (
7033
7033
TargetTransformInfo::SK_ExtractSubvector, cast<VectorType>(VectorTy),
7034
7034
None, VF.getKnownMinValue () - 1 , FixedVectorType::get (RetTy, 1 ));
@@ -8554,11 +8554,16 @@ VPRecipeBuilder::tryToCreateWidenRecipe(Instruction *Instr,
8554
8554
if (auto Phi = dyn_cast<PHINode>(Instr)) {
8555
8555
if (Phi->getParent () != OrigLoop->getHeader ())
8556
8556
return tryToBlend (Phi, Operands, Plan);
8557
+
8558
+ // Always record recipes for header phis. Later first-order recurrence phis
8559
+ // can have earlier phis as incoming values.
8560
+ recordRecipeOf (Phi);
8561
+
8557
8562
if ((Recipe = tryToOptimizeInductionPHI (Phi, Operands, *Plan, Range)))
8558
8563
return toVPRecipeResult (Recipe);
8559
8564
8560
8565
VPHeaderPHIRecipe *PhiRecipe = nullptr ;
8561
- if (Legal->isReductionVariable (Phi) || Legal->isFirstOrderRecurrence (Phi)) {
8566
+ if (Legal->isReductionVariable (Phi) || Legal->isFixedOrderRecurrence (Phi)) {
8562
8567
VPValue *StartV = Operands[0 ];
8563
8568
if (Legal->isReductionVariable (Phi)) {
8564
8569
const RecurrenceDescriptor &RdxDesc =
@@ -8569,14 +8574,22 @@ VPRecipeBuilder::tryToCreateWidenRecipe(Instruction *Instr,
8569
8574
CM.isInLoopReduction (Phi),
8570
8575
CM.useOrderedReductions (RdxDesc));
8571
8576
} else {
8572
- PhiRecipe = new VPFirstOrderRecurrencePHIRecipe (Phi, *StartV);
8577
+ // TODO: Currently fixed-order recurrences are modeled as chains of
8578
+ // first-order recurrences. If there are no users of the intermediate
8579
+ // recurrences in the chain, the fixed order recurrence should be modeled
8580
+ // directly, enabling more efficient codegen.
8581
+ PhiRecipe = new VPFirstOrderRecurrencePHIRecipe (Phi, *StartV);
8573
8582
}
8574
8583
8575
- // Record the incoming value from the backedge, so we can add the incoming
8576
- // value from the backedge after all recipes have been created.
8577
- recordRecipeOf (cast<Instruction>(
8578
- Phi->getIncomingValueForBlock (OrigLoop->getLoopLatch ())));
8579
- PhisToFix.push_back (PhiRecipe);
8584
+ // Record the incoming value from the backedge, so we can add the incoming
8585
+ // value from the backedge after all recipes have been created.
8586
+ auto *Inc = cast<Instruction>(
8587
+ Phi->getIncomingValueForBlock (OrigLoop->getLoopLatch ()));
8588
+ auto RecipeIter = Ingredient2Recipe.find (Inc);
8589
+ if (RecipeIter == Ingredient2Recipe.end ())
8590
+ recordRecipeOf (Inc);
8591
+
8592
+ PhisToFix.push_back (PhiRecipe);
8580
8593
} else {
8581
8594
// TODO: record backedge value for remaining pointer induction phis.
8582
8595
assert (Phi->getType ()->isPointerTy () &&
@@ -8587,7 +8600,6 @@ VPRecipeBuilder::tryToCreateWidenRecipe(Instruction *Instr,
8587
8600
VPValue *Start = Plan->getOrAddVPValue (II.getStartValue ());
8588
8601
PhiRecipe = new VPWidenPHIRecipe (Phi, Start);
8589
8602
}
8590
-
8591
8603
return toVPRecipeResult (PhiRecipe);
8592
8604
}
8593
8605
@@ -8648,7 +8660,7 @@ void LoopVectorizationPlanner::buildVPlansWithVPRecipes(ElementCount MinVF,
8648
8660
assert (
8649
8661
SinkTarget != FirstInst &&
8650
8662
" Must find a live instruction (at least the one feeding the "
8651
- " first -order recurrence PHI) before reaching beginning of the block" );
8663
+ " fixed -order recurrence PHI) before reaching beginning of the block" );
8652
8664
SinkTarget = SinkTarget->getPrevNode ();
8653
8665
assert (SinkTarget != P.first &&
8654
8666
" sink source equals target, no sinking required" );
@@ -8952,14 +8964,19 @@ VPlanPtr LoopVectorizationPlanner::buildVPlanWithVPRecipes(
8952
8964
RecipeBuilder, Range.Start );
8953
8965
8954
8966
// Introduce a recipe to combine the incoming and previous values of a
8955
- // first -order recurrence.
8967
+ // fixed -order recurrence.
8956
8968
for (VPRecipeBase &R :
8957
8969
Plan->getVectorLoopRegion ()->getEntryBasicBlock ()->phis ()) {
8958
8970
auto *RecurPhi = dyn_cast<VPFirstOrderRecurrencePHIRecipe>(&R);
8959
8971
if (!RecurPhi)
8960
8972
continue ;
8961
8973
8962
8974
VPRecipeBase *PrevRecipe = RecurPhi->getBackedgeRecipe ();
8975
+ // Fixed-order recurrences do not contain cycles, so this loop is guaranteed
8976
+ // to terminate.
8977
+ while (auto *PrevPhi =
8978
+ dyn_cast<VPFirstOrderRecurrencePHIRecipe>(PrevRecipe))
8979
+ PrevRecipe = PrevPhi->getBackedgeRecipe ();
8963
8980
VPBasicBlock *InsertBlock = PrevRecipe->getParent ();
8964
8981
auto *Region = GetReplicateRegion (PrevRecipe);
8965
8982
if (Region)
0 commit comments