llvm.org GIT mirror llvm / bf4ec2b
[Dominators] Add the DomTreeUpdater class Summary: This patch is the first in a series of patches related to the [[ http://lists.llvm.org/pipermail/llvm-dev/2018-June/123883.html | RFC - A new dominator tree updater for LLVM ]]. This patch introduces the DomTreeUpdater class, which provides a cleaner API to perform updates on available dominator trees (none, only DomTree, only PostDomTree, both) using different update strategies (eagerly or lazily) to simplify the updating process. —Prior to the patch— - Directly calling update functions of DominatorTree updates the data structure eagerly while DeferredDominance does updates lazily. - DeferredDominance class cannot be used when a PostDominatorTree also needs to be updated. - Functions receiving DT/DDT need to branch a lot which is currently necessary. - Functions using both DomTree and PostDomTree need to call the update function separately on both trees. - People need to construct an additional DeferredDominance class to use functions only receiving DDT. —After the patch— Patch by Chijun Sima <simachijun@gmail.com>. Reviewers: kuhar, brzycki, dmgreen, grosser, davide Reviewed By: kuhar, brzycki Subscribers: vsk, mgorny, llvm-commits Author: NutshellySima Differential Revision: https://reviews.llvm.org/D48383 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@336114 91177308-0d34-0410-b5e6-96231b3b80d8 Jakub Kuderski 1 year, 3 months ago
6 changed file(s) with 1450 addition(s) and 0 deletion(s). Raw diff Collapse all Expand all
0 //===- DomTreeUpdater.h - DomTree/Post DomTree Updater ----------*- C++ -*-===//
1 //
2 // The LLVM Compiler Infrastructure
3 //
4 // This file is distributed under the University of Illinois Open Source
5 // License. See LICENSE.TXT for details.
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // This file defines the DomTreeUpdater class, which provides a uniform way to
10 // update dominator tree related data structures.
11 //
12 //===----------------------------------------------------------------------===//
13
14 #ifndef LLVM_DOMTREEUPDATER_H
15 #define LLVM_DOMTREEUPDATER_H
16
17 #include "llvm/Analysis/PostDominators.h"
18 #include "llvm/IR/Dominators.h"
19 #include "llvm/IR/Instructions.h"
20 #include "llvm/IR/ValueHandle.h"
21 #include "llvm/Support/GenericDomTree.h"
22 #include
23
24 namespace llvm {
25 class DomTreeUpdater {
26 public:
27 enum class UpdateStrategy : unsigned char { Eager = 0, Lazy = 1 };
28
29 explicit DomTreeUpdater(UpdateStrategy Strategy_) : Strategy(Strategy_) {}
30 DomTreeUpdater(DominatorTree &DT_, UpdateStrategy Strategy_)
31 : DT(&DT_), Strategy(Strategy_) {}
32 DomTreeUpdater(PostDominatorTree &PDT_, UpdateStrategy Strategy_)
33 : PDT(&PDT_), Strategy(Strategy_) {}
34 DomTreeUpdater(DominatorTree &DT_, PostDominatorTree &PDT_,
35 UpdateStrategy Strategy_)
36 : DT(&DT_), PDT(&PDT_), Strategy(Strategy_) {}
37
38 ~DomTreeUpdater() { flush(); }
39
40 /// Returns the UpdateStrategy of the class instance.
41 UpdateStrategy getUpdateStrategy() const { return Strategy; };
42
43 /// Returns true if it holds a DominatorTree.
44 bool hasDomTree() const { return DT != nullptr; }
45
46 /// Returns true if it holds a PostDominatorTree.
47 bool hasPostDomTree() const { return PDT != nullptr; }
48
49 /// Returns true if there is BasicBlock awaiting deletion.
50 /// The deletion will only happen until a flush event and
51 /// all available trees are up-to-date.
52 /// Returns false under Eager UpdateStrategy.
53 bool hasPendingDeletedBB() const { return !DeletedBBs.empty(); }
54
55 /// Returns true if DelBB is awaiting deletion.
56 /// Returns false under Eager UpdateStrategy.
57 bool isBBPendingDeletion(BasicBlock *DelBB) const;
58
59 /// Returns true if either of DT or PDT is valid and the tree has at
60 /// least one update pending. If DT or PDT is nullptr it is treated
61 /// as having no pending updates. This function does not check
62 /// whether there is BasicBlock awaiting deletion.
63 /// Returns false under Eager UpdateStrategy.
64 bool hasPendingUpdates() const;
65
66 /// Returns true if there are DominatorTree updates queued.
67 /// Returns false under Eager UpdateStrategy.
68 bool hasPendingDomTreeUpdates() const;
69
70 /// Returns true if there are PostDominatorTree updates queued.
71 /// Returns false under Eager UpdateStrategy.
72 bool hasPendingPostDomTreeUpdates() const;
73
74 /// Apply updates on all available trees. Under Eager UpdateStrategy with
75 /// ForceRemoveDuplicates enabled or under Lazy UpdateStrategy, it will
76 /// discard duplicated updates and self-dominance updates. The Eager
77 /// Strategy applies the updates immediately while the Lazy Strategy
78 /// queues the updates. It is required for the state of
79 /// the LLVM IR to be updated *before* applying the Updates because the
80 /// internal update routine will analyze the current state of the relationship
81 /// between a pair of (From, To) BasicBlocks to determine whether a single
82 /// update needs to be discarded.
83 void applyUpdates(ArrayRef Updates,
84 bool ForceRemoveDuplicates = false);
85
86 /// Notify all available trees on an edge insertion. Under either Strategy,
87 /// self-dominance update will be removed. The Eager Strategy applies
88 /// the update immediately while the Lazy Strategy queues the update.
89 /// It is recommended to only use this method when you have exactly one
90 /// insertion (and no deletions). It is recommended to use applyUpdates() in
91 /// all other cases. This function has to be called *after* making the update
92 /// on the actual CFG. An internal functions checks if the edge exists in the
93 /// CFG in DEBUG mode.
94 void insertEdge(BasicBlock *From, BasicBlock *To);
95
96 /// Notify all available trees on an edge insertion.
97 /// Under either Strategy, these updates will be discard silently in the
98 /// following sequence
99 /// 1. Invalid - Inserting an edge that does not exist in the CFG.
100 /// 2. Self-dominance update.
101 /// The Eager Strategy applies the update immediately while the Lazy Strategy
102 /// queues the update. It is recommended to only use this method when you have
103 /// exactly one insertion (and no deletions) and want to discard an invalid
104 /// update. Returns true if the update is valid.
105 bool insertEdgeRelaxed(BasicBlock *From, BasicBlock *To);
106
107 /// Notify all available trees on an edge deletion. Under either Strategy,
108 /// self-dominance update will be removed. The Eager Strategy applies
109 /// the update immediately while the Lazy Strategy queues the update.
110 /// It is recommended to only use this method when you have exactly one
111 /// deletion (and no insertions). It is recommended to use applyUpdates() in
112 /// all other cases. This function has to be called *after* making the update
113 /// on the actual CFG. An internal functions checks if the edge doesn't exist
114 /// in the CFG in DEBUG mode.
115 void deleteEdge(BasicBlock *From, BasicBlock *To);
116
117 /// Notify all available trees on an edge deletion.
118 /// Under either Strategy, these updates will be discard silently in the
119 /// following sequence:
120 /// 1. Invalid - Deleting an edge that still exists in the CFG.
121 /// 2. Self-dominance update.
122 /// The Eager Strategy applies the update immediately while the Lazy Strategy
123 /// queues the update. It is recommended to only use this method when you have
124 /// exactly one deletion (and no insertions) and want to discard an invalid
125 /// update. Returns true if the update is valid.
126 bool deleteEdgeRelaxed(BasicBlock *From, BasicBlock *To);
127
128 /// Delete DelBB. DelBB will be removed from its Parent and
129 /// erased from available trees if it exists and finally get deleted.
130 /// Under Eager UpdateStrategy, DelBB will be processed immediately.
131 /// Under Lazy UpdateStrategy, DelBB will be queued until a flush event and
132 /// all available trees are up-to-date.
133 void deleteBB(BasicBlock *DelBB);
134
135 /// Delete DelBB. DelBB will be removed from its Parent and
136 /// erased from available trees if it exists. Then the callback will
137 /// be called. Finally, DelBB will be deleted.
138 /// Under Eager UpdateStrategy, DelBB will be processed immediately.
139 /// Under Lazy UpdateStrategy, DelBB will be queued until a flush event and
140 /// all available trees are up-to-date.
141 /// Multiple callbacks can be queued for one DelBB under Lazy UpdateStrategy.
142 void callbackDeleteBB(BasicBlock *DelBB,
143 function_ref Callback);
144
145 /// Recalculate all available trees.
146 /// Under Lazy Strategy, available trees will only be recalculated if there
147 /// are pending updates or there is BasicBlock awaiting deletion. Returns true
148 /// if at least one tree is recalculated.
149 bool recalculate(Function &F);
150
151 /// Flush DomTree updates and return DomTree.
152 /// It also flush out of date updates applied by all available trees
153 /// and flush Deleted BBs if both trees are up-to-date.
154 /// It must only be called when it has a DomTree.
155 DominatorTree &getDomTree();
156
157 /// Flush PostDomTree updates and return PostDomTree.
158 /// It also flush out of date updates applied by all available trees
159 /// and flush Deleted BBs if both trees are up-to-date.
160 /// It must only be called when it has a PostDomTree.
161 PostDominatorTree &getPostDomTree();
162
163 /// Apply all pending updates to available trees and flush all BasicBlocks
164 /// awaiting deletion.
165 /// Does nothing under Eager UpdateStrategy.
166 void flush();
167
168 /// Debug method to help view the internal state of this class.
169 LLVM_DUMP_METHOD void dump() const;
170
171 private:
172 class CallBackOnDeletion final : public CallbackVH {
173 public:
174 CallBackOnDeletion(BasicBlock *V, function_ref Callback)
175 : CallbackVH(V), DelBB(V), Callback_(Callback) {}
176
177 private:
178 BasicBlock *DelBB = nullptr;
179 function_ref Callback_;
180
181 void deleted() override {
182 Callback_(DelBB);
183 CallbackVH::deleted();
184 }
185 };
186
187 SmallVector PendUpdates;
188 size_t PendDTUpdateIndex = 0;
189 size_t PendPDTUpdateIndex = 0;
190 DominatorTree *DT = nullptr;
191 PostDominatorTree *PDT = nullptr;
192 const UpdateStrategy Strategy;
193 SmallPtrSet DeletedBBs;
194 std::vector Callbacks;
195 bool IsRecalculatingDomTree = false;
196 bool IsRecalculatingPostDomTree = false;
197
198 /// First remove all the instructions of DelBB and then make sure DelBB has a
199 /// valid terminator instruction which is necessary to have when DelBB still
200 /// has to be inside of its parent Function while awaiting deletion under Lazy
201 /// UpdateStrategy to prevent other routines from asserting the state of the
202 /// IR is inconsistent. Assert if DelBB is nullptr or has predecessors.
203 void validateDeleteBB(BasicBlock *DelBB);
204
205 /// Returns true if at least one BasicBlock is deleted.
206 bool forceFlushDeletedBB();
207
208 /// Deduplicate and remove unnecessary updates (no-ops) when using Lazy
209 /// UpdateStrategy. Returns true if the update is queued for update.
210 bool applyLazyUpdate(DominatorTree::UpdateKind Kind, BasicBlock *From,
211 BasicBlock *To);
212
213 /// Helper function to apply all pending DomTree updates.
214 void applyDomTreeUpdates();
215
216 /// Helper function to apply all pending PostDomTree updates.
217 void applyPostDomTreeUpdates();
218
219 /// Helper function to flush deleted BasicBlocks if all available
220 /// trees are up-to-date.
221 void tryFlushDeletedBB();
222
223 /// Drop all updates applied by all available trees and delete BasicBlocks if
224 /// all available trees are up-to-date.
225 void dropOutOfDateUpdates();
226
227 /// Erase Basic Block node that has been unlinked from Function
228 /// in the DomTree and PostDomTree.
229 void eraseDelBBNode(BasicBlock *DelBB);
230
231 /// Returns true if the update appears in the LLVM IR.
232 /// It is used to check whether an update is valid in
233 /// insertEdge/deleteEdge or is unnecessary in the batch update.
234 bool isUpdateValid(DominatorTree::UpdateType Update) const;
235
236 /// Returns true if the update is self dominance.
237 bool isSelfDominance(DominatorTree::UpdateType Update) const;
238 };
239 } // namespace llvm
240
241 #endif // LLVM_DOMTREEUPDATER_H
195195 module IR_CFG { header "IR/CFG.h" export * }
196196 module IR_ConstantRange { header "IR/ConstantRange.h" export * }
197197 module IR_Dominators { header "IR/Dominators.h" export * }
198 module Analysis_PostDominators { header "Analysis/PostDominators.h" export * }
199 module IR_DomTreeUpdater { header "IR/DomTreeUpdater.h" export * }
198200 module IR_IRBuilder { header "IR/IRBuilder.h" export * }
199201 module IR_PassManager { header "IR/PassManager.h" export * }
200202 module IR_PredIteratorCache { header "IR/PredIteratorCache.h" export * }
2020 DiagnosticInfo.cpp
2121 DiagnosticPrinter.cpp
2222 Dominators.cpp
23 DomTreeUpdater.cpp
2324 Function.cpp
2425 GVMaterializer.cpp
2526 Globals.cpp
0 //===- DomTreeUpdater.cpp - DomTree/Post DomTree Updater --------*- C++ -*-===//
1 //
2 // The LLVM Compiler Infrastructure
3 //
4 // This file is distributed under the University of Illinois Open Source
5 // License. See LICENSE.TXT for details.
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // This file implements the DomTreeUpdater class, which provides a uniform way
10 // to update dominator tree related data structures.
11 //
12 //===----------------------------------------------------------------------===//
13
14 #include "llvm/IR/DomTreeUpdater.h"
15 #include "llvm/Analysis/PostDominators.h"
16 #include "llvm/IR/Dominators.h"
17 #include "llvm/Support/GenericDomTree.h"
18 #include
19
20 namespace llvm {
21
22 bool DomTreeUpdater::isUpdateValid(
23 const DominatorTree::UpdateType Update) const {
24 const auto *From = Update.getFrom();
25 const auto *To = Update.getTo();
26 const auto Kind = Update.getKind();
27
28 // Discard updates by inspecting the current state of successors of From.
29 // Since isUpdateValid() must be called *after* the Terminator of From is
30 // altered we can determine if the update is unnecessary for batch updates
31 // or invalid for a single update.
32 const bool HasEdge = llvm::any_of(
33 successors(From), [To](const BasicBlock *B) { return B == To; });
34
35 // If the IR does not match the update,
36 // 1. In batch updates, this update is unnecessary.
37 // 2. When called by insertEdge*()/deleteEdge*(), this update is invalid.
38 // Edge does not exist in IR.
39 if (Kind == DominatorTree::Insert && !HasEdge)
40 return false;
41
42 // Edge exists in IR.
43 if (Kind == DominatorTree::Delete && HasEdge)
44 return false;
45
46 return true;
47 }
48
49 bool DomTreeUpdater::isSelfDominance(
50 const DominatorTree::UpdateType Update) const {
51 // Won't affect DomTree and PostDomTree.
52 return Update.getFrom() == Update.getTo();
53 }
54
55 bool DomTreeUpdater::applyLazyUpdate(DominatorTree::UpdateKind Kind,
56 BasicBlock *From, BasicBlock *To) {
57 assert(Strategy == DomTreeUpdater::UpdateStrategy::Lazy &&
58 "Call applyLazyUpdate() with Eager strategy error");
59 // Analyze pending updates to determine if the update is unnecessary.
60 const DominatorTree::UpdateType Update = {Kind, From, To};
61 const DominatorTree::UpdateType Invert = {Kind != DominatorTree::Insert
62 ? DominatorTree::Insert
63 : DominatorTree::Delete,
64 From, To};
65 // Only check duplicates in updates that are not applied by both trees.
66 auto I =
67 PendUpdates.begin() + std::max(PendDTUpdateIndex, PendPDTUpdateIndex);
68 const auto E = PendUpdates.end();
69
70 assert(I <= E && "Iterator out of range.");
71
72 for (; I != E; ++I) {
73 if (Update == *I)
74 return false; // Discard duplicate updates.
75
76 if (Invert == *I) {
77 // Update and Invert are both valid (equivalent to a no-op). Remove
78 // Invert from PendUpdates and discard the Update.
79 PendUpdates.erase(I);
80 return false;
81 }
82 }
83
84 PendUpdates.push_back(Update); // Save the valid update.
85 return true;
86 }
87
88 void DomTreeUpdater::applyDomTreeUpdates() {
89 // No pending DomTreeUpdates.
90 if (Strategy != UpdateStrategy::Lazy || !DT)
91 return;
92
93 // Only apply updates not are applied by DomTree.
94 if (hasPendingDomTreeUpdates()) {
95 const auto I = PendUpdates.begin() + PendDTUpdateIndex;
96 const auto E = PendUpdates.end();
97 assert(I < E && "Iterator range invalid; there should be DomTree updates.");
98 DT->applyUpdates(ArrayRef(I, E));
99 PendDTUpdateIndex = PendUpdates.size();
100 }
101 }
102
103 void DomTreeUpdater::flush() {
104 applyDomTreeUpdates();
105 applyPostDomTreeUpdates();
106 dropOutOfDateUpdates();
107 }
108
109 void DomTreeUpdater::applyPostDomTreeUpdates() {
110 // No pending PostDomTreeUpdates.
111 if (Strategy != UpdateStrategy::Lazy || !PDT)
112 return;
113
114 // Only apply updates not are applied by PostDomTree.
115 if (hasPendingPostDomTreeUpdates()) {
116 const auto I = PendUpdates.begin() + PendPDTUpdateIndex;
117 const auto E = PendUpdates.end();
118 assert(I < E &&
119 "Iterator range invalid; there should be PostDomTree updates.");
120 PDT->applyUpdates(ArrayRef(I, E));
121 PendPDTUpdateIndex = PendUpdates.size();
122 }
123 }
124
125 void DomTreeUpdater::tryFlushDeletedBB() {
126 if (!hasPendingUpdates())
127 forceFlushDeletedBB();
128 }
129
130 bool DomTreeUpdater::forceFlushDeletedBB() {
131 if (DeletedBBs.empty())
132 return false;
133
134 for (auto *BB : DeletedBBs) {
135 BB->removeFromParent();
136 eraseDelBBNode(BB);
137 delete BB;
138 }
139 DeletedBBs.clear();
140 Callbacks.clear();
141 return true;
142 }
143
144 bool DomTreeUpdater::recalculate(Function &F) {
145 if (!DT && !PDT)
146 return false;
147
148 if (Strategy == UpdateStrategy::Eager) {
149 if (DT)
150 DT->recalculate(F);
151 if (PDT)
152 PDT->recalculate(F);
153 return true;
154 }
155
156 // Prevent forceFlushDeletedBB() from erasing DomTree or PostDomTree nodes.
157 IsRecalculatingDomTree = IsRecalculatingPostDomTree = true;
158
159 // Because all trees are going to be up-to-date after recalculation,
160 // flush awaiting deleted BasicBlocks.
161 if (forceFlushDeletedBB() || hasPendingUpdates()) {
162 if (DT)
163 DT->recalculate(F);
164 if (PDT)
165 PDT->recalculate(F);
166
167 // Resume forceFlushDeletedBB() to erase DomTree or PostDomTree nodes.
168 IsRecalculatingDomTree = IsRecalculatingPostDomTree = false;
169 PendDTUpdateIndex = PendPDTUpdateIndex = PendUpdates.size();
170 dropOutOfDateUpdates();
171 return true;
172 }
173
174 // Resume forceFlushDeletedBB() to erase DomTree or PostDomTree nodes.
175 IsRecalculatingDomTree = IsRecalculatingPostDomTree = false;
176 return false;
177 }
178
179 bool DomTreeUpdater::hasPendingUpdates() const {
180 return hasPendingDomTreeUpdates() || hasPendingPostDomTreeUpdates();
181 }
182
183 bool DomTreeUpdater::hasPendingDomTreeUpdates() const {
184 if (!DT)
185 return false;
186 return PendUpdates.size() != PendDTUpdateIndex;
187 }
188
189 bool DomTreeUpdater::hasPendingPostDomTreeUpdates() const {
190 if (!PDT)
191 return false;
192 return PendUpdates.size() != PendPDTUpdateIndex;
193 }
194
195 bool DomTreeUpdater::isBBPendingDeletion(llvm::BasicBlock *DelBB) const {
196 if (Strategy == UpdateStrategy::Eager || DeletedBBs.empty())
197 return false;
198 return DeletedBBs.count(DelBB) != 0;
199 }
200
201 // The DT and PDT require the nodes related to updates
202 // are not deleted when update functions are called.
203 // So BasicBlock deletions must be pended when the
204 // UpdateStrategy is Lazy. When the UpdateStrategy is
205 // Eager, the BasicBlock will be deleted immediately.
206 void DomTreeUpdater::deleteBB(BasicBlock *DelBB) {
207 validateDeleteBB(DelBB);
208 if (Strategy == UpdateStrategy::Lazy) {
209 DeletedBBs.insert(DelBB);
210 return;
211 }
212
213 DelBB->removeFromParent();
214 eraseDelBBNode(DelBB);
215 delete DelBB;
216 }
217
218 void DomTreeUpdater::callbackDeleteBB(
219 BasicBlock *DelBB, function_ref Callback) {
220 validateDeleteBB(DelBB);
221 if (Strategy == UpdateStrategy::Lazy) {
222 Callbacks.push_back(CallBackOnDeletion(DelBB, Callback));
223 DeletedBBs.insert(DelBB);
224 return;
225 }
226
227 DelBB->removeFromParent();
228 eraseDelBBNode(DelBB);
229 Callback(DelBB);
230 delete DelBB;
231 }
232
233 void DomTreeUpdater::eraseDelBBNode(BasicBlock *DelBB) {
234 if (DT && !IsRecalculatingDomTree)
235 if (DT->getNode(DelBB))
236 DT->eraseNode(DelBB);
237
238 if (PDT && !IsRecalculatingPostDomTree)
239 if (PDT->getNode(DelBB))
240 PDT->eraseNode(DelBB);
241 }
242
243 void DomTreeUpdater::validateDeleteBB(BasicBlock *DelBB) {
244 assert(DelBB && "Invalid push_back of nullptr DelBB.");
245 assert(pred_empty(DelBB) && "DelBB has one or more predecessors.");
246 // DelBB is unreachable and all its instructions are dead.
247 while (!DelBB->empty()) {
248 Instruction &I = DelBB->back();
249 // Replace used instructions with an arbitrary value (undef).
250 if (!I.use_empty())
251 I.replaceAllUsesWith(llvm::UndefValue::get(I.getType()));
252 DelBB->getInstList().pop_back();
253 }
254 // Make sure DelBB has a valid terminator instruction. As long as DelBB is a
255 // Child of Function F it must contain valid IR.
256 new UnreachableInst(DelBB->getContext(), DelBB);
257 }
258
259 void DomTreeUpdater::applyUpdates(ArrayRef Updates,
260 bool ForceRemoveDuplicates) {
261 if (Strategy == UpdateStrategy::Lazy || ForceRemoveDuplicates) {
262 SmallVector Seen;
263 for (const auto U : Updates)
264 // For Lazy UpdateStrategy, avoid duplicates to applyLazyUpdate() to save
265 // on analysis.
266 if (llvm::none_of(
267 Seen,
268 [U](const DominatorTree::UpdateType S) { return S == U; }) &&
269 isUpdateValid(U) && !isSelfDominance(U)) {
270 Seen.push_back(U);
271 if (Strategy == UpdateStrategy::Lazy)
272 applyLazyUpdate(U.getKind(), U.getFrom(), U.getTo());
273 }
274 if (Strategy == UpdateStrategy::Lazy)
275 return;
276
277 if (DT)
278 DT->applyUpdates(Seen);
279 if (PDT)
280 PDT->applyUpdates(Seen);
281 return;
282 }
283
284 if (DT)
285 DT->applyUpdates(Updates);
286 if (PDT)
287 PDT->applyUpdates(Updates);
288 }
289
290 DominatorTree &DomTreeUpdater::getDomTree() {
291 assert(DT && "Invalid acquisition of a null DomTree");
292 applyDomTreeUpdates();
293 dropOutOfDateUpdates();
294 return *DT;
295 }
296
297 PostDominatorTree &DomTreeUpdater::getPostDomTree() {
298 assert(PDT && "Invalid acquisition of a null PostDomTree");
299 applyPostDomTreeUpdates();
300 dropOutOfDateUpdates();
301 return *PDT;
302 }
303
304 void DomTreeUpdater::insertEdge(BasicBlock *From, BasicBlock *To) {
305
306 #ifndef NDEBUG
307 assert(isUpdateValid({DominatorTree::Insert, From, To}) &&
308 "Inserted edge does not appear in the CFG");
309 #endif
310
311 // Won't affect DomTree and PostDomTree; discard update.
312 if (From == To)
313 return;
314
315 if (Strategy == UpdateStrategy::Eager) {
316 if (DT)
317 DT->insertEdge(From, To);
318 if (PDT)
319 PDT->insertEdge(From, To);
320 return;
321 }
322
323 applyLazyUpdate(DominatorTree::Insert, From, To);
324 }
325
326 bool DomTreeUpdater::insertEdgeRelaxed(BasicBlock *From, BasicBlock *To) {
327 if (!isUpdateValid({DominatorTree::Insert, From, To}))
328 return false;
329
330 if (From == To)
331 return true;
332
333 if (Strategy == UpdateStrategy::Eager) {
334 if (DT)
335 DT->insertEdge(From, To);
336 if (PDT)
337 PDT->insertEdge(From, To);
338 return true;
339 }
340
341 applyLazyUpdate(DominatorTree::Insert, From, To);
342 return true;
343 }
344
345 void DomTreeUpdater::deleteEdge(BasicBlock *From, BasicBlock *To) {
346
347 #ifndef NDEBUG
348 assert(isUpdateValid({DominatorTree::Delete, From, To}) &&
349 "Deleted edge still exists in the CFG!");
350 #endif
351
352 // Won't affect DomTree and PostDomTree; discard update.
353 if (From == To)
354 return;
355
356 if (Strategy == UpdateStrategy::Eager) {
357 if (DT)
358 DT->deleteEdge(From, To);
359 if (PDT)
360 PDT->deleteEdge(From, To);
361 return;
362 }
363
364 applyLazyUpdate(DominatorTree::Delete, From, To);
365 }
366
367 bool DomTreeUpdater::deleteEdgeRelaxed(BasicBlock *From, BasicBlock *To) {
368 if (!isUpdateValid({DominatorTree::Delete, From, To}))
369 return false;
370
371 if (From == To)
372 return true;
373
374 if (Strategy == UpdateStrategy::Eager) {
375 if (DT)
376 DT->deleteEdge(From, To);
377 if (PDT)
378 PDT->deleteEdge(From, To);
379 return true;
380 }
381
382 applyLazyUpdate(DominatorTree::Delete, From, To);
383 return true;
384 }
385
386 void DomTreeUpdater::dropOutOfDateUpdates() {
387 if (Strategy == DomTreeUpdater::UpdateStrategy::Eager)
388 return;
389
390 tryFlushDeletedBB();
391
392 // Drop all updates applied by both trees.
393 if (!DT)
394 PendDTUpdateIndex = PendUpdates.size();
395 if (!PDT)
396 PendPDTUpdateIndex = PendUpdates.size();
397
398 const size_t dropIndex = std::min(PendDTUpdateIndex, PendPDTUpdateIndex);
399 const auto B = PendUpdates.begin();
400 const auto E = PendUpdates.begin() + dropIndex;
401 assert(B <= E && "Iterator out of range.");
402 PendUpdates.erase(B, E);
403 // Calculate current index.
404 PendDTUpdateIndex -= dropIndex;
405 PendPDTUpdateIndex -= dropIndex;
406 }
407
408 #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
409 LLVM_DUMP_METHOD void DomTreeUpdater::dump() const {
410 raw_ostream &OS = llvm::dbgs();
411
412 OS << "Available Trees: ";
413 if (DT || PDT) {
414 if (DT)
415 OS << "DomTree ";
416 if (PDT)
417 OS << "PostDomTree ";
418 OS << "\n";
419 } else
420 OS << "None\n";
421
422 OS << "UpdateStrategy: ";
423 if (Strategy == UpdateStrategy::Eager) {
424 OS << "Eager\n";
425 return;
426 } else
427 OS << "Lazy\n";
428 int Index = 0;
429
430 auto printUpdates =
431 [&](ArrayRef::const_iterator begin,
432 ArrayRef::const_iterator end) {
433 if (begin == end)
434 OS << " None\n";
435 Index = 0;
436 for (auto It = begin, ItEnd = end; It != ItEnd; ++It) {
437 auto U = *It;
438 OS << " " << Index << " : ";
439 ++Index;
440 if (U.getKind() == DominatorTree::Insert)
441 OS << "Insert, ";
442 else
443 OS << "Delete, ";
444 BasicBlock *From = U.getFrom();
445 if (From) {
446 auto S = From->getName();
447 if (!From->hasName())
448 S = "(no name)";
449 OS << S << "(" << From << "), ";
450 } else {
451 OS << "(badref), ";
452 }
453 BasicBlock *To = U.getTo();
454 if (To) {
455 auto S = To->getName();
456 if (!To->hasName())
457 S = "(no_name)";
458 OS << S << "(" << To << ")\n";
459 } else {
460 OS << "(badref)\n";
461 }
462 }
463 };
464
465 if (DT) {
466 const auto I = PendUpdates.begin() + PendDTUpdateIndex;
467 assert(PendUpdates.begin() <= I && I <= PendUpdates.end() &&
468 "Iterator out of range.");
469 OS << "Applied but not cleared DomTreeUpdates:\n";
470 printUpdates(PendUpdates.begin(), I);
471 OS << "Pending DomTreeUpdates:\n";
472 printUpdates(I, PendUpdates.end());
473 }
474
475 if (PDT) {
476 const auto I = PendUpdates.begin() + PendPDTUpdateIndex;
477 assert(PendUpdates.begin() <= I && I <= PendUpdates.end() &&
478 "Iterator out of range.");
479 OS << "Applied but not cleared PostDomTreeUpdates:\n";
480 printUpdates(PendUpdates.begin(), I);
481 OS << "Pending PostDomTreeUpdates:\n";
482 printUpdates(I, PendUpdates.end());
483 }
484
485 OS << "Pending DeletedBBs:\n";
486 Index = 0;
487 for (auto BB : DeletedBBs) {
488 OS << " " << Index << " : ";
489 ++Index;
490 if (BB->hasName())
491 OS << BB->getName() << "(";
492 else
493 OS << "(no_name)(";
494 OS << BB << ")\n";
495 }
496
497 OS << "Pending Callbacks:\n";
498 Index = 0;
499 for (auto BB : Callbacks) {
500 OS << " " << Index << " : ";
501 ++Index;
502 if (BB->hasName())
503 OS << BB->getName() << "(";
504 else
505 OS << "(no_name)(";
506 OS << BB << ")\n";
507 }
508 }
509 #endif
510 } // namespace llvm
1717 DeferredDominanceTest.cpp
1818 DominatorTreeTest.cpp
1919 DominatorTreeBatchUpdatesTest.cpp
20 DomTreeUpdaterTest.cpp
2021 FunctionTest.cpp
2122 PassBuilderCallbacksTest.cpp
2223 IRBuilderTest.cpp
0 //==- llvm/unittests/IR/DomTreeUpdaterTest.cpp - DomTreeUpdater unit tests ===//
1 //
2 // The LLVM Compiler Infrastructure
3 //
4 // This file is distributed under the University of Illinois Open Source
5 // License. See LICENSE.TXT for details.
6 //
7 //===----------------------------------------------------------------------===//
8
9 #include "llvm/IR/DomTreeUpdater.h"
10 #include "llvm/Analysis/PostDominators.h"
11 #include "llvm/AsmParser/Parser.h"
12 #include "llvm/IR/Constants.h"
13 #include "llvm/IR/Dominators.h"
14 #include "llvm/IR/Instructions.h"
15 #include "llvm/IR/LLVMContext.h"
16 #include "llvm/IR/Module.h"
17 #include "llvm/Support/SourceMgr.h"
18 #include "gtest/gtest.h"
19 #include
20
21 using namespace llvm;
22
23 static std::unique_ptr makeLLVMModule(LLVMContext &Context,
24 StringRef ModuleStr) {
25 SMDiagnostic Err;
26 std::unique_ptr M = parseAssemblyString(ModuleStr, Err, Context);
27 assert(M && "Bad LLVM IR?");
28 return M;
29 }
30
31 TEST(DomTreeUpdater, EagerUpdateBasicOperations) {
32 StringRef FuncName = "f";
33 StringRef ModuleString = R"(
34 define i32 @f(i32 %i, i32 *%p) {
35 bb0:
36 store i32 %i, i32 *%p
37 switch i32 %i, label %bb1 [
38 i32 1, label %bb2
39 i32 2, label %bb3
40 ]
41 bb1:
42 ret i32 1
43 bb2:
44 ret i32 2
45 bb3:
46 ret i32 3
47 })";
48 // Make the module.
49 LLVMContext Context;
50 std::unique_ptr M = makeLLVMModule(Context, ModuleString);
51 Function *F = M->getFunction(FuncName);
52
53 // Make the DomTreeUpdater.
54 DominatorTree DT(*F);
55 PostDominatorTree PDT(*F);
56 DomTreeUpdater DTU(DT, PDT, DomTreeUpdater::UpdateStrategy::Eager);
57
58 ASSERT_TRUE(DTU.hasDomTree());
59 ASSERT_TRUE(DTU.hasPostDomTree());
60 ASSERT_EQ(DTU.getUpdateStrategy(), DomTreeUpdater::UpdateStrategy::Eager);
61 ASSERT_TRUE(DTU.getDomTree().verify());
62 ASSERT_TRUE(DTU.getPostDomTree().verify());
63 ASSERT_FALSE(DTU.hasPendingUpdates());
64
65 Function::iterator FI = F->begin();
66 BasicBlock *BB0 = &*FI++;
67 BasicBlock *BB1 = &*FI++;
68 BasicBlock *BB2 = &*FI++;
69 BasicBlock *BB3 = &*FI++;
70 SwitchInst *SI = dyn_cast(BB0->getTerminator());
71 ASSERT_NE(SI, nullptr) << "Couldn't get SwitchInst.";
72
73 ASSERT_FALSE(DTU.insertEdgeRelaxed(BB0, BB0));
74 ASSERT_TRUE(DTU.deleteEdgeRelaxed(BB0, BB0));
75
76 // Delete edge bb0 -> bb3 and push the update twice to verify duplicate
77 // entries are discarded.
78 std::vector Updates;
79 Updates.reserve(4);
80 Updates.push_back({DominatorTree::Delete, BB0, BB3});
81 Updates.push_back({DominatorTree::Delete, BB0, BB3});
82
83 // Invalid Insert: no edge bb1 -> bb2 after change to bb0.
84 Updates.push_back({DominatorTree::Insert, BB1, BB2});
85 // Invalid Delete: edge exists bb0 -> bb1 after change to bb0.
86 Updates.push_back({DominatorTree::Delete, BB0, BB1});
87
88 // CFG Change: remove edge bb0 -> bb3.
89 EXPECT_EQ(BB0->getTerminator()->getNumSuccessors(), 3u);
90 BB3->removePredecessor(BB0);
91 for (auto i = SI->case_begin(), e = SI->case_end(); i != e; ++i) {
92 if (i->getCaseSuccessor() == BB3) {
93 SI->removeCase(i);
94 break;
95 }
96 }
97 EXPECT_EQ(BB0->getTerminator()->getNumSuccessors(), 2u);
98 // Deletion of a BasicBlock is an immediate event. We remove all uses to the
99 // contained Instructions and change the Terminator to "unreachable" when
100 // queued for deletion.
101 ASSERT_FALSE(isa(BB3->getTerminator()));
102 EXPECT_FALSE(DTU.isBBPendingDeletion(BB3));
103 DTU.applyUpdates(Updates, /*ForceRemoveDuplicates*/ true);
104 ASSERT_FALSE(DTU.hasPendingUpdates());
105
106 // Invalid Insert: no edge bb1 -> bb2 after change to bb0.
107 ASSERT_FALSE(DTU.insertEdgeRelaxed(BB1, BB2));
108 // Invalid Delete: edge exists bb0 -> bb1 after change to bb0.
109 ASSERT_FALSE(DTU.deleteEdgeRelaxed(BB0, BB1));
110
111 // DTU working with Eager UpdateStrategy does not need to flush.
112 ASSERT_TRUE(DT.verify());
113 ASSERT_TRUE(PDT.verify());
114
115 // Test callback utils.
116 ASSERT_EQ(BB3->getParent(), F);
117 DTU.callbackDeleteBB(BB3,
118 [&F](BasicBlock *BB) { ASSERT_NE(BB->getParent(), F); });
119
120 ASSERT_TRUE(DT.verify());
121 ASSERT_TRUE(PDT.verify());
122 ASSERT_FALSE(DTU.hasPendingUpdates());
123
124 // Unnecessary flush() test
125 DTU.flush();
126 EXPECT_TRUE(DT.verify());
127 EXPECT_TRUE(PDT.verify());
128
129 // Remove all case branch to BB2 to test Eager recalculation.
130 // Code section from llvm::ConstantFoldTerminator
131 for (auto i = SI->case_begin(), e = SI->case_end(); i != e;) {
132 if (i->getCaseSuccessor() == BB2) {
133 // Remove this entry.
134 BB2->removePredecessor(BB0);
135 i = SI->removeCase(i);
136 e = SI->case_end();
137 } else
138 ++i;
139 }
140 ASSERT_FALSE(DT.verify());
141 ASSERT_FALSE(PDT.verify());
142 DTU.recalculate(*F);
143 ASSERT_TRUE(DT.verify());
144 ASSERT_TRUE(PDT.verify());
145 }
146
147 TEST(DomTreeUpdater, EagerUpdateReplaceEntryBB) {
148 StringRef FuncName = "f";
149 StringRef ModuleString = R"(
150 define i32 @f() {
151 bb0:
152 br label %bb1
153 bb1:
154 ret i32 1
155 }
156 )";
157 // Make the module.
158 LLVMContext Context;
159 std::unique_ptr M = makeLLVMModule(Context, ModuleString);
160 Function *F = M->getFunction(FuncName);
161
162 // Make the DTU.
163 DominatorTree DT(*F);
164 PostDominatorTree PDT(*F);
165 DomTreeUpdater DTU(DT, PDT, DomTreeUpdater::UpdateStrategy::Eager);
166 ASSERT_TRUE(DTU.hasDomTree());
167 ASSERT_TRUE(DTU.hasPostDomTree());
168 ASSERT_EQ(DTU.getUpdateStrategy(), DomTreeUpdater::UpdateStrategy::Eager);
169 ASSERT_TRUE(DT.verify());
170 ASSERT_TRUE(PDT.verify());
171
172 Function::iterator FI = F->begin();
173 BasicBlock *BB0 = &*FI++;
174 BasicBlock *BB1 = &*FI++;
175
176 // Add a block as the new function entry BB. We also link it to BB0.
177 BasicBlock *NewEntry =
178 BasicBlock::Create(F->getContext(), "new_entry", F, BB0);
179 BranchInst::Create(BB0, NewEntry);
180 EXPECT_EQ(F->begin()->getName(), NewEntry->getName());
181 EXPECT_TRUE(&F->getEntryBlock() == NewEntry);
182
183 ASSERT_TRUE(DTU.insertEdgeRelaxed(NewEntry, BB0));
184
185 // Changing the Entry BB requires a full recalculation of DomTree.
186 DTU.recalculate(*F);
187 ASSERT_TRUE(DT.verify());
188 ASSERT_TRUE(PDT.verify());
189
190 // CFG Change: remove new_edge -> bb0 and redirect to new_edge -> bb1.
191 EXPECT_EQ(NewEntry->getTerminator()->getNumSuccessors(), 1u);
192 NewEntry->getTerminator()->eraseFromParent();
193 BranchInst::Create(BB1, NewEntry);
194 EXPECT_EQ(BB0->getTerminator()->getNumSuccessors(), 1u);
195
196 // Update the DTU. At this point bb0 now has no predecessors but is still a
197 // Child of F.
198 DTU.applyUpdates({{DominatorTree::Delete, NewEntry, BB0},
199 {DominatorTree::Insert, NewEntry, BB1}});
200 ASSERT_TRUE(DT.verify());
201 ASSERT_TRUE(PDT.verify());
202
203 // Now remove bb0 from F.
204 ASSERT_FALSE(isa(BB0->getTerminator()));
205 EXPECT_FALSE(DTU.isBBPendingDeletion(BB0));
206 DTU.deleteBB(BB0);
207 ASSERT_TRUE(DT.verify());
208 ASSERT_TRUE(PDT.verify());
209 }
210
211 TEST(DomTreeUpdater, LazyUpdateDTBasicOperations) {
212 StringRef FuncName = "f";
213 StringRef ModuleString = R"(
214 define i32 @f(i32 %i, i32 *%p) {
215 bb0:
216 store i32 %i, i32 *%p
217 switch i32 %i, label %bb1 [
218 i32 0, label %bb2
219 i32 1, label %bb2
220 i32 2, label %bb3
221 ]
222 bb1:
223 ret i32 1
224 bb2:
225 ret i32 2
226 bb3:
227 ret i32 3
228 }
229 )";
230 // Make the module.
231 LLVMContext Context;
232 std::unique_ptr M = makeLLVMModule(Context, ModuleString);
233 Function *F = M->getFunction(FuncName);
234
235 // Make the DTU.
236 DominatorTree DT(*F);
237 DomTreeUpdater DTU(DT, DomTreeUpdater::UpdateStrategy::Lazy);
238 ASSERT_TRUE(DTU.hasDomTree());
239 ASSERT_FALSE(DTU.hasPostDomTree());
240 ASSERT_EQ(DTU.getUpdateStrategy(), DomTreeUpdater::UpdateStrategy::Lazy);
241 ASSERT_TRUE(DTU.getDomTree().verify());
242
243 Function::iterator FI = F->begin();
244 BasicBlock *BB0 = &*FI++;
245 BasicBlock *BB1 = &*FI++;
246 BasicBlock *BB2 = &*FI++;
247 BasicBlock *BB3 = &*FI++;
248
249 // Test discards of self-domination update.
250 DTU.deleteEdge(BB0, BB0);
251 ASSERT_FALSE(DTU.hasPendingDomTreeUpdates());
252
253 // Delete edge bb0 -> bb3 and push the update twice to verify duplicate
254 // entries are discarded.
255 std::vector Updates;
256 Updates.reserve(4);
257 Updates.push_back({DominatorTree::Delete, BB0, BB3});
258 Updates.push_back({DominatorTree::Delete, BB0, BB3});
259
260 // Invalid Insert: no edge bb1 -> bb2 after change to bb0.
261 Updates.push_back({DominatorTree::Insert, BB1, BB2});
262 // Invalid Delete: edge exists bb0 -> bb1 after change to bb0.
263 Updates.push_back({DominatorTree::Delete, BB0, BB1});
264
265 // CFG Change: remove edge bb0 -> bb3 and one duplicate edge bb0 -> bb2.
266 EXPECT_EQ(BB0->getTerminator()->getNumSuccessors(), 4u);
267 BB0->getTerminator()->eraseFromParent();
268 BranchInst::Create(BB1, BB2, ConstantInt::getTrue(F->getContext()), BB0);
269 EXPECT_EQ(BB0->getTerminator()->getNumSuccessors(), 2u);
270
271 // Verify. Updates to DTU must be applied *after* all changes to the CFG
272 // (including block deletion).
273 DTU.applyUpdates(Updates);
274 ASSERT_TRUE(DTU.getDomTree().verify());
275
276 // Deletion of a BasicBlock is an immediate event. We remove all uses to the
277 // contained Instructions and change the Terminator to "unreachable" when
278 // queued for deletion. Its parent is still F until all the pending updates
279 // are applied to all trees held by the DomTreeUpdater (DomTree/PostDomTree).
280 // We don't defer this action because it can cause problems for other
281 // transforms or analysis as it's part of the actual CFG. We only defer
282 // updates to the DominatorTrees. This code will crash if it is placed before
283 // the BranchInst::Create() call above. After a deletion of a BasicBlock. Only
284 // an explicit flush event can trigger the flushing of deleteBBs. Because some
285 // passes using Lazy UpdateStrategy rely on this behavior.
286
287 ASSERT_FALSE(isa(BB3->getTerminator()));
288 EXPECT_FALSE(DTU.isBBPendingDeletion(BB3));
289 EXPECT_FALSE(DTU.hasPendingDeletedBB());
290 DTU.deleteBB(BB3);
291 EXPECT_TRUE(DTU.isBBPendingDeletion(BB3));
292 EXPECT_TRUE(DTU.hasPendingDeletedBB());
293 ASSERT_TRUE(isa(BB3->getTerminator()));
294 EXPECT_EQ(BB3->getParent(), F);
295 DTU.recalculate(*F);
296
297 EXPECT_FALSE(DTU.hasPendingDeletedBB());
298 }
299
300 TEST(DomTreeUpdater, LazyUpdateDTInheritedPreds) {
301 StringRef FuncName = "f";
302 StringRef ModuleString = R"(
303 define i32 @f(i32 %i, i32 *%p) {
304 bb0:
305 store i32 %i, i32 *%p
306 switch i32 %i, label %bb1 [
307 i32 2, label %bb2
308 i32 3, label %bb3
309 ]
310 bb1:
311 br label %bb3
312 bb2:
313 br label %bb3
314 bb3:
315 ret i32 3
316 }
317 )";
318 // Make the module.
319 LLVMContext Context;
320 std::unique_ptr M = makeLLVMModule(Context, ModuleString);
321 Function *F = M->getFunction(FuncName);
322
323 // Make the DTU.
324 DominatorTree DT(*F);
325 DomTreeUpdater DTU(DT, DomTreeUpdater::UpdateStrategy::Lazy);
326 ASSERT_TRUE(DTU.hasDomTree());
327 ASSERT_FALSE(DTU.hasPostDomTree());
328 ASSERT_EQ(DTU.getUpdateStrategy(), DomTreeUpdater::UpdateStrategy::Lazy);
329 ASSERT_TRUE(DTU.getDomTree().verify());
330
331 Function::iterator FI = F->begin();
332 BasicBlock *BB0 = &*FI++;
333 BasicBlock *BB1 = &*FI++;
334 BasicBlock *BB2 = &*FI++;
335 BasicBlock *BB3 = &*FI++;
336
337 // There are several CFG locations where we have:
338 //
339 // pred1..predN
340 // | |
341 // +> curr <+ converted into: pred1..predN curr
342 // | | |
343 // v +> succ <+
344 // succ
345 //
346 // There is a specific shape of this we have to be careful of:
347 //
348 // pred1..predN
349 // || |
350 // |+> curr <+ converted into: pred1..predN curr
351 // | | | |
352 // | v +> succ <+
353 // +-> succ
354 //
355 // While the final CFG form is functionally identical the updates to
356 // DTU are not. In the first case we must have DTU.insertEdge(Pred1, Succ)
357 // while in the latter case we must *NOT* have DTU.insertEdge(Pred1, Succ).
358
359 // CFG Change: bb0 now only has bb0 -> bb1 and bb0 -> bb3. We are preparing to
360 // remove bb2.
361 EXPECT_EQ(BB0->getTerminator()->getNumSuccessors(), 3u);
362 BB0->getTerminator()->eraseFromParent();
363 BranchInst::Create(BB1, BB3, ConstantInt::getTrue(F->getContext()), BB0);
364 EXPECT_EQ(BB0->getTerminator()->getNumSuccessors(), 2u);
365
366 // Test callback utils.
367 std::vector BasicBlocks;
368 BasicBlocks.push_back(BB1);
369 BasicBlocks.push_back(BB2);
370 auto Eraser = [&](BasicBlock *BB) {
371 BasicBlocks.erase(
372 std::remove_if(BasicBlocks.begin(), BasicBlocks.end(),
373 [&](const BasicBlock *i) { return i == BB; }),
374 BasicBlocks.end());
375 };
376 ASSERT_EQ(BasicBlocks.size(), static_cast(2));
377 // Remove bb2 from F. This has to happen before the call to applyUpdates() for
378 // DTU to detect there is no longer an edge between bb2 -> bb3. The deleteBB()
379 // method converts bb2's TI into "unreachable".
380 ASSERT_FALSE(isa(BB2->getTerminator()));
381 EXPECT_FALSE(DTU.isBBPendingDeletion(BB2));
382 DTU.callbackDeleteBB(BB2, Eraser);
383 EXPECT_TRUE(DTU.isBBPendingDeletion(BB2));
384 ASSERT_TRUE(isa(BB2->getTerminator()));
385 EXPECT_EQ(BB2->getParent(), F);
386
387 // Queue up the DTU updates.
388 std::vector Updates;
389 Updates.reserve(4);
390 Updates.push_back({DominatorTree::Delete, BB0, BB2});
391 Updates.push_back({DominatorTree::Delete, BB2, BB3});
392
393 // Handle the specific shape case next.
394 // CFG Change: bb0 now only branches to bb3. We are preparing to remove bb1.
395 EXPECT_EQ(BB0->getTerminator()->getNumSuccessors(), 2u);
396 BB0->getTerminator()->eraseFromParent();
397 BranchInst::Create(BB3, BB0);
398 EXPECT_EQ(BB0->getTerminator()->getNumSuccessors(), 1u);
399
400 // Remove bb1 from F. This has to happen before the call to applyUpdates() for
401 // DTU to detect there is no longer an edge between bb1 -> bb3. The deleteBB()
402 // method converts bb1's TI into "unreachable".
403 ASSERT_FALSE(isa(BB1->getTerminator()));
404 EXPECT_FALSE(DTU.isBBPendingDeletion(BB1));
405 DTU.callbackDeleteBB(BB1, Eraser);
406 EXPECT_TRUE(DTU.isBBPendingDeletion(BB1));
407 ASSERT_TRUE(isa(BB1->getTerminator()));
408 EXPECT_EQ(BB1->getParent(), F);
409
410 // Update the DTU. In this case we don't call DTU.insertEdge(BB0, BB3) because
411 // the edge previously existed at the start of this test when DT was first
412 // created.
413 Updates.push_back({DominatorTree::Delete, BB0, BB1});
414 Updates.push_back({DominatorTree::Delete, BB1, BB3});
415
416 // Verify everything.
417 DTU.applyUpdates(Updates);
418 ASSERT_EQ(BasicBlocks.size(), static_cast(2));
419 DTU.flush();
420 ASSERT_EQ(BasicBlocks.size(), static_cast(0));
421 ASSERT_TRUE(DT.verify());
422 }
423
424 TEST(DomTreeUpdater, LazyUpdateBasicOperations) {
425 StringRef FuncName = "f";
426 StringRef ModuleString = R"(
427 define i32 @f(i32 %i, i32 *%p) {
428 bb0:
429 store i32 %i, i32 *%p
430 switch i32 %i, label %bb1 [
431 i32 0, label %bb2
432 i32 1, label %bb2
433 i32 2, label %bb3
434 ]
435 bb1:
436 ret i32 1
437 bb2:
438 ret i32 2
439 bb3:
440 ret i32 3
441 }
442 )";
443 // Make the module.
444 LLVMContext Context;
445 std::unique_ptr M = makeLLVMModule(Context, ModuleString);
446 Function *F = M->getFunction(FuncName);
447
448 // Make the DTU.
449 DominatorTree DT(*F);
450 PostDominatorTree PDT(*F);
451 DomTreeUpdater DTU(DT, PDT, DomTreeUpdater::UpdateStrategy::Lazy);
452 ASSERT_TRUE(DTU.hasDomTree());
453 ASSERT_TRUE(DTU.hasPostDomTree());
454 ASSERT_EQ(DTU.getUpdateStrategy(), DomTreeUpdater::UpdateStrategy::Lazy);
455 ASSERT_TRUE(DTU.getDomTree().verify());
456 ASSERT_TRUE(DTU.getPostDomTree().verify());
457
458 Function::iterator FI = F->begin();
459 BasicBlock *BB0 = &*FI++;
460 BasicBlock *BB1 = &*FI++;
461 BasicBlock *BB2 = &*FI++;
462 BasicBlock *BB3 = &*FI++;
463 // Test discards of self-domination update.
464 DTU.deleteEdge(BB0, BB0);
465
466 // Delete edge bb0 -> bb3 and push the update twice to verify duplicate
467 // entries are discarded.
468 std::vector Updates;
469 Updates.reserve(4);
470 Updates.push_back({DominatorTree::Delete, BB0, BB3});
471 Updates.push_back({DominatorTree::Delete, BB0, BB3});
472
473 // Unnecessary Insert: no edge bb1 -> bb2 after change to bb0.
474 Updates.push_back({DominatorTree::Insert, BB1, BB2});
475 // Unnecessary Delete: edge exists bb0 -> bb1 after change to bb0.
476 Updates.push_back({DominatorTree::Delete, BB0, BB1});
477
478 // CFG Change: remove edge bb0 -> bb3 and one duplicate edge bb0 -> bb2.
479 EXPECT_EQ(BB0->getTerminator()->getNumSuccessors(), 4u);
480 BB0->getTerminator()->eraseFromParent();
481 BranchInst::Create(BB1, BB2, ConstantInt::getTrue(F->getContext()), BB0);
482 EXPECT_EQ(BB0->getTerminator()->getNumSuccessors(), 2u);
483
484 // Deletion of a BasicBlock is an immediate event. We remove all uses to the
485 // contained Instructions and change the Terminator to "unreachable" when
486 // queued for deletion. Its parent is still F until DTU.flushDomTree is
487 // called. We don't defer this action because it can cause problems for other
488 // transforms or analysis as it's part of the actual CFG. We only defer
489 // updates to the DominatorTree. This code will crash if it is placed before
490 // the BranchInst::Create() call above.
491 bool CallbackFlag = false;
492 ASSERT_FALSE(isa(BB3->getTerminator()));
493 EXPECT_FALSE(DTU.isBBPendingDeletion(BB3));
494 DTU.callbackDeleteBB(BB3, [&](BasicBlock *) { CallbackFlag = true; });
495 EXPECT_TRUE(DTU.isBBPendingDeletion(BB3));
496 ASSERT_TRUE(isa(BB3->getTerminator()));
497 EXPECT_EQ(BB3->getParent(), F);
498
499 // Verify. Updates to DTU must be applied *after* all changes to the CFG
500 // (including block deletion).
501 DTU.applyUpdates(Updates);
502 ASSERT_TRUE(DTU.getDomTree().verify());
503 ASSERT_TRUE(DTU.hasPendingUpdates());
504 ASSERT_TRUE(DTU.hasPendingPostDomTreeUpdates());
505 ASSERT_FALSE(DTU.hasPendingDomTreeUpdates());
506 ASSERT_TRUE(DTU.hasPendingDeletedBB());
507 ASSERT_TRUE(DTU.getPostDomTree().verify());
508 ASSERT_FALSE(DTU.hasPendingUpdates());
509 ASSERT_FALSE(DTU.hasPendingPostDomTreeUpdates());
510 ASSERT_FALSE(DTU.hasPendingDomTreeUpdates());
511 ASSERT_FALSE(DTU.hasPendingDeletedBB());
512 ASSERT_EQ(CallbackFlag, true);
513 }
514
515 TEST(DomTreeUpdater, LazyUpdateReplaceEntryBB) {
516 StringRef FuncName = "f";
517 StringRef ModuleString = R"(
518 define i32 @f() {
519 bb0:
520 br label %bb1
521 bb1:
522 ret i32 1
523 }
524 )";
525 // Make the module.
526 LLVMContext Context;
527 std::unique_ptr M = makeLLVMModule(Context, ModuleString);
528 Function *F = M->getFunction(FuncName);
529
530 // Make the DTU.
531 DominatorTree DT(*F);
532 PostDominatorTree PDT(*F);
533 DomTreeUpdater DTU(DT, PDT, DomTreeUpdater::UpdateStrategy::Lazy);
534 ASSERT_TRUE(DTU.hasDomTree());
535 ASSERT_TRUE(DTU.hasPostDomTree());
536 ASSERT_EQ(DTU.getUpdateStrategy(), DomTreeUpdater::UpdateStrategy::Lazy);
537 ASSERT_TRUE(DTU.getDomTree().verify());
538 ASSERT_TRUE(DTU.getPostDomTree().verify());
539
540 Function::iterator FI = F->begin();
541 BasicBlock *BB0 = &*FI++;
542 BasicBlock *BB1 = &*FI++;
543
544 // Add a block as the new function entry BB. We also link it to BB0.
545 BasicBlock *NewEntry =
546 BasicBlock::Create(F->getContext(), "new_entry", F, BB0);
547 BranchInst::Create(BB0, NewEntry);
548 EXPECT_EQ(F->begin()->getName(), NewEntry->getName());
549 EXPECT_TRUE(&F->getEntryBlock() == NewEntry);
550
551 // Insert the new edge between new_entry -> bb0. Without this the
552 // recalculate() call below will not actually recalculate the DT as there
553 // are no changes pending and no blocks deleted.
554 DTU.insertEdge(NewEntry, BB0);
555
556 // Changing the Entry BB requires a full recalculation.
557 DTU.recalculate(*F);
558 ASSERT_TRUE(DTU.getDomTree().verify());
559 ASSERT_TRUE(DTU.getPostDomTree().verify());
560
561 // CFG Change: remove new_edge -> bb0 and redirect to new_edge -> bb1.
562 EXPECT_EQ(NewEntry->getTerminator()->getNumSuccessors(), 1u);
563 NewEntry->getTerminator()->eraseFromParent();
564 BranchInst::Create(BB1, NewEntry);
565 EXPECT_EQ(BB0->getTerminator()->getNumSuccessors(), 1u);
566
567 // Update the DTU. At this point bb0 now has no predecessors but is still a
568 // Child of F.
569 DTU.applyUpdates({{DominatorTree::Delete, NewEntry, BB0},
570 {DominatorTree::Insert, NewEntry, BB1}});
571 DTU.flush();
572 ASSERT_TRUE(DT.verify());
573 ASSERT_TRUE(PDT.verify());
574
575 // Now remove bb0 from F.
576 ASSERT_FALSE(isa(BB0->getTerminator()));
577 EXPECT_FALSE(DTU.isBBPendingDeletion(BB0));
578 DTU.deleteBB(BB0);
579 EXPECT_TRUE(DTU.isBBPendingDeletion(BB0));
580 ASSERT_TRUE(isa(BB0->getTerminator()));
581 EXPECT_EQ(BB0->getParent(), F);
582
583 // Perform a full recalculation of the DTU. It is not necessary here but we
584 // do this to test the case when there are no pending DT updates but there are
585 // pending deleted BBs.
586 ASSERT_TRUE(DTU.hasPendingDeletedBB());
587 DTU.recalculate(*F);
588 ASSERT_FALSE(DTU.hasPendingDeletedBB());
589 }
590
591 TEST(DomTreeUpdater, LazyUpdateStepTest) {
592 // This test focus on testing a DTU holding both trees applying multiple
593 // updates and DT/PDT not flushed together.
594 StringRef FuncName = "f";
595 StringRef ModuleString = R"(
596 define i32 @f(i32 %i, i32 *%p) {
597 bb0:
598 store i32 %i, i32 *%p
599 switch i32 %i, label %bb1 [
600 i32 0, label %bb1
601 i32 1, label %bb2
602 i32 2, label %bb3
603 i32 3, label %bb1
604 ]
605 bb1:
606 ret i32 1
607 bb2:
608 ret i32 2
609 bb3:
610 ret i32 3
611 }
612 )";
613 // Make the module.
614 LLVMContext Context;
615 std::unique_ptr M = makeLLVMModule(Context, ModuleString);
616 Function *F = M->getFunction(FuncName);
617
618 // Make the DomTreeUpdater.
619 DominatorTree DT(*F);
620 PostDominatorTree PDT(*F);
621 DomTreeUpdater DTU(DT, PDT, DomTreeUpdater::UpdateStrategy::Lazy);
622
623 ASSERT_TRUE(DTU.hasDomTree());
624 ASSERT_TRUE(DTU.hasPostDomTree());
625 ASSERT_EQ(DTU.getUpdateStrategy(), DomTreeUpdater::UpdateStrategy::Lazy);
626 ASSERT_TRUE(DTU.getDomTree().verify());
627 ASSERT_TRUE(DTU.getPostDomTree().verify());
628 ASSERT_FALSE(DTU.hasPendingUpdates());
629
630 Function::iterator FI = F->begin();
631 BasicBlock *BB0 = &*FI++;
632 FI++;
633 BasicBlock *BB2 = &*FI++;
634 BasicBlock *BB3 = &*FI++;
635 SwitchInst *SI = dyn_cast(BB0->getTerminator());
636 ASSERT_NE(SI, nullptr) << "Couldn't get SwitchInst.";
637
638 // Delete edge bb0 -> bb3 and push the update twice to verify duplicate
639 // entries are discarded.
640 std::vector Updates;
641 Updates.reserve(1);
642 Updates.push_back({DominatorTree::Delete, BB0, BB3});
643
644 // CFG Change: remove edge bb0 -> bb3.
645 EXPECT_EQ(BB0->getTerminator()->getNumSuccessors(), 5u);
646 BB3->removePredecessor(BB0);
647 for (auto i = SI->case_begin(), e = SI->case_end(); i != e; ++i) {
648 if (i->getCaseIndex() == 2) {
649 SI->removeCase(i);
650 break;
651 }
652 }
653 EXPECT_EQ(BB0->getTerminator()->getNumSuccessors(), 4u);
654 // Deletion of a BasicBlock is an immediate event. We remove all uses to the
655 // contained Instructions and change the Terminator to "unreachable" when
656 // queued for deletion.
657 ASSERT_FALSE(isa(BB3->getTerminator()));
658 EXPECT_FALSE(DTU.isBBPendingDeletion(BB3));
659 DTU.applyUpdates(Updates);
660
661 // Only flush DomTree.
662 ASSERT_TRUE(DTU.getDomTree().verify());
663 ASSERT_TRUE(DTU.hasPendingPostDomTreeUpdates());
664 ASSERT_FALSE(DTU.hasPendingDomTreeUpdates());
665
666 ASSERT_EQ(BB3->getParent(), F);
667 DTU.deleteBB(BB3);
668
669 Updates.clear();
670
671 // Remove all case branch to BB2 to test Eager recalculation.
672 // Code section from llvm::ConstantFoldTerminator
673 for (auto i = SI->case_begin(), e = SI->case_end(); i != e;) {
674 if (i->getCaseSuccessor() == BB2) {
675 // Remove this entry.
676 BB2->removePredecessor(BB0);
677 i = SI->removeCase(i);
678 e = SI->case_end();
679 Updates.push_back({DominatorTree::Delete, BB0, BB2});
680 } else
681 ++i;
682 }
683
684 DTU.applyUpdates(Updates);
685 // flush PostDomTree
686 ASSERT_TRUE(DTU.getPostDomTree().verify());
687 ASSERT_FALSE(DTU.hasPendingPostDomTreeUpdates());
688 ASSERT_TRUE(DTU.hasPendingDomTreeUpdates());
689 // flush both trees
690 DTU.flush();
691 ASSERT_TRUE(DT.verify());
692 }