Make LoopSimplify change conditional branches in loop exiting blocks

which branch on undef to branch on a boolean constant for the edge
exiting the loop. This helps ScalarEvolution compute trip counts for
loops.

Teach ScalarEvolution to recognize single-value PHIs, when safe, and
ForgetSymbolicName to forget such single-value PHI nodes as apprpriate
in ForgetSymbolicName.


git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@97126 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Dan Gohman 2010-02-25 06:57:05 +00:00
parent a5028a6463
commit 8566963713
6 changed files with 128 additions and 30 deletions

View File

@ -2549,14 +2549,14 @@ PushDefUseChildren(Instruction *I,
/// the Scalars map if they reference SymName. This is used during PHI
/// resolution.
void
ScalarEvolution::ForgetSymbolicName(Instruction *I, const SCEV *SymName) {
ScalarEvolution::ForgetSymbolicName(Instruction *PN, const SCEV *SymName) {
SmallVector<Instruction *, 16> Worklist;
PushDefUseChildren(I, Worklist);
PushDefUseChildren(PN, Worklist);
SmallPtrSet<Instruction *, 8> Visited;
Visited.insert(I);
Visited.insert(PN);
while (!Worklist.empty()) {
I = Worklist.pop_back_val();
Instruction *I = Worklist.pop_back_val();
if (!Visited.insert(I)) continue;
std::map<SCEVCallbackVH, const SCEV *>::iterator It =
@ -2568,12 +2568,15 @@ ScalarEvolution::ForgetSymbolicName(Instruction *I, const SCEV *SymName) {
continue;
// SCEVUnknown for a PHI either means that it has an unrecognized
// structure, or it's a PHI that's in the progress of being computed
// by createNodeForPHI. In the former case, additional loop trip
// count information isn't going to change anything. In the later
// case, createNodeForPHI will perform the necessary updates on its
// own when it gets to that point.
if (!isa<PHINode>(I) || !isa<SCEVUnknown>(It->second)) {
// structure, it's a PHI that's in the progress of being computed
// by createNodeForPHI, or it's a single-value PHI. In the first case,
// additional loop trip count information isn't going to change anything.
// In the second case, createNodeForPHI will perform the necessary
// updates on its own when it gets to that point. In the third, we do
// want to forget the SCEVUnknown.
if (!isa<PHINode>(I) ||
!isa<SCEVUnknown>(It->second) ||
(I != PN && It->second == SymName)) {
ValuesAtScopes.erase(It->second);
Scalars.erase(It);
}
@ -2696,9 +2699,21 @@ const SCEV *ScalarEvolution::createNodeForPHI(PHINode *PN) {
return SymbolicName;
}
// It's tempting to recognize PHIs with a unique incoming value, however
// this leads passes like indvars to break LCSSA form. Fortunately, such
// PHIs are rare, as instcombine zaps them.
// If the PHI has a single incoming value, follow that value, unless the
// PHI's incoming blocks are in a different loop, in which case doing so
// risks breaking LCSSA form. Instcombine would normally zap these, but
// it doesn't have DominatorTree information, so it may miss cases.
if (Value *V = PN->hasConstantValue(DT)) {
bool AllSameLoop = true;
Loop *PNLoop = LI->getLoopFor(PN->getParent());
for (size_t i = 0, e = PN->getNumIncomingValues(); i != e; ++i)
if (LI->getLoopFor(PN->getIncomingBlock(i)) != PNLoop) {
AllSameLoop = false;
break;
}
if (AllSameLoop)
return getSCEV(V);
}
// If it's not a loop phi, we can't handle it yet.
return getUnknown(PN);

View File

@ -384,17 +384,18 @@ bool IndVarSimplify::runOnLoop(Loop *L, LPPassManager &LPM) {
// in this loop, insert a canonical induction variable of the largest size.
Value *IndVar = 0;
if (NeedCannIV) {
// Check to see if the loop already has a canonical-looking induction
// variable. If one is present and it's wider than the planned canonical
// induction variable, temporarily remove it, so that the Rewriter
// doesn't attempt to reuse it.
PHINode *OldCannIV = L->getCanonicalInductionVariable();
if (OldCannIV) {
// Check to see if the loop already has any canonical-looking induction
// variables. If any are present and wider than the planned canonical
// induction variable, temporarily remove them, so that the Rewriter
// doesn't attempt to reuse them.
SmallVector<PHINode *, 2> OldCannIVs;
while (PHINode *OldCannIV = L->getCanonicalInductionVariable()) {
if (SE->getTypeSizeInBits(OldCannIV->getType()) >
SE->getTypeSizeInBits(LargestType))
OldCannIV->removeFromParent();
else
OldCannIV = 0;
break;
OldCannIVs.push_back(OldCannIV);
}
IndVar = Rewriter.getOrInsertCanonicalInductionVariable(L, LargestType);
@ -404,17 +405,21 @@ bool IndVarSimplify::runOnLoop(Loop *L, LPPassManager &LPM) {
DEBUG(dbgs() << "INDVARS: New CanIV: " << *IndVar << '\n');
// Now that the official induction variable is established, reinsert
// the old canonical-looking variable after it so that the IR remains
// consistent. It will be deleted as part of the dead-PHI deletion at
// any old canonical-looking variables after it so that the IR remains
// consistent. They will be deleted as part of the dead-PHI deletion at
// the end of the pass.
if (OldCannIV)
OldCannIV->insertAfter(cast<Instruction>(IndVar));
while (!OldCannIVs.empty()) {
PHINode *OldCannIV = OldCannIVs.pop_back_val();
OldCannIV->insertBefore(L->getHeader()->getFirstNonPHI());
}
}
// If we have a trip count expression, rewrite the loop's exit condition
// using it. We can currently only handle loops with a single exit.
ICmpInst *NewICmp = 0;
if (!isa<SCEVCouldNotCompute>(BackedgeTakenCount) && ExitingBlock) {
if (!isa<SCEVCouldNotCompute>(BackedgeTakenCount) &&
!BackedgeTakenCount->isZero() &&
ExitingBlock) {
assert(NeedCannIV &&
"LinearFunctionTestReplace requires a canonical induction variable");
// Can't rewrite non-branch yet.

View File

@ -159,6 +159,22 @@ ReprocessLoop:
}
}
// If there are exiting blocks with branches on undef, resolve the undef in
// the direction which will exit the loop. This will help simplify loop
// trip count computations.
SmallVector<BasicBlock*, 8> ExitingBlocks;
L->getExitingBlocks(ExitingBlocks);
for (SmallVectorImpl<BasicBlock *>::iterator I = ExitingBlocks.begin(),
E = ExitingBlocks.end(); I != E; ++I)
if (BranchInst *BI = dyn_cast<BranchInst>((*I)->getTerminator()))
if (BI->isConditional()) {
if (UndefValue *Cond = dyn_cast<UndefValue>(BI->getCondition())) {
BI->setCondition(ConstantInt::get(Cond->getType(),
!L->contains(BI->getSuccessor(0))));
Changed = true;
}
}
// Does the loop already have a preheader? If so, don't insert one.
BasicBlock *Preheader = L->getLoopPreheader();
if (!Preheader) {
@ -250,8 +266,6 @@ ReprocessLoop:
break;
}
if (UniqueExit) {
SmallVector<BasicBlock*, 8> ExitingBlocks;
L->getExitingBlocks(ExitingBlocks);
for (unsigned i = 0, e = ExitingBlocks.size(); i != e; ++i) {
BasicBlock *ExitingBlock = ExitingBlocks[i];
if (!ExitingBlock->getSinglePredecessor()) continue;

View File

@ -8,8 +8,7 @@
define i64 @hammer_time(i64 %modulep, i64 %physfree) nounwind ssp noredzone noimplicitfloat {
; CHECK: hammer_time:
; CHECK: movq $Xrsvd, %rax
; CHECK: movq $Xrsvd, %rsi
; CHECK: movq $Xrsvd, %rdi
; CHECK: movq $Xrsvd, %rcx
entry:
br i1 undef, label %if.then, label %if.end

View File

@ -7,7 +7,7 @@ define i32 @test() {
LoopHead: ; preds = %LoopHead, %0, %0
%A = phi i32 [ 7, %0 ], [ 7, %0 ], [ %B, %LoopHead ] ; <i32> [#uses=1]
%B = add i32 %A, 1 ; <i32> [#uses=2]
br i1 undef, label %LoopHead, label %Out
br i1 true, label %LoopHead, label %Out
Out: ; preds = %LoopHead
ret i32 %B

View File

@ -0,0 +1,65 @@
; RUN: opt < %s -S -indvars -loop-deletion -simplifycfg | FileCheck %s
; PR5794
; Indvars and loop deletion should be able to eliminate all looping
; in this testcase.
; CHECK: define i32 @pmat(i32 %m, i32 %n, double* %y) nounwind {
; CHECK-NEXT: entry:
; CHECK-NEXT: ret i32 0
; CHECK-NEXT: }
target datalayout = "e-p:64:64:64"
define i32 @pmat(i32 %m, i32 %n, double* %y) nounwind {
entry:
%cmp4 = icmp sgt i32 %m, 0
br i1 %cmp4, label %bb.n10, label %w.e12
w.c:
%cmp = icmp slt i32 %inc11, %m
br i1 %cmp, label %w.c2.p, label %w.c.w.e12c
w.c.w.e12c:
br label %w.c.w.e12c.s
w.c.w.e12c.s:
br label %w.e12
bb.n10:
%cmp51 = icmp sgt i32 %n, 0
br i1 %cmp51, label %bb.n10.w.c.w.e12c.sc, label %bb.n10.bb.n10.sc
bb.n10.bb.n10.sc:
br label %bb.n10.s
bb.n10.w.c.w.e12c.sc:
br label %w.c.w.e12c.s
bb.n10.s:
br label %w.c2.p
w.c2.p:
%i.05 = phi i32 [ 0, %bb.n10.s ], [ %inc11, %w.c ]
br i1 false, label %bb.n, label %w.e
w.c2:
br i1 undef, label %w.b6, label %w.c2.w.ec
w.c2.w.ec:
br label %w.e
bb.n:
br label %w.b6
w.b6:
br label %w.c2
w.e:
%i.08 = phi i32 [ undef, %w.c2.w.ec ], [ %i.05, %w.c2.p ]
%inc11 = add nsw i32 %i.08, 1
br label %w.c
w.e12:
ret i32 0
}