Index: llvm/include/llvm/Analysis/ScalarEvolution.h =================================================================== --- llvm/include/llvm/Analysis/ScalarEvolution.h +++ llvm/include/llvm/Analysis/ScalarEvolution.h @@ -1314,6 +1314,7 @@ const SCEV *ExactNotTaken; // The exit is not taken exactly this many times const SCEV *ConstantMaxNotTaken; // The exit is not taken at most this many // times + const SCEV *SymbolicMaxNotTaken; // Not taken either exactly ConstantMaxNotTaken or zero times bool MaxOrZero = false; @@ -1360,14 +1361,16 @@ PoisoningVH ExitingBlock; const SCEV *ExactNotTaken; const SCEV *ConstantMaxNotTaken; + const SCEV *SymbolicMaxNotTaken; SmallPtrSet Predicates; explicit ExitNotTakenInfo( PoisoningVH ExitingBlock, const SCEV *ExactNotTaken, - const SCEV *ConstantMaxNotTaken, + const SCEV *ConstantMaxNotTaken, const SCEV *SymbolicMaxNotTaken, const SmallPtrSet &Predicates) : ExitingBlock(ExitingBlock), ExactNotTaken(ExactNotTaken), - ConstantMaxNotTaken(ConstantMaxNotTaken), Predicates(Predicates) {} + ConstantMaxNotTaken(ConstantMaxNotTaken), + SymbolicMaxNotTaken(SymbolicMaxNotTaken), Predicates(Predicates) {} bool hasAlwaysTruePredicate() const { return Predicates.empty(); Index: llvm/lib/Analysis/ScalarEvolution.cpp =================================================================== --- llvm/lib/Analysis/ScalarEvolution.cpp +++ llvm/lib/Analysis/ScalarEvolution.cpp @@ -8559,8 +8559,11 @@ const SCEV *ScalarEvolution::BackedgeTakenInfo::getSymbolicMax( const BasicBlock *ExitingBlock, ScalarEvolution *SE) const { - // FIXME: Need to implement this. Return exact for now. - return getExact(ExitingBlock, SE); + for (const auto &ENT : ExitNotTaken) + if (ENT.ExitingBlock == ExitingBlock && ENT.hasAlwaysTruePredicate()) + return ENT.SymbolicMaxNotTaken; + + return SE->getCouldNotCompute(); } /// getConstantMax - Get the constant max backedge taken count for the loop. @@ -8610,6 +8613,13 @@ if (ConstantMaxNotTaken->isZero()) ExactNotTaken = ConstantMaxNotTaken; + // FIXME: For now, SymbolicMaxNotTaken is either exact (if available) or + // constant max. In the future, we are planning to make it more powerful. + if (isa(ExactNotTaken)) + SymbolicMaxNotTaken = ConstantMaxNotTaken; + else + SymbolicMaxNotTaken = ExactNotTaken; + assert((isa(ExactNotTaken) || !isa(ConstantMaxNotTaken)) && "Exact is not allowed to be less precise than Max"); @@ -8646,7 +8656,8 @@ BasicBlock *ExitBB = EEI.first; const ExitLimit &EL = EEI.second; return ExitNotTakenInfo(ExitBB, EL.ExactNotTaken, - EL.ConstantMaxNotTaken, EL.Predicates); + EL.ConstantMaxNotTaken, EL.SymbolicMaxNotTaken, + EL.Predicates); }); assert((isa(ConstantMax) || isa(ConstantMax)) && @@ -14751,9 +14762,6 @@ for (BasicBlock *ExitingBB : ExitingBlocks) { const SCEV *ExitCount = getExitCount(L, ExitingBB, ScalarEvolution::SymbolicMaximum); - if (isa(ExitCount)) - ExitCount = getExitCount(L, ExitingBB, - ScalarEvolution::ConstantMaximum); if (!isa(ExitCount)) { assert(DT.dominates(ExitingBB, L->getLoopLatch()) && "We should only have known counts for exiting blocks that "