[llvm-commits] [llvm] r97126 - in /llvm/trunk: lib/Analysis/ScalarEvolution.cpp lib/Transforms/Scalar/IndVarSimplify.cpp lib/Transforms/Utils/LoopSimplify.cpp test/CodeGen/X86/2009-09-07-CoalescerBug.ll test/Transforms/IndVarSimplify/2003-09-12-MultiplePred.ll test/Transforms/LoopDeletion/simplify-then-delete.ll

Dan Gohman gohman at apple.com
Wed Feb 24 22:57:05 PST 2010


Author: djg
Date: Thu Feb 25 00:57:05 2010
New Revision: 97126

URL: http://llvm.org/viewvc/llvm-project?rev=97126&view=rev
Log:
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.

Added:
    llvm/trunk/test/Transforms/LoopDeletion/simplify-then-delete.ll
Modified:
    llvm/trunk/lib/Analysis/ScalarEvolution.cpp
    llvm/trunk/lib/Transforms/Scalar/IndVarSimplify.cpp
    llvm/trunk/lib/Transforms/Utils/LoopSimplify.cpp
    llvm/trunk/test/CodeGen/X86/2009-09-07-CoalescerBug.ll
    llvm/trunk/test/Transforms/IndVarSimplify/2003-09-12-MultiplePred.ll

Modified: llvm/trunk/lib/Analysis/ScalarEvolution.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Analysis/ScalarEvolution.cpp?rev=97126&r1=97125&r2=97126&view=diff
==============================================================================
--- llvm/trunk/lib/Analysis/ScalarEvolution.cpp (original)
+++ llvm/trunk/lib/Analysis/ScalarEvolution.cpp Thu Feb 25 00:57:05 2010
@@ -2549,14 +2549,14 @@
 /// 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 @@
         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 @@
         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);

Modified: llvm/trunk/lib/Transforms/Scalar/IndVarSimplify.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Scalar/IndVarSimplify.cpp?rev=97126&r1=97125&r2=97126&view=diff
==============================================================================
--- llvm/trunk/lib/Transforms/Scalar/IndVarSimplify.cpp (original)
+++ llvm/trunk/lib/Transforms/Scalar/IndVarSimplify.cpp Thu Feb 25 00:57:05 2010
@@ -384,17 +384,18 @@
   // 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 @@
     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.

Modified: llvm/trunk/lib/Transforms/Utils/LoopSimplify.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Utils/LoopSimplify.cpp?rev=97126&r1=97125&r2=97126&view=diff
==============================================================================
--- llvm/trunk/lib/Transforms/Utils/LoopSimplify.cpp (original)
+++ llvm/trunk/lib/Transforms/Utils/LoopSimplify.cpp Thu Feb 25 00:57:05 2010
@@ -159,6 +159,22 @@
     }
   }
 
+  // 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 @@
         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;

Modified: llvm/trunk/test/CodeGen/X86/2009-09-07-CoalescerBug.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/2009-09-07-CoalescerBug.ll?rev=97126&r1=97125&r2=97126&view=diff
==============================================================================
--- llvm/trunk/test/CodeGen/X86/2009-09-07-CoalescerBug.ll (original)
+++ llvm/trunk/test/CodeGen/X86/2009-09-07-CoalescerBug.ll Thu Feb 25 00:57:05 2010
@@ -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
 

Modified: llvm/trunk/test/Transforms/IndVarSimplify/2003-09-12-MultiplePred.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/IndVarSimplify/2003-09-12-MultiplePred.ll?rev=97126&r1=97125&r2=97126&view=diff
==============================================================================
--- llvm/trunk/test/Transforms/IndVarSimplify/2003-09-12-MultiplePred.ll (original)
+++ llvm/trunk/test/Transforms/IndVarSimplify/2003-09-12-MultiplePred.ll Thu Feb 25 00:57:05 2010
@@ -7,7 +7,7 @@
 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

Added: llvm/trunk/test/Transforms/LoopDeletion/simplify-then-delete.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/LoopDeletion/simplify-then-delete.ll?rev=97126&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/LoopDeletion/simplify-then-delete.ll (added)
+++ llvm/trunk/test/Transforms/LoopDeletion/simplify-then-delete.ll Thu Feb 25 00:57:05 2010
@@ -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
+}





More information about the llvm-commits mailing list