diff options
author | Dan Gohman <gohman@apple.com> | 2010-02-25 06:57:05 +0000 |
---|---|---|
committer | Dan Gohman <gohman@apple.com> | 2010-02-25 06:57:05 +0000 |
commit | 85669637139089eaed8def1583ac04266c9654e2 (patch) | |
tree | 9179b71a2387b88fd18bfb147114734c0c7d0ccc | |
parent | a5028a64634f995630e93390c5c23374a09a450f (diff) |
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
-rw-r--r-- | lib/Analysis/ScalarEvolution.cpp | 41 | ||||
-rw-r--r-- | lib/Transforms/Scalar/IndVarSimplify.cpp | 29 | ||||
-rw-r--r-- | lib/Transforms/Utils/LoopSimplify.cpp | 18 | ||||
-rw-r--r-- | test/CodeGen/X86/2009-09-07-CoalescerBug.ll | 3 | ||||
-rw-r--r-- | test/Transforms/IndVarSimplify/2003-09-12-MultiplePred.ll | 2 | ||||
-rw-r--r-- | test/Transforms/LoopDeletion/simplify-then-delete.ll | 65 |
6 files changed, 128 insertions, 30 deletions
diff --git a/lib/Analysis/ScalarEvolution.cpp b/lib/Analysis/ScalarEvolution.cpp index 5bad4b2972..fba6e20308 100644 --- a/lib/Analysis/ScalarEvolution.cpp +++ b/lib/Analysis/ScalarEvolution.cpp @@ -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); diff --git a/lib/Transforms/Scalar/IndVarSimplify.cpp b/lib/Transforms/Scalar/IndVarSimplify.cpp index 6ee1fd6fed..4fe08e42de 100644 --- a/lib/Transforms/Scalar/IndVarSimplify.cpp +++ b/lib/Transforms/Scalar/IndVarSimplify.cpp @@ -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. diff --git a/lib/Transforms/Utils/LoopSimplify.cpp b/lib/Transforms/Utils/LoopSimplify.cpp index 57bab60e6b..2e1f9354f7 100644 --- a/lib/Transforms/Utils/LoopSimplify.cpp +++ b/lib/Transforms/Utils/LoopSimplify.cpp @@ -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; diff --git a/test/CodeGen/X86/2009-09-07-CoalescerBug.ll b/test/CodeGen/X86/2009-09-07-CoalescerBug.ll index a5b4a79401..41b4bc0872 100644 --- a/test/CodeGen/X86/2009-09-07-CoalescerBug.ll +++ b/test/CodeGen/X86/2009-09-07-CoalescerBug.ll @@ -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 diff --git a/test/Transforms/IndVarSimplify/2003-09-12-MultiplePred.ll b/test/Transforms/IndVarSimplify/2003-09-12-MultiplePred.ll index 30d9ea6fb3..ecd5086f73 100644 --- a/test/Transforms/IndVarSimplify/2003-09-12-MultiplePred.ll +++ b/test/Transforms/IndVarSimplify/2003-09-12-MultiplePred.ll @@ -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 diff --git a/test/Transforms/LoopDeletion/simplify-then-delete.ll b/test/Transforms/LoopDeletion/simplify-then-delete.ll new file mode 100644 index 0000000000..5a21672a59 --- /dev/null +++ b/test/Transforms/LoopDeletion/simplify-then-delete.ll @@ -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 +} |