Generalize ScalarEvolution's PHI analysis to handle loops that don't
authorDan Gohman <gohman@apple.com>
Mon, 12 Apr 2010 07:49:36 +0000 (07:49 +0000)
committerDan Gohman <gohman@apple.com>
Mon, 12 Apr 2010 07:49:36 +0000 (07:49 +0000)
have preheaders or dedicated exit blocks, as clients may not otherwise
need to run LoopSimplify.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@101030 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Analysis/ScalarEvolution.cpp
test/Analysis/ScalarEvolution/unsimplified-loop.ll [new file with mode: 0644]

index 32fc9b6f712b0351950f37dbe14637335c60cb3f..c773c675e7a98d7a03442524714ad059780dbb03 100644 (file)
@@ -2597,14 +2597,29 @@ ScalarEvolution::ForgetSymbolicName(Instruction *PN, const SCEV *SymName) {
 /// a loop header, making it a potential recurrence, or it doesn't.
 ///
 const SCEV *ScalarEvolution::createNodeForPHI(PHINode *PN) {
-  if (PN->getNumIncomingValues() == 2)  // The loops have been canonicalized.
-    if (const Loop *L = LI->getLoopFor(PN->getParent()))
-      if (L->getHeader() == PN->getParent()) {
-        // If it lives in the loop header, it has two incoming values, one
-        // from outside the loop, and one from inside.
-        unsigned IncomingEdge = L->contains(PN->getIncomingBlock(0));
-        unsigned BackEdge     = IncomingEdge^1;
-
+  if (const Loop *L = LI->getLoopFor(PN->getParent()))
+    if (L->getHeader() == PN->getParent()) {
+      // The loop may have multiple entrances or multiple exits; we can analyze
+      // this phi as an addrec if it has a unique entry value and a unique
+      // backedge value.
+      Value *BEValueV = 0, *StartValueV = 0;
+      for (unsigned i = 0, e = PN->getNumIncomingValues(); i != e; ++i) {
+        Value *V = PN->getIncomingValue(i);
+        if (L->contains(PN->getIncomingBlock(i))) {
+          if (!BEValueV) {
+            BEValueV = V;
+          } else if (BEValueV != V) {
+            BEValueV = 0;
+            break;
+          }
+        } else if (!StartValueV) {
+          StartValueV = V;
+        } else if (StartValueV != V) {
+          StartValueV = 0;
+          break;
+        }
+      }
+      if (BEValueV && StartValueV) {
         // While we are analyzing this PHI node, handle its value symbolically.
         const SCEV *SymbolicName = getUnknown(PN);
         assert(Scalars.find(PN) == Scalars.end() &&
@@ -2613,7 +2628,6 @@ const SCEV *ScalarEvolution::createNodeForPHI(PHINode *PN) {
 
         // Using this symbolic name for the PHI, analyze the value coming around
         // the back-edge.
-        Value *BEValueV = PN->getIncomingValue(BackEdge);
         const SCEV *BEValue = getSCEV(BEValueV);
 
         // NOTE: If BEValue is loop invariant, we know that the PHI node just
@@ -2657,8 +2671,7 @@ const SCEV *ScalarEvolution::createNodeForPHI(PHINode *PN) {
                   HasNSW = true;
               }
 
-              const SCEV *StartVal =
-                getSCEV(PN->getIncomingValue(IncomingEdge));
+              const SCEV *StartVal = getSCEV(StartValueV);
               const SCEV *PHISCEV =
                 getAddRecExpr(StartVal, Accum, L, HasNUW, HasNSW);
 
@@ -2684,7 +2697,7 @@ const SCEV *ScalarEvolution::createNodeForPHI(PHINode *PN) {
           // Because the other in-value of i (0) fits the evolution of BEValue
           // i really is an addrec evolution.
           if (AddRec->getLoop() == L && AddRec->isAffine()) {
-            const SCEV *StartVal = getSCEV(PN->getIncomingValue(IncomingEdge));
+            const SCEV *StartVal = getSCEV(StartValueV);
 
             // If StartVal = j.start - j.stride, we can use StartVal as the
             // initial step of the addrec evolution.
@@ -2702,9 +2715,8 @@ const SCEV *ScalarEvolution::createNodeForPHI(PHINode *PN) {
             }
           }
         }
-
-        return SymbolicName;
       }
+    }
 
   // 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
diff --git a/test/Analysis/ScalarEvolution/unsimplified-loop.ll b/test/Analysis/ScalarEvolution/unsimplified-loop.ll
new file mode 100644 (file)
index 0000000..a317507
--- /dev/null
@@ -0,0 +1,29 @@
+; RUN: opt -analyze -scalar-evolution < %s | FileCheck %s
+
+; This loop has no preheader, multiple backedges, etc., but ScalarEvolution
+; should still be able to analyze it.
+
+; CHECK: %i = phi i64 [ 5, %entry ], [ 5, %alt ], [ %i.next, %loop.a ], [ %i.next, %loop.b ]
+; CHECK-NEXT: -->  {5,+,1}<%loop>
+
+define void @foo(i1 %p, i1 %q, i1 %s, i1 %u) {
+entry:
+  br i1 %p, label %loop, label %alt
+
+alt:
+  br i1 %s, label %loop, label %exit
+
+loop:
+  %i = phi i64 [ 5, %entry ], [ 5, %alt ], [ %i.next, %loop.a ], [ %i.next, %loop.b ]
+  %i.next = add i64 %i, 1
+  br i1 %q, label %loop.a, label %loop.b
+
+loop.a:
+  br label %loop
+
+loop.b:
+  br i1 %u, label %loop, label %exit
+
+exit:
+  ret void
+}