Index: lib/Transforms/Utils/Local.cpp =================================================================== --- lib/Transforms/Utils/Local.cpp +++ lib/Transforms/Utils/Local.cpp @@ -714,7 +714,8 @@ if (ReplaceEntryBB) DestBB->moveAfter(PredBB); - if (DT) { + // Entry block does not have IDom. + if (DT && !ReplaceEntryBB) { // For some irreducible CFG we end up having forward-unreachable blocks // so check if getNode returns a valid node before updating the domtree. if (DomTreeNode *DTN = DT->getNode(PredBB)) { @@ -735,6 +736,11 @@ DDT->applyUpdates(Updates); } else { PredBB->eraseFromParent(); // Nuke BB. + // The entry block was removed and there is no external interface for the + // dominator tree to be notified of this change. In this corner-case we + // recalculate the entire tree. + if (DT && ReplaceEntryBB) + DT->recalculate(*(DestBB->getParent())); } } Index: unittests/Transforms/Utils/Local.cpp =================================================================== --- unittests/Transforms/Utils/Local.cpp +++ unittests/Transforms/Utils/Local.cpp @@ -176,6 +176,18 @@ TEST(Local, MergeBasicBlockIntoOnlyPred) { LLVMContext C; + auto runMergeBasicBlockIntoOnlyPred = [&](Function &F, DominatorTree *DT) { + for (Function::iterator I = F.begin(), E = F.end(); I != E;) { + BasicBlock *BB = &*I++; + BasicBlock *SinglePred = BB->getSinglePredecessor(); + if (!SinglePred || SinglePred == BB || BB->hasAddressTaken()) + continue; + BranchInst *Term = dyn_cast(SinglePred->getTerminator()); + if (Term && !Term->isConditional()) + MergeBasicBlockIntoOnlyPred(BB, DT); + } + }; + std::unique_ptr M = parseIR(C, R"( define i32 @f(i8* %str) { @@ -194,18 +206,28 @@ ret i32 0 } )"); - runWithDomTree( - *M, "f", [&](Function &F, DominatorTree *DT) { - for (Function::iterator I = F.begin(), E = F.end(); I != E;) { - BasicBlock *BB = &*I++; - BasicBlock *SinglePred = BB->getSinglePredecessor(); - if (!SinglePred || SinglePred == BB || BB->hasAddressTaken()) continue; - BranchInst *Term = dyn_cast(SinglePred->getTerminator()); - if (Term && !Term->isConditional()) - MergeBasicBlockIntoOnlyPred(BB, DT); - } - EXPECT_TRUE(DT->verify()); - }); + runWithDomTree(*M, "f", [&](Function &F, DominatorTree *DT) { + runMergeBasicBlockIntoOnlyPred(F, DT); + EXPECT_TRUE(DT->verify()); + }); + + // Test we can merge away entry block and update DT correctly. + // entry block does not have IDom. + std::unique_ptr M2 = parseIR(C, + R"( + define i32 @f(i8* %str) { + entry: + br label %bb2.i + bb2.i: ; preds = %bb4.i, %entry + br label %base2flt.exit204 + base2flt.exit204: ; preds = %bb7.i197, %bb7.i197, %bb2.i, %bb4.i + ret i32 0 + } + )"); + runWithDomTree(*M2, "f", [&](Function &F, DominatorTree *DT) { + runMergeBasicBlockIntoOnlyPred(F, DT); + EXPECT_TRUE(DT->verify()); + }); } TEST(Local, ConstantFoldTerminator) {