Index: llvm/lib/Transforms/Scalar/IndVarSimplify.cpp =================================================================== --- llvm/lib/Transforms/Scalar/IndVarSimplify.cpp +++ llvm/lib/Transforms/Scalar/IndVarSimplify.cpp @@ -2332,7 +2332,8 @@ // Returns true if the condition of \p BI being checked is invariant and can be // proved to be trivially true during at least first \p MaxIter iterations. static bool isTrivialCond(const Loop *L, BranchInst *BI, ScalarEvolution *SE, - bool ProvingLoopExit, const SCEV *MaxIter) { + bool ProvingLoopExit, const SCEV *MaxIter, + bool SkipLastIter) { ICmpInst::Predicate Pred; Value *LHS, *RHS; using namespace PatternMatch; @@ -2388,6 +2389,10 @@ if (AR->getType() != MaxIter->getType()) return false; + + if (SkipLastIter) + MaxIter = SE->getMinusSCEV(MaxIter, One, SCEV::FlagNUW); + // First, check the predicate on the 1st iteration. const SCEV *Start = AR->getStart(); if (!SE->isKnownPredicateAt(Pred, Start, RHSS, BI)) @@ -2485,13 +2490,14 @@ }; bool Changed = false; + bool SkipLastIter = false; SmallSet DominatingExitCounts; for (BasicBlock *ExitingBB : ExitingBlocks) { const SCEV *ExitCount = SE->getExitCount(L, ExitingBB); if (isa(ExitCount)) { auto *BI = cast(ExitingBB->getTerminator()); - auto OptimizeCond = [&](bool Inverted, const SCEV *MaxIter) { - if (isTrivialCond(L, BI, SE, Inverted, MaxIter)) { + auto OptimizeCond = [&](bool Inverted, bool SkipLastIter) { + if (isTrivialCond(L, BI, SE, Inverted, MaxExitCount, SkipLastIter)) { FoldExit(ExitingBB, Inverted); return true; } @@ -2499,13 +2505,40 @@ }; // Okay, we do not know the exit count here. Can we at least prove that it // will remain the same within iteration space? - if (OptimizeCond(false, MaxExitCount)) + if (OptimizeCond(false, false)) Changed = true; - else if (OptimizeCond(true, MaxExitCount)) + else if (OptimizeCond(true, false)) Changed = true; + else if (SkipLastIter) { + // If we cannot prove it on the last loop iteration, try to benefit + // from the fact that this check will not be executed on the last + // iteration. + // TODO: What we really want is to query with (MaxExitCount - 1), + // and the check should only check the condition on pre-last iteration + // if the backedge was taken at least once. Consider loop: + // + // for (i = len; i != 0; i--) { ... check (i ult X) ... } + // + // If len = 0 then MaxExitCount = 0, and the pre-last iteration will + // not be executed at all. But SCEV does not always recognize this and + // may start thinking that i on the iteration (MaxExitCount - 1) is a + // huge value. So we just query this separately. + // + // The checks against MaxExitCount above can be removed once we find a + // good way to resolve this problem. + if (OptimizeCond(false, true)) + Changed = true; + else if (OptimizeCond(true, true)) + Changed = true; + } continue; } + if (MaxExitCount == ExitCount) + // If the loop has more than 1 iteration, all further checks will be + // executed 1 iteration less. + SkipLastIter = true; + // If we know we'd exit on the first iteration, rewrite the exit to // reflect this. This does not imply the loop must exit through this // exit; there may be an earlier one taken on the first iteration. Index: llvm/test/Transforms/IndVarSimplify/predicated_ranges.ll =================================================================== --- llvm/test/Transforms/IndVarSimplify/predicated_ranges.ll +++ llvm/test/Transforms/IndVarSimplify/predicated_ranges.ll @@ -21,8 +21,7 @@ ; CHECK-NEXT: br i1 [[ZERO_COND]], label [[EXIT:%.*]], label [[RANGE_CHECK_BLOCK:%.*]] ; CHECK: range_check_block: ; CHECK-NEXT: [[IV_NEXT]] = sub i32 [[IV]], 1 -; CHECK-NEXT: [[RANGE_CHECK:%.*]] = icmp ult i32 [[IV_NEXT]], [[LEN]] -; CHECK-NEXT: br i1 [[RANGE_CHECK]], label [[BACKEDGE]], label [[FAIL:%.*]] +; CHECK-NEXT: br i1 true, label [[BACKEDGE]], label [[FAIL:%.*]] ; CHECK: backedge: ; CHECK-NEXT: [[EL_PTR:%.*]] = getelementptr i32, i32* [[P]], i32 [[IV]] ; CHECK-NEXT: [[EL:%.*]] = load i32, i32* [[EL_PTR]], align 4