@@ -1293,6 +1293,7 @@ class LoopVectorizationCostModel {
12931293 " from latch block\n " );
12941294 return true ;
12951295 }
1296+
12961297 if (IsVectorizing && InterleaveInfo.requiresScalarEpilogue ()) {
12971298 LLVM_DEBUG (dbgs () << " LV: Loop requires scalar epilogue: "
12981299 " interleaved group requires scalar epilogue\n " );
@@ -4084,6 +4085,7 @@ static bool willGenerateVectors(VPlan &Plan, ElementCount VF,
40844085 continue ;
40854086 case VPDef::VPReductionSC:
40864087 case VPDef::VPActiveLaneMaskPHISC:
4088+ case VPDef::VPLastActiveMaskPHISC:
40874089 case VPDef::VPWidenCallSC:
40884090 case VPDef::VPWidenCanonicalIVSC:
40894091 case VPDef::VPWidenCastSC:
@@ -4302,11 +4304,15 @@ bool LoopVectorizationPlanner::isCandidateForEpilogueVectorization(
43024304 ElementCount VF) const {
43034305 // Cross iteration phis such as fixed-order recurrences and FMaxNum/FMinNum
43044306 // reductions need special handling and are currently unsupported.
4307+ // FindLast reductions also require special handling for the synthesized
4308+ // mask PHI.
43054309 if (any_of (OrigLoop->getHeader ()->phis (), [&](PHINode &Phi) {
43064310 if (!Legal->isReductionVariable (&Phi))
43074311 return Legal->isFixedOrderRecurrence (&Phi);
4308- return RecurrenceDescriptor::isFPMinMaxNumRecurrenceKind (
4309- Legal->getRecurrenceDescriptor (&Phi).getRecurrenceKind ());
4312+ RecurKind Kind =
4313+ Legal->getRecurrenceDescriptor (&Phi).getRecurrenceKind ();
4314+ return RecurrenceDescriptor::isFindLastRecurrenceKind (Kind) ||
4315+ RecurrenceDescriptor::isFPMinMaxNumRecurrenceKind (Kind);
43104316 }))
43114317 return false ;
43124318
@@ -4612,6 +4618,12 @@ LoopVectorizationPlanner::selectInterleaveCount(VPlan &Plan, ElementCount VF,
46124618 any_of (Plan.getVectorLoopRegion ()->getEntryBasicBlock ()->phis (),
46134619 IsaPred<VPReductionPHIRecipe>);
46144620
4621+ // FIXME: implement interleaving for FindLast transform correctly.
4622+ for (auto &[_, RdxDesc] : Legal->getReductionVars ())
4623+ if (RecurrenceDescriptor::isFindLastRecurrenceKind (
4624+ RdxDesc.getRecurrenceKind ()))
4625+ return 1 ;
4626+
46154627 // If we did not calculate the cost for VF (because the user selected the VF)
46164628 // then we calculate the cost of VF here.
46174629 if (LoopCost == 0 ) {
@@ -8586,6 +8598,10 @@ VPlanPtr LoopVectorizationPlanner::tryToBuildVPlanWithVPRecipes(
85868598 *Plan, Builder))
85878599 return nullptr ;
85888600
8601+ // Create whole-vector selects for find-last recurrences.
8602+ VPlanTransforms::runPass (VPlanTransforms::convertFindLastRecurrences, *Plan,
8603+ RecipeBuilder, Legal);
8604+
85898605 if (useActiveLaneMask (Style)) {
85908606 // TODO: Move checks to VPlanTransforms::addActiveLaneMask once
85918607 // TailFoldingStyle is visible there.
@@ -8669,10 +8685,11 @@ void LoopVectorizationPlanner::adjustRecipesForReductions(
86698685 continue ;
86708686
86718687 RecurKind Kind = PhiR->getRecurrenceKind ();
8672- assert (
8673- !RecurrenceDescriptor::isAnyOfRecurrenceKind (Kind) &&
8674- !RecurrenceDescriptor::isFindIVRecurrenceKind (Kind) &&
8675- " AnyOf and FindIV reductions are not allowed for in-loop reductions" );
8688+ assert (!RecurrenceDescriptor::isFindLastRecurrenceKind (Kind) &&
8689+ !RecurrenceDescriptor::isAnyOfRecurrenceKind (Kind) &&
8690+ !RecurrenceDescriptor::isFindIVRecurrenceKind (Kind) &&
8691+ " AnyOf, FindIV, and FindLast reductions are not allowed for in-loop "
8692+ " reductions" );
86768693
86778694 bool IsFPRecurrence =
86788695 RecurrenceDescriptor::isFloatingPointRecurrenceKind (Kind);
@@ -8976,7 +8993,8 @@ void LoopVectorizationPlanner::adjustRecipesForReductions(
89768993 RecurKind RK = RdxDesc.getRecurrenceKind ();
89778994 if ((!RecurrenceDescriptor::isAnyOfRecurrenceKind (RK) &&
89788995 !RecurrenceDescriptor::isFindIVRecurrenceKind (RK) &&
8979- !RecurrenceDescriptor::isMinMaxRecurrenceKind (RK))) {
8996+ !RecurrenceDescriptor::isMinMaxRecurrenceKind (RK) &&
8997+ !RecurrenceDescriptor::isFindLastRecurrenceKind (RK))) {
89808998 VPBuilder PHBuilder (Plan->getVectorPreheader ());
89818999 VPValue *Iden = Plan->getOrAddLiveIn (
89829000 getRecurrenceIdentity (RK, PhiTy, RdxDesc.getFastMathFlags ()));
@@ -9389,7 +9407,7 @@ static void preparePlanForMainVectorLoop(VPlan &MainPlan, VPlan &EpiPlan) {
93899407 SmallPtrSet<PHINode *, 2 > EpiWidenedPhis;
93909408 for (VPRecipeBase &R :
93919409 EpiPlan.getVectorLoopRegion ()->getEntryBasicBlock ()->phis ()) {
9392- if (isa<VPCanonicalIVPHIRecipe>(&R))
9410+ if (isa<VPCanonicalIVPHIRecipe, VPLastActiveMaskPHIRecipe >(&R))
93939411 continue ;
93949412 EpiWidenedPhis.insert (
93959413 cast<PHINode>(R.getVPSingleValue ()->getUnderlyingValue ()));
@@ -9586,6 +9604,10 @@ static SmallVector<Instruction *> preparePlanForEpilogueVectorLoop(
95869604 continue ;
95879605 }
95889606 }
9607+ } else if (isa<VPLastActiveMaskPHIRecipe>(R)) {
9608+ // LastActiveMasks are only used as part of FindLast reductions,
9609+ // and aren't passed to the scalar loop.
9610+ continue ;
95899611 } else {
95909612 // Retrieve the induction resume values for wide inductions from
95919613 // their original phi nodes in the scalar loop.
@@ -10107,6 +10129,21 @@ bool LoopVectorizePass::processLoop(Loop *L) {
1010710129 // Override IC if user provided an interleave count.
1010810130 IC = UserIC > 0 ? UserIC : IC;
1010910131
10132+ // FIXME: Enable interleaving for last_active reductions.
10133+ if (any_of (make_second_range (LVL.getReductionVars ()), [&](auto &RdxDesc) {
10134+ return RecurrenceDescriptor::isFindLastRecurrenceKind (
10135+ RdxDesc.getRecurrenceKind ());
10136+ })) {
10137+ LLVM_DEBUG (dbgs () << " LV: Not interleaving without vectorization due "
10138+ << " to conditional scalar assignments.\n " );
10139+ IntDiagMsg = {
10140+ " ConditionalAssignmentPreventsScalarInterleaving" ,
10141+ " Unable to interleave without vectorization due to conditional "
10142+ " assignments" };
10143+ InterleaveLoop = false ;
10144+ IC = 1 ;
10145+ }
10146+
1011010147 // Emit diagnostic messages, if any.
1011110148 const char *VAPassName = Hints.vectorizeAnalysisPassName ();
1011210149 if (!VectorizeLoop && !InterleaveLoop) {
0 commit comments