@@ -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 ) {
@@ -8624,6 +8636,10 @@ VPlanPtr LoopVectorizationPlanner::tryToBuildVPlanWithVPRecipes(
86248636 *Plan, Builder))
86258637 return nullptr ;
86268638
8639+ // Create whole-vector selects for find-last recurrences.
8640+ VPlanTransforms::runPass (VPlanTransforms::convertFindLastRecurrences, *Plan,
8641+ RecipeBuilder, Legal);
8642+
86278643 if (useActiveLaneMask (Style)) {
86288644 // TODO: Move checks to VPlanTransforms::addActiveLaneMask once
86298645 // TailFoldingStyle is visible there.
@@ -8707,10 +8723,11 @@ void LoopVectorizationPlanner::adjustRecipesForReductions(
87078723 continue ;
87088724
87098725 RecurKind Kind = PhiR->getRecurrenceKind ();
8710- assert (
8711- !RecurrenceDescriptor::isAnyOfRecurrenceKind (Kind) &&
8712- !RecurrenceDescriptor::isFindIVRecurrenceKind (Kind) &&
8713- " AnyOf and FindIV reductions are not allowed for in-loop reductions" );
8726+ assert (!RecurrenceDescriptor::isFindLastRecurrenceKind (Kind) &&
8727+ !RecurrenceDescriptor::isAnyOfRecurrenceKind (Kind) &&
8728+ !RecurrenceDescriptor::isFindIVRecurrenceKind (Kind) &&
8729+ " AnyOf, FindIV, and FindLast reductions are not allowed for in-loop "
8730+ " reductions" );
87148731
87158732 bool IsFPRecurrence =
87168733 RecurrenceDescriptor::isFloatingPointRecurrenceKind (Kind);
@@ -9017,7 +9034,8 @@ void LoopVectorizationPlanner::adjustRecipesForReductions(
90179034 RecurKind RK = RdxDesc.getRecurrenceKind ();
90189035 if ((!RecurrenceDescriptor::isAnyOfRecurrenceKind (RK) &&
90199036 !RecurrenceDescriptor::isFindIVRecurrenceKind (RK) &&
9020- !RecurrenceDescriptor::isMinMaxRecurrenceKind (RK))) {
9037+ !RecurrenceDescriptor::isMinMaxRecurrenceKind (RK) &&
9038+ !RecurrenceDescriptor::isFindLastRecurrenceKind (RK))) {
90219039 VPBuilder PHBuilder (Plan->getVectorPreheader ());
90229040 VPValue *Iden = Plan->getOrAddLiveIn (
90239041 getRecurrenceIdentity (RK, PhiTy, RdxDesc.getFastMathFlags ()));
@@ -9430,7 +9448,7 @@ static void preparePlanForMainVectorLoop(VPlan &MainPlan, VPlan &EpiPlan) {
94309448 SmallPtrSet<PHINode *, 2 > EpiWidenedPhis;
94319449 for (VPRecipeBase &R :
94329450 EpiPlan.getVectorLoopRegion ()->getEntryBasicBlock ()->phis ()) {
9433- if (isa<VPCanonicalIVPHIRecipe>(&R))
9451+ if (isa<VPCanonicalIVPHIRecipe, VPLastActiveMaskPHIRecipe >(&R))
94349452 continue ;
94359453 EpiWidenedPhis.insert (
94369454 cast<PHINode>(R.getVPSingleValue ()->getUnderlyingValue ()));
@@ -9627,6 +9645,10 @@ static SmallVector<Instruction *> preparePlanForEpilogueVectorLoop(
96279645 continue ;
96289646 }
96299647 }
9648+ } else if (isa<VPLastActiveMaskPHIRecipe>(R)) {
9649+ // LastActiveMasks are only used as part of FindLast reductions,
9650+ // and aren't passed to the scalar loop.
9651+ continue ;
96309652 } else {
96319653 // Retrieve the induction resume values for wide inductions from
96329654 // their original phi nodes in the scalar loop.
@@ -10148,6 +10170,21 @@ bool LoopVectorizePass::processLoop(Loop *L) {
1014810170 // Override IC if user provided an interleave count.
1014910171 IC = UserIC > 0 ? UserIC : IC;
1015010172
10173+ // FIXME: Enable interleaving for last_active reductions.
10174+ if (any_of (make_second_range (LVL.getReductionVars ()), [&](auto &RdxDesc) {
10175+ return RecurrenceDescriptor::isFindLastRecurrenceKind (
10176+ RdxDesc.getRecurrenceKind ());
10177+ })) {
10178+ LLVM_DEBUG (dbgs () << " LV: Not interleaving without vectorization due "
10179+ << " to conditional scalar assignments.\n " );
10180+ IntDiagMsg = {
10181+ " ConditionalAssignmentPreventsScalarInterleaving" ,
10182+ " Unable to interleave without vectorization due to conditional "
10183+ " assignments" };
10184+ InterleaveLoop = false ;
10185+ IC = 1 ;
10186+ }
10187+
1015110188 // Emit diagnostic messages, if any.
1015210189 const char *VAPassName = Hints.vectorizeAnalysisPassName ();
1015310190 if (!VectorizeLoop && !InterleaveLoop) {
0 commit comments