diff --git a/llvm/include/llvm/Analysis/DomTreeUpdater.h b/llvm/include/llvm/Analysis/DomTreeUpdater.h index 2b838a311440e..9ffd4948c1750 100644 --- a/llvm/include/llvm/Analysis/DomTreeUpdater.h +++ b/llvm/include/llvm/Analysis/DomTreeUpdater.h @@ -16,7 +16,6 @@ #include "llvm/ADT/SmallPtrSet.h" #include "llvm/Analysis/GenericDomTreeUpdater.h" -#include "llvm/Analysis/PostDominators.h" #include "llvm/IR/Dominators.h" #include "llvm/IR/ValueHandle.h" #include "llvm/Support/Compiler.h" @@ -26,6 +25,8 @@ namespace llvm { +class PostDominatorTree; + class DomTreeUpdater : public GenericDomTreeUpdater { @@ -110,27 +111,15 @@ class DomTreeUpdater bool forceFlushDeletedBB(); /// Debug method to help view the internal state of this class. - LLVM_DUMP_METHOD void dump() const { - Base::dump(); -#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) - raw_ostream &OS = dbgs(); - OS << "Pending Callbacks:\n"; - int Index = 0; - for (const auto &BB : Callbacks) { - OS << " " << Index << " : "; - ++Index; - if (BB->hasName()) - OS << BB->getName() << "("; - else - OS << "(no_name)("; - OS << BB << ")\n"; - } -#endif - } + LLVM_DUMP_METHOD void dump() const; }; extern template class GenericDomTreeUpdater; + +extern template void +GenericDomTreeUpdater::recalculate(Function &F); } // namespace llvm #endif // LLVM_ANALYSIS_DOMTREEUPDATER_H diff --git a/llvm/include/llvm/Analysis/GenericDomTreeUpdater.h b/llvm/include/llvm/Analysis/GenericDomTreeUpdater.h index 7092c67083a67..644230264bfe0 100644 --- a/llvm/include/llvm/Analysis/GenericDomTreeUpdater.h +++ b/llvm/include/llvm/Analysis/GenericDomTreeUpdater.h @@ -16,8 +16,7 @@ #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/SmallSet.h" -#include "llvm/Support/Debug.h" -#include "llvm/Support/raw_ostream.h" +#include "llvm/Support/Compiler.h" namespace llvm { @@ -52,10 +51,10 @@ class GenericDomTreeUpdater { ~GenericDomTreeUpdater() { flush(); } /// Returns true if the current strategy is Lazy. - bool isLazy() const { return Strategy == UpdateStrategy::Lazy; }; + bool isLazy() const { return Strategy == UpdateStrategy::Lazy; } /// Returns true if the current strategy is Eager. - bool isEager() const { return Strategy == UpdateStrategy::Eager; }; + bool isEager() const { return Strategy == UpdateStrategy::Eager; } /// Returns true if it holds a DomTreeT. bool hasDomTree() const { return DT != nullptr; } @@ -126,34 +125,7 @@ class GenericDomTreeUpdater { /// Notify DTU that the entry block was replaced. /// Recalculate all available trees and flush all BasicBlocks /// awaiting deletion immediately. - template void recalculate(FuncT &F) { - if (Strategy == UpdateStrategy::Eager) { - if (DT) - DT->recalculate(F); - if (PDT) - PDT->recalculate(F); - return; - } - - // There is little performance gain if we pend the recalculation under - // Lazy UpdateStrategy so we recalculate available trees immediately. - - // Prevent forceFlushDeletedBB() from erasing DomTree or PostDomTree nodes. - IsRecalculatingDomTree = IsRecalculatingPostDomTree = true; - - // Because all trees are going to be up-to-date after recalculation, - // flush awaiting deleted BasicBlocks. - derived().forceFlushDeletedBB(); - if (DT) - DT->recalculate(F); - if (PDT) - PDT->recalculate(F); - - // Resume forceFlushDeletedBB() to erase DomTree or PostDomTree nodes. - IsRecalculatingDomTree = IsRecalculatingPostDomTree = false; - PendDTUpdateIndex = PendPDTUpdateIndex = PendUpdates.size(); - dropOutOfDateUpdates(); - } + template void recalculate(FuncT &F); /// Submit updates to all available trees. /// The Eager Strategy flushes updates immediately while the Lazy Strategy @@ -170,24 +142,7 @@ class GenericDomTreeUpdater { /// 2. It is illegal to submit any update that has already been submitted, /// i.e., you are supposed not to insert an existent edge or delete a /// nonexistent edge. - void applyUpdates(ArrayRef Updates) { - if (!DT && !PDT) - return; - - if (Strategy == UpdateStrategy::Lazy) { - PendUpdates.reserve(PendUpdates.size() + Updates.size()); - for (const auto &U : Updates) - if (!isSelfDominance(U)) - PendUpdates.push_back(U); - - return; - } - - if (DT) - DT->applyUpdates(Updates); - if (PDT) - PDT->applyUpdates(Updates); - } + void applyUpdates(ArrayRef Updates); /// Submit updates to all available trees. It will also /// 1. discard duplicated updates, @@ -210,58 +165,7 @@ class GenericDomTreeUpdater { /// 3. It is only legal to submit updates to an edge in the order CFG changes /// are made. The order you submit updates on different edges is not /// restricted. - void applyUpdatesPermissive(ArrayRef Updates) { - if (!DT && !PDT) - return; - - SmallSet, 8> Seen; - SmallVector DeduplicatedUpdates; - for (const auto &U : Updates) { - auto Edge = std::make_pair(U.getFrom(), U.getTo()); - // Because it is illegal to submit updates that have already been applied - // and updates to an edge need to be strictly ordered, - // it is safe to infer the existence of an edge from the first update - // to this edge. - // If the first update to an edge is "Delete", it means that the edge - // existed before. If the first update to an edge is "Insert", it means - // that the edge didn't exist before. - // - // For example, if the user submits {{Delete, A, B}, {Insert, A, B}}, - // because - // 1. it is illegal to submit updates that have already been applied, - // i.e., user cannot delete an nonexistent edge, - // 2. updates to an edge need to be strictly ordered, - // So, initially edge A -> B existed. - // We can then safely ignore future updates to this edge and directly - // inspect the current CFG: - // a. If the edge still exists, because the user cannot insert an existent - // edge, so both {Delete, A, B}, {Insert, A, B} actually happened and - // resulted in a no-op. DTU won't submit any update in this case. - // b. If the edge doesn't exist, we can then infer that {Delete, A, B} - // actually happened but {Insert, A, B} was an invalid update which never - // happened. DTU will submit {Delete, A, B} in this case. - if (!isSelfDominance(U) && Seen.count(Edge) == 0) { - Seen.insert(Edge); - // If the update doesn't appear in the CFG, it means that - // either the change isn't made or relevant operations - // result in a no-op. - if (isUpdateValid(U)) { - if (isLazy()) - PendUpdates.push_back(U); - else - DeduplicatedUpdates.push_back(U); - } - } - } - - if (Strategy == UpdateStrategy::Lazy) - return; - - if (DT) - DT->applyUpdates(DeduplicatedUpdates); - if (PDT) - PDT->applyUpdates(DeduplicatedUpdates); - } + void applyUpdatesPermissive(ArrayRef Updates); ///@} @@ -275,22 +179,12 @@ class GenericDomTreeUpdater { /// Flush DomTree updates and return DomTree. /// It flushes Deleted BBs if both trees are up-to-date. /// It must only be called when it has a DomTree. - DomTreeT &getDomTree() { - assert(DT && "Invalid acquisition of a null DomTree"); - applyDomTreeUpdates(); - dropOutOfDateUpdates(); - return *DT; - } + DomTreeT &getDomTree(); /// Flush PostDomTree updates and return PostDomTree. /// It flushes Deleted BBs if both trees are up-to-date. /// It must only be called when it has a PostDomTree. - PostDomTreeT &getPostDomTree() { - assert(PDT && "Invalid acquisition of a null PostDomTree"); - applyPostDomTreeUpdates(); - dropOutOfDateUpdates(); - return *PDT; - } + PostDomTreeT &getPostDomTree(); /// Apply all pending updates to available trees and flush all BasicBlocks /// awaiting deletion. @@ -304,98 +198,7 @@ class GenericDomTreeUpdater { ///@} /// Debug method to help view the internal state of this class. - LLVM_DUMP_METHOD void dump() const { -#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) - raw_ostream &OS = llvm::dbgs(); - - OS << "Available Trees: "; - if (DT || PDT) { - if (DT) - OS << "DomTree "; - if (PDT) - OS << "PostDomTree "; - OS << "\n"; - } else - OS << "None\n"; - - OS << "UpdateStrategy: "; - if (Strategy == UpdateStrategy::Eager) { - OS << "Eager\n"; - return; - } else - OS << "Lazy\n"; - int Index = 0; - - auto printUpdates = - [&](typename ArrayRef::const_iterator - begin, - typename ArrayRef::const_iterator - end) { - if (begin == end) - OS << " None\n"; - Index = 0; - for (auto It = begin, ItEnd = end; It != ItEnd; ++It) { - auto U = *It; - OS << " " << Index << " : "; - ++Index; - if (U.getKind() == DomTreeT::Insert) - OS << "Insert, "; - else - OS << "Delete, "; - BasicBlockT *From = U.getFrom(); - if (From) { - auto S = From->getName(); - if (!From->hasName()) - S = "(no name)"; - OS << S << "(" << From << "), "; - } else { - OS << "(badref), "; - } - BasicBlockT *To = U.getTo(); - if (To) { - auto S = To->getName(); - if (!To->hasName()) - S = "(no_name)"; - OS << S << "(" << To << ")\n"; - } else { - OS << "(badref)\n"; - } - } - }; - - if (DT) { - const auto I = PendUpdates.begin() + PendDTUpdateIndex; - assert(PendUpdates.begin() <= I && I <= PendUpdates.end() && - "Iterator out of range."); - OS << "Applied but not cleared DomTreeUpdates:\n"; - printUpdates(PendUpdates.begin(), I); - OS << "Pending DomTreeUpdates:\n"; - printUpdates(I, PendUpdates.end()); - } - - if (PDT) { - const auto I = PendUpdates.begin() + PendPDTUpdateIndex; - assert(PendUpdates.begin() <= I && I <= PendUpdates.end() && - "Iterator out of range."); - OS << "Applied but not cleared PostDomTreeUpdates:\n"; - printUpdates(PendUpdates.begin(), I); - OS << "Pending PostDomTreeUpdates:\n"; - printUpdates(I, PendUpdates.end()); - } - - OS << "Pending DeletedBBs:\n"; - Index = 0; - for (const auto *BB : DeletedBBs) { - OS << " " << Index << " : "; - ++Index; - if (BB->hasName()) - OS << BB->getName() << "("; - else - OS << "(no_name)("; - OS << BB << ")\n"; - } -#endif - } + LLVM_DUMP_METHOD void dump() const; protected: SmallVector PendUpdates; @@ -415,109 +218,27 @@ class GenericDomTreeUpdater { } /// Helper function to apply all pending DomTree updates. - void applyDomTreeUpdates() { - // No pending DomTreeUpdates. - if (Strategy != UpdateStrategy::Lazy || !DT) - return; - - // Only apply updates not are applied by DomTree. - if (hasPendingDomTreeUpdates()) { - const auto I = PendUpdates.begin() + PendDTUpdateIndex; - const auto E = PendUpdates.end(); - assert(I < E && - "Iterator range invalid; there should be DomTree updates."); - DT->applyUpdates(ArrayRef(I, E)); - PendDTUpdateIndex = PendUpdates.size(); - } - } + void applyDomTreeUpdates(); /// Helper function to apply all pending PostDomTree updates. - void applyPostDomTreeUpdates() { - // No pending PostDomTreeUpdates. - if (Strategy != UpdateStrategy::Lazy || !PDT) - return; - - // Only apply updates not are applied by PostDomTree. - if (hasPendingPostDomTreeUpdates()) { - const auto I = PendUpdates.begin() + PendPDTUpdateIndex; - const auto E = PendUpdates.end(); - assert(I < E && - "Iterator range invalid; there should be PostDomTree updates."); - PDT->applyUpdates(ArrayRef(I, E)); - PendPDTUpdateIndex = PendUpdates.size(); - } - } + void applyPostDomTreeUpdates(); /// Returns true if the update appears in the LLVM IR. /// It is used to check whether an update is valid in /// insertEdge/deleteEdge or is unnecessary in the batch update. - bool isUpdateValid(typename DomTreeT::UpdateType Update) const { - const auto *From = Update.getFrom(); - const auto *To = Update.getTo(); - const auto Kind = Update.getKind(); - - // Discard updates by inspecting the current state of successors of From. - // Since isUpdateValid() must be called *after* the Terminator of From is - // altered we can determine if the update is unnecessary for batch updates - // or invalid for a single update. - const bool HasEdge = llvm::is_contained(successors(From), To); - - // If the IR does not match the update, - // 1. In batch updates, this update is unnecessary. - // 2. When called by insertEdge*()/deleteEdge*(), this update is invalid. - // Edge does not exist in IR. - if (Kind == DomTreeT::Insert && !HasEdge) - return false; - - // Edge exists in IR. - if (Kind == DomTreeT::Delete && HasEdge) - return false; - - return true; - } + bool isUpdateValid(typename DomTreeT::UpdateType Update) const; /// Erase Basic Block node that has been unlinked from Function /// in the DomTree and PostDomTree. - void eraseDelBBNode(BasicBlockT *DelBB) { - if (DT && !IsRecalculatingDomTree) - if (DT->getNode(DelBB)) - DT->eraseNode(DelBB); - - if (PDT && !IsRecalculatingPostDomTree) - if (PDT->getNode(DelBB)) - PDT->eraseNode(DelBB); - } + void eraseDelBBNode(BasicBlockT *DelBB); /// Helper function to flush deleted BasicBlocks if all available /// trees are up-to-date. - void tryFlushDeletedBB() { - if (!hasPendingUpdates()) - derived().forceFlushDeletedBB(); - } + void tryFlushDeletedBB(); /// Drop all updates applied by all available trees and delete BasicBlocks if /// all available trees are up-to-date. - void dropOutOfDateUpdates() { - if (Strategy == UpdateStrategy::Eager) - return; - - tryFlushDeletedBB(); - - // Drop all updates applied by both trees. - if (!DT) - PendDTUpdateIndex = PendUpdates.size(); - if (!PDT) - PendPDTUpdateIndex = PendUpdates.size(); - - const size_t dropIndex = std::min(PendDTUpdateIndex, PendPDTUpdateIndex); - const auto B = PendUpdates.begin(); - const auto E = PendUpdates.begin() + dropIndex; - assert(B <= E && "Iterator out of range."); - PendUpdates.erase(B, E); - // Calculate current index. - PendDTUpdateIndex -= dropIndex; - PendPDTUpdateIndex -= dropIndex; - } + void dropOutOfDateUpdates(); }; } // namespace llvm diff --git a/llvm/include/llvm/Analysis/GenericDomTreeUpdaterImpl.h b/llvm/include/llvm/Analysis/GenericDomTreeUpdaterImpl.h new file mode 100644 index 0000000000000..35c54a6062bfd --- /dev/null +++ b/llvm/include/llvm/Analysis/GenericDomTreeUpdaterImpl.h @@ -0,0 +1,353 @@ +//===- GenericDomTreeUpdaterImpl.h ------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This file implements the GenericDomTreeUpdater class. This file should only +// be included by files that implement a specialization of the relevant +// templates. Currently these are: +// - llvm/lib/Analysis/DomTreeUpdater.cpp +// - llvm/lib/CodeGen/MachineDomTreeUpdater.cpp +// +//===----------------------------------------------------------------------===// +#ifndef LLVM_ANALYSIS_GENERICDOMTREEUPDATERIMPL_H +#define LLVM_ANALYSIS_GENERICDOMTREEUPDATERIMPL_H + +#include "llvm/Analysis/GenericDomTreeUpdater.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/raw_ostream.h" + +namespace llvm { + +template +template +void GenericDomTreeUpdater::recalculate( + FuncT &F) { + if (Strategy == UpdateStrategy::Eager) { + if (DT) + DT->recalculate(F); + if (PDT) + PDT->recalculate(F); + return; + } + + // There is little performance gain if we pend the recalculation under + // Lazy UpdateStrategy so we recalculate available trees immediately. + + // Prevent forceFlushDeletedBB() from erasing DomTree or PostDomTree nodes. + IsRecalculatingDomTree = IsRecalculatingPostDomTree = true; + + // Because all trees are going to be up-to-date after recalculation, + // flush awaiting deleted BasicBlocks. + derived().forceFlushDeletedBB(); + if (DT) + DT->recalculate(F); + if (PDT) + PDT->recalculate(F); + + // Resume forceFlushDeletedBB() to erase DomTree or PostDomTree nodes. + IsRecalculatingDomTree = IsRecalculatingPostDomTree = false; + PendDTUpdateIndex = PendPDTUpdateIndex = PendUpdates.size(); + dropOutOfDateUpdates(); +} + +template +void GenericDomTreeUpdater::applyUpdates( + ArrayRef Updates) { + if (!DT && !PDT) + return; + + if (Strategy == UpdateStrategy::Lazy) { + PendUpdates.reserve(PendUpdates.size() + Updates.size()); + for (const auto &U : Updates) + if (!isSelfDominance(U)) + PendUpdates.push_back(U); + + return; + } + + if (DT) + DT->applyUpdates(Updates); + if (PDT) + PDT->applyUpdates(Updates); +} + +template +void GenericDomTreeUpdater:: + applyUpdatesPermissive(ArrayRef Updates) { + if (!DT && !PDT) + return; + + SmallSet, 8> Seen; + SmallVector DeduplicatedUpdates; + for (const auto &U : Updates) { + auto Edge = std::make_pair(U.getFrom(), U.getTo()); + // Because it is illegal to submit updates that have already been applied + // and updates to an edge need to be strictly ordered, + // it is safe to infer the existence of an edge from the first update + // to this edge. + // If the first update to an edge is "Delete", it means that the edge + // existed before. If the first update to an edge is "Insert", it means + // that the edge didn't exist before. + // + // For example, if the user submits {{Delete, A, B}, {Insert, A, B}}, + // because + // 1. it is illegal to submit updates that have already been applied, + // i.e., user cannot delete an nonexistent edge, + // 2. updates to an edge need to be strictly ordered, + // So, initially edge A -> B existed. + // We can then safely ignore future updates to this edge and directly + // inspect the current CFG: + // a. If the edge still exists, because the user cannot insert an existent + // edge, so both {Delete, A, B}, {Insert, A, B} actually happened and + // resulted in a no-op. DTU won't submit any update in this case. + // b. If the edge doesn't exist, we can then infer that {Delete, A, B} + // actually happened but {Insert, A, B} was an invalid update which never + // happened. DTU will submit {Delete, A, B} in this case. + if (!isSelfDominance(U) && Seen.count(Edge) == 0) { + Seen.insert(Edge); + // If the update doesn't appear in the CFG, it means that + // either the change isn't made or relevant operations + // result in a no-op. + if (isUpdateValid(U)) { + if (isLazy()) + PendUpdates.push_back(U); + else + DeduplicatedUpdates.push_back(U); + } + } + } + + if (Strategy == UpdateStrategy::Lazy) + return; + + if (DT) + DT->applyUpdates(DeduplicatedUpdates); + if (PDT) + PDT->applyUpdates(DeduplicatedUpdates); +} + +template +DomTreeT & +GenericDomTreeUpdater::getDomTree() { + assert(DT && "Invalid acquisition of a null DomTree"); + applyDomTreeUpdates(); + dropOutOfDateUpdates(); + return *DT; +} + +template +PostDomTreeT & +GenericDomTreeUpdater::getPostDomTree() { + assert(PDT && "Invalid acquisition of a null PostDomTree"); + applyPostDomTreeUpdates(); + dropOutOfDateUpdates(); + return *PDT; +} + +template +LLVM_DUMP_METHOD void +GenericDomTreeUpdater::dump() const { +#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) + raw_ostream &OS = llvm::dbgs(); + + OS << "Available Trees: "; + if (DT || PDT) { + if (DT) + OS << "DomTree "; + if (PDT) + OS << "PostDomTree "; + OS << "\n"; + } else + OS << "None\n"; + + OS << "UpdateStrategy: "; + if (Strategy == UpdateStrategy::Eager) { + OS << "Eager\n"; + return; + } else + OS << "Lazy\n"; + int Index = 0; + + auto printUpdates = + [&](typename ArrayRef::const_iterator + begin, + typename ArrayRef::const_iterator + end) { + if (begin == end) + OS << " None\n"; + Index = 0; + for (auto It = begin, ItEnd = end; It != ItEnd; ++It) { + auto U = *It; + OS << " " << Index << " : "; + ++Index; + if (U.getKind() == DomTreeT::Insert) + OS << "Insert, "; + else + OS << "Delete, "; + BasicBlockT *From = U.getFrom(); + if (From) { + auto S = From->getName(); + if (!From->hasName()) + S = "(no name)"; + OS << S << "(" << From << "), "; + } else { + OS << "(badref), "; + } + BasicBlockT *To = U.getTo(); + if (To) { + auto S = To->getName(); + if (!To->hasName()) + S = "(no_name)"; + OS << S << "(" << To << ")\n"; + } else { + OS << "(badref)\n"; + } + } + }; + + if (DT) { + const auto I = PendUpdates.begin() + PendDTUpdateIndex; + assert(PendUpdates.begin() <= I && I <= PendUpdates.end() && + "Iterator out of range."); + OS << "Applied but not cleared DomTreeUpdates:\n"; + printUpdates(PendUpdates.begin(), I); + OS << "Pending DomTreeUpdates:\n"; + printUpdates(I, PendUpdates.end()); + } + + if (PDT) { + const auto I = PendUpdates.begin() + PendPDTUpdateIndex; + assert(PendUpdates.begin() <= I && I <= PendUpdates.end() && + "Iterator out of range."); + OS << "Applied but not cleared PostDomTreeUpdates:\n"; + printUpdates(PendUpdates.begin(), I); + OS << "Pending PostDomTreeUpdates:\n"; + printUpdates(I, PendUpdates.end()); + } + + OS << "Pending DeletedBBs:\n"; + Index = 0; + for (const auto *BB : DeletedBBs) { + OS << " " << Index << " : "; + ++Index; + if (BB->hasName()) + OS << BB->getName() << "("; + else + OS << "(no_name)("; + OS << BB << ")\n"; + } +#endif +} + +template +void GenericDomTreeUpdater::applyDomTreeUpdates() { + // No pending DomTreeUpdates. + if (Strategy != UpdateStrategy::Lazy || !DT) + return; + + // Only apply updates not are applied by DomTree. + if (hasPendingDomTreeUpdates()) { + const auto I = PendUpdates.begin() + PendDTUpdateIndex; + const auto E = PendUpdates.end(); + assert(I < E && "Iterator range invalid; there should be DomTree updates."); + DT->applyUpdates(ArrayRef(I, E)); + PendDTUpdateIndex = PendUpdates.size(); + } +} + +template +void GenericDomTreeUpdater::applyPostDomTreeUpdates() { + // No pending PostDomTreeUpdates. + if (Strategy != UpdateStrategy::Lazy || !PDT) + return; + + // Only apply updates not are applied by PostDomTree. + if (hasPendingPostDomTreeUpdates()) { + const auto I = PendUpdates.begin() + PendPDTUpdateIndex; + const auto E = PendUpdates.end(); + assert(I < E && + "Iterator range invalid; there should be PostDomTree updates."); + PDT->applyUpdates(ArrayRef(I, E)); + PendPDTUpdateIndex = PendUpdates.size(); + } +} + +template +bool GenericDomTreeUpdater::isUpdateValid( + typename DomTreeT::UpdateType Update) const { + const auto *From = Update.getFrom(); + const auto *To = Update.getTo(); + const auto Kind = Update.getKind(); + + // Discard updates by inspecting the current state of successors of From. + // Since isUpdateValid() must be called *after* the Terminator of From is + // altered we can determine if the update is unnecessary for batch updates + // or invalid for a single update. + const bool HasEdge = llvm::is_contained(successors(From), To); + + // If the IR does not match the update, + // 1. In batch updates, this update is unnecessary. + // 2. When called by insertEdge*()/deleteEdge*(), this update is invalid. + // Edge does not exist in IR. + if (Kind == DomTreeT::Insert && !HasEdge) + return false; + + // Edge exists in IR. + if (Kind == DomTreeT::Delete && HasEdge) + return false; + + return true; +} + +template +void GenericDomTreeUpdater::eraseDelBBNode( + BasicBlockT *DelBB) { + if (DT && !IsRecalculatingDomTree) + if (DT->getNode(DelBB)) + DT->eraseNode(DelBB); + + if (PDT && !IsRecalculatingPostDomTree) + if (PDT->getNode(DelBB)) + PDT->eraseNode(DelBB); +} + +template +void GenericDomTreeUpdater::tryFlushDeletedBB() { + if (!hasPendingUpdates()) + derived().forceFlushDeletedBB(); +} + +template +void GenericDomTreeUpdater::dropOutOfDateUpdates() { + if (Strategy == UpdateStrategy::Eager) + return; + + tryFlushDeletedBB(); + + // Drop all updates applied by both trees. + if (!DT) + PendDTUpdateIndex = PendUpdates.size(); + if (!PDT) + PendPDTUpdateIndex = PendUpdates.size(); + + const size_t dropIndex = std::min(PendDTUpdateIndex, PendPDTUpdateIndex); + const auto B = PendUpdates.begin(); + const auto E = PendUpdates.begin() + dropIndex; + assert(B <= E && "Iterator out of range."); + PendUpdates.erase(B, E); + // Calculate current index. + PendDTUpdateIndex -= dropIndex; + PendPDTUpdateIndex -= dropIndex; +} + +} // namespace llvm + +#endif // LLVM_ANALYSIS_GENERICDOMTREEUPDATERIMPL_H diff --git a/llvm/include/llvm/CodeGen/MachineDomTreeUpdater.h b/llvm/include/llvm/CodeGen/MachineDomTreeUpdater.h index 9e59ba5f01ab7..e08b6b54c8e70 100644 --- a/llvm/include/llvm/CodeGen/MachineDomTreeUpdater.h +++ b/llvm/include/llvm/CodeGen/MachineDomTreeUpdater.h @@ -14,18 +14,13 @@ #ifndef LLVM_CODEGEN_MACHINEDOMTREEUPDATER_H #define LLVM_CODEGEN_MACHINEDOMTREEUPDATER_H -#include "llvm/ADT/SmallPtrSet.h" #include "llvm/Analysis/GenericDomTreeUpdater.h" #include "llvm/CodeGen/MachineDominators.h" -#include "llvm/CodeGen/MachinePostDominators.h" -#include "llvm/IR/ValueHandle.h" -#include "llvm/Support/Compiler.h" -#include -#include -#include namespace llvm { +class MachinePostDominatorTree; + class MachineDomTreeUpdater : public GenericDomTreeUpdater { @@ -67,5 +62,10 @@ class MachineDomTreeUpdater extern template class GenericDomTreeUpdater< MachineDomTreeUpdater, MachineDominatorTree, MachinePostDominatorTree>; + +extern template void +GenericDomTreeUpdater::recalculate(MachineFunction + &MF); } // namespace llvm #endif // LLVM_CODEGEN_MACHINEDOMTREEUPDATER_H diff --git a/llvm/lib/Analysis/DomTreeUpdater.cpp b/llvm/lib/Analysis/DomTreeUpdater.cpp index 676cb87210176..6895317c1d03a 100644 --- a/llvm/lib/Analysis/DomTreeUpdater.cpp +++ b/llvm/lib/Analysis/DomTreeUpdater.cpp @@ -13,6 +13,7 @@ #include "llvm/Analysis/DomTreeUpdater.h" #include "llvm/ADT/SmallSet.h" +#include "llvm/Analysis/GenericDomTreeUpdaterImpl.h" #include "llvm/Analysis/PostDominators.h" #include "llvm/IR/Constants.h" #include "llvm/IR/Instructions.h" @@ -26,6 +27,10 @@ namespace llvm { template class GenericDomTreeUpdater; +template void +GenericDomTreeUpdater::recalculate(Function &F); + bool DomTreeUpdater::forceFlushDeletedBB() { if (DeletedBBs.empty()) return false; @@ -94,4 +99,23 @@ void DomTreeUpdater::validateDeleteBB(BasicBlock *DelBB) { new UnreachableInst(DelBB->getContext(), DelBB); } +LLVM_DUMP_METHOD +void DomTreeUpdater::dump() const { + Base::dump(); +#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) + raw_ostream &OS = dbgs(); + OS << "Pending Callbacks:\n"; + int Index = 0; + for (const auto &BB : Callbacks) { + OS << " " << Index << " : "; + ++Index; + if (BB->hasName()) + OS << BB->getName() << "("; + else + OS << "(no_name)("; + OS << BB << ")\n"; + } +#endif +} + } // namespace llvm diff --git a/llvm/lib/CodeGen/MachineDomTreeUpdater.cpp b/llvm/lib/CodeGen/MachineDomTreeUpdater.cpp index 86b3185ca90a3..afffafb245e67 100644 --- a/llvm/lib/CodeGen/MachineDomTreeUpdater.cpp +++ b/llvm/lib/CodeGen/MachineDomTreeUpdater.cpp @@ -13,9 +13,8 @@ #include "llvm/CodeGen/MachineDomTreeUpdater.h" #include "llvm/ADT/SmallSet.h" +#include "llvm/Analysis/GenericDomTreeUpdaterImpl.h" #include "llvm/CodeGen/MachinePostDominators.h" -#include "llvm/IR/Constants.h" -#include "llvm/IR/Instructions.h" #include "llvm/Support/GenericDomTree.h" #include #include @@ -26,6 +25,11 @@ namespace llvm { template class GenericDomTreeUpdater< MachineDomTreeUpdater, MachineDominatorTree, MachinePostDominatorTree>; +template void +GenericDomTreeUpdater::recalculate(MachineFunction + &MF); + bool MachineDomTreeUpdater::forceFlushDeletedBB() { if (DeletedBBs.empty()) return false;