When a value is used multiple times within a single PHI, instructions
authorDan Gohman <gohman@apple.com>
Sat, 27 Jun 2009 05:16:57 +0000 (05:16 +0000)
committerDan Gohman <gohman@apple.com>
Sat, 27 Jun 2009 05:16:57 +0000 (05:16 +0000)
inserted to replace that value must dominate all of of the basic
blocks associated with the uses of the value in the PHI, not just
one of them.

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

lib/Transforms/Scalar/IndVarSimplify.cpp
test/Transforms/IndVarSimplify/phi-uses-value-multiple-times.ll [new file with mode: 0644]

index d2ba25637e02d155622814d363c4756f8d6ed77d..27e377f9037956ebb780273b87a8471fd9189c24 100644 (file)
@@ -70,6 +70,7 @@ namespace {
     IVUsers         *IU;
     LoopInfo        *LI;
     ScalarEvolution *SE;
+    DominatorTree   *DT;
     bool Changed;
   public:
 
@@ -329,6 +330,7 @@ bool IndVarSimplify::runOnLoop(Loop *L, LPPassManager &LPM) {
   IU = &getAnalysis<IVUsers>();
   LI = &getAnalysis<LoopInfo>();
   SE = &getAnalysis<ScalarEvolution>();
+  DT = &getAnalysis<DominatorTree>();
   Changed = false;
 
   // If there are any floating-point recurrences, attempt to
@@ -479,12 +481,22 @@ void IndVarSimplify::RewriteIVExpressions(Loop *L, const Type *LargestType,
       if (!AR->isLoopInvariant(L) && !Stride->isLoopInvariant(L))
         continue;
 
+      // Determine the insertion point for this user. By default, insert
+      // immediately before the user. The SCEVExpander class will automatically
+      // hoist loop invariants out of the loop. For PHI nodes, there may be
+      // multiple uses, so compute the nearest common dominator for the
+      // incoming blocks.
       Instruction *InsertPt = User;
       if (PHINode *PHI = dyn_cast<PHINode>(InsertPt))
-        for (unsigned i = 0; ++i)
+        for (unsigned i = 0, e = PHI->getNumIncomingValues(); i != e; ++i)
           if (PHI->getIncomingValue(i) == Op) {
-            InsertPt = PHI->getIncomingBlock(i)->getTerminator();
-            break;
+            if (InsertPt == User)
+              InsertPt = PHI->getIncomingBlock(i)->getTerminator();
+            else
+              InsertPt =
+                DT->findNearestCommonDominator(InsertPt->getParent(),
+                                               PHI->getIncomingBlock(i))
+                      ->getTerminator();
           }
 
       // Now expand it into actual Instructions and patch it into place.
diff --git a/test/Transforms/IndVarSimplify/phi-uses-value-multiple-times.ll b/test/Transforms/IndVarSimplify/phi-uses-value-multiple-times.ll
new file mode 100644 (file)
index 0000000..7119cbb
--- /dev/null
@@ -0,0 +1,33 @@
+; RUN: llvm-as < %s | opt -indvars
+target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128"
+
+@ue = external global i64
+
+define i32 @foo() nounwind {
+entry:
+       br label %bb38.i
+
+bb14.i27:
+       %t0 = load i64* @ue, align 8
+       %t1 = sub i64 %t0, %i.0.i35
+       %t2 = add i64 %t1, 1
+       br i1 undef, label %bb15.i28, label %bb19.i31
+
+bb15.i28:
+       br label %bb19.i31
+
+bb19.i31:
+       %y.0.i = phi i64 [ %t2, %bb15.i28 ], [ %t2, %bb14.i27 ]
+       br label %bb35.i
+
+bb35.i:
+       br i1 undef, label %bb37.i, label %bb14.i27
+
+bb37.i:
+       %t3 = add i64 %i.0.i35, 1
+       br label %bb38.i
+
+bb38.i:
+       %i.0.i35 = phi i64 [ 1, %entry ], [ %t3, %bb37.i ]
+       br label %bb35.i
+}