diff --git a/llvm/lib/Analysis/ScalarEvolution.cpp b/llvm/lib/Analysis/ScalarEvolution.cpp index 5cb96a2111c7..c6a1328c6b00 100644 --- a/llvm/lib/Analysis/ScalarEvolution.cpp +++ b/llvm/lib/Analysis/ScalarEvolution.cpp @@ -11742,10 +11742,29 @@ ScalarEvolution::howManyLessThans(const SCEV *LHS, const SCEV *RHS, if (isLoopEntryGuardedByCond(L, Cond, getMinusSCEV(OrigStart, Stride), OrigRHS)) BECount = BECountIfBackedgeTaken; else { + auto canProveRHSGreaterThanEqualStart = [&]() { + auto CondGE = IsSigned ? ICmpInst::ICMP_SGE : ICmpInst::ICMP_UGE; + if (isLoopEntryGuardedByCond(L, CondGE, OrigRHS, OrigStart)) + return true; + + // (RHS > Start - 1) implies RHS >= Start. + // * "RHS >= Start" is trivially equivalent to "RHS > Start - 1" if + // "Start - 1" doesn't overflow. + // * For signed comparison, if Start - 1 does overflow, it's equal + // to INT_MAX, and "RHS >s INT_MAX" is trivially false. + // * For unsigned comparison, if Start - 1 does overflow, it's equal + // to UINT_MAX, and "RHS >u UINT_MAX" is trivially false. + // + // FIXME: Should isLoopEntryGuardedByCond do this for us? + auto CondGT = IsSigned ? ICmpInst::ICMP_SGT : ICmpInst::ICMP_UGT; + auto *StartMinusOne = getAddExpr(OrigStart, + getMinusOne(OrigStart->getType())); + return isLoopEntryGuardedByCond(L, CondGT, OrigRHS, StartMinusOne); + }; + // If we know that RHS >= Start in the context of loop, then we know that // max(RHS, Start) = RHS at this point. - if (isLoopEntryGuardedByCond( - L, IsSigned ? ICmpInst::ICMP_SGE : ICmpInst::ICMP_UGE, OrigRHS, OrigStart)) + if (canProveRHSGreaterThanEqualStart()) End = RHS; else End = IsSigned ? getSMaxExpr(RHS, Start) : getUMaxExpr(RHS, Start);