Skip to content

Commit b864c1f

Browse files
committedApr 1, 2015
[SCEV] Look at backedge dominating conditions (re-land r233447).
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. This re-lands r233447. r233447 was reverted because it caused massive compile-time regressions. This change has a fix for the same issue. llvm-svn: 233829
1 parent 0ae7844 commit b864c1f

File tree

3 files changed

+121
-2
lines changed

3 files changed

+121
-2
lines changed
 

‎llvm/include/llvm/Analysis/ScalarEvolution.h

+4
Original file line numberDiff line numberDiff line change
@@ -256,6 +256,10 @@ namespace llvm {
256256
/// Mark predicate values currently being processed by isImpliedCond.
257257
DenseSet<Value*> PendingLoopPredicates;
258258

259+
/// Set to true by isLoopBackedgeGuardedByCond when we're walking the set of
260+
/// conditions dominating the backedge of a loop.
261+
bool WalkingBEDominatingConds;
262+
259263
/// ExitLimit - Information about the number of loop iterations for which a
260264
/// loop exit's branch condition evaluates to the not-taken path. This is a
261265
/// temporary pair of exact and max expressions that are eventually

‎llvm/lib/Analysis/ScalarEvolution.cpp

+62-2
Original file line numberDiff line numberDiff line change
@@ -6698,6 +6698,65 @@ ScalarEvolution::isLoopBackedgeGuardedByCond(const Loop *L,
66986698
return true;
66996699
}
67006700

6701+
struct ClearWalkingBEDominatingCondsOnExit {
6702+
ScalarEvolution &SE;
6703+
6704+
explicit ClearWalkingBEDominatingCondsOnExit(ScalarEvolution &SE)
6705+
: SE(SE){};
6706+
6707+
~ClearWalkingBEDominatingCondsOnExit() {
6708+
SE.WalkingBEDominatingConds = false;
6709+
}
6710+
};
6711+
6712+
// We don't want more than one activation of the following loop on the stack
6713+
// -- that can lead to O(n!) time complexity.
6714+
if (WalkingBEDominatingConds)
6715+
return false;
6716+
6717+
WalkingBEDominatingConds = true;
6718+
ClearWalkingBEDominatingCondsOnExit ClearOnExit(*this);
6719+
6720+
// If the loop is not reachable from the entry block, we risk running into an
6721+
// infinite loop as we walk up into the dom tree. These loops do not matter
6722+
// anyway, so we just return a conservative answer when we see them.
6723+
if (!DT->isReachableFromEntry(L->getHeader()))
6724+
return false;
6725+
6726+
for (DomTreeNode *DTN = (*DT)[Latch], *HeaderDTN = (*DT)[L->getHeader()];
6727+
DTN != HeaderDTN;
6728+
DTN = DTN->getIDom()) {
6729+
6730+
assert(DTN && "should reach the loop header before reaching the root!");
6731+
6732+
BasicBlock *BB = DTN->getBlock();
6733+
BasicBlock *PBB = BB->getSinglePredecessor();
6734+
if (!PBB)
6735+
continue;
6736+
6737+
BranchInst *ContinuePredicate = dyn_cast<BranchInst>(PBB->getTerminator());
6738+
if (!ContinuePredicate || !ContinuePredicate->isConditional())
6739+
continue;
6740+
6741+
Value *Condition = ContinuePredicate->getCondition();
6742+
6743+
// If we have an edge `E` within the loop body that dominates the only
6744+
// latch, the condition guarding `E` also guards the backedge. This
6745+
// reasoning works only for loops with a single latch.
6746+
6747+
BasicBlockEdge DominatingEdge(PBB, BB);
6748+
if (DominatingEdge.isSingleEdge()) {
6749+
// We're constructively (and conservatively) enumerating edges within the
6750+
// loop body that dominate the latch. The dominator tree better agree
6751+
// with us on this:
6752+
assert(DT->dominates(DominatingEdge, Latch) && "should be!");
6753+
6754+
if (isImpliedCond(Pred, LHS, RHS, Condition,
6755+
BB != ContinuePredicate->getSuccessor(0)))
6756+
return true;
6757+
}
6758+
}
6759+
67016760
return false;
67026761
}
67036762

