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"
17*a5bbc6efSBill Wendling #include "llvm/IR/Constants.h"
18f6cb987dSSimon Pilgrim #include "llvm/IR/Instructions.h"
195f436fc5SRichard Trieu #include "llvm/Support/GenericDomTree.h"
205f436fc5SRichard Trieu #include <algorithm>
215f436fc5SRichard Trieu #include <functional>
2270e97163SChijun Sima #include <utility>
235f436fc5SRichard Trieu 
245f436fc5SRichard Trieu namespace llvm {
255f436fc5SRichard Trieu 
isUpdateValid(const DominatorTree::UpdateType Update) const265f436fc5SRichard Trieu bool DomTreeUpdater::isUpdateValid(
275f436fc5SRichard Trieu     const DominatorTree::UpdateType Update) const {
285f436fc5SRichard Trieu   const auto *From = Update.getFrom();
295f436fc5SRichard Trieu   const auto *To = Update.getTo();
305f436fc5SRichard Trieu   const auto Kind = Update.getKind();
315f436fc5SRichard Trieu 
325f436fc5SRichard Trieu   // Discard updates by inspecting the current state of successors of From.
335f436fc5SRichard Trieu   // Since isUpdateValid() must be called *after* the Terminator of From is
345f436fc5SRichard Trieu   // altered we can determine if the update is unnecessary for batch updates
355f436fc5SRichard Trieu   // or invalid for a single update.
36226beb49SKazu Hirata   const bool HasEdge = llvm::is_contained(successors(From), 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 
isSelfDominance(const DominatorTree::UpdateType Update) const525f436fc5SRichard 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 
applyDomTreeUpdates()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 
flush()735f436fc5SRichard Trieu void DomTreeUpdater::flush() {
745f436fc5SRichard Trieu   applyDomTreeUpdates();
755f436fc5SRichard Trieu   applyPostDomTreeUpdates();
765f436fc5SRichard Trieu   dropOutOfDateUpdates();
775f436fc5SRichard Trieu }
785f436fc5SRichard Trieu 
applyPostDomTreeUpdates()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 
tryFlushDeletedBB()955f436fc5SRichard Trieu void DomTreeUpdater::tryFlushDeletedBB() {
965f436fc5SRichard Trieu   if (!hasPendingUpdates())
975f436fc5SRichard Trieu     forceFlushDeletedBB();
985f436fc5SRichard Trieu }
995f436fc5SRichard Trieu 
forceFlushDeletedBB()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 
recalculate(Function & F)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 
hasPendingUpdates() const1515f436fc5SRichard Trieu bool DomTreeUpdater::hasPendingUpdates() const {
1525f436fc5SRichard Trieu   return hasPendingDomTreeUpdates() || hasPendingPostDomTreeUpdates();
1535f436fc5SRichard Trieu }
1545f436fc5SRichard Trieu 
hasPendingDomTreeUpdates() const1555f436fc5SRichard Trieu bool DomTreeUpdater::hasPendingDomTreeUpdates() const {
1565f436fc5SRichard Trieu   if (!DT)
1575f436fc5SRichard Trieu     return false;
1585f436fc5SRichard Trieu   return PendUpdates.size() != PendDTUpdateIndex;
1595f436fc5SRichard Trieu }
1605f436fc5SRichard Trieu 
hasPendingPostDomTreeUpdates() const1615f436fc5SRichard Trieu bool DomTreeUpdater::hasPendingPostDomTreeUpdates() const {
1625f436fc5SRichard Trieu   if (!PDT)
1635f436fc5SRichard Trieu     return false;
1645f436fc5SRichard Trieu   return PendUpdates.size() != PendPDTUpdateIndex;
1655f436fc5SRichard Trieu }
1665f436fc5SRichard Trieu 
isBBPendingDeletion(llvm::BasicBlock * DelBB) const1675f436fc5SRichard Trieu bool DomTreeUpdater::isBBPendingDeletion(llvm::BasicBlock *DelBB) const {
1685f436fc5SRichard Trieu   if (Strategy == UpdateStrategy::Eager || DeletedBBs.empty())
1695f436fc5SRichard Trieu     return false;
170b7c5e0b0SKazu Hirata   return DeletedBBs.contains(DelBB);
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.
deleteBB(BasicBlock * DelBB)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 
callbackDeleteBB(BasicBlock * DelBB,std::function<void (BasicBlock *)> Callback)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 
eraseDelBBNode(BasicBlock * DelBB)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 
validateDeleteBB(BasicBlock * DelBB)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 
applyUpdates(ArrayRef<DominatorTree::UpdateType> Updates)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) {
2366d44b3c5SRoman Lebedev     PendUpdates.reserve(PendUpdates.size() + Updates.size());
2378dc7b982SMark de Wever     for (const auto &U : Updates)
23870e97163SChijun Sima       if (!isSelfDominance(U))
23970e97163SChijun Sima         PendUpdates.push_back(U);
2405f436fc5SRichard Trieu 
2415f436fc5SRichard Trieu     return;
2425f436fc5SRichard Trieu   }
2435f436fc5SRichard Trieu 
2445f436fc5SRichard Trieu   if (DT)
2455f436fc5SRichard Trieu     DT->applyUpdates(Updates);
2465f436fc5SRichard Trieu   if (PDT)
2475f436fc5SRichard Trieu     PDT->applyUpdates(Updates);
2485f436fc5SRichard Trieu }
2495f436fc5SRichard Trieu 
applyUpdatesPermissive(ArrayRef<DominatorTree::UpdateType> Updates)25070e97163SChijun Sima void DomTreeUpdater::applyUpdatesPermissive(
25170e97163SChijun Sima     ArrayRef<DominatorTree::UpdateType> Updates) {
25270e97163SChijun Sima   if (!DT && !PDT)
25370e97163SChijun Sima     return;
25470e97163SChijun Sima 
25570e97163SChijun Sima   SmallSet<std::pair<BasicBlock *, BasicBlock *>, 8> Seen;
25670e97163SChijun Sima   SmallVector<DominatorTree::UpdateType, 8> DeduplicatedUpdates;
2578dc7b982SMark de Wever   for (const auto &U : Updates) {
25870e97163SChijun Sima     auto Edge = std::make_pair(U.getFrom(), U.getTo());
25970e97163SChijun Sima     // Because it is illegal to submit updates that have already been applied
26070e97163SChijun Sima     // and updates to an edge need to be strictly ordered,
26170e97163SChijun Sima     // it is safe to infer the existence of an edge from the first update
26270e97163SChijun Sima     // to this edge.
26370e97163SChijun Sima     // If the first update to an edge is "Delete", it means that the edge
26470e97163SChijun Sima     // existed before. If the first update to an edge is "Insert", it means
26570e97163SChijun Sima     // that the edge didn't exist before.
26670e97163SChijun Sima     //
26770e97163SChijun Sima     // For example, if the user submits {{Delete, A, B}, {Insert, A, B}},
26870e97163SChijun Sima     // because
26970e97163SChijun Sima     // 1. it is illegal to submit updates that have already been applied,
27070e97163SChijun Sima     // i.e., user cannot delete an nonexistent edge,
27170e97163SChijun Sima     // 2. updates to an edge need to be strictly ordered,
27270e97163SChijun Sima     // So, initially edge A -> B existed.
27370e97163SChijun Sima     // We can then safely ignore future updates to this edge and directly
27470e97163SChijun Sima     // inspect the current CFG:
27570e97163SChijun Sima     // a. If the edge still exists, because the user cannot insert an existent
27670e97163SChijun Sima     // edge, so both {Delete, A, B}, {Insert, A, B} actually happened and
27770e97163SChijun Sima     // resulted in a no-op. DTU won't submit any update in this case.
27870e97163SChijun Sima     // b. If the edge doesn't exist, we can then infer that {Delete, A, B}
27970e97163SChijun Sima     // actually happened but {Insert, A, B} was an invalid update which never
28070e97163SChijun Sima     // happened. DTU will submit {Delete, A, B} in this case.
28170e97163SChijun Sima     if (!isSelfDominance(U) && Seen.count(Edge) == 0) {
28270e97163SChijun Sima       Seen.insert(Edge);
28370e97163SChijun Sima       // If the update doesn't appear in the CFG, it means that
28470e97163SChijun Sima       // either the change isn't made or relevant operations
28570e97163SChijun Sima       // result in a no-op.
28670e97163SChijun Sima       if (isUpdateValid(U)) {
28770e97163SChijun Sima         if (isLazy())
28870e97163SChijun Sima           PendUpdates.push_back(U);
28970e97163SChijun Sima         else
29070e97163SChijun Sima           DeduplicatedUpdates.push_back(U);
29170e97163SChijun Sima       }
29270e97163SChijun Sima     }
29370e97163SChijun Sima   }
29470e97163SChijun Sima 
29570e97163SChijun Sima   if (Strategy == UpdateStrategy::Lazy)
29670e97163SChijun Sima     return;
29770e97163SChijun Sima 
29870e97163SChijun Sima   if (DT)
29970e97163SChijun Sima     DT->applyUpdates(DeduplicatedUpdates);
30070e97163SChijun Sima   if (PDT)
30170e97163SChijun Sima     PDT->applyUpdates(DeduplicatedUpdates);
30270e97163SChijun Sima }
30370e97163SChijun Sima 
getDomTree()3045f436fc5SRichard Trieu DominatorTree &DomTreeUpdater::getDomTree() {
3055f436fc5SRichard Trieu   assert(DT && "Invalid acquisition of a null DomTree");
3065f436fc5SRichard Trieu   applyDomTreeUpdates();
3075f436fc5SRichard Trieu   dropOutOfDateUpdates();
3085f436fc5SRichard Trieu   return *DT;
3095f436fc5SRichard Trieu }
3105f436fc5SRichard Trieu 
getPostDomTree()3115f436fc5SRichard Trieu PostDominatorTree &DomTreeUpdater::getPostDomTree() {
3125f436fc5SRichard Trieu   assert(PDT && "Invalid acquisition of a null PostDomTree");
3135f436fc5SRichard Trieu   applyPostDomTreeUpdates();
3145f436fc5SRichard Trieu   dropOutOfDateUpdates();
3155f436fc5SRichard Trieu   return *PDT;
3165f436fc5SRichard Trieu }
3175f436fc5SRichard Trieu 
dropOutOfDateUpdates()3185f436fc5SRichard Trieu void DomTreeUpdater::dropOutOfDateUpdates() {
3195f436fc5SRichard Trieu   if (Strategy == DomTreeUpdater::UpdateStrategy::Eager)
3205f436fc5SRichard Trieu     return;
3215f436fc5SRichard Trieu 
3225f436fc5SRichard Trieu   tryFlushDeletedBB();
3235f436fc5SRichard Trieu 
3245f436fc5SRichard Trieu   // Drop all updates applied by both trees.
3255f436fc5SRichard Trieu   if (!DT)
3265f436fc5SRichard Trieu     PendDTUpdateIndex = PendUpdates.size();
3275f436fc5SRichard Trieu   if (!PDT)
3285f436fc5SRichard Trieu     PendPDTUpdateIndex = PendUpdates.size();
3295f436fc5SRichard Trieu 
3305f436fc5SRichard Trieu   const size_t dropIndex = std::min(PendDTUpdateIndex, PendPDTUpdateIndex);
3315f436fc5SRichard Trieu   const auto B = PendUpdates.begin();
3325f436fc5SRichard Trieu   const auto E = PendUpdates.begin() + dropIndex;
3335f436fc5SRichard Trieu   assert(B <= E && "Iterator out of range.");
3345f436fc5SRichard Trieu   PendUpdates.erase(B, E);
3355f436fc5SRichard Trieu   // Calculate current index.
3365f436fc5SRichard Trieu   PendDTUpdateIndex -= dropIndex;
3375f436fc5SRichard Trieu   PendPDTUpdateIndex -= dropIndex;
3385f436fc5SRichard Trieu }
3395f436fc5SRichard Trieu 
3405f436fc5SRichard Trieu #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
dump() const3415f436fc5SRichard Trieu LLVM_DUMP_METHOD void DomTreeUpdater::dump() const {
3425f436fc5SRichard Trieu   raw_ostream &OS = llvm::dbgs();
3435f436fc5SRichard Trieu 
3445f436fc5SRichard Trieu   OS << "Available Trees: ";
3455f436fc5SRichard Trieu   if (DT || PDT) {
3465f436fc5SRichard Trieu     if (DT)
3475f436fc5SRichard Trieu       OS << "DomTree ";
3485f436fc5SRichard Trieu     if (PDT)
3495f436fc5SRichard Trieu       OS << "PostDomTree ";
3505f436fc5SRichard Trieu     OS << "\n";
3515f436fc5SRichard Trieu   } else
3525f436fc5SRichard Trieu     OS << "None\n";
3535f436fc5SRichard Trieu 
3545f436fc5SRichard Trieu   OS << "UpdateStrategy: ";
3555f436fc5SRichard Trieu   if (Strategy == UpdateStrategy::Eager) {
3565f436fc5SRichard Trieu     OS << "Eager\n";
3575f436fc5SRichard Trieu     return;
3585f436fc5SRichard Trieu   } else
3595f436fc5SRichard Trieu     OS << "Lazy\n";
3605f436fc5SRichard Trieu   int Index = 0;
3615f436fc5SRichard Trieu 
3625f436fc5SRichard Trieu   auto printUpdates =
3635f436fc5SRichard Trieu       [&](ArrayRef<DominatorTree::UpdateType>::const_iterator begin,
3645f436fc5SRichard Trieu           ArrayRef<DominatorTree::UpdateType>::const_iterator end) {
3655f436fc5SRichard Trieu         if (begin == end)
3665f436fc5SRichard Trieu           OS << "  None\n";
3675f436fc5SRichard Trieu         Index = 0;
3685f436fc5SRichard Trieu         for (auto It = begin, ItEnd = end; It != ItEnd; ++It) {
3695f436fc5SRichard Trieu           auto U = *It;
3705f436fc5SRichard Trieu           OS << "  " << Index << " : ";
3715f436fc5SRichard Trieu           ++Index;
3725f436fc5SRichard Trieu           if (U.getKind() == DominatorTree::Insert)
3735f436fc5SRichard Trieu             OS << "Insert, ";
3745f436fc5SRichard Trieu           else
3755f436fc5SRichard Trieu             OS << "Delete, ";
3765f436fc5SRichard Trieu           BasicBlock *From = U.getFrom();
3775f436fc5SRichard Trieu           if (From) {
3785f436fc5SRichard Trieu             auto S = From->getName();
3795f436fc5SRichard Trieu             if (!From->hasName())
3805f436fc5SRichard Trieu               S = "(no name)";
3815f436fc5SRichard Trieu             OS << S << "(" << From << "), ";
3825f436fc5SRichard Trieu           } else {
3835f436fc5SRichard Trieu             OS << "(badref), ";
3845f436fc5SRichard Trieu           }
3855f436fc5SRichard Trieu           BasicBlock *To = U.getTo();
3865f436fc5SRichard Trieu           if (To) {
3875f436fc5SRichard Trieu             auto S = To->getName();
3885f436fc5SRichard Trieu             if (!To->hasName())
3895f436fc5SRichard Trieu               S = "(no_name)";
3905f436fc5SRichard Trieu             OS << S << "(" << To << ")\n";
3915f436fc5SRichard Trieu           } else {
3925f436fc5SRichard Trieu             OS << "(badref)\n";
3935f436fc5SRichard Trieu           }
3945f436fc5SRichard Trieu         }
3955f436fc5SRichard Trieu       };
3965f436fc5SRichard Trieu 
3975f436fc5SRichard Trieu   if (DT) {
3985f436fc5SRichard Trieu     const auto I = PendUpdates.begin() + PendDTUpdateIndex;
3995f436fc5SRichard Trieu     assert(PendUpdates.begin() <= I && I <= PendUpdates.end() &&
4005f436fc5SRichard Trieu            "Iterator out of range.");
4015f436fc5SRichard Trieu     OS << "Applied but not cleared DomTreeUpdates:\n";
4025f436fc5SRichard Trieu     printUpdates(PendUpdates.begin(), I);
4035f436fc5SRichard Trieu     OS << "Pending DomTreeUpdates:\n";
4045f436fc5SRichard Trieu     printUpdates(I, PendUpdates.end());
4055f436fc5SRichard Trieu   }
4065f436fc5SRichard Trieu 
4075f436fc5SRichard Trieu   if (PDT) {
4085f436fc5SRichard Trieu     const auto I = PendUpdates.begin() + PendPDTUpdateIndex;
4095f436fc5SRichard Trieu     assert(PendUpdates.begin() <= I && I <= PendUpdates.end() &&
4105f436fc5SRichard Trieu            "Iterator out of range.");
4115f436fc5SRichard Trieu     OS << "Applied but not cleared PostDomTreeUpdates:\n";
4125f436fc5SRichard Trieu     printUpdates(PendUpdates.begin(), I);
4135f436fc5SRichard Trieu     OS << "Pending PostDomTreeUpdates:\n";
4145f436fc5SRichard Trieu     printUpdates(I, PendUpdates.end());
4155f436fc5SRichard Trieu   }
4165f436fc5SRichard Trieu 
4175f436fc5SRichard Trieu   OS << "Pending DeletedBBs:\n";
4185f436fc5SRichard Trieu   Index = 0;
419ec00aa99SFlorian Hahn   for (const auto *BB : DeletedBBs) {
4205f436fc5SRichard Trieu     OS << "  " << Index << " : ";
4215f436fc5SRichard Trieu     ++Index;
4225f436fc5SRichard Trieu     if (BB->hasName())
4235f436fc5SRichard Trieu       OS << BB->getName() << "(";
4245f436fc5SRichard Trieu     else
4255f436fc5SRichard Trieu       OS << "(no_name)(";
4265f436fc5SRichard Trieu     OS << BB << ")\n";
4275f436fc5SRichard Trieu   }
4285f436fc5SRichard Trieu 
4295f436fc5SRichard Trieu   OS << "Pending Callbacks:\n";
4305f436fc5SRichard Trieu   Index = 0;
431b69e0f67SSimon Pilgrim   for (const auto &BB : Callbacks) {
4325f436fc5SRichard Trieu     OS << "  " << Index << " : ";
4335f436fc5SRichard Trieu     ++Index;
4345f436fc5SRichard Trieu     if (BB->hasName())
4355f436fc5SRichard Trieu       OS << BB->getName() << "(";
4365f436fc5SRichard Trieu     else
4375f436fc5SRichard Trieu       OS << "(no_name)(";
4385f436fc5SRichard Trieu     OS << BB << ")\n";
4395f436fc5SRichard Trieu   }
4405f436fc5SRichard Trieu }
4415f436fc5SRichard Trieu #endif
4425f436fc5SRichard Trieu } // namespace llvm
443