1 //===- DomTreeUpdater.cpp - DomTree/Post DomTree Updater --------*- C++ -*-===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
9 // This file implements the DomTreeUpdater class, which provides a uniform way
10 // to update dominator tree related data structures.
12 //===----------------------------------------------------------------------===//
14 #include "llvm/Analysis/DomTreeUpdater.h"
15 #include "llvm/Analysis/PostDominators.h"
16 #include "llvm/IR/Dominators.h"
17 #include "llvm/Support/GenericDomTree.h"
23 bool DomTreeUpdater::isUpdateValid(
24 const DominatorTree::UpdateType Update
) const {
25 const auto *From
= Update
.getFrom();
26 const auto *To
= Update
.getTo();
27 const auto Kind
= Update
.getKind();
29 // Discard updates by inspecting the current state of successors of From.
30 // Since isUpdateValid() must be called *after* the Terminator of From is
31 // altered we can determine if the update is unnecessary for batch updates
32 // or invalid for a single update.
33 const bool HasEdge
= llvm::any_of(
34 successors(From
), [To
](const BasicBlock
*B
) { return B
== To
; });
36 // If the IR does not match the update,
37 // 1. In batch updates, this update is unnecessary.
38 // 2. When called by insertEdge*()/deleteEdge*(), this update is invalid.
39 // Edge does not exist in IR.
40 if (Kind
== DominatorTree::Insert
&& !HasEdge
)
44 if (Kind
== DominatorTree::Delete
&& HasEdge
)
50 bool DomTreeUpdater::isSelfDominance(
51 const DominatorTree::UpdateType Update
) const {
52 // Won't affect DomTree and PostDomTree.
53 return Update
.getFrom() == Update
.getTo();
56 bool DomTreeUpdater::applyLazyUpdate(DominatorTree::UpdateKind Kind
,
57 BasicBlock
*From
, BasicBlock
*To
) {
59 "Call applyLazyUpdate() when both DT and PDT are nullptrs.");
60 assert(Strategy
== DomTreeUpdater::UpdateStrategy::Lazy
&&
61 "Call applyLazyUpdate() with Eager strategy error");
62 // Analyze pending updates to determine if the update is unnecessary.
63 const DominatorTree::UpdateType Update
= {Kind
, From
, To
};
64 const DominatorTree::UpdateType Invert
= {Kind
!= DominatorTree::Insert
65 ? DominatorTree::Insert
66 : DominatorTree::Delete
,
68 // Only check duplicates in updates that are not applied by both trees.
70 PendUpdates
.begin() + std::max(PendDTUpdateIndex
, PendPDTUpdateIndex
);
71 const auto E
= PendUpdates
.end();
73 assert(I
<= E
&& "Iterator out of range.");
77 return false; // Discard duplicate updates.
80 // Update and Invert are both valid (equivalent to a no-op). Remove
81 // Invert from PendUpdates and discard the Update.
87 PendUpdates
.push_back(Update
); // Save the valid update.
91 void DomTreeUpdater::applyDomTreeUpdates() {
92 // No pending DomTreeUpdates.
93 if (Strategy
!= UpdateStrategy::Lazy
|| !DT
)
96 // Only apply updates not are applied by DomTree.
97 if (hasPendingDomTreeUpdates()) {
98 const auto I
= PendUpdates
.begin() + PendDTUpdateIndex
;
99 const auto E
= PendUpdates
.end();
100 assert(I
< E
&& "Iterator range invalid; there should be DomTree updates.");
101 DT
->applyUpdates(ArrayRef
<DominatorTree::UpdateType
>(I
, E
));
102 PendDTUpdateIndex
= PendUpdates
.size();
106 void DomTreeUpdater::flush() {
107 applyDomTreeUpdates();
108 applyPostDomTreeUpdates();
109 dropOutOfDateUpdates();
112 void DomTreeUpdater::applyPostDomTreeUpdates() {
113 // No pending PostDomTreeUpdates.
114 if (Strategy
!= UpdateStrategy::Lazy
|| !PDT
)
117 // Only apply updates not are applied by PostDomTree.
118 if (hasPendingPostDomTreeUpdates()) {
119 const auto I
= PendUpdates
.begin() + PendPDTUpdateIndex
;
120 const auto E
= PendUpdates
.end();
122 "Iterator range invalid; there should be PostDomTree updates.");
123 PDT
->applyUpdates(ArrayRef
<DominatorTree::UpdateType
>(I
, E
));
124 PendPDTUpdateIndex
= PendUpdates
.size();
128 void DomTreeUpdater::tryFlushDeletedBB() {
129 if (!hasPendingUpdates())
130 forceFlushDeletedBB();
133 bool DomTreeUpdater::forceFlushDeletedBB() {
134 if (DeletedBBs
.empty())
137 for (auto *BB
: DeletedBBs
) {
138 // After calling deleteBB or callbackDeleteBB under Lazy UpdateStrategy,
139 // validateDeleteBB() removes all instructions of DelBB and adds an
140 // UnreachableInst as its terminator. So we check whether the BasicBlock to
141 // delete only has an UnreachableInst inside.
142 assert(BB
->getInstList().size() == 1 &&
143 isa
<UnreachableInst
>(BB
->getTerminator()) &&
144 "DelBB has been modified while awaiting deletion.");
145 BB
->removeFromParent();
154 void DomTreeUpdater::recalculate(Function
&F
) {
156 if (Strategy
== UpdateStrategy::Eager
) {
164 // There is little performance gain if we pend the recalculation under
165 // Lazy UpdateStrategy so we recalculate available trees immediately.
167 // Prevent forceFlushDeletedBB() from erasing DomTree or PostDomTree nodes.
168 IsRecalculatingDomTree
= IsRecalculatingPostDomTree
= true;
170 // Because all trees are going to be up-to-date after recalculation,
171 // flush awaiting deleted BasicBlocks.
172 forceFlushDeletedBB();
178 // Resume forceFlushDeletedBB() to erase DomTree or PostDomTree nodes.
179 IsRecalculatingDomTree
= IsRecalculatingPostDomTree
= false;
180 PendDTUpdateIndex
= PendPDTUpdateIndex
= PendUpdates
.size();
181 dropOutOfDateUpdates();
184 bool DomTreeUpdater::hasPendingUpdates() const {
185 return hasPendingDomTreeUpdates() || hasPendingPostDomTreeUpdates();
188 bool DomTreeUpdater::hasPendingDomTreeUpdates() const {
191 return PendUpdates
.size() != PendDTUpdateIndex
;
194 bool DomTreeUpdater::hasPendingPostDomTreeUpdates() const {
197 return PendUpdates
.size() != PendPDTUpdateIndex
;
200 bool DomTreeUpdater::isBBPendingDeletion(llvm::BasicBlock
*DelBB
) const {
201 if (Strategy
== UpdateStrategy::Eager
|| DeletedBBs
.empty())
203 return DeletedBBs
.count(DelBB
) != 0;
206 // The DT and PDT require the nodes related to updates
207 // are not deleted when update functions are called.
208 // So BasicBlock deletions must be pended when the
209 // UpdateStrategy is Lazy. When the UpdateStrategy is
210 // Eager, the BasicBlock will be deleted immediately.
211 void DomTreeUpdater::deleteBB(BasicBlock
*DelBB
) {
212 validateDeleteBB(DelBB
);
213 if (Strategy
== UpdateStrategy::Lazy
) {
214 DeletedBBs
.insert(DelBB
);
218 DelBB
->removeFromParent();
219 eraseDelBBNode(DelBB
);
223 void DomTreeUpdater::callbackDeleteBB(
224 BasicBlock
*DelBB
, std::function
<void(BasicBlock
*)> Callback
) {
225 validateDeleteBB(DelBB
);
226 if (Strategy
== UpdateStrategy::Lazy
) {
227 Callbacks
.push_back(CallBackOnDeletion(DelBB
, Callback
));
228 DeletedBBs
.insert(DelBB
);
232 DelBB
->removeFromParent();
233 eraseDelBBNode(DelBB
);
238 void DomTreeUpdater::eraseDelBBNode(BasicBlock
*DelBB
) {
239 if (DT
&& !IsRecalculatingDomTree
)
240 if (DT
->getNode(DelBB
))
241 DT
->eraseNode(DelBB
);
243 if (PDT
&& !IsRecalculatingPostDomTree
)
244 if (PDT
->getNode(DelBB
))
245 PDT
->eraseNode(DelBB
);
248 void DomTreeUpdater::validateDeleteBB(BasicBlock
*DelBB
) {
249 assert(DelBB
&& "Invalid push_back of nullptr DelBB.");
250 assert(pred_empty(DelBB
) && "DelBB has one or more predecessors.");
251 // DelBB is unreachable and all its instructions are dead.
252 while (!DelBB
->empty()) {
253 Instruction
&I
= DelBB
->back();
254 // Replace used instructions with an arbitrary value (undef).
256 I
.replaceAllUsesWith(llvm::UndefValue::get(I
.getType()));
257 DelBB
->getInstList().pop_back();
259 // Make sure DelBB has a valid terminator instruction. As long as DelBB is a
260 // Child of Function F it must contain valid IR.
261 new UnreachableInst(DelBB
->getContext(), DelBB
);
264 void DomTreeUpdater::applyUpdates(ArrayRef
<DominatorTree::UpdateType
> Updates
,
265 bool ForceRemoveDuplicates
) {
269 if (Strategy
== UpdateStrategy::Lazy
|| ForceRemoveDuplicates
) {
270 SmallVector
<DominatorTree::UpdateType
, 8> Seen
;
271 for (const auto U
: Updates
)
272 // For Lazy UpdateStrategy, avoid duplicates to applyLazyUpdate() to save
276 [U
](const DominatorTree::UpdateType S
) { return S
== U
; }) &&
277 isUpdateValid(U
) && !isSelfDominance(U
)) {
279 if (Strategy
== UpdateStrategy::Lazy
)
280 applyLazyUpdate(U
.getKind(), U
.getFrom(), U
.getTo());
282 if (Strategy
== UpdateStrategy::Lazy
)
286 DT
->applyUpdates(Seen
);
288 PDT
->applyUpdates(Seen
);
293 DT
->applyUpdates(Updates
);
295 PDT
->applyUpdates(Updates
);
298 DominatorTree
&DomTreeUpdater::getDomTree() {
299 assert(DT
&& "Invalid acquisition of a null DomTree");
300 applyDomTreeUpdates();
301 dropOutOfDateUpdates();
305 PostDominatorTree
&DomTreeUpdater::getPostDomTree() {
306 assert(PDT
&& "Invalid acquisition of a null PostDomTree");
307 applyPostDomTreeUpdates();
308 dropOutOfDateUpdates();
312 void DomTreeUpdater::insertEdge(BasicBlock
*From
, BasicBlock
*To
) {
315 assert(isUpdateValid({DominatorTree::Insert
, From
, To
}) &&
316 "Inserted edge does not appear in the CFG");
322 // Won't affect DomTree and PostDomTree; discard update.
326 if (Strategy
== UpdateStrategy::Eager
) {
328 DT
->insertEdge(From
, To
);
330 PDT
->insertEdge(From
, To
);
334 applyLazyUpdate(DominatorTree::Insert
, From
, To
);
337 void DomTreeUpdater::insertEdgeRelaxed(BasicBlock
*From
, BasicBlock
*To
) {
344 if (!isUpdateValid({DominatorTree::Insert
, From
, To
}))
347 if (Strategy
== UpdateStrategy::Eager
) {
349 DT
->insertEdge(From
, To
);
351 PDT
->insertEdge(From
, To
);
355 applyLazyUpdate(DominatorTree::Insert
, From
, To
);
358 void DomTreeUpdater::deleteEdge(BasicBlock
*From
, BasicBlock
*To
) {
361 assert(isUpdateValid({DominatorTree::Delete
, From
, To
}) &&
362 "Deleted edge still exists in the CFG!");
368 // Won't affect DomTree and PostDomTree; discard update.
372 if (Strategy
== UpdateStrategy::Eager
) {
374 DT
->deleteEdge(From
, To
);
376 PDT
->deleteEdge(From
, To
);
380 applyLazyUpdate(DominatorTree::Delete
, From
, To
);
383 void DomTreeUpdater::deleteEdgeRelaxed(BasicBlock
*From
, BasicBlock
*To
) {
390 if (!isUpdateValid({DominatorTree::Delete
, From
, To
}))
393 if (Strategy
== UpdateStrategy::Eager
) {
395 DT
->deleteEdge(From
, To
);
397 PDT
->deleteEdge(From
, To
);
401 applyLazyUpdate(DominatorTree::Delete
, From
, To
);
404 void DomTreeUpdater::dropOutOfDateUpdates() {
405 if (Strategy
== DomTreeUpdater::UpdateStrategy::Eager
)
410 // Drop all updates applied by both trees.
412 PendDTUpdateIndex
= PendUpdates
.size();
414 PendPDTUpdateIndex
= PendUpdates
.size();
416 const size_t dropIndex
= std::min(PendDTUpdateIndex
, PendPDTUpdateIndex
);
417 const auto B
= PendUpdates
.begin();
418 const auto E
= PendUpdates
.begin() + dropIndex
;
419 assert(B
<= E
&& "Iterator out of range.");
420 PendUpdates
.erase(B
, E
);
421 // Calculate current index.
422 PendDTUpdateIndex
-= dropIndex
;
423 PendPDTUpdateIndex
-= dropIndex
;
426 #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
427 LLVM_DUMP_METHOD
void DomTreeUpdater::dump() const {
428 raw_ostream
&OS
= llvm::dbgs();
430 OS
<< "Available Trees: ";
435 OS
<< "PostDomTree ";
440 OS
<< "UpdateStrategy: ";
441 if (Strategy
== UpdateStrategy::Eager
) {
449 [&](ArrayRef
<DominatorTree::UpdateType
>::const_iterator begin
,
450 ArrayRef
<DominatorTree::UpdateType
>::const_iterator end
) {
454 for (auto It
= begin
, ItEnd
= end
; It
!= ItEnd
; ++It
) {
456 OS
<< " " << Index
<< " : ";
458 if (U
.getKind() == DominatorTree::Insert
)
462 BasicBlock
*From
= U
.getFrom();
464 auto S
= From
->getName();
465 if (!From
->hasName())
467 OS
<< S
<< "(" << From
<< "), ";
471 BasicBlock
*To
= U
.getTo();
473 auto S
= To
->getName();
476 OS
<< S
<< "(" << To
<< ")\n";
484 const auto I
= PendUpdates
.begin() + PendDTUpdateIndex
;
485 assert(PendUpdates
.begin() <= I
&& I
<= PendUpdates
.end() &&
486 "Iterator out of range.");
487 OS
<< "Applied but not cleared DomTreeUpdates:\n";
488 printUpdates(PendUpdates
.begin(), I
);
489 OS
<< "Pending DomTreeUpdates:\n";
490 printUpdates(I
, PendUpdates
.end());
494 const auto I
= PendUpdates
.begin() + PendPDTUpdateIndex
;
495 assert(PendUpdates
.begin() <= I
&& I
<= PendUpdates
.end() &&
496 "Iterator out of range.");
497 OS
<< "Applied but not cleared PostDomTreeUpdates:\n";
498 printUpdates(PendUpdates
.begin(), I
);
499 OS
<< "Pending PostDomTreeUpdates:\n";
500 printUpdates(I
, PendUpdates
.end());
503 OS
<< "Pending DeletedBBs:\n";
505 for (auto BB
: DeletedBBs
) {
506 OS
<< " " << Index
<< " : ";
509 OS
<< BB
->getName() << "(";
515 OS
<< "Pending Callbacks:\n";
517 for (auto BB
: Callbacks
) {
518 OS
<< " " << Index
<< " : ";
521 OS
<< BB
->getName() << "(";