xref: /openbsd-src/gnu/llvm/llvm/lib/Analysis/DomTreeUpdater.cpp (revision d415bd752c734aee168c4ee86ff32e8cc249eb16)
109467b48Spatrick //===- DomTreeUpdater.cpp - DomTree/Post DomTree Updater --------*- C++ -*-===//
209467b48Spatrick //
309467b48Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
409467b48Spatrick // See https://llvm.org/LICENSE.txt for license information.
509467b48Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
609467b48Spatrick //
709467b48Spatrick //===----------------------------------------------------------------------===//
809467b48Spatrick //
909467b48Spatrick // This file implements the DomTreeUpdater class, which provides a uniform way
1009467b48Spatrick // to update dominator tree related data structures.
1109467b48Spatrick //
1209467b48Spatrick //===----------------------------------------------------------------------===//
1309467b48Spatrick 
1409467b48Spatrick #include "llvm/Analysis/DomTreeUpdater.h"
1509467b48Spatrick #include "llvm/ADT/SmallSet.h"
1609467b48Spatrick #include "llvm/Analysis/PostDominators.h"
17*d415bd75Srobert #include "llvm/IR/Constants.h"
18097a140dSpatrick #include "llvm/IR/Instructions.h"
1909467b48Spatrick #include "llvm/Support/GenericDomTree.h"
2009467b48Spatrick #include <algorithm>
2109467b48Spatrick #include <functional>
2209467b48Spatrick #include <utility>
2309467b48Spatrick 
2409467b48Spatrick namespace llvm {
2509467b48Spatrick 
isUpdateValid(const DominatorTree::UpdateType Update) const2609467b48Spatrick bool DomTreeUpdater::isUpdateValid(
2709467b48Spatrick     const DominatorTree::UpdateType Update) const {
2809467b48Spatrick   const auto *From = Update.getFrom();
2909467b48Spatrick   const auto *To = Update.getTo();
3009467b48Spatrick   const auto Kind = Update.getKind();
3109467b48Spatrick 
3209467b48Spatrick   // Discard updates by inspecting the current state of successors of From.
3309467b48Spatrick   // Since isUpdateValid() must be called *after* the Terminator of From is
3409467b48Spatrick   // altered we can determine if the update is unnecessary for batch updates
3509467b48Spatrick   // or invalid for a single update.
3673471bf0Spatrick   const bool HasEdge = llvm::is_contained(successors(From), To);
3709467b48Spatrick 
3809467b48Spatrick   // If the IR does not match the update,
3909467b48Spatrick   // 1. In batch updates, this update is unnecessary.
4009467b48Spatrick   // 2. When called by insertEdge*()/deleteEdge*(), this update is invalid.
4109467b48Spatrick   // Edge does not exist in IR.
4209467b48Spatrick   if (Kind == DominatorTree::Insert && !HasEdge)
4309467b48Spatrick     return false;
4409467b48Spatrick 
4509467b48Spatrick   // Edge exists in IR.
4609467b48Spatrick   if (Kind == DominatorTree::Delete && HasEdge)
4709467b48Spatrick     return false;
4809467b48Spatrick 
4909467b48Spatrick   return true;
5009467b48Spatrick }
5109467b48Spatrick 
isSelfDominance(const DominatorTree::UpdateType Update) const5209467b48Spatrick bool DomTreeUpdater::isSelfDominance(
5309467b48Spatrick     const DominatorTree::UpdateType Update) const {
5409467b48Spatrick   // Won't affect DomTree and PostDomTree.
5509467b48Spatrick   return Update.getFrom() == Update.getTo();
5609467b48Spatrick }
5709467b48Spatrick 
applyDomTreeUpdates()5809467b48Spatrick void DomTreeUpdater::applyDomTreeUpdates() {
5909467b48Spatrick   // No pending DomTreeUpdates.
6009467b48Spatrick   if (Strategy != UpdateStrategy::Lazy || !DT)
6109467b48Spatrick     return;
6209467b48Spatrick 
6309467b48Spatrick   // Only apply updates not are applied by DomTree.
6409467b48Spatrick   if (hasPendingDomTreeUpdates()) {
6509467b48Spatrick     const auto I = PendUpdates.begin() + PendDTUpdateIndex;
6609467b48Spatrick     const auto E = PendUpdates.end();
6709467b48Spatrick     assert(I < E && "Iterator range invalid; there should be DomTree updates.");
6809467b48Spatrick     DT->applyUpdates(ArrayRef<DominatorTree::UpdateType>(I, E));
6909467b48Spatrick     PendDTUpdateIndex = PendUpdates.size();
7009467b48Spatrick   }
7109467b48Spatrick }
7209467b48Spatrick 
flush()7309467b48Spatrick void DomTreeUpdater::flush() {
7409467b48Spatrick   applyDomTreeUpdates();
7509467b48Spatrick   applyPostDomTreeUpdates();
7609467b48Spatrick   dropOutOfDateUpdates();
7709467b48Spatrick }
7809467b48Spatrick 
applyPostDomTreeUpdates()7909467b48Spatrick void DomTreeUpdater::applyPostDomTreeUpdates() {
8009467b48Spatrick   // No pending PostDomTreeUpdates.
8109467b48Spatrick   if (Strategy != UpdateStrategy::Lazy || !PDT)
8209467b48Spatrick     return;
8309467b48Spatrick 
8409467b48Spatrick   // Only apply updates not are applied by PostDomTree.
8509467b48Spatrick   if (hasPendingPostDomTreeUpdates()) {
8609467b48Spatrick     const auto I = PendUpdates.begin() + PendPDTUpdateIndex;
8709467b48Spatrick     const auto E = PendUpdates.end();
8809467b48Spatrick     assert(I < E &&
8909467b48Spatrick            "Iterator range invalid; there should be PostDomTree updates.");
9009467b48Spatrick     PDT->applyUpdates(ArrayRef<DominatorTree::UpdateType>(I, E));
9109467b48Spatrick     PendPDTUpdateIndex = PendUpdates.size();
9209467b48Spatrick   }
9309467b48Spatrick }
9409467b48Spatrick 
tryFlushDeletedBB()9509467b48Spatrick void DomTreeUpdater::tryFlushDeletedBB() {
9609467b48Spatrick   if (!hasPendingUpdates())
9709467b48Spatrick     forceFlushDeletedBB();
9809467b48Spatrick }
9909467b48Spatrick 
forceFlushDeletedBB()10009467b48Spatrick bool DomTreeUpdater::forceFlushDeletedBB() {
10109467b48Spatrick   if (DeletedBBs.empty())
10209467b48Spatrick     return false;
10309467b48Spatrick 
10409467b48Spatrick   for (auto *BB : DeletedBBs) {
10509467b48Spatrick     // After calling deleteBB or callbackDeleteBB under Lazy UpdateStrategy,
10609467b48Spatrick     // validateDeleteBB() removes all instructions of DelBB and adds an
10709467b48Spatrick     // UnreachableInst as its terminator. So we check whether the BasicBlock to
10809467b48Spatrick     // delete only has an UnreachableInst inside.
109*d415bd75Srobert     assert(BB->size() == 1 && isa<UnreachableInst>(BB->getTerminator()) &&
11009467b48Spatrick            "DelBB has been modified while awaiting deletion.");
11109467b48Spatrick     BB->removeFromParent();
11209467b48Spatrick     eraseDelBBNode(BB);
11309467b48Spatrick     delete BB;
11409467b48Spatrick   }
11509467b48Spatrick   DeletedBBs.clear();
11609467b48Spatrick   Callbacks.clear();
11709467b48Spatrick   return true;
11809467b48Spatrick }
11909467b48Spatrick 
recalculate(Function & F)12009467b48Spatrick void DomTreeUpdater::recalculate(Function &F) {
12109467b48Spatrick 
12209467b48Spatrick   if (Strategy == UpdateStrategy::Eager) {
12309467b48Spatrick     if (DT)
12409467b48Spatrick       DT->recalculate(F);
12509467b48Spatrick     if (PDT)
12609467b48Spatrick       PDT->recalculate(F);
12709467b48Spatrick     return;
12809467b48Spatrick   }
12909467b48Spatrick 
13009467b48Spatrick   // There is little performance gain if we pend the recalculation under
13109467b48Spatrick   // Lazy UpdateStrategy so we recalculate available trees immediately.
13209467b48Spatrick 
13309467b48Spatrick   // Prevent forceFlushDeletedBB() from erasing DomTree or PostDomTree nodes.
13409467b48Spatrick   IsRecalculatingDomTree = IsRecalculatingPostDomTree = true;
13509467b48Spatrick 
13609467b48Spatrick   // Because all trees are going to be up-to-date after recalculation,
13709467b48Spatrick   // flush awaiting deleted BasicBlocks.
13809467b48Spatrick   forceFlushDeletedBB();
13909467b48Spatrick   if (DT)
14009467b48Spatrick     DT->recalculate(F);
14109467b48Spatrick   if (PDT)
14209467b48Spatrick     PDT->recalculate(F);
14309467b48Spatrick 
14409467b48Spatrick   // Resume forceFlushDeletedBB() to erase DomTree or PostDomTree nodes.
14509467b48Spatrick   IsRecalculatingDomTree = IsRecalculatingPostDomTree = false;
14609467b48Spatrick   PendDTUpdateIndex = PendPDTUpdateIndex = PendUpdates.size();
14709467b48Spatrick   dropOutOfDateUpdates();
14809467b48Spatrick }
14909467b48Spatrick 
hasPendingUpdates() const15009467b48Spatrick bool DomTreeUpdater::hasPendingUpdates() const {
15109467b48Spatrick   return hasPendingDomTreeUpdates() || hasPendingPostDomTreeUpdates();
15209467b48Spatrick }
15309467b48Spatrick 
hasPendingDomTreeUpdates() const15409467b48Spatrick bool DomTreeUpdater::hasPendingDomTreeUpdates() const {
15509467b48Spatrick   if (!DT)
15609467b48Spatrick     return false;
15709467b48Spatrick   return PendUpdates.size() != PendDTUpdateIndex;
15809467b48Spatrick }
15909467b48Spatrick 
hasPendingPostDomTreeUpdates() const16009467b48Spatrick bool DomTreeUpdater::hasPendingPostDomTreeUpdates() const {
16109467b48Spatrick   if (!PDT)
16209467b48Spatrick     return false;
16309467b48Spatrick   return PendUpdates.size() != PendPDTUpdateIndex;
16409467b48Spatrick }
16509467b48Spatrick 
isBBPendingDeletion(llvm::BasicBlock * DelBB) const16609467b48Spatrick bool DomTreeUpdater::isBBPendingDeletion(llvm::BasicBlock *DelBB) const {
16709467b48Spatrick   if (Strategy == UpdateStrategy::Eager || DeletedBBs.empty())
16809467b48Spatrick     return false;
16973471bf0Spatrick   return DeletedBBs.contains(DelBB);
17009467b48Spatrick }
17109467b48Spatrick 
17209467b48Spatrick // The DT and PDT require the nodes related to updates
17309467b48Spatrick // are not deleted when update functions are called.
17409467b48Spatrick // So BasicBlock deletions must be pended when the
17509467b48Spatrick // UpdateStrategy is Lazy. When the UpdateStrategy is
17609467b48Spatrick // Eager, the BasicBlock will be deleted immediately.
deleteBB(BasicBlock * DelBB)17709467b48Spatrick void DomTreeUpdater::deleteBB(BasicBlock *DelBB) {
17809467b48Spatrick   validateDeleteBB(DelBB);
17909467b48Spatrick   if (Strategy == UpdateStrategy::Lazy) {
18009467b48Spatrick     DeletedBBs.insert(DelBB);
18109467b48Spatrick     return;
18209467b48Spatrick   }
18309467b48Spatrick 
18409467b48Spatrick   DelBB->removeFromParent();
18509467b48Spatrick   eraseDelBBNode(DelBB);
18609467b48Spatrick   delete DelBB;
18709467b48Spatrick }
18809467b48Spatrick 
callbackDeleteBB(BasicBlock * DelBB,std::function<void (BasicBlock *)> Callback)18909467b48Spatrick void DomTreeUpdater::callbackDeleteBB(
19009467b48Spatrick     BasicBlock *DelBB, std::function<void(BasicBlock *)> Callback) {
19109467b48Spatrick   validateDeleteBB(DelBB);
19209467b48Spatrick   if (Strategy == UpdateStrategy::Lazy) {
19309467b48Spatrick     Callbacks.push_back(CallBackOnDeletion(DelBB, Callback));
19409467b48Spatrick     DeletedBBs.insert(DelBB);
19509467b48Spatrick     return;
19609467b48Spatrick   }
19709467b48Spatrick 
19809467b48Spatrick   DelBB->removeFromParent();
19909467b48Spatrick   eraseDelBBNode(DelBB);
20009467b48Spatrick   Callback(DelBB);
20109467b48Spatrick   delete DelBB;
20209467b48Spatrick }
20309467b48Spatrick 
eraseDelBBNode(BasicBlock * DelBB)20409467b48Spatrick void DomTreeUpdater::eraseDelBBNode(BasicBlock *DelBB) {
20509467b48Spatrick   if (DT && !IsRecalculatingDomTree)
20609467b48Spatrick     if (DT->getNode(DelBB))
20709467b48Spatrick       DT->eraseNode(DelBB);
20809467b48Spatrick 
20909467b48Spatrick   if (PDT && !IsRecalculatingPostDomTree)
21009467b48Spatrick     if (PDT->getNode(DelBB))
21109467b48Spatrick       PDT->eraseNode(DelBB);
21209467b48Spatrick }
21309467b48Spatrick 
validateDeleteBB(BasicBlock * DelBB)21409467b48Spatrick void DomTreeUpdater::validateDeleteBB(BasicBlock *DelBB) {
21509467b48Spatrick   assert(DelBB && "Invalid push_back of nullptr DelBB.");
21609467b48Spatrick   assert(pred_empty(DelBB) && "DelBB has one or more predecessors.");
21709467b48Spatrick   // DelBB is unreachable and all its instructions are dead.
21809467b48Spatrick   while (!DelBB->empty()) {
21909467b48Spatrick     Instruction &I = DelBB->back();
220*d415bd75Srobert     // Replace used instructions with an arbitrary value (poison).
22109467b48Spatrick     if (!I.use_empty())
222*d415bd75Srobert       I.replaceAllUsesWith(PoisonValue::get(I.getType()));
223*d415bd75Srobert     DelBB->back().eraseFromParent();
22409467b48Spatrick   }
22509467b48Spatrick   // Make sure DelBB has a valid terminator instruction. As long as DelBB is a
22609467b48Spatrick   // Child of Function F it must contain valid IR.
22709467b48Spatrick   new UnreachableInst(DelBB->getContext(), DelBB);
22809467b48Spatrick }
22909467b48Spatrick 
applyUpdates(ArrayRef<DominatorTree::UpdateType> Updates)23009467b48Spatrick void DomTreeUpdater::applyUpdates(ArrayRef<DominatorTree::UpdateType> Updates) {
23109467b48Spatrick   if (!DT && !PDT)
23209467b48Spatrick     return;
23309467b48Spatrick 
23409467b48Spatrick   if (Strategy == UpdateStrategy::Lazy) {
23573471bf0Spatrick     PendUpdates.reserve(PendUpdates.size() + Updates.size());
23609467b48Spatrick     for (const auto &U : Updates)
23709467b48Spatrick       if (!isSelfDominance(U))
23809467b48Spatrick         PendUpdates.push_back(U);
23909467b48Spatrick 
24009467b48Spatrick     return;
24109467b48Spatrick   }
24209467b48Spatrick 
24309467b48Spatrick   if (DT)
24409467b48Spatrick     DT->applyUpdates(Updates);
24509467b48Spatrick   if (PDT)
24609467b48Spatrick     PDT->applyUpdates(Updates);
24709467b48Spatrick }
24809467b48Spatrick 
applyUpdatesPermissive(ArrayRef<DominatorTree::UpdateType> Updates)24909467b48Spatrick void DomTreeUpdater::applyUpdatesPermissive(
25009467b48Spatrick     ArrayRef<DominatorTree::UpdateType> Updates) {
25109467b48Spatrick   if (!DT && !PDT)
25209467b48Spatrick     return;
25309467b48Spatrick 
25409467b48Spatrick   SmallSet<std::pair<BasicBlock *, BasicBlock *>, 8> Seen;
25509467b48Spatrick   SmallVector<DominatorTree::UpdateType, 8> DeduplicatedUpdates;
25609467b48Spatrick   for (const auto &U : Updates) {
25709467b48Spatrick     auto Edge = std::make_pair(U.getFrom(), U.getTo());
25809467b48Spatrick     // Because it is illegal to submit updates that have already been applied
25909467b48Spatrick     // and updates to an edge need to be strictly ordered,
26009467b48Spatrick     // it is safe to infer the existence of an edge from the first update
26109467b48Spatrick     // to this edge.
26209467b48Spatrick     // If the first update to an edge is "Delete", it means that the edge
26309467b48Spatrick     // existed before. If the first update to an edge is "Insert", it means
26409467b48Spatrick     // that the edge didn't exist before.
26509467b48Spatrick     //
26609467b48Spatrick     // For example, if the user submits {{Delete, A, B}, {Insert, A, B}},
26709467b48Spatrick     // because
26809467b48Spatrick     // 1. it is illegal to submit updates that have already been applied,
26909467b48Spatrick     // i.e., user cannot delete an nonexistent edge,
27009467b48Spatrick     // 2. updates to an edge need to be strictly ordered,
27109467b48Spatrick     // So, initially edge A -> B existed.
27209467b48Spatrick     // We can then safely ignore future updates to this edge and directly
27309467b48Spatrick     // inspect the current CFG:
27409467b48Spatrick     // a. If the edge still exists, because the user cannot insert an existent
27509467b48Spatrick     // edge, so both {Delete, A, B}, {Insert, A, B} actually happened and
27609467b48Spatrick     // resulted in a no-op. DTU won't submit any update in this case.
27709467b48Spatrick     // b. If the edge doesn't exist, we can then infer that {Delete, A, B}
27809467b48Spatrick     // actually happened but {Insert, A, B} was an invalid update which never
27909467b48Spatrick     // happened. DTU will submit {Delete, A, B} in this case.
28009467b48Spatrick     if (!isSelfDominance(U) && Seen.count(Edge) == 0) {
28109467b48Spatrick       Seen.insert(Edge);
28209467b48Spatrick       // If the update doesn't appear in the CFG, it means that
28309467b48Spatrick       // either the change isn't made or relevant operations
28409467b48Spatrick       // result in a no-op.
28509467b48Spatrick       if (isUpdateValid(U)) {
28609467b48Spatrick         if (isLazy())
28709467b48Spatrick           PendUpdates.push_back(U);
28809467b48Spatrick         else
28909467b48Spatrick           DeduplicatedUpdates.push_back(U);
29009467b48Spatrick       }
29109467b48Spatrick     }
29209467b48Spatrick   }
29309467b48Spatrick 
29409467b48Spatrick   if (Strategy == UpdateStrategy::Lazy)
29509467b48Spatrick     return;
29609467b48Spatrick 
29709467b48Spatrick   if (DT)
29809467b48Spatrick     DT->applyUpdates(DeduplicatedUpdates);
29909467b48Spatrick   if (PDT)
30009467b48Spatrick     PDT->applyUpdates(DeduplicatedUpdates);
30109467b48Spatrick }
30209467b48Spatrick 
getDomTree()30309467b48Spatrick DominatorTree &DomTreeUpdater::getDomTree() {
30409467b48Spatrick   assert(DT && "Invalid acquisition of a null DomTree");
30509467b48Spatrick   applyDomTreeUpdates();
30609467b48Spatrick   dropOutOfDateUpdates();
30709467b48Spatrick   return *DT;
30809467b48Spatrick }
30909467b48Spatrick 
getPostDomTree()31009467b48Spatrick PostDominatorTree &DomTreeUpdater::getPostDomTree() {
31109467b48Spatrick   assert(PDT && "Invalid acquisition of a null PostDomTree");
31209467b48Spatrick   applyPostDomTreeUpdates();
31309467b48Spatrick   dropOutOfDateUpdates();
31409467b48Spatrick   return *PDT;
31509467b48Spatrick }
31609467b48Spatrick 
dropOutOfDateUpdates()31709467b48Spatrick void DomTreeUpdater::dropOutOfDateUpdates() {
31809467b48Spatrick   if (Strategy == DomTreeUpdater::UpdateStrategy::Eager)
31909467b48Spatrick     return;
32009467b48Spatrick 
32109467b48Spatrick   tryFlushDeletedBB();
32209467b48Spatrick 
32309467b48Spatrick   // Drop all updates applied by both trees.
32409467b48Spatrick   if (!DT)
32509467b48Spatrick     PendDTUpdateIndex = PendUpdates.size();
32609467b48Spatrick   if (!PDT)
32709467b48Spatrick     PendPDTUpdateIndex = PendUpdates.size();
32809467b48Spatrick 
32909467b48Spatrick   const size_t dropIndex = std::min(PendDTUpdateIndex, PendPDTUpdateIndex);
33009467b48Spatrick   const auto B = PendUpdates.begin();
33109467b48Spatrick   const auto E = PendUpdates.begin() + dropIndex;
33209467b48Spatrick   assert(B <= E && "Iterator out of range.");
33309467b48Spatrick   PendUpdates.erase(B, E);
33409467b48Spatrick   // Calculate current index.
33509467b48Spatrick   PendDTUpdateIndex -= dropIndex;
33609467b48Spatrick   PendPDTUpdateIndex -= dropIndex;
33709467b48Spatrick }
33809467b48Spatrick 
33909467b48Spatrick #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
dump() const34009467b48Spatrick LLVM_DUMP_METHOD void DomTreeUpdater::dump() const {
34109467b48Spatrick   raw_ostream &OS = llvm::dbgs();
34209467b48Spatrick 
34309467b48Spatrick   OS << "Available Trees: ";
34409467b48Spatrick   if (DT || PDT) {
34509467b48Spatrick     if (DT)
34609467b48Spatrick       OS << "DomTree ";
34709467b48Spatrick     if (PDT)
34809467b48Spatrick       OS << "PostDomTree ";
34909467b48Spatrick     OS << "\n";
35009467b48Spatrick   } else
35109467b48Spatrick     OS << "None\n";
35209467b48Spatrick 
35309467b48Spatrick   OS << "UpdateStrategy: ";
35409467b48Spatrick   if (Strategy == UpdateStrategy::Eager) {
35509467b48Spatrick     OS << "Eager\n";
35609467b48Spatrick     return;
35709467b48Spatrick   } else
35809467b48Spatrick     OS << "Lazy\n";
35909467b48Spatrick   int Index = 0;
36009467b48Spatrick 
36109467b48Spatrick   auto printUpdates =
36209467b48Spatrick       [&](ArrayRef<DominatorTree::UpdateType>::const_iterator begin,
36309467b48Spatrick           ArrayRef<DominatorTree::UpdateType>::const_iterator end) {
36409467b48Spatrick         if (begin == end)
36509467b48Spatrick           OS << "  None\n";
36609467b48Spatrick         Index = 0;
36709467b48Spatrick         for (auto It = begin, ItEnd = end; It != ItEnd; ++It) {
36809467b48Spatrick           auto U = *It;
36909467b48Spatrick           OS << "  " << Index << " : ";
37009467b48Spatrick           ++Index;
37109467b48Spatrick           if (U.getKind() == DominatorTree::Insert)
37209467b48Spatrick             OS << "Insert, ";
37309467b48Spatrick           else
37409467b48Spatrick             OS << "Delete, ";
37509467b48Spatrick           BasicBlock *From = U.getFrom();
37609467b48Spatrick           if (From) {
37709467b48Spatrick             auto S = From->getName();
37809467b48Spatrick             if (!From->hasName())
37909467b48Spatrick               S = "(no name)";
38009467b48Spatrick             OS << S << "(" << From << "), ";
38109467b48Spatrick           } else {
38209467b48Spatrick             OS << "(badref), ";
38309467b48Spatrick           }
38409467b48Spatrick           BasicBlock *To = U.getTo();
38509467b48Spatrick           if (To) {
38609467b48Spatrick             auto S = To->getName();
38709467b48Spatrick             if (!To->hasName())
38809467b48Spatrick               S = "(no_name)";
38909467b48Spatrick             OS << S << "(" << To << ")\n";
39009467b48Spatrick           } else {
39109467b48Spatrick             OS << "(badref)\n";
39209467b48Spatrick           }
39309467b48Spatrick         }
39409467b48Spatrick       };
39509467b48Spatrick 
39609467b48Spatrick   if (DT) {
39709467b48Spatrick     const auto I = PendUpdates.begin() + PendDTUpdateIndex;
39809467b48Spatrick     assert(PendUpdates.begin() <= I && I <= PendUpdates.end() &&
39909467b48Spatrick            "Iterator out of range.");
40009467b48Spatrick     OS << "Applied but not cleared DomTreeUpdates:\n";
40109467b48Spatrick     printUpdates(PendUpdates.begin(), I);
40209467b48Spatrick     OS << "Pending DomTreeUpdates:\n";
40309467b48Spatrick     printUpdates(I, PendUpdates.end());
40409467b48Spatrick   }
40509467b48Spatrick 
40609467b48Spatrick   if (PDT) {
40709467b48Spatrick     const auto I = PendUpdates.begin() + PendPDTUpdateIndex;
40809467b48Spatrick     assert(PendUpdates.begin() <= I && I <= PendUpdates.end() &&
40909467b48Spatrick            "Iterator out of range.");
41009467b48Spatrick     OS << "Applied but not cleared PostDomTreeUpdates:\n";
41109467b48Spatrick     printUpdates(PendUpdates.begin(), I);
41209467b48Spatrick     OS << "Pending PostDomTreeUpdates:\n";
41309467b48Spatrick     printUpdates(I, PendUpdates.end());
41409467b48Spatrick   }
41509467b48Spatrick 
41609467b48Spatrick   OS << "Pending DeletedBBs:\n";
41709467b48Spatrick   Index = 0;
418097a140dSpatrick   for (const auto *BB : DeletedBBs) {
41909467b48Spatrick     OS << "  " << Index << " : ";
42009467b48Spatrick     ++Index;
42109467b48Spatrick     if (BB->hasName())
42209467b48Spatrick       OS << BB->getName() << "(";
42309467b48Spatrick     else
42409467b48Spatrick       OS << "(no_name)(";
42509467b48Spatrick     OS << BB << ")\n";
42609467b48Spatrick   }
42709467b48Spatrick 
42809467b48Spatrick   OS << "Pending Callbacks:\n";
42909467b48Spatrick   Index = 0;
430097a140dSpatrick   for (const auto &BB : Callbacks) {
43109467b48Spatrick     OS << "  " << Index << " : ";
43209467b48Spatrick     ++Index;
43309467b48Spatrick     if (BB->hasName())
43409467b48Spatrick       OS << BB->getName() << "(";
43509467b48Spatrick     else
43609467b48Spatrick       OS << "(no_name)(";
43709467b48Spatrick     OS << BB << ")\n";
43809467b48Spatrick   }
43909467b48Spatrick }
44009467b48Spatrick #endif
44109467b48Spatrick } // namespace llvm
442