@@ -54,6 +54,8 @@ bool RecurrenceDescriptor::isIntegerRecurrenceKind(RecurKind Kind) {
5454 case RecurKind::UMin:
5555 case RecurKind::IAnyOf:
5656 case RecurKind::FAnyOf:
57+ case RecurKind::IFindLastIV:
58+ case RecurKind::FFindLastIV:
5759 return true ;
5860 }
5961 return false ;
@@ -375,7 +377,7 @@ bool RecurrenceDescriptor::AddReductionVar(
375377 // type-promoted).
376378 if (Cur != Start) {
377379 ReduxDesc =
378- isRecurrenceInstr (TheLoop, Phi, Cur, Kind, ReduxDesc, FuncFMF);
380+ isRecurrenceInstr (TheLoop, Phi, Cur, Kind, ReduxDesc, FuncFMF, SE );
379381 ExactFPMathInst = ExactFPMathInst == nullptr
380382 ? ReduxDesc.getExactFPMathInst ()
381383 : ExactFPMathInst;
@@ -662,6 +664,87 @@ RecurrenceDescriptor::isAnyOfPattern(Loop *Loop, PHINode *OrigPhi,
662664 : RecurKind::FAnyOf);
663665}
664666
667+ // We are looking for loops that do something like this:
668+ // int r = 0;
669+ // for (int i = 0; i < n; i++) {
670+ // if (src[i] > 3)
671+ // r = i;
672+ // }
673+ // The reduction value (r) is derived from either the values of an increasing
674+ // induction variable (i) sequence, or from the start value (0).
675+ // The LLVM IR generated for such loops would be as follows:
676+ // for.body:
677+ // %r = phi i32 [ %spec.select, %for.body ], [ 0, %entry ]
678+ // %i = phi i32 [ %inc, %for.body ], [ 0, %entry ]
679+ // ...
680+ // %cmp = icmp sgt i32 %5, 3
681+ // %spec.select = select i1 %cmp, i32 %i, i32 %r
682+ // %inc = add nsw i32 %i, 1
683+ // ...
684+ // Since 'i' is an increasing induction variable, the reduction value after the
685+ // loop will be the maximum value of 'i' that the condition (src[i] > 3) is
686+ // satisfied, or the start value (0 in the example above). When the start value
687+ // of the increasing induction variable 'i' is greater than the minimum value of
688+ // the data type, we can use the minimum value of the data type as a sentinel
689+ // value to replace the start value. This allows us to perform a single
690+ // reduction max operation to obtain the final reduction result.
691+ // TODO: It is possible to solve the case where the start value is the minimum
692+ // value of the data type or a non-constant value by using mask and multiple
693+ // reduction operations.
694+ RecurrenceDescriptor::InstDesc
695+ RecurrenceDescriptor::isFindLastIVPattern (Loop *Loop, PHINode *OrigPhi,
696+ Instruction *I, ScalarEvolution *SE) {
697+ // Only match select with single use cmp condition.
698+ // TODO: Only handle single use for now.
699+ CmpInst::Predicate Pred;
700+ if (!match (I, m_Select (m_OneUse (m_Cmp (Pred, m_Value (), m_Value ())), m_Value (),
701+ m_Value ())))
702+ return InstDesc (false , I);
703+
704+ SelectInst *SI = cast<SelectInst>(I);
705+ Value *NonRdxPhi = nullptr ;
706+
707+ if (OrigPhi == dyn_cast<PHINode>(SI->getTrueValue ()))
708+ NonRdxPhi = SI->getFalseValue ();
709+ else if (OrigPhi == dyn_cast<PHINode>(SI->getFalseValue ()))
710+ NonRdxPhi = SI->getTrueValue ();
711+ else
712+ return InstDesc (false , I);
713+
714+ auto IsIncreasingLoopInduction = [&SE, &Loop](Value *V) {
715+ auto *Phi = dyn_cast<PHINode>(V);
716+ if (!Phi)
717+ return false ;
718+
719+ if (!SE)
720+ return false ;
721+
722+ InductionDescriptor ID;
723+ if (!InductionDescriptor::isInductionPHI (Phi, Loop, SE, ID))
724+ return false ;
725+
726+ const SCEVAddRecExpr *AR = cast<SCEVAddRecExpr>(SE->getSCEV (Phi));
727+ if (!AR->hasNoSignedWrap ())
728+ return false ;
729+
730+ ConstantInt *IVStartValue = dyn_cast<ConstantInt>(ID.getStartValue ());
731+ if (!IVStartValue || IVStartValue->isMinSignedValue ())
732+ return false ;
733+
734+ const SCEV *Step = ID.getStep ();
735+ return SE->isKnownPositive (Step);
736+ };
737+
738+ // We are looking for selects of the form:
739+ // select(cmp(), phi, loop_induction) or
740+ // select(cmp(), loop_induction, phi)
741+ if (!IsIncreasingLoopInduction (NonRdxPhi))
742+ return InstDesc (false , I);
743+
744+ return InstDesc (I, isa<ICmpInst>(I->getOperand (0 )) ? RecurKind::IFindLastIV
745+ : RecurKind::FFindLastIV);
746+ }
747+
665748RecurrenceDescriptor::InstDesc
666749RecurrenceDescriptor::isMinMaxPattern (Instruction *I, RecurKind Kind,
667750 const InstDesc &Prev) {
@@ -765,10 +848,9 @@ RecurrenceDescriptor::isConditionalRdxPattern(RecurKind Kind, Instruction *I) {
765848 return InstDesc (true , SI);
766849}
767850
768- RecurrenceDescriptor::InstDesc
769- RecurrenceDescriptor::isRecurrenceInstr (Loop *L, PHINode *OrigPhi,
770- Instruction *I, RecurKind Kind,
771- InstDesc &Prev, FastMathFlags FuncFMF) {
851+ RecurrenceDescriptor::InstDesc RecurrenceDescriptor::isRecurrenceInstr (
852+ Loop *L, PHINode *OrigPhi, Instruction *I, RecurKind Kind, InstDesc &Prev,
853+ FastMathFlags FuncFMF, ScalarEvolution *SE) {
772854 assert (Prev.getRecKind () == RecurKind::None || Prev.getRecKind () == Kind);
773855 switch (I->getOpcode ()) {
774856 default :
@@ -798,6 +880,8 @@ RecurrenceDescriptor::isRecurrenceInstr(Loop *L, PHINode *OrigPhi,
798880 if (Kind == RecurKind::FAdd || Kind == RecurKind::FMul ||
799881 Kind == RecurKind::Add || Kind == RecurKind::Mul)
800882 return isConditionalRdxPattern (Kind, I);
883+ if (isFindLastIVRecurrenceKind (Kind))
884+ return isFindLastIVPattern (L, OrigPhi, I, SE);
801885 [[fallthrough]];
802886 case Instruction::FCmp:
803887 case Instruction::ICmp:
@@ -902,6 +986,11 @@ bool RecurrenceDescriptor::isReductionPHI(PHINode *Phi, Loop *TheLoop,
902986 << *Phi << " \n " );
903987 return true ;
904988 }
989+ if (AddReductionVar (Phi, RecurKind::IFindLastIV, TheLoop, FMF, RedDes, DB, AC,
990+ DT, SE)) {
991+ LLVM_DEBUG (dbgs () << " Found a FindLastIV reduction PHI." << *Phi << " \n " );
992+ return true ;
993+ }
905994 if (AddReductionVar (Phi, RecurKind::FMul, TheLoop, FMF, RedDes, DB, AC, DT,
906995 SE)) {
907996 LLVM_DEBUG (dbgs () << " Found an FMult reduction PHI." << *Phi << " \n " );
@@ -1091,6 +1180,9 @@ Value *RecurrenceDescriptor::getRecurrenceIdentity(RecurKind K, Type *Tp,
10911180 case RecurKind::FAnyOf:
10921181 return getRecurrenceStartValue ();
10931182 break ;
1183+ case RecurKind::IFindLastIV:
1184+ case RecurKind::FFindLastIV:
1185+ return getRecurrenceIdentity (RecurKind::SMax, Tp, FMF);
10941186 default :
10951187 llvm_unreachable (" Unknown recurrence kind" );
10961188 }
@@ -1118,12 +1210,14 @@ unsigned RecurrenceDescriptor::getOpcode(RecurKind Kind) {
11181210 case RecurKind::UMax:
11191211 case RecurKind::UMin:
11201212 case RecurKind::IAnyOf:
1213+ case RecurKind::IFindLastIV:
11211214 return Instruction::ICmp;
11221215 case RecurKind::FMax:
11231216 case RecurKind::FMin:
11241217 case RecurKind::FMaximum:
11251218 case RecurKind::FMinimum:
11261219 case RecurKind::FAnyOf:
1220+ case RecurKind::FFindLastIV:
11271221 return Instruction::FCmp;
11281222 default :
11291223 llvm_unreachable (" Unknown recurrence operation" );
0 commit comments