Index: llvm/lib/Analysis/ScalarEvolution.cpp =================================================================== --- llvm/lib/Analysis/ScalarEvolution.cpp +++ llvm/lib/Analysis/ScalarEvolution.cpp @@ -11577,6 +11577,69 @@ const SCEVAddRecExpr *IV = dyn_cast(LHS); bool PredicatedIV = false; + auto canAssumeNoSelfWrap = [&](const SCEVAddRecExpr *AR) { + // Can we prove this loop *must* be UB if overflow of IV occurs? + // Reasoning goes as follows: + // * Suppose the IV did self wrap. + // * If Stride evenly divides the iteration space, then once wrap + // occurs, the loop must revisit the same values. + // * We know that RHS is invariant, and that none of those values + // caused this exit to be taken previously. Thus, this exit is + // dynamically dead. + // * If this is the sole exit, then a dead exit implies the loop + // must be infinite if there are no abnormal exits. + // * If the loop were infinite, then it must either not be mustprogress + // or have side effects. Otherwise, it must be UB. + // * It can't (by assumption), be UB so we have contradicted our + // premise and can conclude the IV did not in fact self-wrap. + if (!isLoopInvariant(RHS, L)) + return false; + + auto *StrideC = dyn_cast(AR->getStepRecurrence(*this)); + if (!StrideC || !StrideC->getAPInt().isPowerOf2()) + return false; + + if (!ControlsExit || !loopHasNoAbnormalExits(L)) + return false; + + return loopIsFiniteByAssumption(L); + }; + + if (!IV) { + auto *ZExt = dyn_cast(LHS); + if (ZExt) { + const SCEVAddRecExpr *AR = dyn_cast(ZExt->getOperand()); + if (AR && AR->getLoop() == L && AR->isAffine()) { + auto Flags = AR->getNoWrapFlags(); + if (!hasFlags(Flags, SCEV::FlagNW) && canAssumeNoSelfWrap(AR)) { + Flags = setFlags(Flags, SCEV::FlagNW); + + // These three lines can be dropped once D108601 has landed + if (hasFlags(Flags, SCEV::FlagNW) && + !hasFlags(Flags, SCEV::FlagNUW) && + AR->getStart()->isZero()) + Flags = setFlags(Flags, SCEV::FlagNUW); + + SmallVector Operands{AR->operands()}; + Flags = StrengthenNoWrapFlags(this, scAddRecExpr, Operands, Flags); + + setNoWrapFlags(const_cast(AR), Flags); + } + if (AR->hasNoUnsignedWrap()) { + // Emulate what getZeroExtendExpr would have done during construction + // if we'd been able to infer the fact just above at that time. + const SCEV *Step = AR->getStepRecurrence(*this); + Type *Ty = ZExt->getType(); + auto *S = getAddRecExpr( + getExtendAddRecStart(AR, Ty, this, 0), + getZeroExtendExpr(Step, Ty, 0), L, AR->getNoWrapFlags()); + IV = dyn_cast(S); + } + } + } + } + + if (!IV && AllowPredicates) { // Try to make this an AddRec using runtime tests, in the first X // iterations of this loop, where X is the SCEV expression found by the @@ -11688,37 +11751,12 @@ } } else if (!Stride->isOne() && !NoWrap) { auto isUBOnWrap = [&]() { - // Can we prove this loop *must* be UB if overflow of IV occurs? - // Reasoning goes as follows: - // * Suppose the IV did self wrap. - // * If Stride evenly divides the iteration space, then once wrap - // occurs, the loop must revisit the same values. - // * We know that RHS is invariant, and that none of those values - // caused this exit to be taken previously. Thus, this exit is - // dynamically dead. - // * If this is the sole exit, then a dead exit implies the loop - // must be infinite if there are no abnormal exits. - // * If the loop were infinite, then it must either not be mustprogress - // or have side effects. Otherwise, it must be UB. - // * It can't (by assumption), be UB so we have contradicted our - // premise and can conclude the IV did not in fact self-wrap. // From no-self-wrap, we need to then prove no-(un)signed-wrap. This // follows trivially from the fact that every (un)signed-wrapped, but // not self-wrapped value must be LT than the last value before // (un)signed wrap. Since we know that last value didn't exit, nor // will any smaller one. - - if (!isLoopInvariant(RHS, L)) - return false; - - auto *StrideC = dyn_cast(Stride); - if (!StrideC || !StrideC->getAPInt().isPowerOf2()) - return false; - - if (!ControlsExit || !loopHasNoAbnormalExits(L)) - return false; - - return loopIsFiniteByAssumption(L); + return canAssumeNoSelfWrap(IV); }; // Avoid proven overflow cases: this will ensure that the backedge taken