@@ -58,6 +58,8 @@ bool RecurrenceDescriptor::isIntegerRecurrenceKind(RecurKind Kind) {
5858 case RecurKind::FindFirstIVUMin:
5959 case RecurKind::FindLastIVSMax:
6060 case RecurKind::FindLastIVUMax:
61+ // TODO: Make type-agnostic.
62+ case RecurKind::FindLast:
6163 return true ;
6264 }
6365 return false ;
@@ -721,9 +723,15 @@ RecurrenceDescriptor::isAnyOfPattern(Loop *Loop, PHINode *OrigPhi,
721723// if (src[i] > 3)
722724// r = i;
723725// }
726+ // or like this:
727+ // int r = 0;
728+ // for (int i = 0; i < n; i++) {
729+ // if (src[i] > 3)
730+ // r = <loop-varying value>;
731+ // }
724732// The reduction value (r) is derived from either the values of an induction
725- // variable (i) sequence, or from the start value (0). The LLVM IR generated for
726- // such loops would be as follows:
733+ // variable (i) sequence, an arbitrary loop-varying value, or from the start
734+ // value (0). The LLVM IR generated for such loops would be as follows:
727735// for.body:
728736// %r = phi i32 [ %spec.select, %for.body ], [ 0, %entry ]
729737// %i = phi i32 [ %inc, %for.body ], [ 0, %entry ]
@@ -732,23 +740,27 @@ RecurrenceDescriptor::isAnyOfPattern(Loop *Loop, PHINode *OrigPhi,
732740// %spec.select = select i1 %cmp, i32 %i, i32 %r
733741// %inc = add nsw i32 %i, 1
734742// ...
735- // Since 'i' is an induction variable, the reduction value after the loop will
736- // be the maximum (increasing induction) or minimum (decreasing induction) value
737- // of 'i' that the condition (src[i] > 3) is satisfied, or the start value (0 in
738- // the example above). When the start value of the induction variable 'i' is
739- // greater than the minimum (increasing induction) or maximum (decreasing
740- // induction) value of the data type, we can use the minimum (increasing
741- // induction) or maximum (decreasing induction) value of the data type as a
742- // sentinel value to replace the start value. This allows us to perform a single
743- // reduction max (increasing induction) or min (decreasing induction) operation
744- // to obtain the final reduction result.
743+ // When searching for an induction variable (i) , the reduction value after the
744+ // loop will be the maximum (increasing induction) or minimum (decreasing
745+ // induction) value of 'i' that the condition (src[i] > 3) is satisfied, or the
746+ // start value (0 in the example above). When the start value of the induction
747+ // variable 'i' is greater than the minimum (increasing induction) or maximum
748+ // (decreasing induction) value of the data type, we can use the minimum
749+ // (increasing induction) or maximum (decreasing induction) value of the data
750+ // type as a sentinel value to replace the start value. This allows us to
751+ // perform a single reduction max (increasing induction) or min (decreasing
752+ // induction) operation to obtain the final reduction result.
745753// TODO: It is possible to solve the case where the start value is the minimum
746754// value of the data type or a non-constant value by using mask and multiple
747755// reduction operations.
756+ //
757+ // When searching for an arbitrary loop-varying value, the reduction value will
758+ // either be the initial value (0) if the condition was never met, or the value
759+ // of the loop-varying value in the most recent loop iteration where the
760+ // condition was met.
748761RecurrenceDescriptor::InstDesc
749- RecurrenceDescriptor::isFindIVPattern (RecurKind Kind, Loop *TheLoop,
750- PHINode *OrigPhi, Instruction *I,
751- ScalarEvolution &SE) {
762+ RecurrenceDescriptor::isFindPattern (Loop *TheLoop, PHINode *OrigPhi,
763+ Instruction *I, ScalarEvolution &SE) {
752764 // TODO: Support the vectorization of FindLastIV when the reduction phi is
753765 // used by more than one select instruction. This vectorization is only
754766 // performed when the SCEV of each increasing induction variable used by the
@@ -757,8 +769,10 @@ RecurrenceDescriptor::isFindIVPattern(RecurKind Kind, Loop *TheLoop,
757769 return InstDesc (false , I);
758770
759771 // We are looking for selects of the form:
760- // select(cmp(), phi, loop_induction) or
761- // select(cmp(), loop_induction, phi)
772+ // select(cmp(), phi, value) or
773+ // select(cmp(), value, phi)
774+ // where 'value' must be a loop induction variable
775+ // (for FindFirstIV/FindLastIV) or an arbitrary value (for FindLast).
762776 // TODO: Match selects with multi-use cmp conditions.
763777 Value *NonRdxPhi = nullptr ;
764778 if (!match (I, m_CombineOr (m_Select (m_OneUse (m_Cmp ()), m_Value (NonRdxPhi),
@@ -769,7 +783,7 @@ RecurrenceDescriptor::isFindIVPattern(RecurKind Kind, Loop *TheLoop,
769783
770784 // Returns either FindFirstIV/FindLastIV, if such a pattern is found, or
771785 // std::nullopt.
772- auto GetRecurKind = [&](Value *V) -> std::optional<RecurKind> {
786+ auto GetFindFirstLastIVRecurKind = [&](Value *V) -> std::optional<RecurKind> {
773787 Type *Ty = V->getType ();
774788 if (!SE.isSCEVable (Ty))
775789 return std::nullopt ;
@@ -780,8 +794,9 @@ RecurrenceDescriptor::isFindIVPattern(RecurKind Kind, Loop *TheLoop,
780794 m_SpecificLoop (TheLoop))))
781795 return std::nullopt ;
782796
783- if ((isFindFirstIVRecurrenceKind (Kind) && !SE.isKnownNegative (Step)) ||
784- (isFindLastIVRecurrenceKind (Kind) && !SE.isKnownPositive (Step)))
797+ // We must have a known positive or negative step for FindIV
798+ const bool PositiveStep = SE.isKnownPositive (Step);
799+ if (!SE.isKnownNonZero (Step))
785800 return std::nullopt ;
786801
787802 // Check if the minimum (FindLast) or maximum (FindFirst) value of the
@@ -797,7 +812,7 @@ RecurrenceDescriptor::isFindIVPattern(RecurKind Kind, Loop *TheLoop,
797812 IsSigned ? SE.getSignedRange (AR) : SE.getUnsignedRange (AR);
798813 unsigned NumBits = Ty->getIntegerBitWidth ();
799814 APInt Sentinel;
800- if (isFindLastIVRecurrenceKind (Kind) ) {
815+ if (PositiveStep ) {
801816 Sentinel = IsSigned ? APInt::getSignedMinValue (NumBits)
802817 : APInt::getMinValue (NumBits);
803818 } else {
@@ -806,26 +821,22 @@ RecurrenceDescriptor::isFindIVPattern(RecurKind Kind, Loop *TheLoop,
806821 }
807822 ConstantRange ValidRange = ConstantRange (Sentinel).inverse ();
808823
809- LLVM_DEBUG (dbgs () << " LV: "
810- << (isFindLastIVRecurrenceKind (Kind) ? " FindLastIV"
811- : " FindFirstIV" )
812- << " valid range is " << ValidRange
813- << " , and the range of " << *AR << " is " << IVRange
814- << " \n " );
824+ LLVM_DEBUG (
825+ dbgs () << " LV: " << (PositiveStep ? " FindLastIV" : " FindFirstIV" )
826+ << " valid range is " << ValidRange << " , and the range of "
827+ << *AR << " is " << IVRange << " \n " );
815828
816829 // Ensure the induction variable does not wrap around by verifying that
817830 // its range is fully contained within the valid range.
818831 return ValidRange.contains (IVRange);
819832 };
820- if (isFindLastIVRecurrenceKind (Kind) ) {
833+ if (PositiveStep ) {
821834 if (CheckRange (true ))
822835 return RecurKind::FindLastIVSMax;
823836 if (CheckRange (false ))
824837 return RecurKind::FindLastIVUMax;
825838 return std::nullopt ;
826839 }
827- assert (isFindFirstIVRecurrenceKind (Kind) &&
828- " Kind must either be a FindLastIV or FindFirstIV" );
829840
830841 if (CheckRange (true ))
831842 return RecurKind::FindFirstIVSMin;
@@ -834,10 +845,11 @@ RecurrenceDescriptor::isFindIVPattern(RecurKind Kind, Loop *TheLoop,
834845 return std::nullopt ;
835846 };
836847
837- if (auto RK = GetRecurKind (NonRdxPhi))
848+ if (auto RK = GetFindFirstLastIVRecurKind (NonRdxPhi))
838849 return InstDesc (I, *RK);
839850
840- return InstDesc (false , I);
851+ // If the recurrence is not specific to an IV, return a generic FindLast.
852+ return InstDesc (I, RecurKind::FindLast);
841853}
842854
843855RecurrenceDescriptor::InstDesc
@@ -971,8 +983,8 @@ RecurrenceDescriptor::InstDesc RecurrenceDescriptor::isRecurrenceInstr(
971983 Kind == RecurKind::Add || Kind == RecurKind::Mul ||
972984 Kind == RecurKind::Sub || Kind == RecurKind::AddChainWithSubs)
973985 return isConditionalRdxPattern (I);
974- if (isFindIVRecurrenceKind (Kind) && SE)
975- return isFindIVPattern (Kind, L, OrigPhi, I, *SE);
986+ if (isFindRecurrenceKind (Kind) && SE)
987+ return isFindPattern ( L, OrigPhi, I, *SE);
976988 [[fallthrough]];
977989 case Instruction::FCmp:
978990 case Instruction::ICmp:
@@ -1112,14 +1124,9 @@ bool RecurrenceDescriptor::isReductionPHI(PHINode *Phi, Loop *TheLoop,
11121124 << " \n " );
11131125 return true ;
11141126 }
1115- if (AddReductionVar (Phi, RecurKind::FindLastIVSMax, TheLoop, FMF, RedDes, DB,
1116- AC, DT, SE)) {
1117- LLVM_DEBUG (dbgs () << " Found a FindLastIV reduction PHI." << *Phi << " \n " );
1118- return true ;
1119- }
1120- if (AddReductionVar (Phi, RecurKind::FindFirstIVSMin, TheLoop, FMF, RedDes, DB,
1121- AC, DT, SE)) {
1122- LLVM_DEBUG (dbgs () << " Found a FindFirstIV reduction PHI." << *Phi << " \n " );
1127+ if (AddReductionVar (Phi, RecurKind::FindLast, TheLoop, FMF, RedDes, DB, AC,
1128+ DT, SE)) {
1129+ LLVM_DEBUG (dbgs () << " Found a Find reduction PHI." << *Phi << " \n " );
11231130 return true ;
11241131 }
11251132 if (AddReductionVar (Phi, RecurKind::FMul, TheLoop, FMF, RedDes, DB, AC, DT,
@@ -1169,7 +1176,6 @@ bool RecurrenceDescriptor::isReductionPHI(PHINode *Phi, Loop *TheLoop,
11691176 << " \n " );
11701177 return true ;
11711178 }
1172-
11731179 // Not a reduction of known type.
11741180 return false ;
11751181}
@@ -1294,6 +1300,7 @@ unsigned RecurrenceDescriptor::getOpcode(RecurKind Kind) {
12941300 case RecurKind::FMaximumNum:
12951301 case RecurKind::FMinimumNum:
12961302 return Instruction::FCmp;
1303+ case RecurKind::FindLast:
12971304 case RecurKind::AnyOf:
12981305 case RecurKind::FindFirstIVSMin:
12991306 case RecurKind::FindFirstIVUMin:
0 commit comments