mirror of
https://github.com/RPCS3/llvm.git
synced 2025-01-30 23:33:57 +00:00
[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. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@233829 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
32d9020423
commit
5436372079
@ -256,6 +256,10 @@ namespace llvm {
|
||||
/// Mark predicate values currently being processed by isImpliedCond.
|
||||
DenseSet<Value*> PendingLoopPredicates;
|
||||
|
||||
/// Set to true by isLoopBackedgeGuardedByCond when we're walking the set of
|
||||
/// conditions dominating the backedge of a loop.
|
||||
bool WalkingBEDominatingConds;
|
||||
|
||||
/// ExitLimit - Information about the number of loop iterations for which a
|
||||
/// loop exit's branch condition evaluates to the not-taken path. This is a
|
||||
/// temporary pair of exact and max expressions that are eventually
|
||||
|
@ -6698,6 +6698,65 @@ ScalarEvolution::isLoopBackedgeGuardedByCond(const Loop *L,
|
||||
return true;
|
||||
}
|
||||
|
||||
struct ClearWalkingBEDominatingCondsOnExit {
|
||||
ScalarEvolution &SE;
|
||||
|
||||
explicit ClearWalkingBEDominatingCondsOnExit(ScalarEvolution &SE)
|
||||
: SE(SE){};
|
||||
|
||||
~ClearWalkingBEDominatingCondsOnExit() {
|
||||
SE.WalkingBEDominatingConds = false;
|
||||
}
|
||||
};
|
||||
|
||||
// We don't want more than one activation of the following loop on the stack
|
||||
// -- that can lead to O(n!) time complexity.
|
||||
if (WalkingBEDominatingConds)
|
||||
return false;
|
||||
|
||||
WalkingBEDominatingConds = true;
|
||||
ClearWalkingBEDominatingCondsOnExit ClearOnExit(*this);
|
||||
|
||||
// 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<BranchInst>(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;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -7968,8 +8027,8 @@ ScalarEvolution::SCEVCallbackVH::SCEVCallbackVH(Value *V, ScalarEvolution *se)
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
ScalarEvolution::ScalarEvolution()
|
||||
: FunctionPass(ID), ValuesAtScopes(64), LoopDispositions(64),
|
||||
BlockDispositions(64), FirstUnknown(nullptr) {
|
||||
: FunctionPass(ID), WalkingBEDominatingConds(false), ValuesAtScopes(64),
|
||||
LoopDispositions(64), BlockDispositions(64), FirstUnknown(nullptr) {
|
||||
initializeScalarEvolutionPass(*PassRegistry::getPassRegistry());
|
||||
}
|
||||
|
||||
@ -8000,6 +8059,7 @@ void ScalarEvolution::releaseMemory() {
|
||||
}
|
||||
|
||||
assert(PendingLoopPredicates.empty() && "isImpliedCond garbage");
|
||||
assert(!WalkingBEDominatingConds && "isLoopBackedgeGuardedByCond garbage!");
|
||||
|
||||
BackedgeTakenCounts.clear();
|
||||
ConstantEvolutionLoopExitValue.clear();
|
||||
|
55
test/Analysis/ScalarEvolution/latch-dominating-conditions.ll
Normal file
55
test/Analysis/ScalarEvolution/latch-dominating-conditions.ll
Normal file
@ -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
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user