diff --git a/lib/Transforms/Scalar/IndVarSimplify.cpp b/lib/Transforms/Scalar/IndVarSimplify.cpp index d2ba25637e0..27e377f9037 100644 --- a/lib/Transforms/Scalar/IndVarSimplify.cpp +++ b/lib/Transforms/Scalar/IndVarSimplify.cpp @@ -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(); LI = &getAnalysis(); SE = &getAnalysis(); + DT = &getAnalysis(); 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(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 index 00000000000..7119cbbc05c --- /dev/null +++ b/test/Transforms/IndVarSimplify/phi-uses-value-multiple-times.ll @@ -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 +}