diff options
Diffstat (limited to 'llvm/lib')
-rw-r--r-- | llvm/lib/Transforms/Scalar/NewGVN.cpp | 31 |
1 files changed, 18 insertions, 13 deletions
diff --git a/llvm/lib/Transforms/Scalar/NewGVN.cpp b/llvm/lib/Transforms/Scalar/NewGVN.cpp index c17b9f7fcf2..259a4eade0d 100644 --- a/llvm/lib/Transforms/Scalar/NewGVN.cpp +++ b/llvm/lib/Transforms/Scalar/NewGVN.cpp @@ -2106,21 +2106,26 @@ void NewGVN::deleteInstructionsInBlock(BasicBlock *BB) { DEBUG(dbgs() << " BasicBlock Dead:" << *BB); ++NumGVNBlocksDeleted; - // Change to unreachable does not handle destroying phi nodes. We just replace - // the users with undef. - if (BB->empty()) + // Check to see if there are non-terminating instructions to delete. + if (isa<TerminatorInst>(BB->begin())) return; - auto BBI = BB->begin(); - while (auto *Phi = dyn_cast<PHINode>(BBI)) { - Phi->replaceAllUsesWith(UndefValue::get(Phi->getType())); - ++BBI; - } - Instruction *ToKill = &*BBI; - // Nothing but phi nodes, so nothing left to remove. - if (!ToKill) - return; - NumGVNInstrDeleted += changeToUnreachable(ToKill, false); + // Delete the instructions backwards, as it has a reduced likelihood of having + // to update as many def-use and use-def chains. Start after the terminator. + auto StartPoint = BB->rbegin(); + ++StartPoint; + // Note that we explicitly recalculate BB->rend() on each iteration, + // as it may change when we remove the first instruction. + for (BasicBlock::reverse_iterator I(StartPoint); I != BB->rend();) { + Instruction &Inst = *I++; + if (!Inst.use_empty()) + Inst.replaceAllUsesWith(UndefValue::get(Inst.getType())); + if (isa<LandingPadInst>(Inst)) + continue; + + Inst.eraseFromParent(); + ++NumGVNInstrDeleted; + } } void NewGVN::markInstructionForDeletion(Instruction *I) { |