Index: lib/Transforms/Utils/LoopUnrollRuntime.cpp =================================================================== --- lib/Transforms/Utils/LoopUnrollRuntime.cpp +++ lib/Transforms/Utils/LoopUnrollRuntime.cpp @@ -849,16 +849,18 @@ // the remainder code), we set the immediate dominator as the preheader. if (DT) { DT->changeImmediateDominator(BB, PreHeader); - // Also update the IDom for immediate successors of BB. If the current - // IDom is the header, update the IDom to be the preheader because that is - // the nearest common dominator of all predecessors of SuccBB. We need to - // check for IDom being the header because successors of exit blocks can - // have edges from outside the loop, and we should not incorrectly update - // the IDom in that case. + // Also update the IDom for immediate successors of BB to the Preheader, + // where applicable. for (BasicBlock *SuccBB: successors(BB)) if (ImmediateSuccessorsOfExitBlocks.insert(SuccBB).second) { - if (DT->getNode(SuccBB)->getIDom()->getBlock() == Header) { - assert(!SuccBB->getSinglePredecessor() && + // If the current IDom of SuccBB is within the loop, update the IDom to + // be the preheader because that is the nearest common dominator of all + // predecessors of SuccBB (i.e. BB and other blocks from the loop). + // We need to check for IDom being in the loop because successors of + // exit blocks can have edges from outside the loop, and we should not + // incorrectly update the IDom in that case. + if (LI->getLoopFor(DT->getNode(SuccBB)->getIDom()->getBlock()) == L) { + assert(!SuccBB->getUniquePredecessor() && "BB should be the IDom then!"); DT->changeImmediateDominator(SuccBB, PreHeader); } Index: test/Transforms/LoopUnroll/runtime-loop-multiexit-dom-verify.ll =================================================================== --- test/Transforms/LoopUnroll/runtime-loop-multiexit-dom-verify.ll +++ test/Transforms/LoopUnroll/runtime-loop-multiexit-dom-verify.ll @@ -124,3 +124,50 @@ exitsucc: ; preds = %headerexit ret i64 96 } + +; exit block (%default) has an exiting block and another exit block as predecessors. +define void @test4(i16 %c3) { +; CHECK-LABEL: test4 + +; CHECK-LABEL: exiting.prol: +; CHECK-NEXT: switch i16 %c3, label %default.loopexit.loopexit1 [ + +; CHECK-LABEL: exiting: +; CHECK-NEXT: switch i16 %c3, label %default.loopexit.loopexit [ + +; CHECK-LABEL: default.loopexit.loopexit: +; CHECK-NEXT: br label %default.loopexit + +; CHECK-LABEL: default.loopexit.loopexit1: +; CHECK-NEXT: br label %default.loopexit + +; CHECK-LABEL: default.loopexit: +; CHECK-NEXT: br label %default +preheader: + %c1 = zext i32 undef to i64 + br label %header + +header: ; preds = %latch, %preheader + %indvars.iv = phi i64 [ 0, %preheader ], [ %indvars.iv.next, %latch ] + br label %exiting + +exiting: ; preds = %header + switch i16 %c3, label %default [ + i16 45, label %otherexit + i16 95, label %latch + ] + +latch: ; preds = %exiting + %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1 + %c2 = icmp ult i64 %indvars.iv.next, %c1 + br i1 %c2, label %header, label %latchexit + +latchexit: ; preds = %latch + ret void + +default: ; preds = %otherexit, %exiting + ret void + +otherexit: ; preds = %exiting + br label %default +}