@@ -552,7 +552,7 @@ class InnerLoopVectorizer {
552
552
553
553
// / Create the exit value of first order recurrences in the middle block and
554
554
// / update their users.
555
- void fixFirstOrderRecurrence (VPFirstOrderRecurrencePHIRecipe *PhiR,
555
+ void fixFixedOrderRecurrence (VPFirstOrderRecurrencePHIRecipe *PhiR,
556
556
VPTransformState &State);
557
557
558
558
// / Create code for the loop exit value of the reduction.
@@ -3705,11 +3705,11 @@ void InnerLoopVectorizer::fixCrossIterationPHIs(VPTransformState &State) {
3705
3705
if (auto *ReductionPhi = dyn_cast<VPReductionPHIRecipe>(&R))
3706
3706
fixReduction (ReductionPhi, State);
3707
3707
else if (auto *FOR = dyn_cast<VPFirstOrderRecurrencePHIRecipe>(&R))
3708
- fixFirstOrderRecurrence (FOR, State);
3708
+ fixFixedOrderRecurrence (FOR, State);
3709
3709
}
3710
3710
}
3711
3711
3712
- void InnerLoopVectorizer::fixFirstOrderRecurrence (
3712
+ void InnerLoopVectorizer::fixFixedOrderRecurrence (
3713
3713
VPFirstOrderRecurrencePHIRecipe *PhiR, VPTransformState &State) {
3714
3714
// This is the second phase of vectorizing first-order recurrences. An
3715
3715
// overview of the transformation is described below. Suppose we have the
@@ -4002,7 +4002,7 @@ void InnerLoopVectorizer::fixReduction(VPReductionPHIRecipe *PhiR,
4002
4002
4003
4003
// We know that the loop is in LCSSA form. We need to update the PHI nodes
4004
4004
// in the exit blocks. See comment on analogous loop in
4005
- // fixFirstOrderRecurrence for a more complete explaination of the logic.
4005
+ // fixFixedOrderRecurrence for a more complete explaination of the logic.
4006
4006
if (!Cost->requiresScalarEpilogue (VF))
4007
4007
for (PHINode &LCSSAPhi : LoopExitBlock->phis ())
4008
4008
if (llvm::is_contained (LCSSAPhi.incoming_values (), LoopExitInst)) {
@@ -4738,7 +4738,7 @@ void LoopVectorizationCostModel::collectLoopUniforms(ElementCount VF) {
4738
4738
// First order recurrence Phi's should typically be considered
4739
4739
// non-uniform.
4740
4740
auto *OP = dyn_cast<PHINode>(OV);
4741
- if (OP && Legal->isFirstOrderRecurrence (OP))
4741
+ if (OP && Legal->isFixedOrderRecurrence (OP))
4742
4742
continue ;
4743
4743
// If all the users of the operand are uniform, then add the
4744
4744
// operand into the uniform worklist.
@@ -5427,7 +5427,7 @@ bool LoopVectorizationCostModel::isCandidateForEpilogueVectorization(
5427
5427
// Cross iteration phis such as reductions need special handling and are
5428
5428
// currently unsupported.
5429
5429
if (any_of (L.getHeader ()->phis (),
5430
- [&](PHINode &Phi) { return Legal->isFirstOrderRecurrence (&Phi); }))
5430
+ [&](PHINode &Phi) { return Legal->isFixedOrderRecurrence (&Phi); }))
5431
5431
return false ;
5432
5432
5433
5433
// Phis with uses outside of the loop require special handling and are
@@ -7032,7 +7032,7 @@ LoopVectorizationCostModel::getInstructionCost(Instruction *I, ElementCount VF,
7032
7032
7033
7033
// First-order recurrences are replaced by vector shuffles inside the loop.
7034
7034
// NOTE: Don't use ToVectorTy as SK_ExtractSubvector expects a vector type.
7035
- if (VF.isVector () && Legal->isFirstOrderRecurrence (Phi))
7035
+ if (VF.isVector () && Legal->isFixedOrderRecurrence (Phi))
7036
7036
return TTI.getShuffleCost (
7037
7037
TargetTransformInfo::SK_ExtractSubvector, cast<VectorType>(VectorTy),
7038
7038
None, VF.getKnownMinValue () - 1 , FixedVectorType::get (RetTy, 1 ));
@@ -8509,13 +8509,18 @@ VPRecipeBuilder::tryToCreateWidenRecipe(Instruction *Instr,
8509
8509
if (auto Phi = dyn_cast<PHINode>(Instr)) {
8510
8510
if (Phi->getParent () != OrigLoop->getHeader ())
8511
8511
return tryToBlend (Phi, Operands, Plan);
8512
+
8513
+ // Always record recipes for header phis. Later first-order recurrence phis
8514
+ // can have earlier phis as incoming values.
8515
+ recordRecipeOf (Phi);
8516
+
8512
8517
if ((Recipe = tryToOptimizeInductionPHI (Phi, Operands, *Plan, Range)))
8513
8518
return toVPRecipeResult (Recipe);
8514
8519
8515
8520
VPHeaderPHIRecipe *PhiRecipe = nullptr ;
8516
8521
assert ((Legal->isReductionVariable (Phi) ||
8517
- Legal->isFirstOrderRecurrence (Phi)) &&
8518
- " can only widen reductions and first -order recurrences here" );
8522
+ Legal->isFixedOrderRecurrence (Phi)) &&
8523
+ " can only widen reductions and fixed -order recurrences here" );
8519
8524
VPValue *StartV = Operands[0 ];
8520
8525
if (Legal->isReductionVariable (Phi)) {
8521
8526
const RecurrenceDescriptor &RdxDesc =
@@ -8526,13 +8531,21 @@ VPRecipeBuilder::tryToCreateWidenRecipe(Instruction *Instr,
8526
8531
CM.isInLoopReduction (Phi),
8527
8532
CM.useOrderedReductions (RdxDesc));
8528
8533
} else {
8534
+ // TODO: Currently fixed-order recurrences are modeled as chains of
8535
+ // first-order recurrences. If there are no users of the intermediate
8536
+ // recurrences in the chain, the fixed order recurrence should be modeled
8537
+ // directly, enabling more efficient codegen.
8529
8538
PhiRecipe = new VPFirstOrderRecurrencePHIRecipe (Phi, *StartV);
8530
8539
}
8531
8540
8532
8541
// Record the incoming value from the backedge, so we can add the incoming
8533
8542
// value from the backedge after all recipes have been created.
8534
- recordRecipeOf (cast<Instruction>(
8535
- Phi->getIncomingValueForBlock (OrigLoop->getLoopLatch ())));
8543
+ auto *Inc = cast<Instruction>(
8544
+ Phi->getIncomingValueForBlock (OrigLoop->getLoopLatch ()));
8545
+ auto RecipeIter = Ingredient2Recipe.find (Inc);
8546
+ if (RecipeIter == Ingredient2Recipe.end ())
8547
+ recordRecipeOf (Inc);
8548
+
8536
8549
PhisToFix.push_back (PhiRecipe);
8537
8550
return toVPRecipeResult (PhiRecipe);
8538
8551
}
@@ -8597,7 +8610,7 @@ void LoopVectorizationPlanner::buildVPlansWithVPRecipes(ElementCount MinVF,
8597
8610
assert (
8598
8611
SinkTarget != FirstInst &&
8599
8612
" Must find a live instruction (at least the one feeding the "
8600
- " first -order recurrence PHI) before reaching beginning of the block" );
8613
+ " fixed -order recurrence PHI) before reaching beginning of the block" );
8601
8614
SinkTarget = SinkTarget->getPrevNode ();
8602
8615
assert (SinkTarget != P.first &&
8603
8616
" sink source equals target, no sinking required" );
@@ -8982,14 +8995,19 @@ VPlanPtr LoopVectorizationPlanner::buildVPlanWithVPRecipes(
8982
8995
RecipeBuilder, Range.Start );
8983
8996
8984
8997
// Introduce a recipe to combine the incoming and previous values of a
8985
- // first -order recurrence.
8998
+ // fixed -order recurrence.
8986
8999
for (VPRecipeBase &R :
8987
9000
Plan->getVectorLoopRegion ()->getEntryBasicBlock ()->phis ()) {
8988
9001
auto *RecurPhi = dyn_cast<VPFirstOrderRecurrencePHIRecipe>(&R);
8989
9002
if (!RecurPhi)
8990
9003
continue ;
8991
9004
8992
9005
VPRecipeBase *PrevRecipe = RecurPhi->getBackedgeRecipe ();
9006
+ // Fixed-order recurrences do not contain cycles, so this loop is guaranteed
9007
+ // to terminate.
9008
+ while (auto *PrevPhi =
9009
+ dyn_cast<VPFirstOrderRecurrencePHIRecipe>(PrevRecipe))
9010
+ PrevRecipe = PrevPhi->getBackedgeRecipe ();
8993
9011
VPBasicBlock *InsertBlock = PrevRecipe->getParent ();
8994
9012
auto *Region = GetReplicateRegion (PrevRecipe);
8995
9013
if (Region)
0 commit comments