From e464bbfb5a467fa6e90fc67cdacf4c5a6b3f0ecb Mon Sep 17 00:00:00 2001 From: Sanjoy Das Date: Fri, 27 Mar 2015 23:18:08 +0000 Subject: [PATCH] [SCEV] Look at backedge dominating conditions. Summary: This change teaches ScalarEvolution::isLoopBackedgeGuardedByCond to look at edges within the loop body that dominate the latch. We don't do an exhaustive search for all possible edges, but only a quick walk up the dom tree. Reviewers: atrick, hfinkel Subscribers: llvm-commits Differential Revision: http://reviews.llvm.org/D8627 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@233447 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Analysis/ScalarEvolution.cpp | 40 ++++++++++++++ .../latch-dominating-conditions.ll | 55 +++++++++++++++++++ 2 files changed, 95 insertions(+) create mode 100644 test/Analysis/ScalarEvolution/latch-dominating-conditions.ll diff --git a/lib/Analysis/ScalarEvolution.cpp b/lib/Analysis/ScalarEvolution.cpp index 4e713fb1218..26b468013c6 100644 --- a/lib/Analysis/ScalarEvolution.cpp +++ b/lib/Analysis/ScalarEvolution.cpp @@ -6686,6 +6686,46 @@ ScalarEvolution::isLoopBackedgeGuardedByCond(const Loop *L, 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) diff --git a/test/Analysis/ScalarEvolution/latch-dominating-conditions.ll b/test/Analysis/ScalarEvolution/latch-dominating-conditions.ll new file mode 100644 index 00000000000..3f6f9584cce --- /dev/null +++ b/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 +}