Index: lib/Transforms/Utils/Local.cpp =================================================================== --- lib/Transforms/Utils/Local.cpp +++ lib/Transforms/Utils/Local.cpp @@ -2233,6 +2233,7 @@ BB->dropAllReferences(); } + bool Deleted = false; for (Function::iterator I = ++F.begin(); I != F.end();) { auto *BB = &*I; if (Reachable.count(BB)) { @@ -2240,6 +2241,10 @@ continue; } if (DDT) { + if (DDT->pendingDeletedBB(BB)) // BB has already been deleted. + --NumRemoved; + else + Deleted = true; DDT->deleteBB(BB); // deferred deletion of BB. ++I; } else { @@ -2249,6 +2254,8 @@ if (DDT) DDT->applyUpdates(Updates); + if (DDT && !Deleted) + return false; return true; } Index: unittests/Transforms/Utils/Local.cpp =================================================================== --- unittests/Transforms/Utils/Local.cpp +++ unittests/Transforms/Utils/Local.cpp @@ -618,3 +618,26 @@ verifyModule(*M, &errs(), &BrokenDebugInfo); ASSERT_FALSE(BrokenDebugInfo); } + +TEST(Local, RemoveUnreachableBlocks) { + LLVMContext C; + + std::unique_ptr M = parseIR(C, + R"( + define void @f() { + entry: + br label %entry + bb0: + ret void + } + )"); + + auto callRemoveUnreachableBlocks = [&](Function &F, DominatorTree *DT) { + DeferredDominance DDT(*DT); + EXPECT_TRUE(removeUnreachableBlocks(F, nullptr, &DDT)); + EXPECT_FALSE(removeUnreachableBlocks(F, nullptr, &DDT)); + EXPECT_TRUE(DDT.flush().verify()); + }; + + runWithDomTree(*M, "f", callRemoveUnreachableBlocks); +}