summaryrefslogtreecommitdiff
path: root/include/llvm/IR/Dominators.h
diff options
context:
space:
mode:
Diffstat (limited to 'include/llvm/IR/Dominators.h')
-rw-r--r--include/llvm/IR/Dominators.h126
1 files changed, 100 insertions, 26 deletions
diff --git a/include/llvm/IR/Dominators.h b/include/llvm/IR/Dominators.h
index 6ad99e516fba..f9e992b0ef0c 100644
--- a/include/llvm/IR/Dominators.h
+++ b/include/llvm/IR/Dominators.h
@@ -63,8 +63,10 @@ extern template void DeleteEdge<BBPostDomTree>(BBPostDomTree &DT,
extern template void ApplyUpdates<BBDomTree>(BBDomTree &DT, BBUpdates);
extern template void ApplyUpdates<BBPostDomTree>(BBPostDomTree &DT, BBUpdates);
-extern template bool Verify<BBDomTree>(const BBDomTree &DT);
-extern template bool Verify<BBPostDomTree>(const BBPostDomTree &DT);
+extern template bool Verify<BBDomTree>(const BBDomTree &DT,
+ BBDomTree::VerificationLevel VL);
+extern template bool Verify<BBPostDomTree>(const BBPostDomTree &DT,
+ BBPostDomTree::VerificationLevel VL);
} // namespace DomTreeBuilder
using DomTreeNode = DomTreeNodeBase<BasicBlock>;
@@ -119,7 +121,7 @@ template <> struct DenseMapInfo<BasicBlockEdge> {
}
};
-/// \brief Concrete subclass of DominatorTreeBase that is used to compute a
+/// Concrete subclass of DominatorTreeBase that is used to compute a
/// normal dominator tree.
///
/// Definition: A block is said to be forward statically reachable if there is
@@ -148,19 +150,10 @@ class DominatorTree : public DominatorTreeBase<BasicBlock, false> {
bool invalidate(Function &F, const PreservedAnalyses &PA,
FunctionAnalysisManager::Invalidator &);
- /// \brief Returns *false* if the other dominator tree matches this dominator
- /// tree.
- inline bool compare(const DominatorTree &Other) const {
- const DomTreeNode *R = getRootNode();
- const DomTreeNode *OtherR = Other.getRootNode();
- return !R || !OtherR || R->getBlock() != OtherR->getBlock() ||
- Base::compare(Other);
- }
-
// Ensure base-class overloads are visible.
using Base::dominates;
- /// \brief Return true if Def dominates a use in User.
+ /// Return true if Def dominates a use in User.
///
/// This performs the special checks necessary if Def and User are in the same
/// basic block. Note that Def doesn't dominate a use in Def itself!
@@ -178,15 +171,9 @@ class DominatorTree : public DominatorTreeBase<BasicBlock, false> {
// Ensure base class overloads are visible.
using Base::isReachableFromEntry;
- /// \brief Provide an overload for a Use.
+ /// Provide an overload for a Use.
bool isReachableFromEntry(const Use &U) const;
- /// \brief Verify the correctness of the domtree by re-computing it.
- ///
- /// This should only be used for debugging as it aborts the program if the
- /// verification fails.
- void verifyDomTree() const;
-
// Pop up a GraphViz/gv window with the Dominator Tree rendered using `dot`.
void viewGraph(const Twine &Name, const Twine &Title);
void viewGraph();
@@ -234,20 +221,20 @@ template <> struct GraphTraits<DominatorTree*>
}
};
-/// \brief Analysis pass which computes a \c DominatorTree.
+/// Analysis pass which computes a \c DominatorTree.
class DominatorTreeAnalysis : public AnalysisInfoMixin<DominatorTreeAnalysis> {
friend AnalysisInfoMixin<DominatorTreeAnalysis>;
static AnalysisKey Key;
public:
- /// \brief Provide the result typedef for this analysis pass.
+ /// Provide the result typedef for this analysis pass.
using Result = DominatorTree;
- /// \brief Run the analysis pass over a function and produce a dominator tree.
+ /// Run the analysis pass over a function and produce a dominator tree.
DominatorTree run(Function &F, FunctionAnalysisManager &);
};
-/// \brief Printer pass for the \c DominatorTree.
+/// Printer pass for the \c DominatorTree.
class DominatorTreePrinterPass
: public PassInfoMixin<DominatorTreePrinterPass> {
raw_ostream &OS;
@@ -258,12 +245,12 @@ public:
PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM);
};
-/// \brief Verifier pass for the \c DominatorTree.
+/// Verifier pass for the \c DominatorTree.
struct DominatorTreeVerifierPass : PassInfoMixin<DominatorTreeVerifierPass> {
PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM);
};
-/// \brief Legacy analysis pass which computes a \c DominatorTree.
+/// Legacy analysis pass which computes a \c DominatorTree.
class DominatorTreeWrapperPass : public FunctionPass {
DominatorTree DT;
@@ -290,6 +277,93 @@ public:
void print(raw_ostream &OS, const Module *M = nullptr) const override;
};
+//===-------------------------------------
+/// Class to defer updates to a DominatorTree.
+///
+/// Definition: Applying updates to every edge insertion and deletion is
+/// expensive and not necessary. When one needs the DominatorTree for analysis
+/// they can request a flush() to perform a larger batch update. This has the
+/// advantage of the DominatorTree inspecting the set of updates to find
+/// duplicates or unnecessary subtree updates.
+///
+/// The scope of DeferredDominance operates at a Function level.
+///
+/// It is not necessary for the user to scrub the updates for duplicates or
+/// updates that point to the same block (Delete, BB_A, BB_A). Performance
+/// can be gained if the caller attempts to batch updates before submitting
+/// to applyUpdates(ArrayRef) in cases where duplicate edge requests will
+/// occur.
+///
+/// It is required for the state of the LLVM IR to be applied *before*
+/// submitting updates. The update routines must analyze the current state
+/// between a pair of (From, To) basic blocks to determine if the update
+/// needs to be queued.
+/// Example (good):
+/// TerminatorInstructionBB->removeFromParent();
+/// DDT->deleteEdge(BB, Successor);
+/// Example (bad):
+/// DDT->deleteEdge(BB, Successor);
+/// TerminatorInstructionBB->removeFromParent();
+class DeferredDominance {
+public:
+ DeferredDominance(DominatorTree &DT_) : DT(DT_) {}
+
+ /// Queues multiple updates and discards duplicates.
+ void applyUpdates(ArrayRef<DominatorTree::UpdateType> Updates);
+
+ /// Helper method for a single edge insertion. It's almost always
+ /// better to batch updates and call applyUpdates to quickly remove duplicate
+ /// edges. This is best used when there is only a single insertion needed to
+ /// update Dominators.
+ void insertEdge(BasicBlock *From, BasicBlock *To);
+
+ /// Helper method for a single edge deletion. It's almost always better
+ /// to batch updates and call applyUpdates to quickly remove duplicate edges.
+ /// This is best used when there is only a single deletion needed to update
+ /// Dominators.
+ void deleteEdge(BasicBlock *From, BasicBlock *To);
+
+ /// Delays the deletion of a basic block until a flush() event.
+ void deleteBB(BasicBlock *DelBB);
+
+ /// Returns true if DelBB is awaiting deletion at a flush() event.
+ bool pendingDeletedBB(BasicBlock *DelBB);
+
+ /// Returns true if pending DT updates are queued for a flush() event.
+ bool pending();
+
+ /// Flushes all pending updates and block deletions. Returns a
+ /// correct DominatorTree reference to be used by the caller for analysis.
+ DominatorTree &flush();
+
+ /// Drops all internal state and forces a (slow) recalculation of the
+ /// DominatorTree based on the current state of the LLVM IR in F. This should
+ /// only be used in corner cases such as the Entry block of F being deleted.
+ void recalculate(Function &F);
+
+ /// Debug method to help view the state of pending updates.
+ LLVM_DUMP_METHOD void dump() const;
+
+private:
+ DominatorTree &DT;
+ SmallVector<DominatorTree::UpdateType, 16> PendUpdates;
+ SmallPtrSet<BasicBlock *, 8> DeletedBBs;
+
+ /// Apply an update (Kind, From, To) to the internal queued updates. The
+ /// update is only added when determined to be necessary. Checks for
+ /// self-domination, unnecessary updates, duplicate requests, and balanced
+ /// pairs of requests are all performed. Returns true if the update is
+ /// queued and false if it is discarded.
+ bool applyUpdate(DominatorTree::UpdateKind Kind, BasicBlock *From,
+ BasicBlock *To);
+
+ /// Performs all pending basic block deletions. We have to defer the deletion
+ /// of these blocks until after the DominatorTree updates are applied. The
+ /// internal workings of the DominatorTree code expect every update's From
+ /// and To blocks to exist and to be a member of the same Function.
+ bool flushDelBB();
+};
+
} // end namespace llvm
#endif // LLVM_IR_DOMINATORS_H