Index: lib/Transforms/Utils/LoopUnrollPeel.cpp =================================================================== --- lib/Transforms/Utils/LoopUnrollPeel.cpp +++ lib/Transforms/Utils/LoopUnrollPeel.cpp @@ -241,7 +241,6 @@ InsertTop->getTerminator()->setSuccessor(0, cast(VMap[Header])); // Similarly, for the latch: - // The original exiting edge is still hooked up to the loop exit. // The backedge now goes to the "bottom", which is either the loop's real // header (for the last peeled iteration) or the copied header of the next // iteration (for every other iteration) @@ -249,7 +248,6 @@ BranchInst *LatchBR = cast(NewLatch->getTerminator()); unsigned HeaderIdx = (LatchBR->getSuccessor(0) == Header ? 0 : 1); LatchBR->setSuccessor(HeaderIdx, InsertBot); - LatchBR->setSuccessor(1 - HeaderIdx, Exit); if (DT) DT->changeImmediateDominator(InsertBot, NewLatch); @@ -278,15 +276,17 @@ // Fix up the outgoing values - we need to add a value for the iteration // we've just created. Note that this must happen *after* the incoming - // values are adjusted, since the value going out of the latch may also be + // values are adjusted, since the value going out of the exit may also be // a value coming into the header. + BasicBlock *Exiting = L->getExitingBlock(); + assert(Exiting && "Can't peel loops with more than one exiting block."); for (BasicBlock::iterator I = Exit->begin(); isa(I); ++I) { PHINode *PHI = cast(I); - Value *LatchVal = PHI->getIncomingValueForBlock(Latch); - Instruction *LatchInst = dyn_cast(LatchVal); - if (LatchInst && L->contains(LatchInst)) - LatchVal = VMap[LatchVal]; - PHI->addIncoming(LatchVal, cast(VMap[Latch])); + Value *ExitVal = PHI->getIncomingValueForBlock(Exiting); + Instruction *ExitInst = dyn_cast(ExitVal); + if (ExitInst && L->contains(ExitInst)) + ExitVal = VMap[ExitVal]; + PHI->addIncoming(ExitVal, cast(VMap[Exiting])); } // LastValueMap is updated with the values for the current loop @@ -409,11 +409,15 @@ cloneLoopBlocks(L, Iter, InsertTop, InsertBot, Exit, NewBlocks, LoopBlocks, VMap, LVMap, DT, LI); if (DT) { - // Latches of the cloned loops dominate over the loop exit, so idom of the - // latter is the first cloned loop body, as original PreHeader dominates - // the original loop body. + // The original exit block is reachable either directly from the first + // iteration's exiting block (if the first iteration exists), or through + // the first iteration's latch (if it doesn't). So it's dominated by + // the latch's and the exiting block's common dominator. if (Iter == 0) - DT->changeImmediateDominator(Exit, cast(LVMap[Latch])); + DT->changeImmediateDominator( + Exit, DT->findNearestCommonDominator( + cast(LVMap[Latch]), + cast(LVMap[L->getExitingBlock()]))); #ifndef NDEBUG if (VerifyDomInfo) DT->verifyDomTree(); Index: test/Transforms/LoopUnroll/peel-loop-irreducible.ll =================================================================== --- test/Transforms/LoopUnroll/peel-loop-irreducible.ll +++ test/Transforms/LoopUnroll/peel-loop-irreducible.ll @@ -0,0 +1,36 @@ +; RUN: opt < %s -S -loop-unroll | FileCheck %s + +; Check we can properly handle loops where the latch and the exiting block +; are different +; CHECK-LABEL: @invariant_backedge_irreducible +; CHECK: header.peel: +; CHECK: br i1 {{.*}} label %latch.peel, label %exiting.peel +; CHECK: latch.peel: +; CHECK: br i1 {{.*}} label %header.peel.next, label %exiting.peel +; CHECK: exiting.peel: +; CHECK: br i1 {{.*}} label %latch.peel, label %exit + +define i32 @invariant_backedge_irreducible(i32 %a, i32 %b) { +entry: + br label %header + +header: + %i = phi i32 [ 0, %entry ], [ %inc, %latch ] + %sum = phi i32 [ 0, %entry ], [ %incsum, %latch ] + %plus = phi i32 [ %a, %entry ], [ %b, %latch ] + %cmp.phi = phi i1 [ false, %entry ], [ %cmp, %latch ] + br i1 %cmp.phi, label %latch, label %exiting + +latch: + %incsum = add i32 %sum, %plus + %inc = add i32 %i, 1 + %cmp = icmp slt i32 %i, 1000 + br i1 %cmp, label %header, label %exiting + +exiting: + %cmp.exiting = phi i1 [ %cmp.phi, %header ], [ %cmp, %latch] + br i1 %cmp.exiting, label %latch, label %exit + +exit: + ret i32 %sum +} Index: test/Transforms/LoopUnroll/peel-loop-not-forced.ll =================================================================== --- test/Transforms/LoopUnroll/peel-loop-not-forced.ll +++ test/Transforms/LoopUnroll/peel-loop-not-forced.ll @@ -4,6 +4,7 @@ ; CHECK-LABEL: @invariant_backedge_1 ; CHECK-NOT: %plus = phi ; CHECK: loop.peel: +; CHECK: br i1 {{.*}}, label %loop.peel.next, label %exit ; CHECK: loop: ; CHECK: %i = phi ; CHECK: %sum = phi