Extend ScalarEvolution's executesAtLeastOnce logic to be able to

continue past the first conditional branch when looking for a
relevant test. This helps it avoid using MAX expressions in
loop trip counts in more cases.


git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@54697 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Dan Gohman 2008-08-12 20:17:31 +00:00
parent 1a6c683315
commit 3837218ea0
2 changed files with 92 additions and 55 deletions

View File

@ -2709,66 +2709,68 @@ bool ScalarEvolutionsImpl::executesAtLeastOnce(const Loop *L, bool isSigned,
SCEV *LHS, SCEV *RHS) {
BasicBlock *Preheader = L->getLoopPreheader();
BasicBlock *PreheaderDest = L->getHeader();
if (Preheader == 0) return false;
BranchInst *LoopEntryPredicate =
dyn_cast<BranchInst>(Preheader->getTerminator());
if (!LoopEntryPredicate) return false;
// Starting at the preheader, climb up the predecessor chain, as long as
// there are unique predecessors, looking for a conditional branch that
// protects the loop.
//
// This is a conservative apporoximation of a climb of the
// control-dependence predecessors.
// This might be a critical edge broken out. If the loop preheader ends in
// an unconditional branch to the loop, check to see if the preheader has a
// single predecessor, and if so, look for its terminator.
while (LoopEntryPredicate->isUnconditional()) {
PreheaderDest = Preheader;
Preheader = Preheader->getSinglePredecessor();
if (!Preheader) return false; // Multiple preds.
LoopEntryPredicate =
for (; Preheader; PreheaderDest = Preheader,
Preheader = Preheader->getSinglePredecessor()) {
BranchInst *LoopEntryPredicate =
dyn_cast<BranchInst>(Preheader->getTerminator());
if (!LoopEntryPredicate) return false;
if (!LoopEntryPredicate ||
LoopEntryPredicate->isUnconditional())
continue;
ICmpInst *ICI = dyn_cast<ICmpInst>(LoopEntryPredicate->getCondition());
if (!ICI) continue;
// Now that we found a conditional branch that dominates the loop, check to
// see if it is the comparison we are looking for.
Value *PreCondLHS = ICI->getOperand(0);
Value *PreCondRHS = ICI->getOperand(1);
ICmpInst::Predicate Cond;
if (LoopEntryPredicate->getSuccessor(0) == PreheaderDest)
Cond = ICI->getPredicate();
else
Cond = ICI->getInversePredicate();
switch (Cond) {
case ICmpInst::ICMP_UGT:
if (isSigned) continue;
std::swap(PreCondLHS, PreCondRHS);
Cond = ICmpInst::ICMP_ULT;
break;
case ICmpInst::ICMP_SGT:
if (!isSigned) continue;
std::swap(PreCondLHS, PreCondRHS);
Cond = ICmpInst::ICMP_SLT;
break;
case ICmpInst::ICMP_ULT:
if (isSigned) continue;
break;
case ICmpInst::ICMP_SLT:
if (!isSigned) continue;
break;
default:
continue;
}
if (!PreCondLHS->getType()->isInteger()) continue;
SCEVHandle PreCondLHSSCEV = getSCEV(PreCondLHS);
SCEVHandle PreCondRHSSCEV = getSCEV(PreCondRHS);
if ((LHS == PreCondLHSSCEV && RHS == PreCondRHSSCEV) ||
(LHS == SE.getNotSCEV(PreCondRHSSCEV) &&
RHS == SE.getNotSCEV(PreCondLHSSCEV)))
return true;
}
ICmpInst *ICI = dyn_cast<ICmpInst>(LoopEntryPredicate->getCondition());
if (!ICI) return false;
// Now that we found a conditional branch that dominates the loop, check to
// see if it is the comparison we are looking for.
Value *PreCondLHS = ICI->getOperand(0);
Value *PreCondRHS = ICI->getOperand(1);
ICmpInst::Predicate Cond;
if (LoopEntryPredicate->getSuccessor(0) == PreheaderDest)
Cond = ICI->getPredicate();
else
Cond = ICI->getInversePredicate();
switch (Cond) {
case ICmpInst::ICMP_UGT:
if (isSigned) return false;
std::swap(PreCondLHS, PreCondRHS);
Cond = ICmpInst::ICMP_ULT;
break;
case ICmpInst::ICMP_SGT:
if (!isSigned) return false;
std::swap(PreCondLHS, PreCondRHS);
Cond = ICmpInst::ICMP_SLT;
break;
case ICmpInst::ICMP_ULT:
if (isSigned) return false;
break;
case ICmpInst::ICMP_SLT:
if (!isSigned) return false;
break;
default:
return false;
}
if (!PreCondLHS->getType()->isInteger()) return false;
SCEVHandle PreCondLHSSCEV = getSCEV(PreCondLHS);
SCEVHandle PreCondRHSSCEV = getSCEV(PreCondRHS);
return (LHS == PreCondLHSSCEV && RHS == PreCondRHSSCEV) ||
(LHS == SE.getNotSCEV(PreCondRHSSCEV) &&
RHS == SE.getNotSCEV(PreCondLHSSCEV));
return false;
}
/// HowManyLessThans - Return the number of times a backedge containing the

View File

@ -0,0 +1,35 @@
; RUN: llvm-as < %s | opt -scalar-evolution -analyze | grep {Loop bb3: ( -1 + %n) iterations!}
; We don't want to use a max in the trip count expression in
; this testcase.
define void @foo(i32 %n, i32* %p, i32* %q) nounwind {
entry:
icmp sgt i32 %n, 0
br i1 %0, label %bb, label %return
bb:
load i32* %q, align 4
icmp eq i32 %1, 0
br i1 %2, label %return, label %bb3.preheader
bb3.preheader:
br label %bb3
bb3:
%i.0 = phi i32 [ %7, %bb3 ], [ 0, %bb3.preheader ]
getelementptr i32* %p, i32 %i.0
load i32* %3, align 4
add i32 %4, 1
getelementptr i32* %p, i32 %i.0
store i32 %5, i32* %6, align 4
add i32 %i.0, 1
icmp slt i32 %7, %n
br i1 %8, label %bb3, label %return.loopexit
return.loopexit:
br label %return
return:
ret void
}