xref: /freebsd-src/contrib/llvm-project/llvm/lib/Analysis/DomTreeUpdater.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
10b57cec5SDimitry Andric //===- DomTreeUpdater.cpp - DomTree/Post DomTree Updater --------*- C++ -*-===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric //
90b57cec5SDimitry Andric // This file implements the DomTreeUpdater class, which provides a uniform way
100b57cec5SDimitry Andric // to update dominator tree related data structures.
110b57cec5SDimitry Andric //
120b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
130b57cec5SDimitry Andric 
140b57cec5SDimitry Andric #include "llvm/Analysis/DomTreeUpdater.h"
150b57cec5SDimitry Andric #include "llvm/ADT/SmallSet.h"
16*0fca6ea1SDimitry Andric #include "llvm/Analysis/GenericDomTreeUpdaterImpl.h"
170b57cec5SDimitry Andric #include "llvm/Analysis/PostDominators.h"
1881ad6265SDimitry Andric #include "llvm/IR/Constants.h"
195ffd83dbSDimitry Andric #include "llvm/IR/Instructions.h"
200b57cec5SDimitry Andric #include "llvm/Support/GenericDomTree.h"
210b57cec5SDimitry Andric #include <algorithm>
220b57cec5SDimitry Andric #include <functional>
230b57cec5SDimitry Andric #include <utility>
240b57cec5SDimitry Andric 
250b57cec5SDimitry Andric namespace llvm {
260b57cec5SDimitry Andric 
27*0fca6ea1SDimitry Andric template class GenericDomTreeUpdater<DomTreeUpdater, DominatorTree,
28*0fca6ea1SDimitry Andric                                      PostDominatorTree>;
290b57cec5SDimitry Andric 
30*0fca6ea1SDimitry Andric template void
31*0fca6ea1SDimitry Andric GenericDomTreeUpdater<DomTreeUpdater, DominatorTree,
32*0fca6ea1SDimitry Andric                       PostDominatorTree>::recalculate(Function &F);
330b57cec5SDimitry Andric 
340b57cec5SDimitry Andric bool DomTreeUpdater::forceFlushDeletedBB() {
350b57cec5SDimitry Andric   if (DeletedBBs.empty())
360b57cec5SDimitry Andric     return false;
370b57cec5SDimitry Andric 
380b57cec5SDimitry Andric   for (auto *BB : DeletedBBs) {
390b57cec5SDimitry Andric     // After calling deleteBB or callbackDeleteBB under Lazy UpdateStrategy,
400b57cec5SDimitry Andric     // validateDeleteBB() removes all instructions of DelBB and adds an
410b57cec5SDimitry Andric     // UnreachableInst as its terminator. So we check whether the BasicBlock to
420b57cec5SDimitry Andric     // delete only has an UnreachableInst inside.
43bdd1243dSDimitry Andric     assert(BB->size() == 1 && isa<UnreachableInst>(BB->getTerminator()) &&
440b57cec5SDimitry Andric            "DelBB has been modified while awaiting deletion.");
450b57cec5SDimitry Andric     BB->removeFromParent();
460b57cec5SDimitry Andric     eraseDelBBNode(BB);
470b57cec5SDimitry Andric     delete BB;
480b57cec5SDimitry Andric   }
490b57cec5SDimitry Andric   DeletedBBs.clear();
500b57cec5SDimitry Andric   Callbacks.clear();
510b57cec5SDimitry Andric   return true;
520b57cec5SDimitry Andric }
530b57cec5SDimitry Andric 
540b57cec5SDimitry Andric // The DT and PDT require the nodes related to updates
550b57cec5SDimitry Andric // are not deleted when update functions are called.
560b57cec5SDimitry Andric // So BasicBlock deletions must be pended when the
570b57cec5SDimitry Andric // UpdateStrategy is Lazy. When the UpdateStrategy is
580b57cec5SDimitry Andric // Eager, the BasicBlock will be deleted immediately.
590b57cec5SDimitry Andric void DomTreeUpdater::deleteBB(BasicBlock *DelBB) {
600b57cec5SDimitry Andric   validateDeleteBB(DelBB);
610b57cec5SDimitry Andric   if (Strategy == UpdateStrategy::Lazy) {
620b57cec5SDimitry Andric     DeletedBBs.insert(DelBB);
630b57cec5SDimitry Andric     return;
640b57cec5SDimitry Andric   }
650b57cec5SDimitry Andric 
660b57cec5SDimitry Andric   DelBB->removeFromParent();
670b57cec5SDimitry Andric   eraseDelBBNode(DelBB);
680b57cec5SDimitry Andric   delete DelBB;
690b57cec5SDimitry Andric }
700b57cec5SDimitry Andric 
710b57cec5SDimitry Andric void DomTreeUpdater::callbackDeleteBB(
720b57cec5SDimitry Andric     BasicBlock *DelBB, std::function<void(BasicBlock *)> Callback) {
730b57cec5SDimitry Andric   validateDeleteBB(DelBB);
740b57cec5SDimitry Andric   if (Strategy == UpdateStrategy::Lazy) {
750b57cec5SDimitry Andric     Callbacks.push_back(CallBackOnDeletion(DelBB, Callback));
760b57cec5SDimitry Andric     DeletedBBs.insert(DelBB);
770b57cec5SDimitry Andric     return;
780b57cec5SDimitry Andric   }
790b57cec5SDimitry Andric 
800b57cec5SDimitry Andric   DelBB->removeFromParent();
810b57cec5SDimitry Andric   eraseDelBBNode(DelBB);
820b57cec5SDimitry Andric   Callback(DelBB);
830b57cec5SDimitry Andric   delete DelBB;
840b57cec5SDimitry Andric }
850b57cec5SDimitry Andric 
860b57cec5SDimitry Andric void DomTreeUpdater::validateDeleteBB(BasicBlock *DelBB) {
870b57cec5SDimitry Andric   assert(DelBB && "Invalid push_back of nullptr DelBB.");
880b57cec5SDimitry Andric   assert(pred_empty(DelBB) && "DelBB has one or more predecessors.");
890b57cec5SDimitry Andric   // DelBB is unreachable and all its instructions are dead.
900b57cec5SDimitry Andric   while (!DelBB->empty()) {
910b57cec5SDimitry Andric     Instruction &I = DelBB->back();
92bdd1243dSDimitry Andric     // Replace used instructions with an arbitrary value (poison).
930b57cec5SDimitry Andric     if (!I.use_empty())
94bdd1243dSDimitry Andric       I.replaceAllUsesWith(PoisonValue::get(I.getType()));
95bdd1243dSDimitry Andric     DelBB->back().eraseFromParent();
960b57cec5SDimitry Andric   }
970b57cec5SDimitry Andric   // Make sure DelBB has a valid terminator instruction. As long as DelBB is a
980b57cec5SDimitry Andric   // Child of Function F it must contain valid IR.
990b57cec5SDimitry Andric   new UnreachableInst(DelBB->getContext(), DelBB);
1000b57cec5SDimitry Andric }
1010b57cec5SDimitry Andric 
102*0fca6ea1SDimitry Andric LLVM_DUMP_METHOD
103*0fca6ea1SDimitry Andric void DomTreeUpdater::dump() const {
104*0fca6ea1SDimitry Andric   Base::dump();
1050b57cec5SDimitry Andric #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
106*0fca6ea1SDimitry Andric   raw_ostream &OS = dbgs();
1070b57cec5SDimitry Andric   OS << "Pending Callbacks:\n";
108*0fca6ea1SDimitry Andric   int Index = 0;
1095ffd83dbSDimitry Andric   for (const auto &BB : Callbacks) {
1100b57cec5SDimitry Andric     OS << "  " << Index << " : ";
1110b57cec5SDimitry Andric     ++Index;
1120b57cec5SDimitry Andric     if (BB->hasName())
1130b57cec5SDimitry Andric       OS << BB->getName() << "(";
1140b57cec5SDimitry Andric     else
1150b57cec5SDimitry Andric       OS << "(no_name)(";
1160b57cec5SDimitry Andric     OS << BB << ")\n";
1170b57cec5SDimitry Andric   }
1180b57cec5SDimitry Andric #endif
119*0fca6ea1SDimitry Andric }
120*0fca6ea1SDimitry Andric 
1210b57cec5SDimitry Andric } // namespace llvm
122