llvm.org GIT mirror llvm / 0ac04b4
[DTU] Refine the interface and logic of applyUpdates Summary: This patch separates two semantics of `applyUpdates`: 1. User provides an accurate CFG diff and the dominator tree is updated according to the difference of `the number of edge insertions` and `the number of edge deletions` to infer the status of an edge before and after the update. 2. User provides a sequence of hints. Updates mentioned in this sequence might never happened and even duplicated. Logic changes: Previously, removing invalid updates is considered a side-effect of deduplication and is not guaranteed to be reliable. To handle the second semantic, `applyUpdates` does validity checking before deduplication, which can cause updates that have already been applied to be submitted again. Then, different calls to `applyUpdates` might cause unintended consequences, for example, ``` DTU(Lazy) and Edge A->B exists. 1. DTU.applyUpdates({{Delete, A, B}, {Insert, A, B}}) // User expects these 2 updates result in a no-op, but {Insert, A, B} is queued 2. Remove A->B 3. DTU.applyUpdates({{Delete, A, B}}) // DTU cancels this update with {Insert, A, B} mentioned above together (Unintended) ``` But by restricting the precondition that updates of an edge need to be strictly ordered as how CFG changes were made, we can infer the initial status of this edge to resolve this issue. Interface changes: The second semantic of `applyUpdates` is separated to `applyUpdatesPermissive`. These changes enable DTU(Lazy) to use the first semantic if needed, which is quite useful in `transforms/utils`. Reviewers: kuhar, brzycki, dmgreen, grosser Reviewed By: brzycki Subscribers: hiraditya, llvm-commits Tags: #llvm Differential Revision: https://reviews.llvm.org/D58170 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@354669 91177308-0d34-0410-b5e6-96231b3b80d8 Chijun Sima 5 months ago
8 changed file(s) with 211 addition(s) and 133 deletion(s). Raw diff Collapse all Expand all
102102 /// Although GenericDomTree provides several update primitives,
103103 /// it is not encouraged to use these APIs directly.
104104
105 /// Submit updates to all available trees. Under Eager UpdateStrategy with
106 /// ForceRemoveDuplicates enabled or under Lazy UpdateStrategy, it will
107 /// 1. discard duplicated updates,
108 /// 2. remove invalid updates. (Invalid updates means deletion of an edge that
109 /// still exists or insertion of an edge that does not exist.)
105 /// Submit updates to all available trees.
110106 /// The Eager Strategy flushes updates immediately while the Lazy Strategy
111107 /// queues the updates.
112108 ///
121117 /// 2. It is illegal to submit any update that has already been submitted,
122118 /// i.e., you are supposed not to insert an existent edge or delete a
123119 /// nonexistent edge.
124 void applyUpdates(ArrayRef Updates,
125 bool ForceRemoveDuplicates = false);
120 void applyUpdates(ArrayRef Updates);
121
122 /// Submit updates to all available trees. It will also
123 /// 1. discard duplicated updates,
124 /// 2. remove invalid updates. (Invalid updates means deletion of an edge that
125 /// still exists or insertion of an edge that does not exist.)
126 /// The Eager Strategy flushes updates immediately while the Lazy Strategy
127 /// queues the updates.
128 ///
129 /// Note: The "existence" of an edge in a CFG refers to the CFG which DTU is
130 /// in sync with + all updates before that single update.
131 ///
132 /// CAUTION!
133 /// 1. It is required for the state of the LLVM IR to be updated
134 /// *before* submitting the updates because the internal update routine will
135 /// analyze the current state of the CFG to determine whether an update
136 /// is valid.
137 /// 2. It is illegal to submit any update that has already been submitted,
138 /// i.e., you are supposed not to insert an existent edge or delete a
139 /// nonexistent edge.
140 /// 3. It is only legal to submit updates to an edge in the order CFG changes
141 /// are made. The order you submit updates on different edges is not
142 /// restricted.
143 void applyUpdatesPermissive(ArrayRef Updates);
126144
127145 /// Notify DTU that the entry block was replaced.
128146 /// Recalculate all available trees and flush all BasicBlocks
148166 /// submitted. }
149167 LLVM_ATTRIBUTE_DEPRECATED(void insertEdgeRelaxed(BasicBlock *From,
150168 BasicBlock *To),
151 "Use applyUpdates() instead.");
169 "Use applyUpdatesPermissive() instead.");
152170
153171 /// \deprecated { Submit an edge deletion to all available trees. The Eager
154172 /// Strategy flushes this update immediately while the Lazy Strategy queues
170188 /// submitted. }
171189 LLVM_ATTRIBUTE_DEPRECATED(void deleteEdgeRelaxed(BasicBlock *From,
172190 BasicBlock *To),
173 "Use applyUpdates() instead.");
191 "Use applyUpdatesPermissive() instead.");
174192
175193 /// Delete DelBB. DelBB will be removed from its Parent and
176194 /// erased from available trees if it exists and finally get deleted.
259277 /// Returns true if at least one BasicBlock is deleted.
260278 bool forceFlushDeletedBB();
261279
262 /// Deduplicate and remove unnecessary updates (no-ops) when using Lazy
263 /// UpdateStrategy. Returns true if the update is queued for update.
264 bool applyLazyUpdate(DominatorTree::UpdateKind Kind, BasicBlock *From,
265 BasicBlock *To);
266
267280 /// Helper function to apply all pending DomTree updates.
268281 void applyDomTreeUpdates();
269282
1111 //===----------------------------------------------------------------------===//
1212
1313 #include "llvm/Analysis/DomTreeUpdater.h"
14 #include "llvm/ADT/SmallSet.h"
1415 #include "llvm/Analysis/PostDominators.h"
1516 #include "llvm/IR/Dominators.h"
1617 #include "llvm/Support/GenericDomTree.h"
1718 #include
1819 #include
20 #include
1921
2022 namespace llvm {
2123
5052 const DominatorTree::UpdateType Update) const {
5153 // Won't affect DomTree and PostDomTree.
5254 return Update.getFrom() == Update.getTo();
53 }
54
55 bool DomTreeUpdater::applyLazyUpdate(DominatorTree::UpdateKind Kind,
56 BasicBlock *From, BasicBlock *To) {
57 assert((DT || PDT) &&
58 "Call applyLazyUpdate() when both DT and PDT are nullptrs.");
59 assert(Strategy == DomTreeUpdater::UpdateStrategy::Lazy &&
60 "Call applyLazyUpdate() with Eager strategy error");
61 // Analyze pending updates to determine if the update is unnecessary.
62 const DominatorTree::UpdateType Update = {Kind, From, To};
63 const DominatorTree::UpdateType Invert = {Kind != DominatorTree::Insert
64 ? DominatorTree::Insert
65 : DominatorTree::Delete,
66 From, To};
67 // Only check duplicates in updates that are not applied by both trees.
68 auto I =
69 PendUpdates.begin() + std::max(PendDTUpdateIndex, PendPDTUpdateIndex);
70 const auto E = PendUpdates.end();
71
72 assert(I <= E && "Iterator out of range.");
73
74 for (; I != E; ++I) {
75 if (Update == *I)
76 return false; // Discard duplicate updates.
77
78 if (Invert == *I) {
79 // Update and Invert are both valid (equivalent to a no-op). Remove
80 // Invert from PendUpdates and discard the Update.
81 PendUpdates.erase(I);
82 return false;
83 }
84 }
85
86 PendUpdates.push_back(Update); // Save the valid update.
87 return true;
8855 }
8956
9057 void DomTreeUpdater::applyDomTreeUpdates() {
260227 new UnreachableInst(DelBB->getContext(), DelBB);
261228 }
262229
263 void DomTreeUpdater::applyUpdates(ArrayRef Updates,
264 bool ForceRemoveDuplicates) {
230 void DomTreeUpdater::applyUpdates(ArrayRef Updates) {
265231 if (!DT && !PDT)
266232 return;
267233
268 if (Strategy == UpdateStrategy::Lazy || ForceRemoveDuplicates) {
269 SmallVector Seen;
234 if (Strategy == UpdateStrategy::Lazy) {
270235 for (const auto U : Updates)
271 // For Lazy UpdateStrategy, avoid duplicates to applyLazyUpdate() to save
272 // on analysis.
273 if (llvm::none_of(
274 Seen,
275 [U](const DominatorTree::UpdateType S) { return S == U; }) &&
276 isUpdateValid(U) && !isSelfDominance(U)) {
277 Seen.push_back(U);
278 if (Strategy == UpdateStrategy::Lazy)
279 applyLazyUpdate(U.getKind(), U.getFrom(), U.getTo());
280 }
281 if (Strategy == UpdateStrategy::Lazy)
282 return;
283
284 if (DT)
285 DT->applyUpdates(Seen);
286 if (PDT)
287 PDT->applyUpdates(Seen);
236 if (!isSelfDominance(U))
237 PendUpdates.push_back(U);
238
288239 return;
289240 }
290241
292243 DT->applyUpdates(Updates);
293244 if (PDT)
294245 PDT->applyUpdates(Updates);
246 }
247
248 void DomTreeUpdater::applyUpdatesPermissive(
249 ArrayRef Updates) {
250 if (!DT && !PDT)
251 return;
252
253 SmallSet, 8> Seen;
254 SmallVector DeduplicatedUpdates;
255 for (const auto U : Updates) {
256 auto Edge = std::make_pair(U.getFrom(), U.getTo());
257 // Because it is illegal to submit updates that have already been applied
258 // and updates to an edge need to be strictly ordered,
259 // it is safe to infer the existence of an edge from the first update
260 // to this edge.
261 // If the first update to an edge is "Delete", it means that the edge
262 // existed before. If the first update to an edge is "Insert", it means
263 // that the edge didn't exist before.
264 //
265 // For example, if the user submits {{Delete, A, B}, {Insert, A, B}},
266 // because
267 // 1. it is illegal to submit updates that have already been applied,
268 // i.e., user cannot delete an nonexistent edge,
269 // 2. updates to an edge need to be strictly ordered,
270 // So, initially edge A -> B existed.
271 // We can then safely ignore future updates to this edge and directly
272 // inspect the current CFG:
273 // a. If the edge still exists, because the user cannot insert an existent
274 // edge, so both {Delete, A, B}, {Insert, A, B} actually happened and
275 // resulted in a no-op. DTU won't submit any update in this case.
276 // b. If the edge doesn't exist, we can then infer that {Delete, A, B}
277 // actually happened but {Insert, A, B} was an invalid update which never
278 // happened. DTU will submit {Delete, A, B} in this case.
279 if (!isSelfDominance(U) && Seen.count(Edge) == 0) {
280 Seen.insert(Edge);
281 // If the update doesn't appear in the CFG, it means that
282 // either the change isn't made or relevant operations
283 // result in a no-op.
284 if (isUpdateValid(U)) {
285 if (isLazy())
286 PendUpdates.push_back(U);
287 else
288 DeduplicatedUpdates.push_back(U);
289 }
290 }
291 }
292
293 if (Strategy == UpdateStrategy::Lazy)
294 return;
295
296 if (DT)
297 DT->applyUpdates(DeduplicatedUpdates);
298 if (PDT)
299 PDT->applyUpdates(DeduplicatedUpdates);
295300 }
296301
297302 DominatorTree &DomTreeUpdater::getDomTree() {
330335 return;
331336 }
332337
333 applyLazyUpdate(DominatorTree::Insert, From, To);
338 PendUpdates.push_back({DominatorTree::Insert, From, To});
334339 }
335340
336341 void DomTreeUpdater::insertEdgeRelaxed(BasicBlock *From, BasicBlock *To) {
351356 return;
352357 }
353358
354 applyLazyUpdate(DominatorTree::Insert, From, To);
359 PendUpdates.push_back({DominatorTree::Insert, From, To});
355360 }
356361
357362 void DomTreeUpdater::deleteEdge(BasicBlock *From, BasicBlock *To) {
376381 return;
377382 }
378383
379 applyLazyUpdate(DominatorTree::Delete, From, To);
384 PendUpdates.push_back({DominatorTree::Delete, From, To});
380385 }
381386
382387 void DomTreeUpdater::deleteEdgeRelaxed(BasicBlock *From, BasicBlock *To) {
397402 return;
398403 }
399404
400 applyLazyUpdate(DominatorTree::Delete, From, To);
405 PendUpdates.push_back({DominatorTree::Delete, From, To});
401406 }
402407
403408 void DomTreeUpdater::dropOutOfDateUpdates() {
365365 assert(Splits.size() == 2 && "Expected exactly 2 splits!");
366366 for (unsigned i = 0; i < Splits.size(); i++) {
367367 Splits[i]->getTerminator()->eraseFromParent();
368 DTU.applyUpdates({{DominatorTree::Delete, Splits[i], TailBB}});
368 DTU.applyUpdatesPermissive({{DominatorTree::Delete, Splits[i], TailBB}});
369369 }
370370
371371 // Erase the tail block once done with musttail patching
372372 ++NumDeadCases;
373373 Changed = true;
374374 if (--SuccessorsCount[Succ] == 0)
375 DTU.applyUpdates({{DominatorTree::Delete, BB, Succ}});
375 DTU.applyUpdatesPermissive({{DominatorTree::Delete, BB, Succ}});
376376 continue;
377377 }
378378 if (State == LazyValueInfo::True) {
10901090 << "' folding undef terminator: " << *BBTerm << '\n');
10911091 BranchInst::Create(BBTerm->getSuccessor(BestSucc), BBTerm);
10921092 BBTerm->eraseFromParent();
1093 DTU->applyUpdates(Updates);
1093 DTU->applyUpdatesPermissive(Updates);
10941094 return true;
10951095 }
10961096
11581158 ConstantInt::getFalse(CondCmp->getType());
11591159 ReplaceFoldableUses(CondCmp, CI);
11601160 }
1161 DTU->applyUpdates({{DominatorTree::Delete, BB, ToRemoveSucc}});
1161 DTU->applyUpdatesPermissive(
1162 {{DominatorTree::Delete, BB, ToRemoveSucc}});
11621163 return true;
11631164 }
11641165
12451246 RemoveSucc->removePredecessor(BB);
12461247 BranchInst::Create(KeepSucc, BI);
12471248 BI->eraseFromParent();
1248 DTU->applyUpdates({{DominatorTree::Delete, BB, RemoveSucc}});
1249 DTU->applyUpdatesPermissive({{DominatorTree::Delete, BB, RemoveSucc}});
12491250 return true;
12501251 }
12511252 CurrentBB = CurrentPred;
16751676 Instruction *Term = BB->getTerminator();
16761677 BranchInst::Create(OnlyDest, Term);
16771678 Term->eraseFromParent();
1678 DTU->applyUpdates(Updates);
1679 DTU->applyUpdatesPermissive(Updates);
16791680
16801681 // If the condition is now dead due to the removal of the old terminator,
16811682 // erase it.
20172018 }
20182019
20192020 // Enqueue required DT updates.
2020 DTU->applyUpdates({{DominatorTree::Insert, NewBB, SuccBB},
2021 {DominatorTree::Insert, PredBB, NewBB},
2022 {DominatorTree::Delete, PredBB, BB}});
2021 DTU->applyUpdatesPermissive({{DominatorTree::Insert, NewBB, SuccBB},
2022 {DominatorTree::Insert, PredBB, NewBB},
2023 {DominatorTree::Delete, PredBB, BB}});
20232024
20242025 // If there were values defined in BB that are used outside the block, then we
20252026 // now have to update all uses of the value to use either the original value,
21132114 BFI->setBlockFreq(NewBB, NewBBFreq.getFrequency());
21142115 }
21152116
2116 DTU->applyUpdates(Updates);
2117 DTU->applyUpdatesPermissive(Updates);
21172118 return NewBBs[0];
21182119 }
21192120
23862387
23872388 // Remove the unconditional branch at the end of the PredBB block.
23882389 OldPredBranch->eraseFromParent();
2389 DTU->applyUpdates(Updates);
2390 DTU->applyUpdatesPermissive(Updates);
23902391
23912392 ++NumDupes;
23922393 return true;
24222423
24232424 // The select is now dead.
24242425 SI->eraseFromParent();
2425 DTU->applyUpdates({{DominatorTree::Insert, NewBB, BB},
2426 {DominatorTree::Insert, Pred, NewBB}});
2426 DTU->applyUpdatesPermissive({{DominatorTree::Insert, NewBB, BB},
2427 {DominatorTree::Insert, Pred, NewBB}});
24272428
24282429 // Update any other PHI nodes in BB.
24292430 for (BasicBlock::iterator BI = BB->begin();
26002601 Updates.push_back({DominatorTree::Delete, BB, Succ});
26012602 Updates.push_back({DominatorTree::Insert, SplitBB, Succ});
26022603 }
2603 DTU->applyUpdates(Updates);
2604 DTU->applyUpdatesPermissive(Updates);
26042605 return true;
26052606 }
26062607 return false;
100100 DetatchDeadBlocks(BBs, DTU ? &Updates : nullptr, KeepOneInputPHIs);
101101
102102 if (DTU)
103 DTU->applyUpdates(Updates, /*ForceRemoveDuplicates*/ true);
103 DTU->applyUpdatesPermissive(Updates);
104104
105105 for (BasicBlock *BB : BBs)
106106 if (DTU)
234234 isa(BB->getTerminator()) &&
235235 "The successor list of BB isn't empty before "
236236 "applying corresponding DTU updates.");
237 DTU->applyUpdates(Updates, /*ForceRemoveDuplicates*/ true);
237 DTU->applyUpdatesPermissive(Updates);
238238 DTU->deleteBB(BB);
239239 }
240240
127127 Builder.CreateBr(Destination);
128128 BI->eraseFromParent();
129129 if (DTU)
130 DTU->applyUpdates({{DominatorTree::Delete, BB, OldDest}},
131 /*ForceRemoveDuplicates*/ true);
130 DTU->applyUpdatesPermissive({{DominatorTree::Delete, BB, OldDest}});
132131 return true;
133132 }
134133
204203 i = SI->removeCase(i);
205204 e = SI->case_end();
206205 if (DTU)
207 DTU->applyUpdates({{DominatorTree::Delete, ParentBB, DefaultDest}},
208 /*ForceRemoveDuplicates*/ true);
206 DTU->applyUpdatesPermissive(
207 {{DominatorTree::Delete, ParentBB, DefaultDest}});
209208 continue;
210209 }
211210
253252 if (DeleteDeadConditions)
254253 RecursivelyDeleteTriviallyDeadInstructions(Cond, TLI);
255254 if (DTU)
256 DTU->applyUpdates(Updates, /*ForceRemoveDuplicates*/ true);
255 DTU->applyUpdatesPermissive(Updates);
257256 return true;
258257 }
259258
331330 }
332331
333332 if (DTU)
334 DTU->applyUpdates(Updates, /*ForceRemoveDuplicates*/ true);
333 DTU->applyUpdatesPermissive(Updates);
335334 return true;
336335 }
337336 }
665664 if (PhiIt != OldPhiIt) PhiIt = &BB->front();
666665 }
667666 if (DTU)
668 DTU->applyUpdates({{DominatorTree::Delete, Pred, BB}},
669 /*ForceRemoveDuplicates*/ true);
667 DTU->applyUpdatesPermissive({{DominatorTree::Delete, Pred, BB}});
670668 }
671669
672670 /// MergeBasicBlockIntoOnlyPred - DestBB is a block with one predecessor and its
735733 isa(PredBB->getTerminator()) &&
736734 "The successor list of PredBB isn't empty before "
737735 "applying corresponding DTU updates.");
738 DTU->applyUpdates(Updates, /*ForceRemoveDuplicates*/ true);
736 DTU->applyUpdatesPermissive(Updates);
739737 DTU->deleteBB(PredBB);
740738 // Recalculation of DomTree is needed when updating a forward DomTree and
741739 // the Entry BB is replaced.
10771075 "applying corresponding DTU updates.");
10781076
10791077 if (DTU) {
1080 DTU->applyUpdates(Updates, /*ForceRemoveDuplicates*/ true);
1078 DTU->applyUpdatesPermissive(Updates);
10811079 DTU->deleteBB(BB);
10821080 } else {
10831081 BB->eraseFromParent(); // Delete the old basic block.
19411939 ++NumInstrsRemoved;
19421940 }
19431941 if (DTU)
1944 DTU->applyUpdates(Updates, /*ForceRemoveDuplicates*/ true);
1942 DTU->applyUpdatesPermissive(Updates);
19451943 return NumInstrsRemoved;
19461944 }
19471945
19691967 UnwindDestBB->removePredecessor(BB);
19701968 II->eraseFromParent();
19711969 if (DTU)
1972 DTU->applyUpdates({{DominatorTree::Delete, BB, UnwindDestBB}},
1973 /*ForceRemoveDuplicates*/ true);
1970 DTU->applyUpdatesPermissive({{DominatorTree::Delete, BB, UnwindDestBB}});
19741971 }
19751972
19761973 BasicBlock *llvm::changeToInvokeAndSplitBasicBlock(CallInst *CI,
21172114 UnwindDestBB->removePredecessor(II->getParent());
21182115 II->eraseFromParent();
21192116 if (DTU)
2120 DTU->applyUpdates({{DominatorTree::Delete, BB, UnwindDestBB}},
2121 /*ForceRemoveDuplicates*/ true);
2117 DTU->applyUpdatesPermissive(
2118 {{DominatorTree::Delete, BB, UnwindDestBB}});
21222119 } else
21232120 changeToCall(II, DTU);
21242121 Changed = true;
22072204 TI->replaceAllUsesWith(NewTI);
22082205 TI->eraseFromParent();
22092206 if (DTU)
2210 DTU->applyUpdates({{DominatorTree::Delete, BB, UnwindDest}},
2211 /*ForceRemoveDuplicates*/ true);
2207 DTU->applyUpdatesPermissive({{DominatorTree::Delete, BB, UnwindDest}});
22122208 }
22132209
22142210 /// removeUnreachableBlocks - Remove blocks that are not reachable, even
22732269 }
22742270
22752271 if (DTU) {
2276 DTU->applyUpdates(Updates, /*ForceRemoveDuplicates*/ true);
2272 DTU->applyUpdatesPermissive(Updates);
22772273 bool Deleted = false;
22782274 for (auto *BB : DeadBlockSet) {
22792275 if (DTU->isBBPendingDeletion(BB))
7070 SwitchInst *SI = dyn_cast(BB0->getTerminator());
7171 ASSERT_NE(SI, nullptr) << "Couldn't get SwitchInst.";
7272
73 DTU.applyUpdates(
74 {{DominatorTree::Insert, BB0, BB0}, {DominatorTree::Delete, BB0, BB0}},
75 /*ForceRemoveDuplicates*/ true);
73 DTU.applyUpdatesPermissive(
74 {{DominatorTree::Insert, BB0, BB0}, {DominatorTree::Delete, BB0, BB0}});
75 ASSERT_FALSE(DTU.hasPendingUpdates());
7676
7777 // Delete edge bb0 -> bb3 and push the update twice to verify duplicate
7878 // entries are discarded.
101101 // queued for deletion.
102102 ASSERT_FALSE(isa(BB3->getTerminator()));
103103 EXPECT_FALSE(DTU.isBBPendingDeletion(BB3));
104 DTU.applyUpdates(Updates, /*ForceRemoveDuplicates*/ true);
104 DTU.applyUpdatesPermissive(Updates);
105105 ASSERT_FALSE(DTU.hasPendingUpdates());
106106
107107 // Invalid Insert: no edge bb1 -> bb2 after change to bb0.
108108 // Invalid Delete: edge exists bb0 -> bb1 after change to bb0.
109 DTU.applyUpdates(
110 {{DominatorTree::Insert, BB1, BB2}, {DominatorTree::Delete, BB0, BB1}},
111 /*ForceRemoveDuplicates*/ true);
109 DTU.applyUpdatesPermissive(
110 {{DominatorTree::Insert, BB1, BB2}, {DominatorTree::Delete, BB0, BB1}});
112111
113112 // DTU working with Eager UpdateStrategy does not need to flush.
114113 ASSERT_TRUE(DT.verify());
183182 EXPECT_EQ(F->begin()->getName(), NewEntry->getName());
184183 EXPECT_TRUE(&F->getEntryBlock() == NewEntry);
185184
186 DTU.applyUpdates({{DominatorTree::Insert, NewEntry, BB0}},
187 /*ForceRemoveDuplicates*/ true);
185 DTU.applyUpdates({{DominatorTree::Insert, NewEntry, BB0}});
188186
189187 // Changing the Entry BB requires a full recalculation of DomTree.
190188 DTU.recalculate(*F);
253251 BasicBlock *BB3 = &*FI++;
254252
255253 // Test discards of self-domination update.
256 DTU.applyUpdates({{DominatorTree::Delete, BB0, BB0}});
254 DTU.applyUpdatesPermissive({{DominatorTree::Insert, BB0, BB0}});
257255 ASSERT_FALSE(DTU.hasPendingDomTreeUpdates());
258256
259257 // Delete edge bb0 -> bb3 and push the update twice to verify duplicate
276274
277275 // Verify. Updates to DTU must be applied *after* all changes to the CFG
278276 // (including block deletion).
279 DTU.applyUpdates(Updates);
277 DTU.applyUpdatesPermissive(Updates);
280278 ASSERT_TRUE(DTU.getDomTree().verify());
281279
282280 // Deletion of a BasicBlock is an immediate event. We remove all uses to the
361359 //
362360 // While the final CFG form is functionally identical the updates to
363361 // DTU are not. In the first case we must have
364 // DTU.applyUpdates({{DominatorTree::Insert, Pred1, Succ}}) while in the
365 // latter case we must *NOT* have DTU.applyUpdates({{DominatorTree::Insert,
366 // Pred1, Succ}}).
362 // DTU.applyUpdates({{DominatorTree::Insert, Pred1, Succ}}) while in
363 // the latter case we must *NOT* have
364 // DTU.applyUpdates({{DominatorTree::Insert, Pred1, Succ}}).
367365
368366 // CFG Change: bb0 now only has bb0 -> bb1 and bb0 -> bb3. We are preparing to
369367 // remove bb2.
383381 BasicBlocks.end());
384382 };
385383 ASSERT_EQ(BasicBlocks.size(), static_cast(2));
386 // Remove bb2 from F. This has to happen before the call to applyUpdates() for
387 // DTU to detect there is no longer an edge between bb2 -> bb3. The deleteBB()
388 // method converts bb2's TI into "unreachable".
384 // Remove bb2 from F. This has to happen before the call to
385 // applyUpdates() for DTU to detect there is no longer an edge between
386 // bb2 -> bb3. The deleteBB() method converts bb2's TI into "unreachable".
389387 ASSERT_FALSE(isa(BB2->getTerminator()));
390388 EXPECT_FALSE(DTU.isBBPendingDeletion(BB2));
391389 DTU.callbackDeleteBB(BB2, Eraser);
406404 BranchInst::Create(BB3, BB0);
407405 EXPECT_EQ(BB0->getTerminator()->getNumSuccessors(), 1u);
408406
409 // Remove bb1 from F. This has to happen before the call to applyUpdates() for
410 // DTU to detect there is no longer an edge between bb1 -> bb3. The deleteBB()
411 // method converts bb1's TI into "unreachable".
407 // Remove bb1 from F. This has to happen before the call to
408 // applyUpdates() for DTU to detect there is no longer an edge between
409 // bb1 -> bb3. The deleteBB() method converts bb1's TI into "unreachable".
412410 ASSERT_FALSE(isa(BB1->getTerminator()));
413411 EXPECT_FALSE(DTU.isBBPendingDeletion(BB1));
414412 DTU.callbackDeleteBB(BB1, Eraser);
423421 Updates.push_back({DominatorTree::Delete, BB1, BB3});
424422
425423 // Verify everything.
426 DTU.applyUpdates(Updates);
424 DTU.applyUpdatesPermissive(Updates);
427425 ASSERT_EQ(BasicBlocks.size(), static_cast(2));
428426 DTU.flush();
429427 ASSERT_EQ(BasicBlocks.size(), static_cast(0));
508506
509507 // Verify. Updates to DTU must be applied *after* all changes to the CFG
510508 // (including block deletion).
511 DTU.applyUpdates(Updates);
509 DTU.applyUpdatesPermissive(Updates);
512510 ASSERT_TRUE(DTU.getDomTree().verify());
513511 ASSERT_TRUE(DTU.hasPendingUpdates());
514512 ASSERT_TRUE(DTU.hasPendingPostDomTreeUpdates());
647645 SwitchInst *SI = dyn_cast(BB0->getTerminator());
648646 ASSERT_NE(SI, nullptr) << "Couldn't get SwitchInst.";
649647
650 // Delete edge bb0 -> bb3 and push the update twice to verify duplicate
651 // entries are discarded.
648 // Delete edge bb0 -> bb3.
652649 std::vector Updates;
653650 Updates.reserve(1);
654651 Updates.push_back({DominatorTree::Delete, BB0, BB3});
693690 ++i;
694691 }
695692
696 DTU.applyUpdates(Updates);
693 DTU.applyUpdatesPermissive(Updates);
697694 // flush PostDomTree
698695 ASSERT_TRUE(DTU.getPostDomTree().verify());
699696 ASSERT_FALSE(DTU.hasPendingPostDomTreeUpdates());
728725 DTU.recalculate(*F);
729726 ASSERT_FALSE(DTU.hasPendingDeletedBB());
730727 }
728
729 TEST(DomTreeUpdater, LazyUpdateDeduplicationTest) {
730 StringRef FuncName = "f";
731 StringRef ModuleString = R"(
732 define i32 @f() {
733 bb0:
734 br label %bb1
735 bb1:
736 ret i32 1
737 bb2:
738 ret i32 1
739 }
740 )";
741 // Make the module.
742 LLVMContext Context;
743 std::unique_ptr M = makeLLVMModule(Context, ModuleString);
744 Function *F = M->getFunction(FuncName);
745
746 // Make the DTU.
747 DominatorTree DT(*F);
748 DomTreeUpdater DTU(&DT, nullptr, DomTreeUpdater::UpdateStrategy::Lazy);
749 ASSERT_TRUE(DTU.getDomTree().verify());
750
751 Function::iterator FI = F->begin();
752 BasicBlock *BB0 = &*FI++;
753 BasicBlock *BB1 = &*FI++;
754 BasicBlock *BB2 = &*FI++;
755
756 // CFG Change: remove bb0 -> bb1 and add back bb0 -> bb1.
757 EXPECT_EQ(BB0->getTerminator()->getNumSuccessors(), 1u);
758 BB0->getTerminator()->eraseFromParent();
759 BranchInst::Create(BB1, BB0);
760 EXPECT_EQ(BB0->getTerminator()->getNumSuccessors(), 1u);
761
762 // Update the DTU and simulate duplicates.
763 DTU.applyUpdatesPermissive({{DominatorTree::Delete, BB0, BB1},
764 {DominatorTree::Delete, BB0, BB1},
765 {DominatorTree::Insert, BB0, BB1},
766 {DominatorTree::Insert, BB0, BB1},
767 {DominatorTree::Insert, BB0, BB1}});
768
769 // The above operations result in a no-op.
770 ASSERT_FALSE(DTU.hasPendingUpdates());
771
772 // Update the DTU. Simulate an invalid update.
773 DTU.applyUpdatesPermissive({{DominatorTree::Delete, BB0, BB1}});
774 ASSERT_FALSE(DTU.hasPendingUpdates());
775
776 // CFG Change: remove bb0 -> bb1.
777 EXPECT_EQ(BB0->getTerminator()->getNumSuccessors(), 1u);
778 BB0->getTerminator()->eraseFromParent();
779
780 // Update the DTU and simulate invalid updates.
781 DTU.applyUpdatesPermissive({{DominatorTree::Delete, BB0, BB1},
782 {DominatorTree::Insert, BB0, BB1},
783 {DominatorTree::Delete, BB0, BB1},
784 {DominatorTree::Insert, BB0, BB1},
785 {DominatorTree::Insert, BB0, BB1}});
786 ASSERT_TRUE(DTU.hasPendingUpdates());
787
788 // CFG Change: add bb0 -> bb2.
789 BranchInst::Create(BB2, BB0);
790 EXPECT_EQ(BB0->getTerminator()->getNumSuccessors(), 1u);
791 DTU.applyUpdates({{DominatorTree::Insert, BB0, BB2}});
792 ASSERT_TRUE(DTU.getDomTree().verify());
793 }