blob: f035a86eddaed8b61255139fa94f26d0e343ca8a [file] [log] [blame]
Jakub Kuderski5e3ab7a2018-07-03 02:06:23 +00001//===- DomTreeUpdater.cpp - DomTree/Post DomTree Updater --------*- C++ -*-===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// This file implements the DomTreeUpdater class, which provides a uniform way
11// to update dominator tree related data structures.
12//
13//===----------------------------------------------------------------------===//
14
15#include "llvm/IR/DomTreeUpdater.h"
16#include "llvm/Analysis/PostDominators.h"
17#include "llvm/IR/Dominators.h"
18#include "llvm/Support/GenericDomTree.h"
19#include <algorithm>
20#include <functional>
21
22namespace llvm {
23
24bool DomTreeUpdater::isUpdateValid(
25 const DominatorTree::UpdateType Update) const {
26 const auto *From = Update.getFrom();
27 const auto *To = Update.getTo();
28 const auto Kind = Update.getKind();
29
30 // Discard updates by inspecting the current state of successors of From.
31 // Since isUpdateValid() must be called *after* the Terminator of From is
32 // altered we can determine if the update is unnecessary for batch updates
33 // or invalid for a single update.
34 const bool HasEdge = llvm::any_of(
35 successors(From), [To](const BasicBlock *B) { return B == To; });
36
37 // If the IR does not match the update,
38 // 1. In batch updates, this update is unnecessary.
39 // 2. When called by insertEdge*()/deleteEdge*(), this update is invalid.
40 // Edge does not exist in IR.
41 if (Kind == DominatorTree::Insert && !HasEdge)
42 return false;
43
44 // Edge exists in IR.
45 if (Kind == DominatorTree::Delete && HasEdge)
46 return false;
47
48 return true;
49}
50
51bool DomTreeUpdater::isSelfDominance(
52 const DominatorTree::UpdateType Update) const {
53 // Won't affect DomTree and PostDomTree.
54 return Update.getFrom() == Update.getTo();
55}
56
57bool DomTreeUpdater::applyLazyUpdate(DominatorTree::UpdateKind Kind,
58 BasicBlock *From, BasicBlock *To) {
Erich Keane3b6bcf62018-07-13 14:41:15 +000059 assert((DT || PDT) &&
60 "Call applyLazyUpdate() when both DT and PDT are nullptrs.");
Jakub Kuderski5e3ab7a2018-07-03 02:06:23 +000061 assert(Strategy == DomTreeUpdater::UpdateStrategy::Lazy &&
62 "Call applyLazyUpdate() with Eager strategy error");
63 // Analyze pending updates to determine if the update is unnecessary.
64 const DominatorTree::UpdateType Update = {Kind, From, To};
65 const DominatorTree::UpdateType Invert = {Kind != DominatorTree::Insert
66 ? DominatorTree::Insert
67 : DominatorTree::Delete,
68 From, To};
69 // Only check duplicates in updates that are not applied by both trees.
70 auto I =
71 PendUpdates.begin() + std::max(PendDTUpdateIndex, PendPDTUpdateIndex);
72 const auto E = PendUpdates.end();
73
74 assert(I <= E && "Iterator out of range.");
75
76 for (; I != E; ++I) {
77 if (Update == *I)
78 return false; // Discard duplicate updates.
79
80 if (Invert == *I) {
81 // Update and Invert are both valid (equivalent to a no-op). Remove
82 // Invert from PendUpdates and discard the Update.
83 PendUpdates.erase(I);
84 return false;
85 }
86 }
87
88 PendUpdates.push_back(Update); // Save the valid update.
89 return true;
90}
91
92void DomTreeUpdater::applyDomTreeUpdates() {
93 // No pending DomTreeUpdates.
94 if (Strategy != UpdateStrategy::Lazy || !DT)
95 return;
96
97 // Only apply updates not are applied by DomTree.
98 if (hasPendingDomTreeUpdates()) {
99 const auto I = PendUpdates.begin() + PendDTUpdateIndex;
100 const auto E = PendUpdates.end();
101 assert(I < E && "Iterator range invalid; there should be DomTree updates.");
102 DT->applyUpdates(ArrayRef<DominatorTree::UpdateType>(I, E));
103 PendDTUpdateIndex = PendUpdates.size();
104 }
105}
106
107void DomTreeUpdater::flush() {
108 applyDomTreeUpdates();
109 applyPostDomTreeUpdates();
110 dropOutOfDateUpdates();
111}
112
113void DomTreeUpdater::applyPostDomTreeUpdates() {
114 // No pending PostDomTreeUpdates.
115 if (Strategy != UpdateStrategy::Lazy || !PDT)
116 return;
117
118 // Only apply updates not are applied by PostDomTree.
119 if (hasPendingPostDomTreeUpdates()) {
120 const auto I = PendUpdates.begin() + PendPDTUpdateIndex;
121 const auto E = PendUpdates.end();
122 assert(I < E &&
123 "Iterator range invalid; there should be PostDomTree updates.");
124 PDT->applyUpdates(ArrayRef<DominatorTree::UpdateType>(I, E));
125 PendPDTUpdateIndex = PendUpdates.size();
126 }
127}
128
129void DomTreeUpdater::tryFlushDeletedBB() {
130 if (!hasPendingUpdates())
131 forceFlushDeletedBB();
132}
133
134bool DomTreeUpdater::forceFlushDeletedBB() {
135 if (DeletedBBs.empty())
136 return false;
137
138 for (auto *BB : DeletedBBs) {
Chijun Simabd5d80d2018-07-25 06:18:33 +0000139 // After calling deleteBB or callbackDeleteBB under Lazy UpdateStrategy,
140 // validateDeleteBB() removes all instructions of DelBB and adds an
141 // UnreachableInst as its terminator. So we check whether the BasicBlock to
142 // delete only has an UnreachableInst inside.
143 assert(BB->getInstList().size() == 1 &&
144 isa<UnreachableInst>(BB->getTerminator()) &&
145 "DelBB has been modified while awaiting deletion.");
Jakub Kuderski5e3ab7a2018-07-03 02:06:23 +0000146 BB->removeFromParent();
147 eraseDelBBNode(BB);
148 delete BB;
149 }
150 DeletedBBs.clear();
151 Callbacks.clear();
152 return true;
153}
154
155bool DomTreeUpdater::recalculate(Function &F) {
156 if (!DT && !PDT)
157 return false;
158
159 if (Strategy == UpdateStrategy::Eager) {
160 if (DT)
161 DT->recalculate(F);
162 if (PDT)
163 PDT->recalculate(F);
164 return true;
165 }
166
167 // Prevent forceFlushDeletedBB() from erasing DomTree or PostDomTree nodes.
168 IsRecalculatingDomTree = IsRecalculatingPostDomTree = true;
169
170 // Because all trees are going to be up-to-date after recalculation,
171 // flush awaiting deleted BasicBlocks.
172 if (forceFlushDeletedBB() || hasPendingUpdates()) {
173 if (DT)
174 DT->recalculate(F);
175 if (PDT)
176 PDT->recalculate(F);
177
178 // Resume forceFlushDeletedBB() to erase DomTree or PostDomTree nodes.
179 IsRecalculatingDomTree = IsRecalculatingPostDomTree = false;
180 PendDTUpdateIndex = PendPDTUpdateIndex = PendUpdates.size();
181 dropOutOfDateUpdates();
182 return true;
183 }
184
185 // Resume forceFlushDeletedBB() to erase DomTree or PostDomTree nodes.
186 IsRecalculatingDomTree = IsRecalculatingPostDomTree = false;
187 return false;
188}
189
190bool DomTreeUpdater::hasPendingUpdates() const {
191 return hasPendingDomTreeUpdates() || hasPendingPostDomTreeUpdates();
192}
193
194bool DomTreeUpdater::hasPendingDomTreeUpdates() const {
195 if (!DT)
196 return false;
197 return PendUpdates.size() != PendDTUpdateIndex;
198}
199
200bool DomTreeUpdater::hasPendingPostDomTreeUpdates() const {
201 if (!PDT)
202 return false;
203 return PendUpdates.size() != PendPDTUpdateIndex;
204}
205
206bool DomTreeUpdater::isBBPendingDeletion(llvm::BasicBlock *DelBB) const {
207 if (Strategy == UpdateStrategy::Eager || DeletedBBs.empty())
208 return false;
209 return DeletedBBs.count(DelBB) != 0;
210}
211
212// The DT and PDT require the nodes related to updates
213// are not deleted when update functions are called.
214// So BasicBlock deletions must be pended when the
215// UpdateStrategy is Lazy. When the UpdateStrategy is
216// Eager, the BasicBlock will be deleted immediately.
217void DomTreeUpdater::deleteBB(BasicBlock *DelBB) {
218 validateDeleteBB(DelBB);
219 if (Strategy == UpdateStrategy::Lazy) {
220 DeletedBBs.insert(DelBB);
221 return;
222 }
223
224 DelBB->removeFromParent();
225 eraseDelBBNode(DelBB);
226 delete DelBB;
227}
228
229void DomTreeUpdater::callbackDeleteBB(
230 BasicBlock *DelBB, std::function<void(BasicBlock *)> Callback) {
231 validateDeleteBB(DelBB);
232 if (Strategy == UpdateStrategy::Lazy) {
233 Callbacks.push_back(CallBackOnDeletion(DelBB, Callback));
234 DeletedBBs.insert(DelBB);
235 return;
236 }
237
238 DelBB->removeFromParent();
239 eraseDelBBNode(DelBB);
240 Callback(DelBB);
241 delete DelBB;
242}
243
244void DomTreeUpdater::eraseDelBBNode(BasicBlock *DelBB) {
245 if (DT && !IsRecalculatingDomTree)
246 if (DT->getNode(DelBB))
247 DT->eraseNode(DelBB);
248
249 if (PDT && !IsRecalculatingPostDomTree)
250 if (PDT->getNode(DelBB))
251 PDT->eraseNode(DelBB);
252}
253
254void DomTreeUpdater::validateDeleteBB(BasicBlock *DelBB) {
255 assert(DelBB && "Invalid push_back of nullptr DelBB.");
256 assert(pred_empty(DelBB) && "DelBB has one or more predecessors.");
257 // DelBB is unreachable and all its instructions are dead.
258 while (!DelBB->empty()) {
259 Instruction &I = DelBB->back();
260 // Replace used instructions with an arbitrary value (undef).
261 if (!I.use_empty())
262 I.replaceAllUsesWith(llvm::UndefValue::get(I.getType()));
263 DelBB->getInstList().pop_back();
264 }
265 // Make sure DelBB has a valid terminator instruction. As long as DelBB is a
266 // Child of Function F it must contain valid IR.
267 new UnreachableInst(DelBB->getContext(), DelBB);
268}
269
270void DomTreeUpdater::applyUpdates(ArrayRef<DominatorTree::UpdateType> Updates,
271 bool ForceRemoveDuplicates) {
Chijun Sima00712cb2018-07-13 04:02:13 +0000272 if (!DT && !PDT)
273 return;
274
Jakub Kuderski5e3ab7a2018-07-03 02:06:23 +0000275 if (Strategy == UpdateStrategy::Lazy || ForceRemoveDuplicates) {
276 SmallVector<DominatorTree::UpdateType, 8> Seen;
277 for (const auto U : Updates)
278 // For Lazy UpdateStrategy, avoid duplicates to applyLazyUpdate() to save
279 // on analysis.
280 if (llvm::none_of(
281 Seen,
282 [U](const DominatorTree::UpdateType S) { return S == U; }) &&
283 isUpdateValid(U) && !isSelfDominance(U)) {
284 Seen.push_back(U);
285 if (Strategy == UpdateStrategy::Lazy)
286 applyLazyUpdate(U.getKind(), U.getFrom(), U.getTo());
287 }
288 if (Strategy == UpdateStrategy::Lazy)
289 return;
290
291 if (DT)
292 DT->applyUpdates(Seen);
293 if (PDT)
294 PDT->applyUpdates(Seen);
295 return;
296 }
297
298 if (DT)
299 DT->applyUpdates(Updates);
300 if (PDT)
301 PDT->applyUpdates(Updates);
302}
303
304DominatorTree &DomTreeUpdater::getDomTree() {
305 assert(DT && "Invalid acquisition of a null DomTree");
306 applyDomTreeUpdates();
307 dropOutOfDateUpdates();
308 return *DT;
309}
310
311PostDominatorTree &DomTreeUpdater::getPostDomTree() {
312 assert(PDT && "Invalid acquisition of a null PostDomTree");
313 applyPostDomTreeUpdates();
314 dropOutOfDateUpdates();
315 return *PDT;
316}
317
318void DomTreeUpdater::insertEdge(BasicBlock *From, BasicBlock *To) {
319
320#ifndef NDEBUG
321 assert(isUpdateValid({DominatorTree::Insert, From, To}) &&
322 "Inserted edge does not appear in the CFG");
323#endif
324
Chijun Sima00712cb2018-07-13 04:02:13 +0000325 if (!DT && !PDT)
326 return;
327
Jakub Kuderski5e3ab7a2018-07-03 02:06:23 +0000328 // Won't affect DomTree and PostDomTree; discard update.
329 if (From == To)
330 return;
331
332 if (Strategy == UpdateStrategy::Eager) {
333 if (DT)
334 DT->insertEdge(From, To);
335 if (PDT)
336 PDT->insertEdge(From, To);
337 return;
338 }
339
340 applyLazyUpdate(DominatorTree::Insert, From, To);
341}
342
Chijun Sima00712cb2018-07-13 04:02:13 +0000343void DomTreeUpdater::insertEdgeRelaxed(BasicBlock *From, BasicBlock *To) {
Jakub Kuderski5e3ab7a2018-07-03 02:06:23 +0000344 if (From == To)
Chijun Sima00712cb2018-07-13 04:02:13 +0000345 return;
346
347 if (!DT && !PDT)
348 return;
349
350 if (!isUpdateValid({DominatorTree::Insert, From, To}))
351 return;
Jakub Kuderski5e3ab7a2018-07-03 02:06:23 +0000352
353 if (Strategy == UpdateStrategy::Eager) {
354 if (DT)
355 DT->insertEdge(From, To);
356 if (PDT)
357 PDT->insertEdge(From, To);
Chijun Sima00712cb2018-07-13 04:02:13 +0000358 return;
Jakub Kuderski5e3ab7a2018-07-03 02:06:23 +0000359 }
360
361 applyLazyUpdate(DominatorTree::Insert, From, To);
Jakub Kuderski5e3ab7a2018-07-03 02:06:23 +0000362}
363
364void DomTreeUpdater::deleteEdge(BasicBlock *From, BasicBlock *To) {
365
366#ifndef NDEBUG
367 assert(isUpdateValid({DominatorTree::Delete, From, To}) &&
368 "Deleted edge still exists in the CFG!");
369#endif
370
Chijun Sima00712cb2018-07-13 04:02:13 +0000371 if (!DT && !PDT)
372 return;
373
Jakub Kuderski5e3ab7a2018-07-03 02:06:23 +0000374 // Won't affect DomTree and PostDomTree; discard update.
375 if (From == To)
376 return;
377
378 if (Strategy == UpdateStrategy::Eager) {
379 if (DT)
380 DT->deleteEdge(From, To);
381 if (PDT)
382 PDT->deleteEdge(From, To);
383 return;
384 }
385
386 applyLazyUpdate(DominatorTree::Delete, From, To);
387}
388
Chijun Sima00712cb2018-07-13 04:02:13 +0000389void DomTreeUpdater::deleteEdgeRelaxed(BasicBlock *From, BasicBlock *To) {
Jakub Kuderski5e3ab7a2018-07-03 02:06:23 +0000390 if (From == To)
Chijun Sima00712cb2018-07-13 04:02:13 +0000391 return;
392
393 if (!DT && !PDT)
394 return;
395
396 if (!isUpdateValid({DominatorTree::Delete, From, To}))
397 return;
Jakub Kuderski5e3ab7a2018-07-03 02:06:23 +0000398
399 if (Strategy == UpdateStrategy::Eager) {
400 if (DT)
401 DT->deleteEdge(From, To);
402 if (PDT)
403 PDT->deleteEdge(From, To);
Chijun Sima00712cb2018-07-13 04:02:13 +0000404 return;
Jakub Kuderski5e3ab7a2018-07-03 02:06:23 +0000405 }
406
407 applyLazyUpdate(DominatorTree::Delete, From, To);
Jakub Kuderski5e3ab7a2018-07-03 02:06:23 +0000408}
409
410void DomTreeUpdater::dropOutOfDateUpdates() {
411 if (Strategy == DomTreeUpdater::UpdateStrategy::Eager)
412 return;
413
414 tryFlushDeletedBB();
415
416 // Drop all updates applied by both trees.
417 if (!DT)
418 PendDTUpdateIndex = PendUpdates.size();
419 if (!PDT)
420 PendPDTUpdateIndex = PendUpdates.size();
421
422 const size_t dropIndex = std::min(PendDTUpdateIndex, PendPDTUpdateIndex);
423 const auto B = PendUpdates.begin();
424 const auto E = PendUpdates.begin() + dropIndex;
425 assert(B <= E && "Iterator out of range.");
426 PendUpdates.erase(B, E);
427 // Calculate current index.
428 PendDTUpdateIndex -= dropIndex;
429 PendPDTUpdateIndex -= dropIndex;
430}
431
432#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
433LLVM_DUMP_METHOD void DomTreeUpdater::dump() const {
434 raw_ostream &OS = llvm::dbgs();
435
436 OS << "Available Trees: ";
437 if (DT || PDT) {
438 if (DT)
439 OS << "DomTree ";
440 if (PDT)
441 OS << "PostDomTree ";
442 OS << "\n";
443 } else
444 OS << "None\n";
445
446 OS << "UpdateStrategy: ";
447 if (Strategy == UpdateStrategy::Eager) {
448 OS << "Eager\n";
449 return;
450 } else
451 OS << "Lazy\n";
452 int Index = 0;
453
454 auto printUpdates =
455 [&](ArrayRef<DominatorTree::UpdateType>::const_iterator begin,
456 ArrayRef<DominatorTree::UpdateType>::const_iterator end) {
457 if (begin == end)
458 OS << " None\n";
459 Index = 0;
460 for (auto It = begin, ItEnd = end; It != ItEnd; ++It) {
461 auto U = *It;
462 OS << " " << Index << " : ";
463 ++Index;
464 if (U.getKind() == DominatorTree::Insert)
465 OS << "Insert, ";
466 else
467 OS << "Delete, ";
468 BasicBlock *From = U.getFrom();
469 if (From) {
470 auto S = From->getName();
471 if (!From->hasName())
472 S = "(no name)";
473 OS << S << "(" << From << "), ";
474 } else {
475 OS << "(badref), ";
476 }
477 BasicBlock *To = U.getTo();
478 if (To) {
479 auto S = To->getName();
480 if (!To->hasName())
481 S = "(no_name)";
482 OS << S << "(" << To << ")\n";
483 } else {
484 OS << "(badref)\n";
485 }
486 }
487 };
488
489 if (DT) {
490 const auto I = PendUpdates.begin() + PendDTUpdateIndex;
491 assert(PendUpdates.begin() <= I && I <= PendUpdates.end() &&
492 "Iterator out of range.");
493 OS << "Applied but not cleared DomTreeUpdates:\n";
494 printUpdates(PendUpdates.begin(), I);
495 OS << "Pending DomTreeUpdates:\n";
496 printUpdates(I, PendUpdates.end());
497 }
498
499 if (PDT) {
500 const auto I = PendUpdates.begin() + PendPDTUpdateIndex;
501 assert(PendUpdates.begin() <= I && I <= PendUpdates.end() &&
502 "Iterator out of range.");
503 OS << "Applied but not cleared PostDomTreeUpdates:\n";
504 printUpdates(PendUpdates.begin(), I);
505 OS << "Pending PostDomTreeUpdates:\n";
506 printUpdates(I, PendUpdates.end());
507 }
508
509 OS << "Pending DeletedBBs:\n";
510 Index = 0;
511 for (auto BB : DeletedBBs) {
512 OS << " " << Index << " : ";
513 ++Index;
514 if (BB->hasName())
515 OS << BB->getName() << "(";
516 else
517 OS << "(no_name)(";
518 OS << BB << ")\n";
519 }
520
521 OS << "Pending Callbacks:\n";
522 Index = 0;
523 for (auto BB : Callbacks) {
524 OS << " " << Index << " : ";
525 ++Index;
526 if (BB->hasName())
527 OS << BB->getName() << "(";
528 else
529 OS << "(no_name)(";
530 OS << BB << ")\n";
531 }
532}
533#endif
534} // namespace llvm