@@ -56,6 +56,8 @@ bool RecurrenceDescriptor::isIntegerRecurrenceKind(RecurKind Kind) {
5656 case RecurKind::FindFirstIVUMin:
5757 case RecurKind::FindLastIVSMax:
5858 case RecurKind::FindLastIVUMax:
59+ // TODO: Make type-agnostic.
60+ case RecurKind::FindLast:
5961 return true ;
6062 }
6163 return false ;
@@ -691,9 +693,9 @@ RecurrenceDescriptor::isAnyOfPattern(Loop *Loop, PHINode *OrigPhi,
691693// value of the data type or a non-constant value by using mask and multiple
692694// reduction operations.
693695RecurrenceDescriptor::InstDesc
694- RecurrenceDescriptor::isFindIVPattern (RecurKind Kind, Loop *TheLoop,
695- PHINode *OrigPhi, Instruction *I,
696- ScalarEvolution &SE) {
696+ RecurrenceDescriptor::isFindPattern (RecurKind Kind, Loop *TheLoop,
697+ PHINode *OrigPhi, Instruction *I,
698+ ScalarEvolution &SE) {
697699 // TODO: Support the vectorization of FindLastIV when the reduction phi is
698700 // used by more than one select instruction. This vectorization is only
699701 // performed when the SCEV of each increasing induction variable used by the
@@ -702,8 +704,10 @@ RecurrenceDescriptor::isFindIVPattern(RecurKind Kind, Loop *TheLoop,
702704 return InstDesc (false , I);
703705
704706 // We are looking for selects of the form:
705- // select(cmp(), phi, loop_induction) or
706- // select(cmp(), loop_induction, phi)
707+ // select(cmp(), phi, value) or
708+ // select(cmp(), value, phi)
709+ // where 'value' might be a loop induction variable
710+ // (for FindFirstIV/FindLastIV) or an arbitrary value (for FindLast).
707711 // TODO: Match selects with multi-use cmp conditions.
708712 Value *NonRdxPhi = nullptr ;
709713 if (!match (I, m_CombineOr (m_Select (m_OneUse (m_Cmp ()), m_Value (NonRdxPhi),
@@ -712,6 +716,25 @@ RecurrenceDescriptor::isFindIVPattern(RecurKind Kind, Loop *TheLoop,
712716 m_Value (NonRdxPhi)))))
713717 return InstDesc (false , I);
714718
719+ if (isFindLastRecurrenceKind (Kind)) {
720+ // Must be an integer scalar.
721+ Type *Type = OrigPhi->getType ();
722+ if (!Type->isIntegerTy () && !Type->isPointerTy ())
723+ return InstDesc (false , I);
724+
725+ // FIXME: Support more complex patterns, including multiple selects.
726+ // The Select must be used only outside the loop and by the PHI.
727+ for (User *U : I->users ()) {
728+ if (U == OrigPhi)
729+ continue ;
730+ if (auto *UI = dyn_cast<Instruction>(U); UI && !TheLoop->contains (UI))
731+ continue ;
732+ return InstDesc (false , I);
733+ }
734+
735+ return InstDesc (I, RecurKind::FindLast);
736+ }
737+
715738 // Returns either FindFirstIV/FindLastIV, if such a pattern is found, or
716739 // std::nullopt.
717740 auto GetRecurKind = [&](Value *V) -> std::optional<RecurKind> {
@@ -920,8 +943,8 @@ RecurrenceDescriptor::InstDesc RecurrenceDescriptor::isRecurrenceInstr(
920943 Kind == RecurKind::Add || Kind == RecurKind::Mul ||
921944 Kind == RecurKind::Sub || Kind == RecurKind::AddChainWithSubs)
922945 return isConditionalRdxPattern (I);
923- if (isFindIVRecurrenceKind (Kind) && SE)
924- return isFindIVPattern (Kind, L, OrigPhi, I, *SE);
946+ if (( isFindIVRecurrenceKind (Kind) || isFindLastRecurrenceKind (Kind) ) && SE)
947+ return isFindPattern (Kind, L, OrigPhi, I, *SE);
925948 [[fallthrough]];
926949 case Instruction::FCmp:
927950 case Instruction::ICmp:
@@ -1118,7 +1141,11 @@ bool RecurrenceDescriptor::isReductionPHI(PHINode *Phi, Loop *TheLoop,
11181141 << " \n " );
11191142 return true ;
11201143 }
1121-
1144+ if (AddReductionVar (Phi, RecurKind::FindLast, TheLoop, FMF, RedDes, DB, AC,
1145+ DT, SE)) {
1146+ LLVM_DEBUG (dbgs () << " Found a FindLast reduction PHI." << *Phi << " \n " );
1147+ return true ;
1148+ }
11221149 // Not a reduction of known type.
11231150 return false ;
11241151}
@@ -1248,6 +1275,8 @@ unsigned RecurrenceDescriptor::getOpcode(RecurKind Kind) {
12481275 case RecurKind::FMaximumNum:
12491276 case RecurKind::FMinimumNum:
12501277 return Instruction::FCmp;
1278+ case RecurKind::FindLast:
1279+ return Instruction::Select;
12511280 default :
12521281 llvm_unreachable (" Unknown recurrence operation" );
12531282 }
0 commit comments