| 1 | //===- DomTreeUpdater.cpp - DomTree/Post DomTree Updater --------*- C++ -*-===// |
| 2 | // |
| 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
| 4 | // See https://llvm.org/LICENSE.txt for license information. |
| 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
| 6 | // |
| 7 | //===----------------------------------------------------------------------===// |
| 8 | // |
| 9 | // This file implements the DomTreeUpdater class, which provides a uniform way |
| 10 | // to update dominator tree related data structures. |
| 11 | // |
| 12 | //===----------------------------------------------------------------------===// |
| 13 | |
| 14 | #include "llvm/Analysis/DomTreeUpdater.h" |
| 15 | #include "llvm/Analysis/GenericDomTreeUpdaterImpl.h" |
| 16 | #include "llvm/Analysis/PostDominators.h" |
| 17 | #include "llvm/IR/Constants.h" |
| 18 | #include "llvm/IR/Instructions.h" |
| 19 | #include "llvm/Support/Compiler.h" |
| 20 | #include "llvm/Support/GenericDomTree.h" |
| 21 | #include <functional> |
| 22 | |
| 23 | namespace llvm { |
| 24 | |
| 25 | template class LLVM_EXPORT_TEMPLATE |
| 26 | GenericDomTreeUpdater<DomTreeUpdater, DominatorTree, PostDominatorTree>; |
| 27 | |
| 28 | template LLVM_EXPORT_TEMPLATE void |
| 29 | GenericDomTreeUpdater<DomTreeUpdater, DominatorTree, |
| 30 | PostDominatorTree>::recalculate(Function &F); |
| 31 | |
| 32 | template LLVM_EXPORT_TEMPLATE void |
| 33 | GenericDomTreeUpdater<DomTreeUpdater, DominatorTree, PostDominatorTree>:: |
| 34 | applyUpdatesImpl</*IsForward=*/true>(); |
| 35 | template LLVM_EXPORT_TEMPLATE void |
| 36 | GenericDomTreeUpdater<DomTreeUpdater, DominatorTree, PostDominatorTree>:: |
| 37 | applyUpdatesImpl</*IsForward=*/false>(); |
| 38 | |
| 39 | bool DomTreeUpdater::forceFlushDeletedBB() { |
| 40 | if (DeletedBBs.empty()) |
| 41 | return false; |
| 42 | |
| 43 | for (auto *BB : DeletedBBs) { |
| 44 | // After calling deleteBB or callbackDeleteBB under Lazy UpdateStrategy, |
| 45 | // validateDeleteBB() removes all instructions of DelBB and adds an |
| 46 | // UnreachableInst as its terminator. So we check whether the BasicBlock to |
| 47 | // delete only has an UnreachableInst inside. |
| 48 | assert(BB->size() == 1 && isa<UnreachableInst>(BB->getTerminator()) && |
| 49 | "DelBB has been modified while awaiting deletion." ); |
| 50 | eraseDelBBNode(DelBB: BB); |
| 51 | BB->eraseFromParent(); |
| 52 | } |
| 53 | DeletedBBs.clear(); |
| 54 | Callbacks.clear(); |
| 55 | return true; |
| 56 | } |
| 57 | |
| 58 | // The DT and PDT require the nodes related to updates |
| 59 | // are not deleted when update functions are called. |
| 60 | // So BasicBlock deletions must be pended when the |
| 61 | // UpdateStrategy is Lazy. When the UpdateStrategy is |
| 62 | // Eager, the BasicBlock will be deleted immediately. |
| 63 | void DomTreeUpdater::deleteBB(BasicBlock *DelBB) { |
| 64 | validateDeleteBB(DelBB); |
| 65 | if (Strategy == UpdateStrategy::Lazy) { |
| 66 | DeletedBBs.insert(Ptr: DelBB); |
| 67 | return; |
| 68 | } |
| 69 | |
| 70 | eraseDelBBNode(DelBB); |
| 71 | DelBB->eraseFromParent(); |
| 72 | } |
| 73 | |
| 74 | void DomTreeUpdater::callbackDeleteBB( |
| 75 | BasicBlock *DelBB, std::function<void(BasicBlock *)> Callback) { |
| 76 | validateDeleteBB(DelBB); |
| 77 | if (Strategy == UpdateStrategy::Lazy) { |
| 78 | Callbacks.push_back(x: CallBackOnDeletion(DelBB, Callback)); |
| 79 | DeletedBBs.insert(Ptr: DelBB); |
| 80 | return; |
| 81 | } |
| 82 | |
| 83 | eraseDelBBNode(DelBB); |
| 84 | DelBB->removeFromParent(); |
| 85 | Callback(DelBB); |
| 86 | delete DelBB; |
| 87 | } |
| 88 | |
| 89 | void DomTreeUpdater::validateDeleteBB(BasicBlock *DelBB) { |
| 90 | assert(DelBB && "Invalid push_back of nullptr DelBB." ); |
| 91 | assert(pred_empty(DelBB) && "DelBB has one or more predecessors." ); |
| 92 | // DelBB is unreachable and all its instructions are dead. |
| 93 | while (!DelBB->empty()) { |
| 94 | Instruction &I = DelBB->back(); |
| 95 | // Replace used instructions with an arbitrary value (poison). |
| 96 | if (!I.use_empty()) |
| 97 | I.replaceAllUsesWith(V: PoisonValue::get(T: I.getType())); |
| 98 | DelBB->back().eraseFromParent(); |
| 99 | } |
| 100 | // Make sure DelBB has a valid terminator instruction. As long as DelBB is a |
| 101 | // Child of Function F it must contain valid IR. |
| 102 | new UnreachableInst(DelBB->getContext(), DelBB); |
| 103 | } |
| 104 | |
| 105 | LLVM_DUMP_METHOD |
| 106 | void DomTreeUpdater::dump() const { |
| 107 | Base::dump(); |
| 108 | #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) |
| 109 | raw_ostream &OS = dbgs(); |
| 110 | OS << "Pending Callbacks:\n" ; |
| 111 | int Index = 0; |
| 112 | for (const auto &BB : Callbacks) { |
| 113 | OS << " " << Index << " : " ; |
| 114 | ++Index; |
| 115 | if (BB->hasName()) |
| 116 | OS << BB->getName() << "(" ; |
| 117 | else |
| 118 | OS << "(no_name)(" ; |
| 119 | OS << BB << ")\n" ; |
| 120 | } |
| 121 | #endif |
| 122 | } |
| 123 | |
| 124 | } // namespace llvm |
| 125 | |