16#ifndef LLVM_ANALYSIS_GENERICDOMTREEUPDATERIMPL_H
17#define LLVM_ANALYSIS_GENERICDOMTREEUPDATERIMPL_H
26template <
typename DerivedT,
typename DomTreeT,
typename PostDomTreeT>
27template <
typename FuncT>
46 derived().forceFlushDeletedBB();
58template <
typename DerivedT,
typename DomTreeT,
typename PostDomTreeT>
66 for (
const auto &U : Updates)
74 DT->applyUpdates(Updates);
76 PDT->applyUpdates(Updates);
79template <
typename DerivedT,
typename DomTreeT,
typename PostDomTreeT>
87 for (
const auto &U : Updates) {
88 auto Edge = std::make_pair(U.getFrom(), U.getTo());
128 DT->applyUpdates(DeduplicatedUpdates);
130 PDT->applyUpdates(DeduplicatedUpdates);
133template <
typename DerivedT,
typename DomTreeT,
typename PostDomTreeT>
146 splitDTCriticalEdges(
E);
148 splitPDTCriticalEdges(
E);
151template <
typename DerivedT,
typename DomTreeT,
typename PostDomTreeT>
154 assert(
DT &&
"Invalid acquisition of a null DomTree");
160template <
typename DerivedT,
typename DomTreeT,
typename PostDomTreeT>
163 assert(
PDT &&
"Invalid acquisition of a null PostDomTree");
169template <
typename DerivedT,
typename DomTreeT,
typename PostDomTreeT>
172#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
175 OS <<
"Available Trees: ";
180 OS <<
"PostDomTree ";
185 OS <<
"UpdateStrategy: ";
195 auto S = BB->getName();
198 OS << S <<
"(" << BB <<
")" << Ending;
200 OS <<
"(badref)" << Ending;
210 for (
auto It = begin, ItEnd = end; It != ItEnd; ++It) {
211 if (!It->IsCriticalEdgeSplit) {
213 OS <<
" " << Index <<
" : ";
215 if (U.getKind() == DomTreeT::Insert)
219 printBlockInfo(U.getFrom(),
", ");
220 printBlockInfo(U.getTo(),
"\n");
222 const auto &Edge = It->EdgeSplit;
223 OS <<
" " << Index++ <<
" : Split critical edge, ";
224 printBlockInfo(Edge.FromBB,
", ");
225 printBlockInfo(Edge.ToBB,
", ");
226 printBlockInfo(Edge.NewBB,
"\n");
234 "Iterator out of range.");
235 OS <<
"Applied but not cleared DomTreeUpdates:\n";
237 OS <<
"Pending DomTreeUpdates:\n";
244 "Iterator out of range.");
245 OS <<
"Applied but not cleared PostDomTreeUpdates:\n";
247 OS <<
"Pending PostDomTreeUpdates:\n";
251 OS <<
"Pending DeletedBBs:\n";
254 OS <<
" " << Index <<
" : ";
257 OS << BB->getName() <<
"(";
265template <
typename DerivedT,
typename DomTreeT,
typename PostDomTreeT>
266template <
bool IsForward>
268 PostDomTreeT>::applyUpdatesImpl() {
269 auto *DomTree = [&]() {
270 if constexpr (IsForward)
276 if (Strategy != UpdateStrategy::Lazy || !DomTree)
278 size_t &PendUpdateIndex = IsForward ? PendDTUpdateIndex : PendPDTUpdateIndex;
281 while (IsForward ? hasPendingDomTreeUpdates()
282 : hasPendingPostDomTreeUpdates()) {
283 auto I = PendUpdates.begin() + PendUpdateIndex;
284 const auto E = PendUpdates.end();
285 assert(
I <
E &&
"Iterator range invalid; there should be DomTree updates.");
286 if (!
I->IsCriticalEdgeSplit) {
288 for (;
I !=
E && !
I->IsCriticalEdgeSplit; ++
I)
289 NormalUpdates.push_back(
I->Update);
290 DomTree->applyUpdates(NormalUpdates);
291 PendUpdateIndex += NormalUpdates.size();
294 for (;
I !=
E &&
I->IsCriticalEdgeSplit; ++
I)
296 IsForward ? splitDTCriticalEdges(CriticalEdges)
297 : splitPDTCriticalEdges(CriticalEdges);
298 PendUpdateIndex += CriticalEdges.size();
303template <
typename DerivedT,
typename DomTreeT,
typename PostDomTreeT>
306 const auto *From = Update.getFrom();
307 const auto *To = Update.getTo();
308 const auto Kind = Update.getKind();
320 if (Kind == DomTreeT::Insert && !HasEdge)
324 if (Kind == DomTreeT::Delete && HasEdge)
330template <
typename DerivedT,
typename DomTreeT,
typename PostDomTreeT>
334 if (
DT->getNode(DelBB))
335 DT->eraseNode(DelBB);
338 if (
PDT->getNode(DelBB))
339 PDT->eraseNode(DelBB);
342template <
typename DerivedT,
typename DomTreeT,
typename PostDomTreeT>
346 derived().forceFlushDeletedBB();
349template <
typename DerivedT,
typename DomTreeT,
typename PostDomTreeT>
366 assert(
B <=
E &&
"Iterator out of range.");
373template <
typename DerivedT,
typename DomTreeT,
typename PostDomTreeT>
377 if (!DT || Edges.
empty())
387 for (
auto &Edge : Edges)
388 NewBBs.
insert(Edge.NewBB);
397 for (
const auto &[Idx, Edge] :
enumerate(Edges)) {
399 BasicBlockT *Succ = Edge.ToBB;
400 auto *SuccDTNode = DT->getNode(Succ);
403 if (PredBB == Edge.NewBB)
420 "critical edge split has more "
421 "than one predecessor!");
424 if (!DT->dominates(SuccDTNode, DT->getNode(PredBB))) {
425 IsNewIDom[Idx] =
false;
434 auto *NewDTNode = DT->addNewBlock(
Edge.NewBB,
Edge.FromBB);
440 DT->changeImmediateDominator(DT->getNode(
Edge.ToBB), NewDTNode);
446template <
typename DerivedT,
typename DomTreeT,
typename PostDomTreeT>
450 if (!PDT || Edges.empty())
453 std::vector<UpdateT> Updates;
454 for (
const auto &
Edge : Edges) {
455 Updates.push_back({PostDomTreeT::Insert,
Edge.FromBB,
Edge.NewBB});
456 Updates.push_back({PostDomTreeT::Insert,
Edge.NewBB,
Edge.ToBB});
458 Updates.push_back({PostDomTreeT::Delete,
Edge.FromBB,
Edge.ToBB});
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
#define LLVM_DUMP_METHOD
Mark debug helper function definitions like dump() that should not be stripped from debug builds.
std::pair< BasicBlock *, BasicBlock * > Edge
This file implements the SmallBitVector class.
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
const_pointer const_iterator
size_t size() const
size - Get the array size.
bool empty() const
empty - Check if the array is empty.
SmallPtrSet< BasicBlockT *, 8 > DeletedBBs
DomTreeT & getDomTree()
Flush DomTree updates and return DomTree.
PostDomTreeT & getPostDomTree()
Flush PostDomTree updates and return PostDomTree.
void applyPostDomTreeUpdates()
Helper function to apply all pending PostDomTree updates.
void applyUpdatesPermissive(ArrayRef< UpdateT > Updates)
Submit updates to all available trees.
void applyUpdates(ArrayRef< UpdateT > Updates)
Submit updates to all available trees.
bool IsRecalculatingPostDomTree
void eraseDelBBNode(BasicBlockT *DelBB)
Erase Basic Block node before it is unlinked from Function in the DomTree and PostDomTree.
bool hasPendingUpdates() const
Returns true if either of DT or PDT is valid and the tree has at least one update pending.
bool isSelfDominance(UpdateT Update) const
Returns true if the update is self dominance.
const UpdateStrategy Strategy
typename DomTreeT::UpdateType UpdateT
typename DomTreeT::NodeType BasicBlockT
void recalculate(FuncT &F)
Notify DTU that the entry block was replaced.
void tryFlushDeletedBB()
Helper function to flush deleted BasicBlocks if all available trees are up-to-date.
void dropOutOfDateUpdates()
Drop all updates applied by all available trees and delete BasicBlocks if all available trees are up-...
bool IsRecalculatingDomTree
size_t PendPDTUpdateIndex
void splitCriticalEdge(BasicBlockT *FromBB, BasicBlockT *ToBB, BasicBlockT *NewBB)
Apply updates that the critical edge (FromBB, ToBB) has been split with NewBB.
void applyDomTreeUpdates()
Helper function to apply all pending DomTree updates.
bool isUpdateValid(UpdateT Update) const
Returns true if the update appears in the LLVM IR.
SmallVector< DomTreeUpdate, 16 > PendUpdates
LLVM_DUMP_METHOD void dump() const
Debug method to help view the internal state of this class.
bool isLazy() const
Returns true if the current strategy is Lazy.
This is a 'bitvector' (really, a variable-sized bit array), optimized for the case when the array is ...
std::pair< iterator, bool > insert(PtrType Ptr)
Inserts Ptr if and only if there is no element in the container equal to Ptr.
bool contains(ConstPtrType Ptr) const
SmallPtrSet - This class implements a set which is optimized for holding SmallSize or less elements.
SmallSet - This maintains a set of unique values, optimizing for the case when the set is small (less...
std::pair< const_iterator, bool > insert(const T &V)
insert - Insert an element into the set if it isn't already there.
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
StringRef - Represent a constant reference to a string, i.e.
This class implements an extremely fast bulk output stream that can only output to a stream.
This is an optimization pass for GlobalISel generic memory operations.
auto enumerate(FirstRange &&First, RestRanges &&...Rest)
Given two or more input ranges, returns a new range whose values are tuples (A, B,...
auto successors(const MachineBasicBlock *BB)
auto pred_size(const MachineBasicBlock *BB)
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
auto pred_begin(const MachineBasicBlock *BB)
auto predecessors(const MachineBasicBlock *BB)
bool is_contained(R &&Range, const E &Element)
Returns true if Element is found in Range.
Helper structure used to hold all the basic blocks involved in the split of a critical edge.