From: Max Kazantsev Date: Fri, 9 Dec 2022 10:05:33 +0000 (+0700) Subject: [IndVars] Use symbolic max block exit count to handle the last iter X-Git-Tag: upstream/17.0.6~24540 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=262f2fed65b83ba9b64227b983d5ed95883fd71e;p=platform%2Fupstream%2Fllvm.git [IndVars] Use symbolic max block exit count to handle the last iter Old logic: when loop symbolic max exit count matched *exact* block exit count, assume that all subsequent blocks will do 1 iteration less. New logic: when loop symbolic max exit count matched *symbolic max* block exit count, assume that all subsequent blocks will do 1 iteration less. The new logic is still legal and is more permissive in situations when exact block exit count is not known. Differential Revision: https://reviews.llvm.org/D139692 Reviewed By: nikic --- diff --git a/llvm/lib/Transforms/Scalar/IndVarSimplify.cpp b/llvm/lib/Transforms/Scalar/IndVarSimplify.cpp index 2687129..1bfecb8 100644 --- a/llvm/lib/Transforms/Scalar/IndVarSimplify.cpp +++ b/llvm/lib/Transforms/Scalar/IndVarSimplify.cpp @@ -1632,6 +1632,8 @@ bool IndVarSimplify::optimizeLoopExits(Loop *L, SCEVExpander &Rewriter) { SmallSet DominatingExactExitCounts; for (BasicBlock *ExitingBB : ExitingBlocks) { const SCEV *ExactExitCount = SE->getExitCount(L, ExitingBB); + const SCEV *MaxExitCount = SE->getExitCount( + L, ExitingBB, ScalarEvolution::ExitCountKind::SymbolicMaximum); if (isa(ExactExitCount)) { // Okay, we do not know the exit count here. Can we at least prove that it // will remain the same within iteration space? @@ -1663,10 +1665,14 @@ bool IndVarSimplify::optimizeLoopExits(Loop *L, SCEVExpander &Rewriter) { else if (SkipLastIter) if (OptimizeCond(false, true) || OptimizeCond(true, true)) Changed = true; + if (MaxBECount == MaxExitCount) + // If the loop has more than 1 iteration, all further checks will be + // executed 1 iteration less. + SkipLastIter = true; continue; } - if (MaxBECount == ExactExitCount) + if (MaxBECount == MaxExitCount) // If the loop has more than 1 iteration, all further checks will be // executed 1 iteration less. SkipLastIter = true; diff --git a/llvm/test/Transforms/IndVarSimplify/turn-to-invariant.ll b/llvm/test/Transforms/IndVarSimplify/turn-to-invariant.ll index 7ef57bd..b43858c 100644 --- a/llvm/test/Transforms/IndVarSimplify/turn-to-invariant.ll +++ b/llvm/test/Transforms/IndVarSimplify/turn-to-invariant.ll @@ -120,22 +120,20 @@ failed_2: ret i32 -2 } - -; TODO: Simplified version 1 of test_litter_conditions. define i32 @test_litter_conditions_01(i32 %start, i32 %len) { ; CHECK-LABEL: @test_litter_conditions_01( ; CHECK-NEXT: entry: +; CHECK-NEXT: [[TMP0:%.*]] = add i32 [[START:%.*]], -1 ; CHECK-NEXT: br label [[LOOP:%.*]] ; CHECK: loop: -; CHECK-NEXT: [[IV:%.*]] = phi i32 [ [[START:%.*]], [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ] +; CHECK-NEXT: [[IV:%.*]] = phi i32 [ [[START]], [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ] ; CHECK-NEXT: [[ZERO_CHECK:%.*]] = icmp ne i32 [[IV]], 0 ; CHECK-NEXT: [[FAKE_1:%.*]] = call i1 @cond() ; CHECK-NEXT: [[AND_1:%.*]] = and i1 [[ZERO_CHECK]], [[FAKE_1]] ; CHECK-NEXT: br i1 [[AND_1]], label [[RANGE_CHECK_BLOCK:%.*]], label [[FAILED_1:%.*]] ; CHECK: range_check_block: -; CHECK-NEXT: [[IV_MINUS_1:%.*]] = add i32 [[IV]], -1 -; CHECK-NEXT: [[RANGE_CHECK:%.*]] = icmp ult i32 [[IV_MINUS_1]], [[LEN:%.*]] -; CHECK-NEXT: br i1 [[RANGE_CHECK]], label [[BACKEDGE]], label [[FAILED_2:%.*]] +; CHECK-NEXT: [[RANGE_CHECK3:%.*]] = icmp ult i32 [[TMP0]], [[LEN:%.*]] +; CHECK-NEXT: br i1 [[RANGE_CHECK3]], label [[BACKEDGE]], label [[FAILED_2:%.*]] ; CHECK: backedge: ; CHECK-NEXT: [[IV_NEXT]] = add i32 [[IV]], -1 ; CHECK-NEXT: [[LOOP_COND:%.*]] = call i1 @cond()