Index: llvm/lib/Analysis/ScalarEvolution.cpp =================================================================== --- llvm/lib/Analysis/ScalarEvolution.cpp +++ llvm/lib/Analysis/ScalarEvolution.cpp @@ -10550,6 +10550,10 @@ return false; }; + // The defining scope is the first point at which our operands are both + // defined. + auto *DefI = getDefiningScopeBound({LHS, RHS}); + // Starting at the block's predecessor, climb up the predecessor chain, as long // as there are predecessors that can be found that have unique successors // leading to the original block. @@ -10564,6 +10568,11 @@ if (ProveViaGuard(Pair.first)) return true; + // There's no need to scan above the defining scope for Expr, by definition + // there's nothing to find in terms of further relevant conditions. + if (!DT.dominates(DefI, Pair.first->getTerminator())) + break; + const BranchInst *LoopEntryPredicate = dyn_cast(Pair.first->getTerminator()); if (!LoopEntryPredicate || @@ -10582,6 +10591,10 @@ auto *CI = cast(AssumeVH); if (!DT.dominates(CI, BB)) continue; + // There's no need to scan above the defining scope for Expr, by definition + // there's nothing to find in terms of further relevant conditions. + if (!DT.dominates(DefI, CI)) + continue; if (ProveViaCond(CI->getArgOperand(0), false)) return true; @@ -13699,6 +13712,7 @@ if (RewrittenRHS) RewriteMap[LHSUnknown->getValue()] = RewrittenRHS; }; + // Starting at the loop predecessor, climb up the predecessor chain, as long // as there are predecessors that can be found that have unique successors // leading to the original header. Index: llvm/test/Transforms/IndVarSimplify/trivial-guard.ll =================================================================== --- llvm/test/Transforms/IndVarSimplify/trivial-guard.ll +++ llvm/test/Transforms/IndVarSimplify/trivial-guard.ll @@ -21,8 +21,11 @@ ; CHECK-NEXT: [[LOOP_COND_1:%.*]] = call i1 @cond() ; CHECK-NEXT: br i1 [[LOOP_COND_1]], label [[LOOP_1]], label [[EXIT_LOOPEXIT:%.*]] ; CHECK: loop.2: -; CHECK-NEXT: br i1 true, label [[GUARDED_2:%.*]], label [[FAIL_LOOPEXIT1:%.*]] +; CHECK-NEXT: [[IV_2:%.*]] = phi i32 [ [[IV_NEXT_2:%.*]], [[GUARDED_2:%.*]] ], [ 0, [[LOOP_2_PREHEADER]] ] +; CHECK-NEXT: [[CHECK_2:%.*]] = icmp slt i32 [[IV_2]], [[X]] +; CHECK-NEXT: br i1 [[CHECK_2]], label [[GUARDED_2]], label [[FAIL_LOOPEXIT1:%.*]] ; CHECK: guarded.2: +; CHECK-NEXT: [[IV_NEXT_2]] = add nuw i32 [[IV_2]], 1 ; CHECK-NEXT: [[LOOP_COND_2:%.*]] = call i1 @cond() ; CHECK-NEXT: br i1 [[LOOP_COND_2]], label [[LOOP_2]], label [[EXIT_LOOPEXIT2:%.*]] ; CHECK: exit.loopexit: @@ -77,13 +80,16 @@ ; CHECK: loop.1.preheader: ; CHECK-NEXT: br label [[LOOP_1:%.*]] ; CHECK: loop.1: -; CHECK-NEXT: br i1 true, label [[GUARDED_1:%.*]], label [[FAIL_LOOPEXIT:%.*]] +; CHECK-NEXT: [[IV_1:%.*]] = phi i32 [ [[IV_NEXT_1:%.*]], [[GUARDED_1:%.*]] ], [ 0, [[LOOP_1_PREHEADER]] ] +; CHECK-NEXT: [[CHECK_1:%.*]] = icmp slt i32 [[IV_1]], [[X:%.*]] +; CHECK-NEXT: br i1 [[CHECK_1]], label [[GUARDED_1]], label [[FAIL_LOOPEXIT:%.*]] ; CHECK: guarded.1: +; CHECK-NEXT: [[IV_NEXT_1]] = add nuw i32 [[IV_1]], 1 ; CHECK-NEXT: [[LOOP_COND_1:%.*]] = call i1 @cond() ; CHECK-NEXT: br i1 [[LOOP_COND_1]], label [[LOOP_1]], label [[EXIT_LOOPEXIT:%.*]] ; CHECK: loop.2: ; CHECK-NEXT: [[IV_2:%.*]] = phi i32 [ [[IV_NEXT_2:%.*]], [[GUARDED_2:%.*]] ], [ 0, [[LOOP_2_PREHEADER]] ] -; CHECK-NEXT: [[CHECK_2:%.*]] = icmp slt i32 [[IV_2]], [[X:%.*]] +; CHECK-NEXT: [[CHECK_2:%.*]] = icmp slt i32 [[IV_2]], [[X]] ; CHECK-NEXT: br i1 [[CHECK_2]], label [[GUARDED_2]], label [[FAIL_LOOPEXIT1:%.*]] ; CHECK: guarded.2: ; CHECK-NEXT: [[IV_NEXT_2]] = add nuw i32 [[IV_2]], 1