@@ -51,6 +51,8 @@ bool RecurrenceDescriptor::isIntegerRecurrenceKind(RecurKind Kind) {
51
51
case RecurKind::UMin:
52
52
case RecurKind::IAnyOf:
53
53
case RecurKind::FAnyOf:
54
+ case RecurKind::IFindLastIV:
55
+ case RecurKind::FFindLastIV:
54
56
return true ;
55
57
}
56
58
return false ;
@@ -372,7 +374,7 @@ bool RecurrenceDescriptor::AddReductionVar(
372
374
// type-promoted).
373
375
if (Cur != Start) {
374
376
ReduxDesc =
375
- isRecurrenceInstr (TheLoop, Phi, Cur, Kind, ReduxDesc, FuncFMF);
377
+ isRecurrenceInstr (TheLoop, Phi, Cur, Kind, ReduxDesc, FuncFMF, SE );
376
378
ExactFPMathInst = ExactFPMathInst == nullptr
377
379
? ReduxDesc.getExactFPMathInst ()
378
380
: ExactFPMathInst;
@@ -658,6 +660,95 @@ RecurrenceDescriptor::isAnyOfPattern(Loop *Loop, PHINode *OrigPhi,
658
660
: RecurKind::FAnyOf);
659
661
}
660
662
663
+ // We are looking for loops that do something like this:
664
+ // int r = 0;
665
+ // for (int i = 0; i < n; i++) {
666
+ // if (src[i] > 3)
667
+ // r = i;
668
+ // }
669
+ // The reduction value (r) is derived from either the values of an increasing
670
+ // induction variable (i) sequence, or from the start value (0).
671
+ // The LLVM IR generated for such loops would be as follows:
672
+ // for.body:
673
+ // %r = phi i32 [ %spec.select, %for.body ], [ 0, %entry ]
674
+ // %i = phi i32 [ %inc, %for.body ], [ 0, %entry ]
675
+ // ...
676
+ // %cmp = icmp sgt i32 %5, 3
677
+ // %spec.select = select i1 %cmp, i32 %i, i32 %r
678
+ // %inc = add nsw i32 %i, 1
679
+ // ...
680
+ // Since 'i' is an increasing induction variable, the reduction value after the
681
+ // loop will be the maximum value of 'i' that the condition (src[i] > 3) is
682
+ // satisfied, or the start value (0 in the example above). When the start value
683
+ // of the increasing induction variable 'i' is greater than the minimum value of
684
+ // the data type, we can use the minimum value of the data type as a sentinel
685
+ // value to replace the start value. This allows us to perform a single
686
+ // reduction max operation to obtain the final reduction result.
687
+ // TODO: It is possible to solve the case where the start value is the minimum
688
+ // value of the data type or a non-constant value by using mask and multiple
689
+ // reduction operations.
690
+ RecurrenceDescriptor::InstDesc
691
+ RecurrenceDescriptor::isFindLastIVPattern (Loop *TheLoop, PHINode *OrigPhi,
692
+ Instruction *I, ScalarEvolution &SE) {
693
+ // TODO: Support the vectorization of FindLastIV when the reduction phi is
694
+ // used by more than one select instruction. This vectorization is only
695
+ // performed when the SCEV of each increasing induction variable used by the
696
+ // select instructions is identical.
697
+ if (!OrigPhi->hasOneUse ())
698
+ return InstDesc (false , I);
699
+
700
+ // TODO: Match selects with multi-use cmp conditions.
701
+ Value *NonRdxPhi = nullptr ;
702
+ if (!match (I, m_CombineOr (m_Select (m_OneUse (m_Cmp ()), m_Value (NonRdxPhi),
703
+ m_Specific (OrigPhi)),
704
+ m_Select (m_OneUse (m_Cmp ()), m_Specific (OrigPhi),
705
+ m_Value (NonRdxPhi)))))
706
+ return InstDesc (false , I);
707
+
708
+ auto IsIncreasingLoopInduction = [&](Value *V) {
709
+ Type *Ty = V->getType ();
710
+ if (!SE.isSCEVable (Ty))
711
+ return false ;
712
+
713
+ auto *AR = dyn_cast<SCEVAddRecExpr>(SE.getSCEV (V));
714
+ if (!AR || AR->getLoop () != TheLoop)
715
+ return false ;
716
+
717
+ const SCEV *Step = AR->getStepRecurrence (SE);
718
+ if (!SE.isKnownPositive (Step))
719
+ return false ;
720
+
721
+ const ConstantRange IVRange = SE.getSignedRange (AR);
722
+ unsigned NumBits = Ty->getIntegerBitWidth ();
723
+ // Keep the minimum value of the recurrence type as the sentinel value.
724
+ // The maximum acceptable range for the increasing induction variable,
725
+ // called the valid range, will be defined as
726
+ // [<sentinel value> + 1, <sentinel value>)
727
+ // where <sentinel value> is SignedMin(<recurrence type>)
728
+ // TODO: This range restriction can be lifted by adding an additional
729
+ // virtual OR reduction.
730
+ const APInt Sentinel = APInt::getSignedMinValue (NumBits);
731
+ const ConstantRange ValidRange =
732
+ ConstantRange::getNonEmpty (Sentinel + 1 , Sentinel);
733
+ LLVM_DEBUG (dbgs () << " LV: FindLastIV valid range is " << ValidRange
734
+ << " , and the signed range of " << *AR << " is "
735
+ << IVRange << " \n " );
736
+ // Ensure the induction variable does not wrap around by verifying that its
737
+ // range is fully contained within the valid range.
738
+ return ValidRange.contains (IVRange);
739
+ };
740
+
741
+ // We are looking for selects of the form:
742
+ // select(cmp(), phi, increasing_loop_induction) or
743
+ // select(cmp(), increasing_loop_induction, phi)
744
+ // TODO: Support for monotonically decreasing induction variable
745
+ if (!IsIncreasingLoopInduction (NonRdxPhi))
746
+ return InstDesc (false , I);
747
+
748
+ return InstDesc (I, isa<ICmpInst>(I->getOperand (0 )) ? RecurKind::IFindLastIV
749
+ : RecurKind::FFindLastIV);
750
+ }
751
+
661
752
RecurrenceDescriptor::InstDesc
662
753
RecurrenceDescriptor::isMinMaxPattern (Instruction *I, RecurKind Kind,
663
754
const InstDesc &Prev) {
@@ -756,10 +847,9 @@ RecurrenceDescriptor::isConditionalRdxPattern(RecurKind Kind, Instruction *I) {
756
847
return InstDesc (true , SI);
757
848
}
758
849
759
- RecurrenceDescriptor::InstDesc
760
- RecurrenceDescriptor::isRecurrenceInstr (Loop *L, PHINode *OrigPhi,
761
- Instruction *I, RecurKind Kind,
762
- InstDesc &Prev, FastMathFlags FuncFMF) {
850
+ RecurrenceDescriptor::InstDesc RecurrenceDescriptor::isRecurrenceInstr (
851
+ Loop *L, PHINode *OrigPhi, Instruction *I, RecurKind Kind, InstDesc &Prev,
852
+ FastMathFlags FuncFMF, ScalarEvolution *SE) {
763
853
assert (Prev.getRecKind () == RecurKind::None || Prev.getRecKind () == Kind);
764
854
switch (I->getOpcode ()) {
765
855
default :
@@ -789,6 +879,8 @@ RecurrenceDescriptor::isRecurrenceInstr(Loop *L, PHINode *OrigPhi,
789
879
if (Kind == RecurKind::FAdd || Kind == RecurKind::FMul ||
790
880
Kind == RecurKind::Add || Kind == RecurKind::Mul)
791
881
return isConditionalRdxPattern (Kind, I);
882
+ if (isFindLastIVRecurrenceKind (Kind) && SE)
883
+ return isFindLastIVPattern (L, OrigPhi, I, *SE);
792
884
[[fallthrough]];
793
885
case Instruction::FCmp:
794
886
case Instruction::ICmp:
@@ -893,6 +985,15 @@ bool RecurrenceDescriptor::isReductionPHI(PHINode *Phi, Loop *TheLoop,
893
985
<< *Phi << " \n " );
894
986
return true ;
895
987
}
988
+ if (AddReductionVar (Phi, RecurKind::IFindLastIV, TheLoop, FMF, RedDes, DB, AC,
989
+ DT, SE)) {
990
+ LLVM_DEBUG (dbgs () << " Found a "
991
+ << (RedDes.getRecurrenceKind () == RecurKind::FFindLastIV
992
+ ? " F"
993
+ : " I" )
994
+ << " FindLastIV reduction PHI." << *Phi << " \n " );
995
+ return true ;
996
+ }
896
997
if (AddReductionVar (Phi, RecurKind::FMul, TheLoop, FMF, RedDes, DB, AC, DT,
897
998
SE)) {
898
999
LLVM_DEBUG (dbgs () << " Found an FMult reduction PHI." << *Phi << " \n " );
@@ -1048,12 +1149,14 @@ unsigned RecurrenceDescriptor::getOpcode(RecurKind Kind) {
1048
1149
case RecurKind::UMax:
1049
1150
case RecurKind::UMin:
1050
1151
case RecurKind::IAnyOf:
1152
+ case RecurKind::IFindLastIV:
1051
1153
return Instruction::ICmp;
1052
1154
case RecurKind::FMax:
1053
1155
case RecurKind::FMin:
1054
1156
case RecurKind::FMaximum:
1055
1157
case RecurKind::FMinimum:
1056
1158
case RecurKind::FAnyOf:
1159
+ case RecurKind::FFindLastIV:
1057
1160
return Instruction::FCmp;
1058
1161
default :
1059
1162
llvm_unreachable (" Unknown recurrence operation" );
0 commit comments