-
Notifications
You must be signed in to change notification settings - Fork 13.6k
[LV] Add support for cmp reductions with decreasing IVs. #140451
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -56,6 +56,13 @@ enum class RecurKind { | |
FindLastIV, ///< FindLast reduction with select(cmp(),x,y) where one of | ||
///< (x,y) is increasing loop induction, and both x and y are | ||
///< integer type. | ||
FindFirstIVUMin, /// FindFirst reduction with select(icmp(),x,y) where one of | ||
///< (x,y) is a decreasing loop induction, and both x and y | ||
///< are integer type. | ||
FindFirstIVSMin /// FindFirst reduction with select(icmp(),x,y) where one of | ||
///< (x,y) is a decreasing loop induction, and both x and y | ||
///< are integer type. | ||
Comment on lines
+59
to
+64
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This patch introduces too many new idioms at once. |
||
|
||
// clang-format on | ||
// TODO: Any_of and FindLast reduction need not be restricted to integer type | ||
// only. | ||
|
@@ -160,12 +167,13 @@ class RecurrenceDescriptor { | |
/// Returns a struct describing whether the instruction is either a | ||
/// Select(ICmp(A, B), X, Y), or | ||
/// Select(FCmp(A, B), X, Y) | ||
/// where one of (X, Y) is an increasing loop induction variable, and the | ||
/// other is a PHI value. | ||
/// where one of (X, Y) is an increasing (FindLast) or decreasing (FindFirst) | ||
/// loop induction variable, and the other is a PHI value. | ||
// TODO: Support non-monotonic variable. FindLast does not need be restricted | ||
// to increasing loop induction variables. | ||
static InstDesc isFindLastIVPattern(Loop *TheLoop, PHINode *OrigPhi, | ||
Instruction *I, ScalarEvolution &SE); | ||
static InstDesc isFindIVPattern(RecurKind Kind, Loop *TheLoop, | ||
PHINode *OrigPhi, Instruction *I, | ||
ScalarEvolution &SE); | ||
|
||
/// Returns a struct describing if the instruction is a | ||
/// Select(FCmp(X, Y), (Z = X op PHINode), PHINode) instruction pattern. | ||
|
@@ -259,17 +267,33 @@ class RecurrenceDescriptor { | |
return Kind == RecurKind::FindLastIV; | ||
} | ||
|
||
/// Returns true if the recurrence kind is of the form | ||
/// select(cmp(),x,y) where one of (x,y) is an increasing or decreasing loop | ||
/// induction. | ||
static bool isFindIVRecurrenceKind(RecurKind Kind) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Factor out isFindFirstIVRecurrenceKind? |
||
return Kind == RecurKind::FindLastIV || | ||
Kind == RecurKind::FindFirstIVUMin || | ||
Kind == RecurKind::FindFirstIVSMin; | ||
} | ||
|
||
/// Returns the type of the recurrence. This type can be narrower than the | ||
/// actual type of the Phi if the recurrence has been type-promoted. | ||
Type *getRecurrenceType() const { return RecurrenceType; } | ||
|
||
/// Returns the sentinel value for FindLastIV recurrences to replace the start | ||
/// value. | ||
/// Returns the sentinel value for FindFirstIV &FindLastIV recurrences to | ||
/// replace the start value. | ||
Value *getSentinelValue() const { | ||
assert(isFindLastIVRecurrenceKind(Kind) && "Unexpected recurrence kind"); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why strip this assert, and move it to a branch? |
||
Type *Ty = StartValue->getType(); | ||
return ConstantInt::get(Ty, | ||
APInt::getSignedMinValue(Ty->getIntegerBitWidth())); | ||
if (isFindLastIVRecurrenceKind(Kind)) { | ||
return ConstantInt::get( | ||
Ty, APInt::getSignedMinValue(Ty->getIntegerBitWidth())); | ||
} else if (Kind == RecurKind::FindFirstIVSMin) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Drop else |
||
return ConstantInt::get( | ||
Ty, APInt::getSignedMaxValue(Ty->getIntegerBitWidth())); | ||
} else { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Drop else |
||
assert(Kind == RecurKind::FindFirstIVUMin); | ||
return ConstantInt::get(Ty, APInt::getMaxValue(Ty->getIntegerBitWidth())); | ||
} | ||
} | ||
Comment on lines
+283
to
297
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. #141788 Try to change the sentinel value to be selected dynamically instead of based on RecurKind statically. |
||
|
||
/// Returns a reference to the instructions used for type-promoting the | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -51,6 +51,8 @@ bool RecurrenceDescriptor::isIntegerRecurrenceKind(RecurKind Kind) { | |
case RecurKind::UMin: | ||
case RecurKind::AnyOf: | ||
case RecurKind::FindLastIV: | ||
case RecurKind::FindFirstIVUMin: | ||
case RecurKind::FindFirstIVSMin: | ||
return true; | ||
} | ||
return false; | ||
|
@@ -683,8 +685,9 @@ RecurrenceDescriptor::isAnyOfPattern(Loop *Loop, PHINode *OrigPhi, | |
// value of the data type or a non-constant value by using mask and multiple | ||
// reduction operations. | ||
RecurrenceDescriptor::InstDesc | ||
RecurrenceDescriptor::isFindLastIVPattern(Loop *TheLoop, PHINode *OrigPhi, | ||
Instruction *I, ScalarEvolution &SE) { | ||
RecurrenceDescriptor::isFindIVPattern(RecurKind Kind, Loop *TheLoop, | ||
PHINode *OrigPhi, Instruction *I, | ||
ScalarEvolution &SE) { | ||
// TODO: Support the vectorization of FindLastIV when the reduction phi is | ||
// used by more than one select instruction. This vectorization is only | ||
// performed when the SCEV of each increasing induction variable used by the | ||
|
@@ -700,7 +703,7 @@ RecurrenceDescriptor::isFindLastIVPattern(Loop *TheLoop, PHINode *OrigPhi, | |
m_Value(NonRdxPhi))))) | ||
return InstDesc(false, I); | ||
|
||
auto IsIncreasingLoopInduction = [&](Value *V) { | ||
auto IsSupportedLoopInduction = [&](Value *V, RecurKind Kind) { | ||
Type *Ty = V->getType(); | ||
if (!SE.isSCEVable(Ty)) | ||
return false; | ||
|
@@ -710,21 +713,39 @@ RecurrenceDescriptor::isFindLastIVPattern(Loop *TheLoop, PHINode *OrigPhi, | |
return false; | ||
|
||
const SCEV *Step = AR->getStepRecurrence(SE); | ||
if (!SE.isKnownPositive(Step)) | ||
if (Kind == RecurKind::FindFirstIVUMin || | ||
Kind == RecurKind::FindFirstIVSMin) { | ||
if (!SE.isKnownNegative(Step)) | ||
return false; | ||
} else if (!SE.isKnownPositive(Step)) | ||
return false; | ||
|
||
const ConstantRange IVRange = SE.getSignedRange(AR); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Shouldn't this be getUnsignedRange in some cases? |
||
unsigned NumBits = Ty->getIntegerBitWidth(); | ||
// Keep the minimum value of the recurrence type as the sentinel value. | ||
// The maximum acceptable range for the increasing induction variable, | ||
// called the valid range, will be defined as | ||
// Keep the minimum (FindLast) or maximum (FindFirst) value of the | ||
// recurrence type as the sentinel value. The maximum acceptable range for | ||
// the induction variable, called the valid range, will be defined as | ||
// [<sentinel value> + 1, <sentinel value>) | ||
// where <sentinel value> is SignedMin(<recurrence type>) | ||
// where <sentinel value> is SignedMin(<recurrence type>) for FindLast or | ||
// UnsignedMax(<recurrence type>) for FindFirst. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We also have a case with SignedMax. |
||
// TODO: This range restriction can be lifted by adding an additional | ||
// virtual OR reduction. | ||
const APInt Sentinel = APInt::getSignedMinValue(NumBits); | ||
const ConstantRange ValidRange = | ||
ConstantRange::getNonEmpty(Sentinel + 1, Sentinel); | ||
const APInt Sentinel = Kind == RecurKind::FindFirstIVUMin | ||
? APInt::getMaxValue(NumBits) | ||
: (Kind == RecurKind::FindFirstIVSMin | ||
? APInt::getSignedMaxValue(NumBits) | ||
: APInt::getSignedMinValue(NumBits)); | ||
Comment on lines
+733
to
+737
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This ternary expression also reads badly? |
||
ConstantRange ValidRange = ConstantRange::getEmpty(NumBits); | ||
if (Kind == RecurKind::FindFirstIVSMin) | ||
ValidRange = | ||
ConstantRange::getNonEmpty(APInt::getSignedMinValue(NumBits), | ||
APInt::getSignedMaxValue(NumBits) - 1); | ||
else { | ||
Comment on lines
+739
to
+743
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Braces |
||
const APInt Sentinel = Kind == RecurKind::FindFirstIVUMin | ||
? APInt::getMaxValue(NumBits) | ||
: APInt::getSignedMinValue(NumBits); | ||
ValidRange = ConstantRange::getNonEmpty(Sentinel + 1, Sentinel); | ||
} | ||
LLVM_DEBUG(dbgs() << "LV: FindLastIV valid range is " << ValidRange | ||
<< ", and the signed range of " << *AR << " is " | ||
<< IVRange << "\n"); | ||
Comment on lines
749
to
751
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Outdated DBG message? |
||
|
@@ -736,11 +757,18 @@ RecurrenceDescriptor::isFindLastIVPattern(Loop *TheLoop, PHINode *OrigPhi, | |
// We are looking for selects of the form: | ||
// select(cmp(), phi, increasing_loop_induction) or | ||
// select(cmp(), increasing_loop_induction, phi) | ||
// TODO: Support for monotonically decreasing induction variable | ||
if (!IsIncreasingLoopInduction(NonRdxPhi)) | ||
if (Kind == RecurKind::FindLastIV) { | ||
if (IsSupportedLoopInduction(NonRdxPhi, Kind)) | ||
return InstDesc(I, Kind); | ||
return InstDesc(false, I); | ||
} | ||
|
||
if (IsSupportedLoopInduction(NonRdxPhi, RecurKind::FindFirstIVSMin)) | ||
return InstDesc(I, RecurKind::FindFirstIVSMin); | ||
if (IsSupportedLoopInduction(NonRdxPhi, RecurKind::FindFirstIVUMin)) | ||
return InstDesc(I, RecurKind::FindFirstIVUMin); | ||
|
||
return InstDesc(I, RecurKind::FindLastIV); | ||
return InstDesc(false, I); | ||
Comment on lines
-739
to
+771
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Get IsSupportedLoopInduction to return a Kind, and compare with |
||
} | ||
|
||
RecurrenceDescriptor::InstDesc | ||
|
@@ -875,8 +903,8 @@ RecurrenceDescriptor::InstDesc RecurrenceDescriptor::isRecurrenceInstr( | |
if (Kind == RecurKind::FAdd || Kind == RecurKind::FMul || | ||
Kind == RecurKind::Add || Kind == RecurKind::Mul) | ||
return isConditionalRdxPattern(Kind, I); | ||
if (isFindLastIVRecurrenceKind(Kind) && SE) | ||
return isFindLastIVPattern(L, OrigPhi, I, *SE); | ||
if (isFindIVRecurrenceKind(Kind) && SE) | ||
return isFindIVPattern(Kind, L, OrigPhi, I, *SE); | ||
[[fallthrough]]; | ||
case Instruction::FCmp: | ||
case Instruction::ICmp: | ||
|
@@ -990,6 +1018,12 @@ bool RecurrenceDescriptor::isReductionPHI(PHINode *Phi, Loop *TheLoop, | |
LLVM_DEBUG(dbgs() << "Found a FindLastIV reduction PHI." << *Phi << "\n"); | ||
return true; | ||
} | ||
if (AddReductionVar(Phi, RecurKind::FindFirstIVUMin, TheLoop, FMF, RedDes, DB, | ||
AC, DT, SE)) { | ||
LLVM_DEBUG(dbgs() << "Found a FindFirstV reduction PHI." << *Phi << "\n"); | ||
return true; | ||
} | ||
Comment on lines
+1021
to
+1025
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I wonder if it's possible to avoid adding two RecurKinds, one for signed and another for unsigned? It's very displeasing to check just one of them? Also, will the FindLast pattern not suffice? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think it may be possible to use RecurrenceDescriptor::isSigned() to unify? Not sure. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. See #141752. You can rebase on top of it, assuming it's a good direction. |
||
|
||
if (AddReductionVar(Phi, RecurKind::FMul, TheLoop, FMF, RedDes, DB, AC, DT, | ||
SE)) { | ||
LLVM_DEBUG(dbgs() << "Found an FMult reduction PHI." << *Phi << "\n"); | ||
|
@@ -1153,6 +1187,8 @@ unsigned RecurrenceDescriptor::getOpcode(RecurKind Kind) { | |
case RecurKind::SMin: | ||
case RecurKind::UMax: | ||
case RecurKind::UMin: | ||
case RecurKind::FindFirstIVUMin: | ||
case RecurKind::FindFirstIVSMin: | ||
return Instruction::ICmp; | ||
case RecurKind::FMax: | ||
case RecurKind::FMin: | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -1244,12 +1244,16 @@ Value *llvm::createAnyOfReduction(IRBuilderBase &Builder, Value *Src, | |
Value *llvm::createFindLastIVReduction(IRBuilderBase &Builder, Value *Src, | ||
Value *Start, | ||
const RecurrenceDescriptor &Desc) { | ||
assert(RecurrenceDescriptor::isFindLastIVRecurrenceKind( | ||
Desc.getRecurrenceKind()) && | ||
"Unexpected reduction kind"); | ||
assert( | ||
RecurrenceDescriptor::isFindIVRecurrenceKind(Desc.getRecurrenceKind()) && | ||
"Unexpected reduction kind"); | ||
Value *Sentinel = Desc.getSentinelValue(); | ||
Value *MaxRdx = Src->getType()->isVectorTy() | ||
? Builder.CreateIntMaxReduce(Src, true) | ||
? (Desc.getRecurrenceKind() == RecurKind::FindLastIV | ||
? Builder.CreateIntMaxReduce(Src, true) | ||
: Builder.CreateIntMinReduce( | ||
Src, Desc.getRecurrenceKind() == | ||
RecurKind::FindFirstIVSMin)) | ||
Comment on lines
-1252
to
+1256
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This ternary expression reads badly? |
||
: Src; | ||
// Correct the final reduction result back to the start value if the maximum | ||
// reduction is sentinel value. | ||
|
@@ -1345,8 +1349,8 @@ Value *llvm::createSimpleReduction(IRBuilderBase &Builder, Value *Src, | |
Value *llvm::createSimpleReduction(VectorBuilder &VBuilder, Value *Src, | ||
RecurKind Kind) { | ||
assert(!RecurrenceDescriptor::isAnyOfRecurrenceKind(Kind) && | ||
!RecurrenceDescriptor::isFindLastIVRecurrenceKind(Kind) && | ||
"AnyOf or FindLastIV reductions are not supported."); | ||
!RecurrenceDescriptor::isFindIVRecurrenceKind(Kind) && | ||
"AnyOf, FindFirstIV and FindLastIV reductions are not supported."); | ||
Intrinsic::ID Id = getReductionIntrinsicID(Kind); | ||
auto *SrcTy = cast<VectorType>(Src->getType()); | ||
Type *SrcEltTy = SrcTy->getElementType(); | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -23092,6 +23092,8 @@ class HorizontalReduction { | |
case RecurKind::FMulAdd: | ||
case RecurKind::AnyOf: | ||
case RecurKind::FindLastIV: | ||
case RecurKind::FindFirstIVUMin: | ||
case RecurKind::FindFirstIVSMin: | ||
case RecurKind::FMaximumNum: | ||
case RecurKind::FMinimumNum: | ||
case RecurKind::None: | ||
|
@@ -23226,6 +23228,8 @@ class HorizontalReduction { | |
case RecurKind::FMulAdd: | ||
case RecurKind::AnyOf: | ||
case RecurKind::FindLastIV: | ||
case RecurKind::FindFirstIVUMin: | ||
case RecurKind::FindFirstIVSMin: | ||
case RecurKind::FMaximumNum: | ||
case RecurKind::FMinimumNum: | ||
case RecurKind::None: | ||
|
@@ -23325,6 +23329,8 @@ class HorizontalReduction { | |
case RecurKind::FMulAdd: | ||
case RecurKind::AnyOf: | ||
case RecurKind::FindLastIV: | ||
case RecurKind::FindFirstIVUMin: | ||
case RecurKind::FindFirstIVSMin: | ||
Comment on lines
23331
to
+23333
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why is this asymmetric? Wouldn't it be nicer to first separate out FindLastIV into FindLastIVSMax/UMax? |
||
case RecurKind::FMaximumNum: | ||
case RecurKind::FMinimumNum: | ||
case RecurKind::None: | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Identical doc?