Skip to content

Commit 7dcc889

Browse files
committed
[SCEV] Generalize no-self-wrap check in isLoopInvariantExitCondDuringFirstIterations
Lift limitation on step being `+/- 1`. In fact, the only thing it is needed for is proving no-self-wrap. We can instead check this flag directly. Theoretically it can increase the scope of the transform, but I could not construct such test easily. Differential Revision: https://reviews.llvm.org/D91126 Reviewed By: apilipenko
1 parent b706748 commit 7dcc889

File tree

1 file changed

+16
-15
lines changed

1 file changed

+16
-15
lines changed

llvm/lib/Analysis/ScalarEvolution.cpp

Lines changed: 16 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -9589,32 +9589,33 @@ bool ScalarEvolution::isLoopInvariantExitCondDuringFirstIterations(
95899589
if (!ICmpInst::isRelational(Pred))
95909590
return false;
95919591

9592-
// TODO: Support steps other than +/- 1.
95939592
const SCEV *Step = AR->getStepRecurrence(*this);
9594-
auto *One = getOne(Step->getType());
9595-
auto *MinusOne = getNegativeSCEV(One);
9596-
if (Step != One && Step != MinusOne)
9593+
bool IsStepNonPositive = isKnownNonPositive(Step);
9594+
if (!IsStepNonPositive && !isKnownNonNegative(Step))
95979595
return false;
9598-
9599-
// Type mismatch here means that MaxIter is potentially larger than max
9600-
// unsigned value in start type, which mean we cannot prove no wrap for the
9601-
// indvar.
9602-
if (AR->getType() != MaxIter->getType())
9596+
bool HasNoSelfWrap = AR->hasNoSelfWrap();
9597+
if (!HasNoSelfWrap)
9598+
// If num iter has same type as the AddRec, and step is +/- 1, even max
9599+
// possible number of iterations is not enough to self-wrap.
9600+
if (MaxIter->getType() == AR->getType())
9601+
if (Step == getOne(AR->getType()) || Step == getMinusOne(AR->getType()))
9602+
HasNoSelfWrap = true;
9603+
// Only proceed with non-self-wrapping ARs.
9604+
if (!HasNoSelfWrap)
96039605
return false;
96049606

96059607
// Value of IV on suggested last iteration.
96069608
const SCEV *Last = AR->evaluateAtIteration(MaxIter, *this);
96079609
// Does it still meet the requirement?
96089610
if (!isKnownPredicateAt(Pred, Last, RHS, Context))
96099611
return false;
9610-
// Because step is +/- 1 and MaxIter has same type as Start (i.e. it does
9611-
// not exceed max unsigned value of this type), this effectively proves
9612-
// that there is no wrap during the iteration. To prove that there is no
9613-
// signed/unsigned wrap, we need to check that
9614-
// Start <= Last for step = 1 or Start >= Last for step = -1.
9612+
// We know that the addrec does not have a self-wrap. To prove that there is
9613+
// no signed/unsigned wrap, we need to check that
9614+
// Start <= Last for positive step or Start >= Last for negative step. Either
9615+
// works for zero step.
96159616
ICmpInst::Predicate NoOverflowPred =
96169617
CmpInst::isSigned(Pred) ? ICmpInst::ICMP_SLE : ICmpInst::ICMP_ULE;
9617-
if (Step == MinusOne)
9618+
if (IsStepNonPositive)
96189619
NoOverflowPred = CmpInst::getSwappedPredicate(NoOverflowPred);
96199620
const SCEV *Start = AR->getStart();
96209621
if (!isKnownPredicateAt(NoOverflowPred, Start, Last, Context))

0 commit comments

Comments
 (0)