diff --git a/lib/Transforms/Utils/Local.cpp b/lib/Transforms/Utils/Local.cpp index 8c29ed50b45..b0f729b2703 100644 --- a/lib/Transforms/Utils/Local.cpp +++ b/lib/Transforms/Utils/Local.cpp @@ -874,6 +874,11 @@ bool llvm::EliminateDuplicatePHINodes(BasicBlock *BB) { PN->replaceAllUsesWith(*Inserted.first); PN->eraseFromParent(); Changed = true; + + // The RAUW can change PHIs that we already visited. Start over from the + // beginning. + PHISet.clear(); + I = BB->begin(); } } diff --git a/unittests/Transforms/Utils/Local.cpp b/unittests/Transforms/Utils/Local.cpp index f0c3ecfbb9b..2ff56047555 100644 --- a/unittests/Transforms/Utils/Local.cpp +++ b/unittests/Transforms/Utils/Local.cpp @@ -58,3 +58,40 @@ TEST(Local, RecursivelyDeleteDeadPHINodes) { delete bb0; delete bb1; } + +TEST(Local, RemoveDuplicatePHINodes) { + LLVMContext &C(getGlobalContext()); + IRBuilder<> B(C); + + std::unique_ptr F( + Function::Create(FunctionType::get(B.getVoidTy(), false), + GlobalValue::ExternalLinkage, "F")); + BasicBlock *Entry(BasicBlock::Create(C, "", F.get())); + BasicBlock *BB(BasicBlock::Create(C, "", F.get())); + BranchInst::Create(BB, Entry); + + B.SetInsertPoint(BB); + + AssertingVH P1 = B.CreatePHI(Type::getInt32Ty(C), 2); + P1->addIncoming(B.getInt32(42), Entry); + + PHINode *P2 = B.CreatePHI(Type::getInt32Ty(C), 2); + P2->addIncoming(B.getInt32(42), Entry); + + AssertingVH P3 = B.CreatePHI(Type::getInt32Ty(C), 2); + P3->addIncoming(B.getInt32(42), Entry); + P3->addIncoming(B.getInt32(23), BB); + + PHINode *P4 = B.CreatePHI(Type::getInt32Ty(C), 2); + P4->addIncoming(B.getInt32(42), Entry); + P4->addIncoming(B.getInt32(23), BB); + + P1->addIncoming(P3, BB); + P2->addIncoming(P4, BB); + BranchInst::Create(BB, BB); + + // Verify that we can eliminate PHIs that become duplicates after chaning PHIs + // downstream. + EXPECT_TRUE(EliminateDuplicatePHINodes(BB)); + EXPECT_EQ(3U, BB->size()); +}