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