@@ -7968,8 +8027,8 @@ ScalarEvolution::SCEVCallbackVH::SCEVCallbackVH(Value *V, ScalarEvolution *se)
79688027
//===----------------------------------------------------------------------===//
79698028

79708029
ScalarEvolution::ScalarEvolution()
7971-
: FunctionPass(ID), ValuesAtScopes(64), LoopDispositions(64),
7972-
BlockDispositions(64), FirstUnknown(nullptr) {
8030+
: FunctionPass(ID), WalkingBEDominatingConds(false), ValuesAtScopes(64),
8031+
LoopDispositions(64), BlockDispositions(64), FirstUnknown(nullptr) {
79738032
initializeScalarEvolutionPass(*PassRegistry::getPassRegistry());
79748033
}
79758034

@@ -8000,6 +8059,7 @@ void ScalarEvolution::releaseMemory() {
80008059
}
80018060

80028061
assert(PendingLoopPredicates.empty() && "isImpliedCond garbage");
8062+
assert(!WalkingBEDominatingConds && "isLoopBackedgeGuardedByCond garbage!");
80038063

80048064
BackedgeTakenCounts.clear();
80058065
ConstantEvolutionLoopExitValue.clear();
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
; RUN: opt -S -indvars < %s | FileCheck %s
2+
3+
declare void @side_effect(i1)
4+
5+
define void @latch_dominating_0(i8 %start) {
6+
; CHECK-LABEL: latch_dominating_0
7+
entry:
8+
%e = icmp slt i8 %start, 42
9+
br i1 %e, label %loop, label %exit
10+
11+
loop:
12+
; CHECK-LABEL: loop
13+
%idx = phi i8 [ %start, %entry ], [ %idx.inc, %be ]
14+
%idx.inc = add i8 %idx, 1
15+
%folds.to.true = icmp slt i8 %idx, 42
16+
; CHECK: call void @side_effect(i1 true)
17+
call void @side_effect(i1 %folds.to.true)
18+
%c0 = icmp slt i8 %idx.inc, 42
19+
br i1 %c0, label %be, label %exit
20+
21+
be:
22+
; CHECK: call void @side_effect(i1 true)
23+
call void @side_effect(i1 %folds.to.true)
24+
%c1 = icmp slt i8 %idx.inc, 100
25+
br i1 %c1, label %loop, label %exit
26+
27+
exit:
28+
ret void
29+
}
30+
31+
define void @latch_dominating_1(i8 %start) {
32+
; CHECK-LABEL: latch_dominating_1
33+
entry:
34+
%e = icmp slt i8 %start, 42
35+
br i1 %e, label %loop, label %exit
36+
37+
loop:
38+
; CHECK-LABEL: loop
39+
%idx = phi i8 [ %start, %entry ], [ %idx.inc, %be ]
40+
%idx.inc = add i8 %idx, 1
41+
%does.not.fold.to.true = icmp slt i8 %idx, 42
42+
; CHECK: call void @side_effect(i1 %does.not.fold.to.true)
43+
call void @side_effect(i1 %does.not.fold.to.true)
44+
%c0 = icmp slt i8 %idx.inc, 42
45+
br i1 %c0, label %be, label %be
46+
47+
be:
48+
; CHECK: call void @side_effect(i1 %does.not.fold.to.true)
49+
call void @side_effect(i1 %does.not.fold.to.true)
50+
%c1 = icmp slt i8 %idx.inc, 100
51+
br i1 %c1, label %loop, label %exit
52+
53+
exit:
54+
ret void
55+
}

0 commit comments

Comments
 (0)