[llvm] r201159 - ScalarEvolution: Analyze trip count of loops with a switch guarding the exit.
Benjamin Kramer
benny.kra at googlemail.com
Tue Feb 11 07:44:33 PST 2014
Author: d0k
Date: Tue Feb 11 09:44:32 2014
New Revision: 201159
URL: http://llvm.org/viewvc/llvm-project?rev=201159&view=rev
Log:
ScalarEvolution: Analyze trip count of loops with a switch guarding the exit.
Added:
llvm/trunk/test/Analysis/ScalarEvolution/trip-count-switch.ll
Modified:
llvm/trunk/include/llvm/Analysis/ScalarEvolution.h
llvm/trunk/lib/Analysis/ScalarEvolution.cpp
Modified: llvm/trunk/include/llvm/Analysis/ScalarEvolution.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Analysis/ScalarEvolution.h?rev=201159&r1=201158&r2=201159&view=diff
==============================================================================
--- llvm/trunk/include/llvm/Analysis/ScalarEvolution.h (original)
+++ llvm/trunk/include/llvm/Analysis/ScalarEvolution.h Tue Feb 11 09:44:32 2014
@@ -469,6 +469,13 @@ namespace llvm {
BasicBlock *FBB,
bool IsSubExpr);
+ /// ComputeExitLimitFromSingleExitSwitch - Compute the number of times the
+ /// backedge of the specified loop will execute if its exit condition were a
+ /// switch with a single exiting case to ExitingBB.
+ ExitLimit
+ ComputeExitLimitFromSingleExitSwitch(const Loop *L, SwitchInst *Switch,
+ BasicBlock *ExitingBB, bool IsSubExpr);
+
/// ComputeLoadConstantCompareExitLimit - Given an exit condition
/// of 'icmp op load X, cst', try to see if we can compute the
/// backedge-taken count.
Modified: llvm/trunk/lib/Analysis/ScalarEvolution.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Analysis/ScalarEvolution.cpp?rev=201159&r1=201158&r2=201159&view=diff
==============================================================================
--- llvm/trunk/lib/Analysis/ScalarEvolution.cpp (original)
+++ llvm/trunk/lib/Analysis/ScalarEvolution.cpp Tue Feb 11 09:44:32 2014
@@ -4453,12 +4453,19 @@ ScalarEvolution::ExitLimit
ScalarEvolution::ComputeExitLimit(const Loop *L, BasicBlock *ExitingBlock) {
// Okay, we've chosen an exiting block. See what condition causes us to
- // exit at this block.
- //
- // FIXME: we should be able to handle switch instructions (with a single exit)
- BranchInst *ExitBr = dyn_cast<BranchInst>(ExitingBlock->getTerminator());
- if (ExitBr == 0) return getCouldNotCompute();
- assert(ExitBr->isConditional() && "If unconditional, it can't be in loop!");
+ // exit at this block and remember the exit block and whether all other targets
+ // lead to the loop header.
+ bool MustExecuteLoopHeader = true;
+ BasicBlock *Exit = 0;
+ for (succ_iterator SI = succ_begin(ExitingBlock), SE = succ_end(ExitingBlock);
+ SI != SE; ++SI)
+ if (!L->contains(*SI)) {
+ if (Exit) // Multiple exit successors.
+ return getCouldNotCompute();
+ Exit = *SI;
+ } else if (*SI != L->getHeader()) {
+ MustExecuteLoopHeader = false;
+ }
// At this point, we know we have a conditional branch that determines whether
// the loop is exited. However, we don't know if the branch is executed each
@@ -4477,13 +4484,11 @@ ScalarEvolution::ComputeExitLimit(const
//
// More extensive analysis could be done to handle more cases here.
//
- if (ExitBr->getSuccessor(0) != L->getHeader() &&
- ExitBr->getSuccessor(1) != L->getHeader() &&
- ExitBr->getParent() != L->getHeader()) {
+ if (!MustExecuteLoopHeader && ExitingBlock != L->getHeader()) {
// The simple checks failed, try climbing the unique predecessor chain
// up to the header.
bool Ok = false;
- for (BasicBlock *BB = ExitBr->getParent(); BB; ) {
+ for (BasicBlock *BB = ExitingBlock; BB; ) {
BasicBlock *Pred = BB->getUniquePredecessor();
if (!Pred)
return getCouldNotCompute();
@@ -4507,11 +4512,20 @@ ScalarEvolution::ComputeExitLimit(const
return getCouldNotCompute();
}
- // Proceed to the next level to examine the exit condition expression.
- return ComputeExitLimitFromCond(L, ExitBr->getCondition(),
- ExitBr->getSuccessor(0),
- ExitBr->getSuccessor(1),
- /*IsSubExpr=*/false);
+ TerminatorInst *Term = ExitingBlock->getTerminator();
+ if (BranchInst *BI = dyn_cast<BranchInst>(Term)) {
+ assert(BI->isConditional() && "If unconditional, it can't be in loop!");
+ // Proceed to the next level to examine the exit condition expression.
+ return ComputeExitLimitFromCond(L, BI->getCondition(), BI->getSuccessor(0),
+ BI->getSuccessor(1),
+ /*IsSubExpr=*/false);
+ }
+
+ if (SwitchInst *SI = dyn_cast<SwitchInst>(Term))
+ return ComputeExitLimitFromSingleExitSwitch(L, SI, Exit,
+ /*IsSubExpr=*/false);
+
+ return getCouldNotCompute();
}
/// ComputeExitLimitFromCond - Compute the number of times the
@@ -4728,6 +4742,30 @@ ScalarEvolution::ComputeExitLimitFromICm
return ComputeExitCountExhaustively(L, ExitCond, !L->contains(TBB));
}
+ScalarEvolution::ExitLimit
+ScalarEvolution::ComputeExitLimitFromSingleExitSwitch(const Loop *L,
+ SwitchInst *Switch,
+ BasicBlock *ExitingBlock,
+ bool IsSubExpr) {
+ assert(!L->contains(ExitingBlock) && "Not an exiting block!");
+
+ // Give up if the exit is the default dest of a switch.
+ if (Switch->getDefaultDest() == ExitingBlock)
+ return getCouldNotCompute();
+
+ assert(L->contains(Switch->getDefaultDest()) &&
+ "Default case must not exit the loop!");
+ const SCEV *LHS = getSCEVAtScope(Switch->getCondition(), L);
+ const SCEV *RHS = getConstant(Switch->findCaseDest(ExitingBlock));
+
+ // while (X != Y) --> while (X-Y != 0)
+ ExitLimit EL = HowFarToZero(getMinusSCEV(LHS, RHS), L, IsSubExpr);
+ if (EL.hasAnyInfo())
+ return EL;
+
+ return getCouldNotCompute();
+}
+
static ConstantInt *
EvaluateConstantChrecAtConstant(const SCEVAddRecExpr *AddRec, ConstantInt *C,
ScalarEvolution &SE) {
Added: llvm/trunk/test/Analysis/ScalarEvolution/trip-count-switch.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Analysis/ScalarEvolution/trip-count-switch.ll?rev=201159&view=auto
==============================================================================
--- llvm/trunk/test/Analysis/ScalarEvolution/trip-count-switch.ll (added)
+++ llvm/trunk/test/Analysis/ScalarEvolution/trip-count-switch.ll Tue Feb 11 09:44:32 2014
@@ -0,0 +1,30 @@
+; RUN: opt < %s -analyze -scalar-evolution | FileCheck %s
+
+declare void @foo()
+
+define void @test1() nounwind {
+entry:
+ br label %for.cond
+
+for.cond: ; preds = %if.end, %entry
+ %i.0 = phi i32 [ 2, %entry ], [ %dec, %if.end ]
+ switch i32 %i.0, label %if.end [
+ i32 0, label %for.end
+ i32 1, label %if.then
+ ]
+
+if.then: ; preds = %for.cond
+ tail call void @foo()
+ br label %if.end
+
+if.end: ; preds = %for.cond, %if.then
+ %dec = add nsw i32 %i.0, -1
+ br label %for.cond
+
+for.end: ; preds = %for.cond
+ ret void
+
+; CHECK-LABEL: @test1
+; CHECK: Loop %for.cond: backedge-taken count is 2
+; CHECK: Loop %for.cond: max backedge-taken count is 2
+}
More information about the llvm-commits
mailing list