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