Skip to content

Commit 62f8377

Browse files
artagnonfhahn
andauthored
[LV] Extend FindFirstIV to unsigned case (#146386)
Extend FindFirstIV vectorization to the unsigned case by introducing and handling FindFirstIVUMin. Co-authored-by: Florian Hahn <flo@fhahn.com>
1 parent 3640a58 commit 62f8377

File tree

5 files changed

+290
-77
lines changed

5 files changed

+290
-77
lines changed

llvm/include/llvm/Analysis/IVDescriptors.h

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,9 @@ enum class RecurKind {
5757
FindFirstIVSMin, /// FindFirst reduction with select(icmp(),x,y) where one of
5858
///< (x,y) is a decreasing loop induction, and both x and y
5959
///< are integer type, producing a SMin reduction.
60+
FindFirstIVUMin, /// FindFirst reduction with select(icmp(),x,y) where one of
61+
///< (x,y) is a decreasing loop induction, and both x and y
62+
///< are integer type, producing a UMin reduction.
6063
FindLastIVSMax, ///< FindLast reduction with select(cmp(),x,y) where one of
6164
///< (x,y) is increasing loop induction, and both x and y
6265
///< are integer type, producing a SMax reduction.
@@ -265,7 +268,8 @@ class RecurrenceDescriptor {
265268
/// Returns true if the recurrence kind is of the form
266269
/// select(cmp(),x,y) where one of (x,y) is decreasing loop induction.
267270
static bool isFindFirstIVRecurrenceKind(RecurKind Kind) {
268-
return Kind == RecurKind::FindFirstIVSMin;
271+
return Kind == RecurKind::FindFirstIVSMin ||
272+
Kind == RecurKind::FindFirstIVUMin;
269273
}
270274

271275
/// Returns true if the recurrence kind is of the form

llvm/lib/Analysis/IVDescriptors.cpp

Lines changed: 35 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ bool RecurrenceDescriptor::isIntegerRecurrenceKind(RecurKind Kind) {
5151
case RecurKind::UMin:
5252
case RecurKind::AnyOf:
5353
case RecurKind::FindFirstIVSMin:
54+
case RecurKind::FindFirstIVUMin:
5455
case RecurKind::FindLastIVSMax:
5556
case RecurKind::FindLastIVUMax:
5657
return true;
@@ -663,9 +664,9 @@ RecurrenceDescriptor::isAnyOfPattern(Loop *Loop, PHINode *OrigPhi,
663664
// if (src[i] > 3)
664665
// r = i;
665666
// }
666-
// The reduction value (r) is derived from either the values of an increasing
667-
// induction variable (i) sequence, or from the start value (0).
668-
// The LLVM IR generated for such loops would be as follows:
667+
// The reduction value (r) is derived from either the values of an induction
668+
// variable (i) sequence, or from the start value (0). The LLVM IR generated for
669+
// such loops would be as follows:
669670
// for.body:
670671
// %r = phi i32 [ %spec.select, %for.body ], [ 0, %entry ]
671672
// %i = phi i32 [ %inc, %for.body ], [ 0, %entry ]
@@ -674,13 +675,16 @@ RecurrenceDescriptor::isAnyOfPattern(Loop *Loop, PHINode *OrigPhi,
674675
// %spec.select = select i1 %cmp, i32 %i, i32 %r
675676
// %inc = add nsw i32 %i, 1
676677
// ...
677-
// Since 'i' is an increasing induction variable, the reduction value after the
678-
// loop will be the maximum value of 'i' that the condition (src[i] > 3) is
679-
// satisfied, or the start value (0 in the example above). When the start value
680-
// of the increasing induction variable 'i' is greater than the minimum value of
681-
// the data type, we can use the minimum value of the data type as a sentinel
682-
// value to replace the start value. This allows us to perform a single
683-
// reduction max operation to obtain the final reduction result.
678+
// Since 'i' is an induction variable, the reduction value after the loop will
679+
// be the maximum (increasing induction) or minimum (decreasing induction) value
680+
// of 'i' that the condition (src[i] > 3) is satisfied, or the start value (0 in
681+
// the example above). When the start value of the induction variable 'i' is
682+
// greater than the minimum (increasing induction) or maximum (decreasing
683+
// induction) value of the data type, we can use the minimum (increasing
684+
// induction) or maximum (decreasing induction) value of the data type as a
685+
// sentinel value to replace the start value. This allows us to perform a single
686+
// reduction max (increasing induction) or min (decreasing induction) operation
687+
// to obtain the final reduction result.
684688
// TODO: It is possible to solve the case where the start value is the minimum
685689
// value of the data type or a non-constant value by using mask and multiple
686690
// reduction operations.
@@ -695,6 +699,9 @@ RecurrenceDescriptor::isFindIVPattern(RecurKind Kind, Loop *TheLoop,
695699
if (!OrigPhi->hasOneUse())
696700
return InstDesc(false, I);
697701

702+
// We are looking for selects of the form:
703+
// select(cmp(), phi, loop_induction) or
704+
// select(cmp(), loop_induction, phi)
698705
// TODO: Match selects with multi-use cmp conditions.
699706
Value *NonRdxPhi = nullptr;
700707
if (!match(I, m_CombineOr(m_Select(m_OneUse(m_Cmp()), m_Value(NonRdxPhi),
@@ -703,8 +710,8 @@ RecurrenceDescriptor::isFindIVPattern(RecurKind Kind, Loop *TheLoop,
703710
m_Value(NonRdxPhi)))))
704711
return InstDesc(false, I);
705712

706-
// Returns a non-nullopt boolean indicating the signedness of the recurrence
707-
// when a valid FindLastIV pattern is found.
713+
// Returns either FindFirstIV/FindLastIV, if such a pattern is found, or
714+
// std::nullopt.
708715
auto GetRecurKind = [&](Value *V) -> std::optional<RecurKind> {
709716
Type *Ty = V->getType();
710717
if (!SE.isSCEVable(Ty))
@@ -719,16 +726,12 @@ RecurrenceDescriptor::isFindIVPattern(RecurKind Kind, Loop *TheLoop,
719726
(isFindLastIVRecurrenceKind(Kind) && !SE.isKnownPositive(Step)))
720727
return std::nullopt;
721728

722-
// Keep the minimum value of the recurrence type as the sentinel value.
723-
// The maximum acceptable range for the increasing induction variable,
724-
// 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
729-
// [<sentinel value> + 1, <sentinel value>)
730-
// where <sentinel value> is [Signed|Unsigned]Min(<recurrence type>) for
731-
// FindLastIV or [Signed|Unsigned]Max(<recurrence type>) for FindFirstIV.
729+
// Check if the minimum (FindLast) or maximum (FindFirst) value of the
730+
// recurrence type can be used as a sentinel value. The maximum acceptable
731+
// range for the induction variable, called the valid range will exclude
732+
// <sentinel value>, where <sentinel value> is
733+
// [Signed|Unsigned]Min(<recurrence type>) for FindLastIV or
734+
// [Signed|Unsigned]Max(<recurrence type>) for FindFirstIV.
732735
// TODO: This range restriction can be lifted by adding an additional
733736
// virtual OR reduction.
734737
auto CheckRange = [&](bool IsSigned) {
@@ -741,10 +744,13 @@ RecurrenceDescriptor::isFindIVPattern(RecurKind Kind, Loop *TheLoop,
741744
: APInt::getMinValue(NumBits);
742745
ValidRange = ConstantRange::getNonEmpty(Sentinel + 1, Sentinel);
743746
} else {
744-
assert(IsSigned && "Only FindFirstIV with SMax is supported currently");
745-
ValidRange =
746-
ConstantRange::getNonEmpty(APInt::getSignedMinValue(NumBits),
747-
APInt::getSignedMaxValue(NumBits) - 1);
747+
if (IsSigned)
748+
ValidRange =
749+
ConstantRange::getNonEmpty(APInt::getSignedMinValue(NumBits),
750+
APInt::getSignedMaxValue(NumBits) - 1);
751+
else
752+
ValidRange = ConstantRange::getNonEmpty(
753+
APInt::getMinValue(NumBits), APInt::getMaxValue(NumBits) - 1);
748754
}
749755

750756
LLVM_DEBUG(dbgs() << "LV: "
@@ -770,13 +776,11 @@ RecurrenceDescriptor::isFindIVPattern(RecurKind Kind, Loop *TheLoop,
770776

771777
if (CheckRange(true))
772778
return RecurKind::FindFirstIVSMin;
779+
if (CheckRange(false))
780+
return RecurKind::FindFirstIVUMin;
773781
return std::nullopt;
774782
};
775783

776-
// We are looking for selects of the form:
777-
// select(cmp(), phi, increasing_loop_induction) or
778-
// select(cmp(), increasing_loop_induction, phi)
779-
// TODO: Support for monotonically decreasing induction variable
780784
if (auto RK = GetRecurKind(NonRdxPhi))
781785
return InstDesc(I, *RK);
782786

@@ -1183,6 +1187,7 @@ unsigned RecurrenceDescriptor::getOpcode(RecurKind Kind) {
11831187
return Instruction::Mul;
11841188
case RecurKind::AnyOf:
11851189
case RecurKind::FindFirstIVSMin:
1190+
case RecurKind::FindFirstIVUMin:
11861191
case RecurKind::FindLastIVSMax:
11871192
case RecurKind::FindLastIVUMax:
11881193
case RecurKind::Or:

llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23133,6 +23133,7 @@ class HorizontalReduction {
2313323133
case RecurKind::FMulAdd:
2313423134
case RecurKind::AnyOf:
2313523135
case RecurKind::FindFirstIVSMin:
23136+
case RecurKind::FindFirstIVUMin:
2313623137
case RecurKind::FindLastIVSMax:
2313723138
case RecurKind::FindLastIVUMax:
2313823139
case RecurKind::FMaximumNum:
@@ -23269,6 +23270,7 @@ class HorizontalReduction {
2326923270
case RecurKind::FMulAdd:
2327023271
case RecurKind::AnyOf:
2327123272
case RecurKind::FindFirstIVSMin:
23273+
case RecurKind::FindFirstIVUMin:
2327223274
case RecurKind::FindLastIVSMax:
2327323275
case RecurKind::FindLastIVUMax:
2327423276
case RecurKind::FMaximumNum:
@@ -23370,6 +23372,7 @@ class HorizontalReduction {
2337023372
case RecurKind::FMulAdd:
2337123373
case RecurKind::AnyOf:
2337223374
case RecurKind::FindFirstIVSMin:
23375+
case RecurKind::FindFirstIVUMin:
2337323376
case RecurKind::FindLastIVSMax:
2337423377
case RecurKind::FindLastIVUMax:
2337523378
case RecurKind::FMaximumNum:

llvm/lib/Transforms/Vectorize/VPlanRecipes.cpp

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -763,14 +763,10 @@ Value *VPInstruction::generate(VPTransformState &State) {
763763
Value *ReducedPartRdx = State.get(getOperand(3));
764764
RecurKind MinMaxKind;
765765
bool IsSigned = RecurrenceDescriptor::isSignedRecurrenceKind(RK);
766-
if (RecurrenceDescriptor::isFindLastIVRecurrenceKind(RK)) {
766+
if (RecurrenceDescriptor::isFindLastIVRecurrenceKind(RK))
767767
MinMaxKind = IsSigned ? RecurKind::SMax : RecurKind::UMax;
768-
} else {
769-
assert(RecurrenceDescriptor::isFindFirstIVRecurrenceKind(RK) &&
770-
"Kind must either be FindLastIV or FindFirstIV");
771-
assert(IsSigned && "Only FindFirstIV with SMax is currently supported");
772-
MinMaxKind = RecurKind::SMin;
773-
}
768+
else
769+
MinMaxKind = IsSigned ? RecurKind::SMin : RecurKind::UMin;
774770
for (unsigned Part = 1; Part < UF; ++Part)
775771
ReducedPartRdx = createMinMaxOp(Builder, MinMaxKind, ReducedPartRdx,
776772
State.get(getOperand(3 + Part)));

0 commit comments

Comments
 (0)