Index: llvm/trunk/lib/Analysis/ScalarEvolution.cpp =================================================================== --- llvm/trunk/lib/Analysis/ScalarEvolution.cpp +++ llvm/trunk/lib/Analysis/ScalarEvolution.cpp @@ -6686,6 +6686,46 @@ LoopContinuePredicate->getSuccessor(0) != L->getHeader())) return true; + // If the loop is not reachable from the entry block, we risk running into an + // infinite loop as we walk up into the dom tree. These loops do not matter + // anyway, so we just return a conservative answer when we see them. + if (!DT->isReachableFromEntry(L->getHeader())) + return false; + + for (DomTreeNode *DTN = (*DT)[Latch], *HeaderDTN = (*DT)[L->getHeader()]; + DTN != HeaderDTN; + DTN = DTN->getIDom()) { + + assert(DTN && "should reach the loop header before reaching the root!"); + + BasicBlock *BB = DTN->getBlock(); + BasicBlock *PBB = BB->getSinglePredecessor(); + if (!PBB) + continue; + + BranchInst *ContinuePredicate = dyn_cast(PBB->getTerminator()); + if (!ContinuePredicate || !ContinuePredicate->isConditional()) + continue; + + Value *Condition = ContinuePredicate->getCondition(); + + // If we have an edge `E` within the loop body that dominates the only + // latch, the condition guarding `E` also guards the backedge. This + // reasoning works only for loops with a single latch. + + BasicBlockEdge DominatingEdge(PBB, BB); + if (DominatingEdge.isSingleEdge()) { + // We're constructively (and conservatively) enumerating edges within the + // loop body that dominate the latch. The dominator tree better agree + // with us on this: + assert(DT->dominates(DominatingEdge, Latch) && "should be!"); + + if (isImpliedCond(Pred, LHS, RHS, Condition, + BB != ContinuePredicate->getSuccessor(0))) + return true; + } + } + // Check conditions due to any @llvm.assume intrinsics. for (auto &AssumeVH : AC->assumptions()) { if (!AssumeVH) Index: llvm/trunk/test/Analysis/ScalarEvolution/latch-dominating-conditions.ll =================================================================== --- llvm/trunk/test/Analysis/ScalarEvolution/latch-dominating-conditions.ll +++ llvm/trunk/test/Analysis/ScalarEvolution/latch-dominating-conditions.ll @@ -0,0 +1,55 @@ +; RUN: opt -S -indvars < %s | FileCheck %s + +declare void @side_effect(i1) + +define void @latch_dominating_0(i8 %start) { +; CHECK-LABEL: latch_dominating_0 + entry: + %e = icmp slt i8 %start, 42 + br i1 %e, label %loop, label %exit + + loop: +; CHECK-LABEL: loop + %idx = phi i8 [ %start, %entry ], [ %idx.inc, %be ] + %idx.inc = add i8 %idx, 1 + %folds.to.true = icmp slt i8 %idx, 42 +; CHECK: call void @side_effect(i1 true) + call void @side_effect(i1 %folds.to.true) + %c0 = icmp slt i8 %idx.inc, 42 + br i1 %c0, label %be, label %exit + + be: +; CHECK: call void @side_effect(i1 true) + call void @side_effect(i1 %folds.to.true) + %c1 = icmp slt i8 %idx.inc, 100 + br i1 %c1, label %loop, label %exit + + exit: + ret void +} + +define void @latch_dominating_1(i8 %start) { +; CHECK-LABEL: latch_dominating_1 + entry: + %e = icmp slt i8 %start, 42 + br i1 %e, label %loop, label %exit + + loop: +; CHECK-LABEL: loop + %idx = phi i8 [ %start, %entry ], [ %idx.inc, %be ] + %idx.inc = add i8 %idx, 1 + %does.not.fold.to.true = icmp slt i8 %idx, 42 +; CHECK: call void @side_effect(i1 %does.not.fold.to.true) + call void @side_effect(i1 %does.not.fold.to.true) + %c0 = icmp slt i8 %idx.inc, 42 + br i1 %c0, label %be, label %be + + be: +; CHECK: call void @side_effect(i1 %does.not.fold.to.true) + call void @side_effect(i1 %does.not.fold.to.true) + %c1 = icmp slt i8 %idx.inc, 100 + br i1 %c1, label %loop, label %exit + + exit: + ret void +}