@@ -50,6 +50,7 @@ bool RecurrenceDescriptor::isIntegerRecurrenceKind(RecurKind Kind) {
5050 case RecurKind::UMax:
5151 case RecurKind::UMin:
5252 case RecurKind::AnyOf:
53+ case RecurKind::FindFirstIVSMin:
5354 case RecurKind::FindLastIVSMax:
5455 case RecurKind::FindLastIVUMax:
5556 return true ;
@@ -684,8 +685,9 @@ RecurrenceDescriptor::isAnyOfPattern(Loop *Loop, PHINode *OrigPhi,
684685// value of the data type or a non-constant value by using mask and multiple
685686// reduction operations.
686687RecurrenceDescriptor::InstDesc
687- RecurrenceDescriptor::isFindLastIVPattern (Loop *TheLoop, PHINode *OrigPhi,
688- Instruction *I, ScalarEvolution &SE) {
688+ RecurrenceDescriptor::isFindIVPattern (RecurKind Kind, Loop *TheLoop,
689+ PHINode *OrigPhi, Instruction *I,
690+ ScalarEvolution &SE) {
689691 // TODO: Support the vectorization of FindLastIV when the reduction phi is
690692 // used by more than one select instruction. This vectorization is only
691693 // performed when the SCEV of each increasing induction variable used by the
@@ -713,36 +715,61 @@ RecurrenceDescriptor::isFindLastIVPattern(Loop *TheLoop, PHINode *OrigPhi,
713715 return std::nullopt ;
714716
715717 const SCEV *Step = AR->getStepRecurrence (SE);
716- if (!SE.isKnownPositive (Step))
718+ if ((isFindFirstIVRecurrenceKind (Kind) && !SE.isKnownNegative (Step)) ||
719+ (isFindLastIVRecurrenceKind (Kind) && !SE.isKnownPositive (Step)))
717720 return std::nullopt ;
718721
719722 // Keep the minimum value of the recurrence type as the sentinel value.
720723 // The maximum acceptable range for the increasing induction variable,
721724 // called the valid range, will be defined as
725+
726+ // Keep the minimum (FindLast) or maximum (FindFirst) value of the
727+ // recurrence type as the sentinel value. The maximum acceptable range for
728+ // the induction variable, called the valid range, will be defined as
722729 // [<sentinel value> + 1, <sentinel value>)
723- // where <sentinel value> is [Signed|Unsigned]Min(<recurrence type>)
730+ // where <sentinel value> is [Signed|Unsigned]Min(<recurrence type>) for
731+ // FindLastIV or [Signed|Unsigned]Max(<recurrence type>) for FindFirstIV.
724732 // TODO: This range restriction can be lifted by adding an additional
725733 // virtual OR reduction.
726734 auto CheckRange = [&](bool IsSigned) {
727735 const ConstantRange IVRange =
728736 IsSigned ? SE.getSignedRange (AR) : SE.getUnsignedRange (AR);
729737 unsigned NumBits = Ty->getIntegerBitWidth ();
730- const APInt Sentinel = IsSigned ? APInt::getSignedMinValue (NumBits)
731- : APInt::getMinValue (NumBits);
732- const ConstantRange ValidRange =
733- ConstantRange::getNonEmpty (Sentinel + 1 , Sentinel);
734- LLVM_DEBUG (dbgs () << " LV: FindLastIV valid range is " << ValidRange
738+ ConstantRange ValidRange = ConstantRange::getEmpty (NumBits);
739+ if (isFindLastIVRecurrenceKind (Kind)) {
740+ APInt Sentinel = IsSigned ? APInt::getSignedMinValue (NumBits)
741+ : APInt::getMinValue (NumBits);
742+ ValidRange = ConstantRange::getNonEmpty (Sentinel + 1 , Sentinel);
743+ } else {
744+ assert (IsSigned && " Only FindFirstIV with SMax is supported currently" );
745+ ValidRange =
746+ ConstantRange::getNonEmpty (APInt::getSignedMinValue (NumBits),
747+ APInt::getSignedMaxValue (NumBits) - 1 );
748+ }
749+
750+ LLVM_DEBUG (dbgs () << " LV: "
751+ << (isFindLastIVRecurrenceKind (Kind) ? " FindLastIV"
752+ : " FindFirstIV" )
753+ << " valid range is " << ValidRange
735754 << " , and the range of " << *AR << " is " << IVRange
736755 << " \n " );
737756
738757 // Ensure the induction variable does not wrap around by verifying that
739758 // its range is fully contained within the valid range.
740759 return ValidRange.contains (IVRange);
741760 };
761+ if (isFindLastIVRecurrenceKind (Kind)) {
762+ if (CheckRange (true ))
763+ return RecurKind::FindLastIVSMax;
764+ if (CheckRange (false ))
765+ return RecurKind::FindLastIVUMax;
766+ return std::nullopt ;
767+ }
768+ assert (isFindFirstIVRecurrenceKind (Kind) &&
769+ " Kind must either be a FindLastIV or FindFirstIV" );
770+
742771 if (CheckRange (true ))
743- return RecurKind::FindLastIVSMax;
744- if (CheckRange (false ))
745- return RecurKind::FindLastIVUMax;
772+ return RecurKind::FindFirstIVSMin;
746773 return std::nullopt ;
747774 };
748775
@@ -888,8 +915,8 @@ RecurrenceDescriptor::InstDesc RecurrenceDescriptor::isRecurrenceInstr(
888915 if (Kind == RecurKind::FAdd || Kind == RecurKind::FMul ||
889916 Kind == RecurKind::Add || Kind == RecurKind::Mul)
890917 return isConditionalRdxPattern (I);
891- if (isFindLastIVRecurrenceKind (Kind) && SE)
892- return isFindLastIVPattern ( L, OrigPhi, I, *SE);
918+ if (isFindIVRecurrenceKind (Kind) && SE)
919+ return isFindIVPattern (Kind, L, OrigPhi, I, *SE);
893920 [[fallthrough]];
894921 case Instruction::FCmp:
895922 case Instruction::ICmp:
@@ -1003,6 +1030,11 @@ bool RecurrenceDescriptor::isReductionPHI(PHINode *Phi, Loop *TheLoop,
10031030 LLVM_DEBUG (dbgs () << " Found a FindLastIV reduction PHI." << *Phi << " \n " );
10041031 return true ;
10051032 }
1033+ if (AddReductionVar (Phi, RecurKind::FindFirstIVSMin, TheLoop, FMF, RedDes, DB,
1034+ AC, DT, SE)) {
1035+ LLVM_DEBUG (dbgs () << " Found a FindFirstIV reduction PHI." << *Phi << " \n " );
1036+ return true ;
1037+ }
10061038 if (AddReductionVar (Phi, RecurKind::FMul, TheLoop, FMF, RedDes, DB, AC, DT,
10071039 SE)) {
10081040 LLVM_DEBUG (dbgs () << " Found an FMult reduction PHI." << *Phi << " \n " );
@@ -1150,6 +1182,7 @@ unsigned RecurrenceDescriptor::getOpcode(RecurKind Kind) {
11501182 case RecurKind::Mul:
11511183 return Instruction::Mul;
11521184 case RecurKind::AnyOf:
1185+ case RecurKind::FindFirstIVSMin:
11531186 case RecurKind::FindLastIVSMax:
11541187 case RecurKind::FindLastIVUMax:
11551188 case RecurKind::Or:
0 commit comments