15f436fc5SRichard Trieu //===- DomTreeUpdater.cpp - DomTree/Post DomTree Updater --------*- C++ -*-===// 25f436fc5SRichard Trieu // 35f436fc5SRichard Trieu // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 45f436fc5SRichard Trieu // See https://llvm.org/LICENSE.txt for license information. 55f436fc5SRichard Trieu // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 65f436fc5SRichard Trieu // 75f436fc5SRichard Trieu //===----------------------------------------------------------------------===// 85f436fc5SRichard Trieu // 95f436fc5SRichard Trieu // This file implements the DomTreeUpdater class, which provides a uniform way 105f436fc5SRichard Trieu // to update dominator tree related data structures. 115f436fc5SRichard Trieu // 125f436fc5SRichard Trieu //===----------------------------------------------------------------------===// 135f436fc5SRichard Trieu 145f436fc5SRichard Trieu #include "llvm/Analysis/DomTreeUpdater.h" 1570e97163SChijun Sima #include "llvm/ADT/SmallSet.h" 165f436fc5SRichard Trieu #include "llvm/Analysis/PostDominators.h" 17f6cb987dSSimon Pilgrim #include "llvm/IR/Instructions.h" 185f436fc5SRichard Trieu #include "llvm/Support/GenericDomTree.h" 195f436fc5SRichard Trieu #include <algorithm> 205f436fc5SRichard Trieu #include <functional> 2170e97163SChijun Sima #include <utility> 225f436fc5SRichard Trieu 235f436fc5SRichard Trieu namespace llvm { 245f436fc5SRichard Trieu 255f436fc5SRichard Trieu bool DomTreeUpdater::isUpdateValid( 265f436fc5SRichard Trieu const DominatorTree::UpdateType Update) const { 275f436fc5SRichard Trieu const auto *From = Update.getFrom(); 285f436fc5SRichard Trieu const auto *To = Update.getTo(); 295f436fc5SRichard Trieu const auto Kind = Update.getKind(); 305f436fc5SRichard Trieu 315f436fc5SRichard Trieu // Discard updates by inspecting the current state of successors of From. 325f436fc5SRichard Trieu // Since isUpdateValid() must be called *after* the Terminator of From is 335f436fc5SRichard Trieu // altered we can determine if the update is unnecessary for batch updates 345f436fc5SRichard Trieu // or invalid for a single update. 355f436fc5SRichard Trieu const bool HasEdge = llvm::any_of( 365f436fc5SRichard Trieu successors(From), [To](const BasicBlock *B) { return B == To; }); 375f436fc5SRichard Trieu 385f436fc5SRichard Trieu // If the IR does not match the update, 395f436fc5SRichard Trieu // 1. In batch updates, this update is unnecessary. 405f436fc5SRichard Trieu // 2. When called by insertEdge*()/deleteEdge*(), this update is invalid. 415f436fc5SRichard Trieu // Edge does not exist in IR. 425f436fc5SRichard Trieu if (Kind == DominatorTree::Insert && !HasEdge) 435f436fc5SRichard Trieu return false; 445f436fc5SRichard Trieu 455f436fc5SRichard Trieu // Edge exists in IR. 465f436fc5SRichard Trieu if (Kind == DominatorTree::Delete && HasEdge) 475f436fc5SRichard Trieu return false; 485f436fc5SRichard Trieu 495f436fc5SRichard Trieu return true; 505f436fc5SRichard Trieu } 515f436fc5SRichard Trieu 525f436fc5SRichard Trieu bool DomTreeUpdater::isSelfDominance( 535f436fc5SRichard Trieu const DominatorTree::UpdateType Update) const { 545f436fc5SRichard Trieu // Won't affect DomTree and PostDomTree. 555f436fc5SRichard Trieu return Update.getFrom() == Update.getTo(); 565f436fc5SRichard Trieu } 575f436fc5SRichard Trieu 585f436fc5SRichard Trieu void DomTreeUpdater::applyDomTreeUpdates() { 595f436fc5SRichard Trieu // No pending DomTreeUpdates. 605f436fc5SRichard Trieu if (Strategy != UpdateStrategy::Lazy || !DT) 615f436fc5SRichard Trieu return; 625f436fc5SRichard Trieu 635f436fc5SRichard Trieu // Only apply updates not are applied by DomTree. 645f436fc5SRichard Trieu if (hasPendingDomTreeUpdates()) { 655f436fc5SRichard Trieu const auto I = PendUpdates.begin() + PendDTUpdateIndex; 665f436fc5SRichard Trieu const auto E = PendUpdates.end(); 675f436fc5SRichard Trieu assert(I < E && "Iterator range invalid; there should be DomTree updates."); 685f436fc5SRichard Trieu DT->applyUpdates(ArrayRef<DominatorTree::UpdateType>(I, E)); 695f436fc5SRichard Trieu PendDTUpdateIndex = PendUpdates.size(); 705f436fc5SRichard Trieu } 715f436fc5SRichard Trieu } 725f436fc5SRichard Trieu 735f436fc5SRichard Trieu void DomTreeUpdater::flush() { 745f436fc5SRichard Trieu applyDomTreeUpdates(); 755f436fc5SRichard Trieu applyPostDomTreeUpdates(); 765f436fc5SRichard Trieu dropOutOfDateUpdates(); 775f436fc5SRichard Trieu } 785f436fc5SRichard Trieu 795f436fc5SRichard Trieu void DomTreeUpdater::applyPostDomTreeUpdates() { 805f436fc5SRichard Trieu // No pending PostDomTreeUpdates. 815f436fc5SRichard Trieu if (Strategy != UpdateStrategy::Lazy || !PDT) 825f436fc5SRichard Trieu return; 835f436fc5SRichard Trieu 845f436fc5SRichard Trieu // Only apply updates not are applied by PostDomTree. 855f436fc5SRichard Trieu if (hasPendingPostDomTreeUpdates()) { 865f436fc5SRichard Trieu const auto I = PendUpdates.begin() + PendPDTUpdateIndex; 875f436fc5SRichard Trieu const auto E = PendUpdates.end(); 885f436fc5SRichard Trieu assert(I < E && 895f436fc5SRichard Trieu "Iterator range invalid; there should be PostDomTree updates."); 905f436fc5SRichard Trieu PDT->applyUpdates(ArrayRef<DominatorTree::UpdateType>(I, E)); 915f436fc5SRichard Trieu PendPDTUpdateIndex = PendUpdates.size(); 925f436fc5SRichard Trieu } 935f436fc5SRichard Trieu } 945f436fc5SRichard Trieu 955f436fc5SRichard Trieu void DomTreeUpdater::tryFlushDeletedBB() { 965f436fc5SRichard Trieu if (!hasPendingUpdates()) 975f436fc5SRichard Trieu forceFlushDeletedBB(); 985f436fc5SRichard Trieu } 995f436fc5SRichard Trieu 1005f436fc5SRichard Trieu bool DomTreeUpdater::forceFlushDeletedBB() { 1015f436fc5SRichard Trieu if (DeletedBBs.empty()) 1025f436fc5SRichard Trieu return false; 1035f436fc5SRichard Trieu 1045f436fc5SRichard Trieu for (auto *BB : DeletedBBs) { 1055f436fc5SRichard Trieu // After calling deleteBB or callbackDeleteBB under Lazy UpdateStrategy, 1065f436fc5SRichard Trieu // validateDeleteBB() removes all instructions of DelBB and adds an 1075f436fc5SRichard Trieu // UnreachableInst as its terminator. So we check whether the BasicBlock to 1085f436fc5SRichard Trieu // delete only has an UnreachableInst inside. 1095f436fc5SRichard Trieu assert(BB->getInstList().size() == 1 && 1105f436fc5SRichard Trieu isa<UnreachableInst>(BB->getTerminator()) && 1115f436fc5SRichard Trieu "DelBB has been modified while awaiting deletion."); 1125f436fc5SRichard Trieu BB->removeFromParent(); 1135f436fc5SRichard Trieu eraseDelBBNode(BB); 1145f436fc5SRichard Trieu delete BB; 1155f436fc5SRichard Trieu } 1165f436fc5SRichard Trieu DeletedBBs.clear(); 1175f436fc5SRichard Trieu Callbacks.clear(); 1185f436fc5SRichard Trieu return true; 1195f436fc5SRichard Trieu } 1205f436fc5SRichard Trieu 1215f436fc5SRichard Trieu void DomTreeUpdater::recalculate(Function &F) { 1225f436fc5SRichard Trieu 1235f436fc5SRichard Trieu if (Strategy == UpdateStrategy::Eager) { 1245f436fc5SRichard Trieu if (DT) 1255f436fc5SRichard Trieu DT->recalculate(F); 1265f436fc5SRichard Trieu if (PDT) 1275f436fc5SRichard Trieu PDT->recalculate(F); 1285f436fc5SRichard Trieu return; 1295f436fc5SRichard Trieu } 1305f436fc5SRichard Trieu 1315f436fc5SRichard Trieu // There is little performance gain if we pend the recalculation under 1325f436fc5SRichard Trieu // Lazy UpdateStrategy so we recalculate available trees immediately. 1335f436fc5SRichard Trieu 1345f436fc5SRichard Trieu // Prevent forceFlushDeletedBB() from erasing DomTree or PostDomTree nodes. 1355f436fc5SRichard Trieu IsRecalculatingDomTree = IsRecalculatingPostDomTree = true; 1365f436fc5SRichard Trieu 1375f436fc5SRichard Trieu // Because all trees are going to be up-to-date after recalculation, 1385f436fc5SRichard Trieu // flush awaiting deleted BasicBlocks. 1395f436fc5SRichard Trieu forceFlushDeletedBB(); 1405f436fc5SRichard Trieu if (DT) 1415f436fc5SRichard Trieu DT->recalculate(F); 1425f436fc5SRichard Trieu if (PDT) 1435f436fc5SRichard Trieu PDT->recalculate(F); 1445f436fc5SRichard Trieu 1455f436fc5SRichard Trieu // Resume forceFlushDeletedBB() to erase DomTree or PostDomTree nodes. 1465f436fc5SRichard Trieu IsRecalculatingDomTree = IsRecalculatingPostDomTree = false; 1475f436fc5SRichard Trieu PendDTUpdateIndex = PendPDTUpdateIndex = PendUpdates.size(); 1485f436fc5SRichard Trieu dropOutOfDateUpdates(); 1495f436fc5SRichard Trieu } 1505f436fc5SRichard Trieu 1515f436fc5SRichard Trieu bool DomTreeUpdater::hasPendingUpdates() const { 1525f436fc5SRichard Trieu return hasPendingDomTreeUpdates() || hasPendingPostDomTreeUpdates(); 1535f436fc5SRichard Trieu } 1545f436fc5SRichard Trieu 1555f436fc5SRichard Trieu bool DomTreeUpdater::hasPendingDomTreeUpdates() const { 1565f436fc5SRichard Trieu if (!DT) 1575f436fc5SRichard Trieu return false; 1585f436fc5SRichard Trieu return PendUpdates.size() != PendDTUpdateIndex; 1595f436fc5SRichard Trieu } 1605f436fc5SRichard Trieu 1615f436fc5SRichard Trieu bool DomTreeUpdater::hasPendingPostDomTreeUpdates() const { 1625f436fc5SRichard Trieu if (!PDT) 1635f436fc5SRichard Trieu return false; 1645f436fc5SRichard Trieu return PendUpdates.size() != PendPDTUpdateIndex; 1655f436fc5SRichard Trieu } 1665f436fc5SRichard Trieu 1675f436fc5SRichard Trieu bool DomTreeUpdater::isBBPendingDeletion(llvm::BasicBlock *DelBB) const { 1685f436fc5SRichard Trieu if (Strategy == UpdateStrategy::Eager || DeletedBBs.empty()) 1695f436fc5SRichard Trieu return false; 1705f436fc5SRichard Trieu return DeletedBBs.count(DelBB) != 0; 1715f436fc5SRichard Trieu } 1725f436fc5SRichard Trieu 1735f436fc5SRichard Trieu // The DT and PDT require the nodes related to updates 1745f436fc5SRichard Trieu // are not deleted when update functions are called. 1755f436fc5SRichard Trieu // So BasicBlock deletions must be pended when the 1765f436fc5SRichard Trieu // UpdateStrategy is Lazy. When the UpdateStrategy is 1775f436fc5SRichard Trieu // Eager, the BasicBlock will be deleted immediately. 1785f436fc5SRichard Trieu void DomTreeUpdater::deleteBB(BasicBlock *DelBB) { 1795f436fc5SRichard Trieu validateDeleteBB(DelBB); 1805f436fc5SRichard Trieu if (Strategy == UpdateStrategy::Lazy) { 1815f436fc5SRichard Trieu DeletedBBs.insert(DelBB); 1825f436fc5SRichard Trieu return; 1835f436fc5SRichard Trieu } 1845f436fc5SRichard Trieu 1855f436fc5SRichard Trieu DelBB->removeFromParent(); 1865f436fc5SRichard Trieu eraseDelBBNode(DelBB); 1875f436fc5SRichard Trieu delete DelBB; 1885f436fc5SRichard Trieu } 1895f436fc5SRichard Trieu 1905f436fc5SRichard Trieu void DomTreeUpdater::callbackDeleteBB( 1915f436fc5SRichard Trieu BasicBlock *DelBB, std::function<void(BasicBlock *)> Callback) { 1925f436fc5SRichard Trieu validateDeleteBB(DelBB); 1935f436fc5SRichard Trieu if (Strategy == UpdateStrategy::Lazy) { 1945f436fc5SRichard Trieu Callbacks.push_back(CallBackOnDeletion(DelBB, Callback)); 1955f436fc5SRichard Trieu DeletedBBs.insert(DelBB); 1965f436fc5SRichard Trieu return; 1975f436fc5SRichard Trieu } 1985f436fc5SRichard Trieu 1995f436fc5SRichard Trieu DelBB->removeFromParent(); 2005f436fc5SRichard Trieu eraseDelBBNode(DelBB); 2015f436fc5SRichard Trieu Callback(DelBB); 2025f436fc5SRichard Trieu delete DelBB; 2035f436fc5SRichard Trieu } 2045f436fc5SRichard Trieu 2055f436fc5SRichard Trieu void DomTreeUpdater::eraseDelBBNode(BasicBlock *DelBB) { 2065f436fc5SRichard Trieu if (DT && !IsRecalculatingDomTree) 2075f436fc5SRichard Trieu if (DT->getNode(DelBB)) 2085f436fc5SRichard Trieu DT->eraseNode(DelBB); 2095f436fc5SRichard Trieu 2105f436fc5SRichard Trieu if (PDT && !IsRecalculatingPostDomTree) 2115f436fc5SRichard Trieu if (PDT->getNode(DelBB)) 2125f436fc5SRichard Trieu PDT->eraseNode(DelBB); 2135f436fc5SRichard Trieu } 2145f436fc5SRichard Trieu 2155f436fc5SRichard Trieu void DomTreeUpdater::validateDeleteBB(BasicBlock *DelBB) { 2165f436fc5SRichard Trieu assert(DelBB && "Invalid push_back of nullptr DelBB."); 2175f436fc5SRichard Trieu assert(pred_empty(DelBB) && "DelBB has one or more predecessors."); 2185f436fc5SRichard Trieu // DelBB is unreachable and all its instructions are dead. 2195f436fc5SRichard Trieu while (!DelBB->empty()) { 2205f436fc5SRichard Trieu Instruction &I = DelBB->back(); 2215f436fc5SRichard Trieu // Replace used instructions with an arbitrary value (undef). 2225f436fc5SRichard Trieu if (!I.use_empty()) 2235f436fc5SRichard Trieu I.replaceAllUsesWith(llvm::UndefValue::get(I.getType())); 2245f436fc5SRichard Trieu DelBB->getInstList().pop_back(); 2255f436fc5SRichard Trieu } 2265f436fc5SRichard Trieu // Make sure DelBB has a valid terminator instruction. As long as DelBB is a 2275f436fc5SRichard Trieu // Child of Function F it must contain valid IR. 2285f436fc5SRichard Trieu new UnreachableInst(DelBB->getContext(), DelBB); 2295f436fc5SRichard Trieu } 2305f436fc5SRichard Trieu 23170e97163SChijun Sima void DomTreeUpdater::applyUpdates(ArrayRef<DominatorTree::UpdateType> Updates) { 2325f436fc5SRichard Trieu if (!DT && !PDT) 2335f436fc5SRichard Trieu return; 2345f436fc5SRichard Trieu 23570e97163SChijun Sima if (Strategy == UpdateStrategy::Lazy) { 2368dc7b982SMark de Wever for (const auto &U : Updates) 23770e97163SChijun Sima if (!isSelfDominance(U)) 23870e97163SChijun Sima PendUpdates.push_back(U); 2395f436fc5SRichard Trieu 2405f436fc5SRichard Trieu return; 2415f436fc5SRichard Trieu } 2425f436fc5SRichard Trieu 2435f436fc5SRichard Trieu if (DT) 2445f436fc5SRichard Trieu DT->applyUpdates(Updates); 2455f436fc5SRichard Trieu if (PDT) 2465f436fc5SRichard Trieu PDT->applyUpdates(Updates); 2475f436fc5SRichard Trieu } 2485f436fc5SRichard Trieu 24970e97163SChijun Sima void DomTreeUpdater::applyUpdatesPermissive( 25070e97163SChijun Sima ArrayRef<DominatorTree::UpdateType> Updates) { 25170e97163SChijun Sima if (!DT && !PDT) 25270e97163SChijun Sima return; 25370e97163SChijun Sima 25470e97163SChijun Sima SmallSet<std::pair<BasicBlock *, BasicBlock *>, 8> Seen; 25570e97163SChijun Sima SmallVector<DominatorTree::UpdateType, 8> DeduplicatedUpdates; 2568dc7b982SMark de Wever for (const auto &U : Updates) { 25770e97163SChijun Sima auto Edge = std::make_pair(U.getFrom(), U.getTo()); 25870e97163SChijun Sima // Because it is illegal to submit updates that have already been applied 25970e97163SChijun Sima // and updates to an edge need to be strictly ordered, 26070e97163SChijun Sima // it is safe to infer the existence of an edge from the first update 26170e97163SChijun Sima // to this edge. 26270e97163SChijun Sima // If the first update to an edge is "Delete", it means that the edge 26370e97163SChijun Sima // existed before. If the first update to an edge is "Insert", it means 26470e97163SChijun Sima // that the edge didn't exist before. 26570e97163SChijun Sima // 26670e97163SChijun Sima // For example, if the user submits {{Delete, A, B}, {Insert, A, B}}, 26770e97163SChijun Sima // because 26870e97163SChijun Sima // 1. it is illegal to submit updates that have already been applied, 26970e97163SChijun Sima // i.e., user cannot delete an nonexistent edge, 27070e97163SChijun Sima // 2. updates to an edge need to be strictly ordered, 27170e97163SChijun Sima // So, initially edge A -> B existed. 27270e97163SChijun Sima // We can then safely ignore future updates to this edge and directly 27370e97163SChijun Sima // inspect the current CFG: 27470e97163SChijun Sima // a. If the edge still exists, because the user cannot insert an existent 27570e97163SChijun Sima // edge, so both {Delete, A, B}, {Insert, A, B} actually happened and 27670e97163SChijun Sima // resulted in a no-op. DTU won't submit any update in this case. 27770e97163SChijun Sima // b. If the edge doesn't exist, we can then infer that {Delete, A, B} 27870e97163SChijun Sima // actually happened but {Insert, A, B} was an invalid update which never 27970e97163SChijun Sima // happened. DTU will submit {Delete, A, B} in this case. 28070e97163SChijun Sima if (!isSelfDominance(U) && Seen.count(Edge) == 0) { 28170e97163SChijun Sima Seen.insert(Edge); 28270e97163SChijun Sima // If the update doesn't appear in the CFG, it means that 28370e97163SChijun Sima // either the change isn't made or relevant operations 28470e97163SChijun Sima // result in a no-op. 28570e97163SChijun Sima if (isUpdateValid(U)) { 28670e97163SChijun Sima if (isLazy()) 28770e97163SChijun Sima PendUpdates.push_back(U); 28870e97163SChijun Sima else 28970e97163SChijun Sima DeduplicatedUpdates.push_back(U); 29070e97163SChijun Sima } 29170e97163SChijun Sima } 29270e97163SChijun Sima } 29370e97163SChijun Sima 29470e97163SChijun Sima if (Strategy == UpdateStrategy::Lazy) 29570e97163SChijun Sima return; 29670e97163SChijun Sima 29770e97163SChijun Sima if (DT) 29870e97163SChijun Sima DT->applyUpdates(DeduplicatedUpdates); 29970e97163SChijun Sima if (PDT) 30070e97163SChijun Sima PDT->applyUpdates(DeduplicatedUpdates); 30170e97163SChijun Sima } 30270e97163SChijun Sima 3035f436fc5SRichard Trieu DominatorTree &DomTreeUpdater::getDomTree() { 3045f436fc5SRichard Trieu assert(DT && "Invalid acquisition of a null DomTree"); 3055f436fc5SRichard Trieu applyDomTreeUpdates(); 3065f436fc5SRichard Trieu dropOutOfDateUpdates(); 3075f436fc5SRichard Trieu return *DT; 3085f436fc5SRichard Trieu } 3095f436fc5SRichard Trieu 3105f436fc5SRichard Trieu PostDominatorTree &DomTreeUpdater::getPostDomTree() { 3115f436fc5SRichard Trieu assert(PDT && "Invalid acquisition of a null PostDomTree"); 3125f436fc5SRichard Trieu applyPostDomTreeUpdates(); 3135f436fc5SRichard Trieu dropOutOfDateUpdates(); 3145f436fc5SRichard Trieu return *PDT; 3155f436fc5SRichard Trieu } 3165f436fc5SRichard Trieu 3175f436fc5SRichard Trieu void DomTreeUpdater::insertEdge(BasicBlock *From, BasicBlock *To) { 3185f436fc5SRichard Trieu 3195f436fc5SRichard Trieu #ifndef NDEBUG 3205f436fc5SRichard Trieu assert(isUpdateValid({DominatorTree::Insert, From, To}) && 3215f436fc5SRichard Trieu "Inserted edge does not appear in the CFG"); 3225f436fc5SRichard Trieu #endif 3235f436fc5SRichard Trieu 3245f436fc5SRichard Trieu if (!DT && !PDT) 3255f436fc5SRichard Trieu return; 3265f436fc5SRichard Trieu 3275f436fc5SRichard Trieu // Won't affect DomTree and PostDomTree; discard update. 3285f436fc5SRichard Trieu if (From == To) 3295f436fc5SRichard Trieu return; 3305f436fc5SRichard Trieu 3315f436fc5SRichard Trieu if (Strategy == UpdateStrategy::Eager) { 3325f436fc5SRichard Trieu if (DT) 3335f436fc5SRichard Trieu DT->insertEdge(From, To); 3345f436fc5SRichard Trieu if (PDT) 3355f436fc5SRichard Trieu PDT->insertEdge(From, To); 3365f436fc5SRichard Trieu return; 3375f436fc5SRichard Trieu } 3385f436fc5SRichard Trieu 33970e97163SChijun Sima PendUpdates.push_back({DominatorTree::Insert, From, To}); 3405f436fc5SRichard Trieu } 3415f436fc5SRichard Trieu 3425f436fc5SRichard Trieu void DomTreeUpdater::insertEdgeRelaxed(BasicBlock *From, BasicBlock *To) { 3435f436fc5SRichard Trieu if (From == To) 3445f436fc5SRichard Trieu return; 3455f436fc5SRichard Trieu 3465f436fc5SRichard Trieu if (!DT && !PDT) 3475f436fc5SRichard Trieu return; 3485f436fc5SRichard Trieu 3495f436fc5SRichard Trieu if (!isUpdateValid({DominatorTree::Insert, From, To})) 3505f436fc5SRichard Trieu return; 3515f436fc5SRichard Trieu 3525f436fc5SRichard Trieu if (Strategy == UpdateStrategy::Eager) { 3535f436fc5SRichard Trieu if (DT) 3545f436fc5SRichard Trieu DT->insertEdge(From, To); 3555f436fc5SRichard Trieu if (PDT) 3565f436fc5SRichard Trieu PDT->insertEdge(From, To); 3575f436fc5SRichard Trieu return; 3585f436fc5SRichard Trieu } 3595f436fc5SRichard Trieu 36070e97163SChijun Sima PendUpdates.push_back({DominatorTree::Insert, From, To}); 3615f436fc5SRichard Trieu } 3625f436fc5SRichard Trieu 3635f436fc5SRichard Trieu void DomTreeUpdater::deleteEdge(BasicBlock *From, BasicBlock *To) { 3645f436fc5SRichard Trieu 3655f436fc5SRichard Trieu #ifndef NDEBUG 3665f436fc5SRichard Trieu assert(isUpdateValid({DominatorTree::Delete, From, To}) && 3675f436fc5SRichard Trieu "Deleted edge still exists in the CFG!"); 3685f436fc5SRichard Trieu #endif 3695f436fc5SRichard Trieu 3705f436fc5SRichard Trieu if (!DT && !PDT) 3715f436fc5SRichard Trieu return; 3725f436fc5SRichard Trieu 3735f436fc5SRichard Trieu // Won't affect DomTree and PostDomTree; discard update. 3745f436fc5SRichard Trieu if (From == To) 3755f436fc5SRichard Trieu return; 3765f436fc5SRichard Trieu 3775f436fc5SRichard Trieu if (Strategy == UpdateStrategy::Eager) { 3785f436fc5SRichard Trieu if (DT) 3795f436fc5SRichard Trieu DT->deleteEdge(From, To); 3805f436fc5SRichard Trieu if (PDT) 3815f436fc5SRichard Trieu PDT->deleteEdge(From, To); 3825f436fc5SRichard Trieu return; 3835f436fc5SRichard Trieu } 3845f436fc5SRichard Trieu 38570e97163SChijun Sima PendUpdates.push_back({DominatorTree::Delete, From, To}); 3865f436fc5SRichard Trieu } 3875f436fc5SRichard Trieu 3885f436fc5SRichard Trieu void DomTreeUpdater::deleteEdgeRelaxed(BasicBlock *From, BasicBlock *To) { 3895f436fc5SRichard Trieu if (From == To) 3905f436fc5SRichard Trieu return; 3915f436fc5SRichard Trieu 3925f436fc5SRichard Trieu if (!DT && !PDT) 3935f436fc5SRichard Trieu return; 3945f436fc5SRichard Trieu 3955f436fc5SRichard Trieu if (!isUpdateValid({DominatorTree::Delete, From, To})) 3965f436fc5SRichard Trieu return; 3975f436fc5SRichard Trieu 3985f436fc5SRichard Trieu if (Strategy == UpdateStrategy::Eager) { 3995f436fc5SRichard Trieu if (DT) 4005f436fc5SRichard Trieu DT->deleteEdge(From, To); 4015f436fc5SRichard Trieu if (PDT) 4025f436fc5SRichard Trieu PDT->deleteEdge(From, To); 4035f436fc5SRichard Trieu return; 4045f436fc5SRichard Trieu } 4055f436fc5SRichard Trieu 40670e97163SChijun Sima PendUpdates.push_back({DominatorTree::Delete, From, To}); 4075f436fc5SRichard Trieu } 4085f436fc5SRichard Trieu 4095f436fc5SRichard Trieu void DomTreeUpdater::dropOutOfDateUpdates() { 4105f436fc5SRichard Trieu if (Strategy == DomTreeUpdater::UpdateStrategy::Eager) 4115f436fc5SRichard Trieu return; 4125f436fc5SRichard Trieu 4135f436fc5SRichard Trieu tryFlushDeletedBB(); 4145f436fc5SRichard Trieu 4155f436fc5SRichard Trieu // Drop all updates applied by both trees. 4165f436fc5SRichard Trieu if (!DT) 4175f436fc5SRichard Trieu PendDTUpdateIndex = PendUpdates.size(); 4185f436fc5SRichard Trieu if (!PDT) 4195f436fc5SRichard Trieu PendPDTUpdateIndex = PendUpdates.size(); 4205f436fc5SRichard Trieu 4215f436fc5SRichard Trieu const size_t dropIndex = std::min(PendDTUpdateIndex, PendPDTUpdateIndex); 4225f436fc5SRichard Trieu const auto B = PendUpdates.begin(); 4235f436fc5SRichard Trieu const auto E = PendUpdates.begin() + dropIndex; 4245f436fc5SRichard Trieu assert(B <= E && "Iterator out of range."); 4255f436fc5SRichard Trieu PendUpdates.erase(B, E); 4265f436fc5SRichard Trieu // Calculate current index. 4275f436fc5SRichard Trieu PendDTUpdateIndex -= dropIndex; 4285f436fc5SRichard Trieu PendPDTUpdateIndex -= dropIndex; 4295f436fc5SRichard Trieu } 4305f436fc5SRichard Trieu 4315f436fc5SRichard Trieu #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) 4325f436fc5SRichard Trieu LLVM_DUMP_METHOD void DomTreeUpdater::dump() const { 4335f436fc5SRichard Trieu raw_ostream &OS = llvm::dbgs(); 4345f436fc5SRichard Trieu 4355f436fc5SRichard Trieu OS << "Available Trees: "; 4365f436fc5SRichard Trieu if (DT || PDT) { 4375f436fc5SRichard Trieu if (DT) 4385f436fc5SRichard Trieu OS << "DomTree "; 4395f436fc5SRichard Trieu if (PDT) 4405f436fc5SRichard Trieu OS << "PostDomTree "; 4415f436fc5SRichard Trieu OS << "\n"; 4425f436fc5SRichard Trieu } else 4435f436fc5SRichard Trieu OS << "None\n"; 4445f436fc5SRichard Trieu 4455f436fc5SRichard Trieu OS << "UpdateStrategy: "; 4465f436fc5SRichard Trieu if (Strategy == UpdateStrategy::Eager) { 4475f436fc5SRichard Trieu OS << "Eager\n"; 4485f436fc5SRichard Trieu return; 4495f436fc5SRichard Trieu } else 4505f436fc5SRichard Trieu OS << "Lazy\n"; 4515f436fc5SRichard Trieu int Index = 0; 4525f436fc5SRichard Trieu 4535f436fc5SRichard Trieu auto printUpdates = 4545f436fc5SRichard Trieu [&](ArrayRef<DominatorTree::UpdateType>::const_iterator begin, 4555f436fc5SRichard Trieu ArrayRef<DominatorTree::UpdateType>::const_iterator end) { 4565f436fc5SRichard Trieu if (begin == end) 4575f436fc5SRichard Trieu OS << " None\n"; 4585f436fc5SRichard Trieu Index = 0; 4595f436fc5SRichard Trieu for (auto It = begin, ItEnd = end; It != ItEnd; ++It) { 4605f436fc5SRichard Trieu auto U = *It; 4615f436fc5SRichard Trieu OS << " " << Index << " : "; 4625f436fc5SRichard Trieu ++Index; 4635f436fc5SRichard Trieu if (U.getKind() == DominatorTree::Insert) 4645f436fc5SRichard Trieu OS << "Insert, "; 4655f436fc5SRichard Trieu else 4665f436fc5SRichard Trieu OS << "Delete, "; 4675f436fc5SRichard Trieu BasicBlock *From = U.getFrom(); 4685f436fc5SRichard Trieu if (From) { 4695f436fc5SRichard Trieu auto S = From->getName(); 4705f436fc5SRichard Trieu if (!From->hasName()) 4715f436fc5SRichard Trieu S = "(no name)"; 4725f436fc5SRichard Trieu OS << S << "(" << From << "), "; 4735f436fc5SRichard Trieu } else { 4745f436fc5SRichard Trieu OS << "(badref), "; 4755f436fc5SRichard Trieu } 4765f436fc5SRichard Trieu BasicBlock *To = U.getTo(); 4775f436fc5SRichard Trieu if (To) { 4785f436fc5SRichard Trieu auto S = To->getName(); 4795f436fc5SRichard Trieu if (!To->hasName()) 4805f436fc5SRichard Trieu S = "(no_name)"; 4815f436fc5SRichard Trieu OS << S << "(" << To << ")\n"; 4825f436fc5SRichard Trieu } else { 4835f436fc5SRichard Trieu OS << "(badref)\n"; 4845f436fc5SRichard Trieu } 4855f436fc5SRichard Trieu } 4865f436fc5SRichard Trieu }; 4875f436fc5SRichard Trieu 4885f436fc5SRichard Trieu if (DT) { 4895f436fc5SRichard Trieu const auto I = PendUpdates.begin() + PendDTUpdateIndex; 4905f436fc5SRichard Trieu assert(PendUpdates.begin() <= I && I <= PendUpdates.end() && 4915f436fc5SRichard Trieu "Iterator out of range."); 4925f436fc5SRichard Trieu OS << "Applied but not cleared DomTreeUpdates:\n"; 4935f436fc5SRichard Trieu printUpdates(PendUpdates.begin(), I); 4945f436fc5SRichard Trieu OS << "Pending DomTreeUpdates:\n"; 4955f436fc5SRichard Trieu printUpdates(I, PendUpdates.end()); 4965f436fc5SRichard Trieu } 4975f436fc5SRichard Trieu 4985f436fc5SRichard Trieu if (PDT) { 4995f436fc5SRichard Trieu const auto I = PendUpdates.begin() + PendPDTUpdateIndex; 5005f436fc5SRichard Trieu assert(PendUpdates.begin() <= I && I <= PendUpdates.end() && 5015f436fc5SRichard Trieu "Iterator out of range."); 5025f436fc5SRichard Trieu OS << "Applied but not cleared PostDomTreeUpdates:\n"; 5035f436fc5SRichard Trieu printUpdates(PendUpdates.begin(), I); 5045f436fc5SRichard Trieu OS << "Pending PostDomTreeUpdates:\n"; 5055f436fc5SRichard Trieu printUpdates(I, PendUpdates.end()); 5065f436fc5SRichard Trieu } 5075f436fc5SRichard Trieu 5085f436fc5SRichard Trieu OS << "Pending DeletedBBs:\n"; 5095f436fc5SRichard Trieu Index = 0; 510*ec00aa99SFlorian Hahn for (const auto *BB : DeletedBBs) { 5115f436fc5SRichard Trieu OS << " " << Index << " : "; 5125f436fc5SRichard Trieu ++Index; 5135f436fc5SRichard Trieu if (BB->hasName()) 5145f436fc5SRichard Trieu OS << BB->getName() << "("; 5155f436fc5SRichard Trieu else 5165f436fc5SRichard Trieu OS << "(no_name)("; 5175f436fc5SRichard Trieu OS << BB << ")\n"; 5185f436fc5SRichard Trieu } 5195f436fc5SRichard Trieu 5205f436fc5SRichard Trieu OS << "Pending Callbacks:\n"; 5215f436fc5SRichard Trieu Index = 0; 522b69e0f67SSimon Pilgrim for (const auto &BB : Callbacks) { 5235f436fc5SRichard Trieu OS << " " << Index << " : "; 5245f436fc5SRichard Trieu ++Index; 5255f436fc5SRichard Trieu if (BB->hasName()) 5265f436fc5SRichard Trieu OS << BB->getName() << "("; 5275f436fc5SRichard Trieu else 5285f436fc5SRichard Trieu OS << "(no_name)("; 5295f436fc5SRichard Trieu OS << BB << ")\n"; 5305f436fc5SRichard Trieu } 5315f436fc5SRichard Trieu } 5325f436fc5SRichard Trieu #endif 5335f436fc5SRichard Trieu } // namespace llvm 534