Index: lib/Transforms/Utils/LoopUnroll.cpp =================================================================== --- lib/Transforms/Utils/LoopUnroll.cpp +++ lib/Transforms/Utils/LoopUnroll.cpp @@ -257,6 +257,7 @@ bool CompletelyUnroll = Count == TripCount; SmallVector ExitBlocks; L->getExitBlocks(ExitBlocks); + std::vector OriginalLoopBlocks = L->getBlocks(); // Go through all exits of L and see if there are any phi-nodes there. We just // conservatively assume that they're inserted to preserve LCSSA form, which @@ -545,20 +546,26 @@ Term->eraseFromParent(); } } - // Update dominators of loop exit blocks. - // Immediate dominator of an exit block might change, because we add more + // Update dominators of blocks we might reach through exits. + // Immediate dominator of such block might change, because we add more // routes which can lead to the exit: we can now reach it from the copied - // iterations too. Thus, the new idom of the exit block will be the nearest + // iterations too. Thus, the new idom of the block will be the nearest // common dominator of the previous idom and common dominator of all copies of - // the exiting block. This is equivalent to the nearest common dominator of + // the previous idom. This is equivalent to the nearest common dominator of // the previous idom and the first latch, which dominates all copies of the - // exiting block. + // previous idom. if (DT && Count > 1) { - for (auto Exit : ExitBlocks) { - BasicBlock *PrevIDom = DT->getNode(Exit)->getIDom()->getBlock(); - BasicBlock *NewIDom = - DT->findNearestCommonDominator(PrevIDom, Latches[0]); - DT->changeImmediateDominator(Exit, NewIDom); + for (auto *BB : OriginalLoopBlocks) { + auto *BBDomNode = DT->getNode(BB); + for (auto *ChildDomNode : BBDomNode->getChildren()) { + auto *ChildBB = ChildDomNode->getBlock(); + if (L->contains(ChildBB)) + continue; + BasicBlock *PrevIDom = ChildDomNode->getIDom()->getBlock(); + BasicBlock *NewIDom = + DT->findNearestCommonDominator(PrevIDom, Latches[0]); + DT->changeImmediateDominator(ChildBB, NewIDom); + } } } Index: test/Transforms/LoopUnroll/pr27157.ll =================================================================== --- /dev/null +++ test/Transforms/LoopUnroll/pr27157.ll @@ -0,0 +1,53 @@ +; RUN: opt -loop-unroll -debug-only=loop-unroll -disable-output < %s +; REQUIRES: asserts +; Compile this test with debug flag on to verify domtree right after loop unrolling. +target datalayout = "E-m:e-i1:8:16-i8:8:16-i64:64-f128:64-v128:64-a:8:16-n32:64" + +; PR27157 +define void @foo() { +entry: + br label %loop_header +loop_header: + %iv = phi i64 [ 0, %entry ], [ %iv_next, %loop_latch ] + br i1 undef, label %loop_latch, label %loop_exiting_bb1 +loop_exiting_bb1: + br i1 false, label %loop_exiting_bb2, label %exit1.loopexit +loop_exiting_bb2: + br i1 false, label %loop_latch, label %bb +bb: + br label %exit1 +loop_latch: + %iv_next = add nuw nsw i64 %iv, 1 + %cmp = icmp ne i64 %iv_next, 2 + br i1 %cmp, label %loop_header, label %exit2 +exit1.loopexit: + br label %exit1 +exit1: + ret void +exit2: + ret void +} + +define void @foo2() { +entry: + br label %loop.header +loop.header: + %iv = phi i32 [ 0, %entry ], [ %iv.inc, %latch ] + %iv.inc = add i32 %iv, 1 + br i1 undef, label %diamond, label %latch +diamond: + br i1 undef, label %left, label %right +left: + br i1 undef, label %exit, label %merge +right: + br i1 undef, label %exit, label %merge +merge: + br label %latch +latch: + %end.cond = icmp eq i32 %iv, 1 + br i1 %end.cond, label %exit1, label %loop.header +exit: + ret void +exit1: + ret void +}