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