1 //===- DomTreeUpdaterTest.cpp - DomTreeUpdater unit tests -----------------===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
9 #include "llvm/Analysis/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"
23 static std::unique_ptr
<Module
> makeLLVMModule(LLVMContext
&Context
,
24 StringRef ModuleStr
) {
26 std::unique_ptr
<Module
> M
= parseAssemblyString(ModuleStr
, Err
, Context
);
27 assert(M
&& "Bad LLVM IR?");
31 TEST(DomTreeUpdater
, EagerUpdateBasicOperations
) {
32 StringRef FuncName
= "f";
33 StringRef ModuleString
= R
"(
34 define i32 @f(i32 %i, i32 *%p) {
37 switch i32 %i, label %bb1 [
50 std::unique_ptr
<Module
> M
= makeLLVMModule(Context
, ModuleString
);
51 Function
*F
= M
->getFunction(FuncName
);
53 // Make the DomTreeUpdater.
55 PostDominatorTree
PDT(*F
);
56 DomTreeUpdater
DTU(DT
, PDT
, DomTreeUpdater::UpdateStrategy::Eager
);
58 ASSERT_TRUE(DTU
.hasDomTree());
59 ASSERT_TRUE(DTU
.hasPostDomTree());
60 ASSERT_TRUE(DTU
.isEager());
61 ASSERT_FALSE(DTU
.isLazy());
62 ASSERT_TRUE(DTU
.getDomTree().verify());
63 ASSERT_TRUE(DTU
.getPostDomTree().verify());
64 ASSERT_FALSE(DTU
.hasPendingUpdates());
66 Function::iterator FI
= F
->begin();
67 BasicBlock
*BB0
= &*FI
++;
68 BasicBlock
*BB1
= &*FI
++;
69 BasicBlock
*BB2
= &*FI
++;
70 BasicBlock
*BB3
= &*FI
++;
71 SwitchInst
*SI
= dyn_cast
<SwitchInst
>(BB0
->getTerminator());
72 ASSERT_NE(SI
, nullptr) << "Couldn't get SwitchInst.";
74 DTU
.applyUpdatesPermissive(
75 {{DominatorTree::Insert
, BB0
, BB0
}, {DominatorTree::Delete
, BB0
, BB0
}});
76 ASSERT_FALSE(DTU
.hasPendingUpdates());
78 // Delete edge bb0 -> bb3 and push the update twice to verify duplicate
79 // entries are discarded.
80 std::vector
<DominatorTree::UpdateType
> Updates
;
82 Updates
.push_back({DominatorTree::Delete
, BB0
, BB3
});
83 Updates
.push_back({DominatorTree::Delete
, BB0
, BB3
});
85 // Invalid Insert: no edge bb1 -> bb2 after change to bb0.
86 Updates
.push_back({DominatorTree::Insert
, BB1
, BB2
});
87 // Invalid Delete: edge exists bb0 -> bb1 after change to bb0.
88 Updates
.push_back({DominatorTree::Delete
, BB0
, BB1
});
90 // CFG Change: remove edge bb0 -> bb3.
91 EXPECT_EQ(BB0
->getTerminator()->getNumSuccessors(), 3u);
92 BB3
->removePredecessor(BB0
);
93 for (auto i
= SI
->case_begin(), e
= SI
->case_end(); i
!= e
; ++i
) {
94 if (i
->getCaseSuccessor() == BB3
) {
99 EXPECT_EQ(BB0
->getTerminator()->getNumSuccessors(), 2u);
100 // Deletion of a BasicBlock is an immediate event. We remove all uses to the
101 // contained Instructions and change the Terminator to "unreachable" when
102 // queued for deletion.
103 ASSERT_FALSE(isa
<UnreachableInst
>(BB3
->getTerminator()));
104 EXPECT_FALSE(DTU
.isBBPendingDeletion(BB3
));
105 DTU
.applyUpdatesPermissive(Updates
);
106 ASSERT_FALSE(DTU
.hasPendingUpdates());
108 // Invalid Insert: no edge bb1 -> bb2 after change to bb0.
109 // Invalid Delete: edge exists bb0 -> bb1 after change to bb0.
110 DTU
.applyUpdatesPermissive(
111 {{DominatorTree::Insert
, BB1
, BB2
}, {DominatorTree::Delete
, BB0
, BB1
}});
113 // DTU working with Eager UpdateStrategy does not need to flush.
114 ASSERT_TRUE(DT
.verify());
115 ASSERT_TRUE(PDT
.verify());
117 // Test callback utils.
118 ASSERT_EQ(BB3
->getParent(), F
);
119 DTU
.callbackDeleteBB(BB3
,
120 [&F
](BasicBlock
*BB
) { ASSERT_NE(BB
->getParent(), F
); });
122 ASSERT_TRUE(DT
.verify());
123 ASSERT_TRUE(PDT
.verify());
124 ASSERT_FALSE(DTU
.hasPendingUpdates());
126 // Unnecessary flush() test
128 EXPECT_TRUE(DT
.verify());
129 EXPECT_TRUE(PDT
.verify());
131 // Remove all case branch to BB2 to test Eager recalculation.
132 // Code section from llvm::ConstantFoldTerminator
133 for (auto i
= SI
->case_begin(), e
= SI
->case_end(); i
!= e
;) {
134 if (i
->getCaseSuccessor() == BB2
) {
135 // Remove this entry.
136 BB2
->removePredecessor(BB0
);
137 i
= SI
->removeCase(i
);
142 ASSERT_FALSE(DT
.verify());
143 ASSERT_FALSE(PDT
.verify());
145 ASSERT_TRUE(DT
.verify());
146 ASSERT_TRUE(PDT
.verify());
149 TEST(DomTreeUpdater
, EagerUpdateReplaceEntryBB
) {
150 StringRef FuncName
= "f";
151 StringRef ModuleString
= R
"(
161 std::unique_ptr
<Module
> M
= makeLLVMModule(Context
, ModuleString
);
162 Function
*F
= M
->getFunction(FuncName
);
165 DominatorTree
DT(*F
);
166 PostDominatorTree
PDT(*F
);
167 DomTreeUpdater
DTU(DT
, PDT
, DomTreeUpdater::UpdateStrategy::Eager
);
168 ASSERT_TRUE(DTU
.hasDomTree());
169 ASSERT_TRUE(DTU
.hasPostDomTree());
170 ASSERT_TRUE(DTU
.isEager());
171 ASSERT_FALSE(DTU
.isLazy());
172 ASSERT_TRUE(DT
.verify());
173 ASSERT_TRUE(PDT
.verify());
175 Function::iterator FI
= F
->begin();
176 BasicBlock
*BB0
= &*FI
++;
177 BasicBlock
*BB1
= &*FI
++;
179 // Add a block as the new function entry BB. We also link it to BB0.
180 BasicBlock
*NewEntry
=
181 BasicBlock::Create(F
->getContext(), "new_entry", F
, BB0
);
182 BranchInst::Create(BB0
, NewEntry
);
183 EXPECT_EQ(F
->begin()->getName(), NewEntry
->getName());
184 EXPECT_TRUE(&F
->getEntryBlock() == NewEntry
);
186 DTU
.applyUpdates({{DominatorTree::Insert
, NewEntry
, BB0
}});
188 // Changing the Entry BB requires a full recalculation of DomTree.
190 ASSERT_TRUE(DT
.verify());
191 ASSERT_TRUE(PDT
.verify());
193 // CFG Change: remove new_edge -> bb0 and redirect to new_edge -> bb1.
194 EXPECT_EQ(NewEntry
->getTerminator()->getNumSuccessors(), 1u);
195 NewEntry
->getTerminator()->eraseFromParent();
196 BranchInst::Create(BB1
, NewEntry
);
197 EXPECT_EQ(BB0
->getTerminator()->getNumSuccessors(), 1u);
199 // Update the DTU. At this point bb0 now has no predecessors but is still a
201 DTU
.applyUpdates({{DominatorTree::Delete
, NewEntry
, BB0
},
202 {DominatorTree::Insert
, NewEntry
, BB1
}});
203 ASSERT_TRUE(DT
.verify());
204 ASSERT_TRUE(PDT
.verify());
206 // Now remove bb0 from F.
207 ASSERT_FALSE(isa
<UnreachableInst
>(BB0
->getTerminator()));
208 EXPECT_FALSE(DTU
.isBBPendingDeletion(BB0
));
210 ASSERT_TRUE(DT
.verify());
211 ASSERT_TRUE(PDT
.verify());
214 TEST(DomTreeUpdater
, LazyUpdateDTBasicOperations
) {
215 StringRef FuncName
= "f";
216 StringRef ModuleString
= R
"(
217 define i32 @f(i32 %i, i32 *%p) {
219 store i32 %i, i32 *%p
220 switch i32 %i, label %bb1 [
235 std::unique_ptr
<Module
> M
= makeLLVMModule(Context
, ModuleString
);
236 Function
*F
= M
->getFunction(FuncName
);
239 DominatorTree
DT(*F
);
240 PostDominatorTree
*PDT
= nullptr;
241 DomTreeUpdater
DTU(&DT
, PDT
, DomTreeUpdater::UpdateStrategy::Lazy
);
242 ASSERT_TRUE(DTU
.hasDomTree());
243 ASSERT_FALSE(DTU
.hasPostDomTree());
244 ASSERT_FALSE(DTU
.isEager());
245 ASSERT_TRUE(DTU
.isLazy());
246 ASSERT_TRUE(DTU
.getDomTree().verify());
248 Function::iterator FI
= F
->begin();
249 BasicBlock
*BB0
= &*FI
++;
250 BasicBlock
*BB1
= &*FI
++;
251 BasicBlock
*BB2
= &*FI
++;
252 BasicBlock
*BB3
= &*FI
++;
254 // Test discards of self-domination update.
255 DTU
.applyUpdatesPermissive({{DominatorTree::Insert
, BB0
, BB0
}});
256 ASSERT_FALSE(DTU
.hasPendingDomTreeUpdates());
258 // Delete edge bb0 -> bb3 and push the update twice to verify duplicate
259 // entries are discarded.
260 std::vector
<DominatorTree::UpdateType
> Updates
;
262 Updates
.push_back({DominatorTree::Delete
, BB0
, BB3
});
263 Updates
.push_back({DominatorTree::Delete
, BB0
, BB3
});
265 // Invalid Insert: no edge bb1 -> bb2 after change to bb0.
266 Updates
.push_back({DominatorTree::Insert
, BB1
, BB2
});
267 // Invalid Delete: edge exists bb0 -> bb1 after change to bb0.
268 Updates
.push_back({DominatorTree::Delete
, BB0
, BB1
});
270 // CFG Change: remove edge bb0 -> bb3 and one duplicate edge bb0 -> bb2.
271 EXPECT_EQ(BB0
->getTerminator()->getNumSuccessors(), 4u);
272 BB0
->getTerminator()->eraseFromParent();
273 BranchInst::Create(BB1
, BB2
, ConstantInt::getTrue(F
->getContext()), BB0
);
274 EXPECT_EQ(BB0
->getTerminator()->getNumSuccessors(), 2u);
276 // Verify. Updates to DTU must be applied *after* all changes to the CFG
277 // (including block deletion).
278 DTU
.applyUpdatesPermissive(Updates
);
279 ASSERT_TRUE(DTU
.getDomTree().verify());
281 // Deletion of a BasicBlock is an immediate event. We remove all uses to the
282 // contained Instructions and change the Terminator to "unreachable" when
283 // queued for deletion. Its parent is still F until all the pending updates
284 // are applied to all trees held by the DomTreeUpdater (DomTree/PostDomTree).
285 // We don't defer this action because it can cause problems for other
286 // transforms or analysis as it's part of the actual CFG. We only defer
287 // updates to the DominatorTrees. This code will crash if it is placed before
288 // the BranchInst::Create() call above. After a deletion of a BasicBlock. Only
289 // an explicit flush event can trigger the flushing of deleteBBs. Because some
290 // passes using Lazy UpdateStrategy rely on this behavior.
292 ASSERT_FALSE(isa
<UnreachableInst
>(BB3
->getTerminator()));
293 EXPECT_FALSE(DTU
.isBBPendingDeletion(BB3
));
294 EXPECT_FALSE(DTU
.hasPendingDeletedBB());
296 EXPECT_TRUE(DTU
.isBBPendingDeletion(BB3
));
297 EXPECT_TRUE(DTU
.hasPendingDeletedBB());
298 ASSERT_TRUE(isa
<UnreachableInst
>(BB3
->getTerminator()));
299 EXPECT_EQ(BB3
->getParent(), F
);
301 EXPECT_FALSE(DTU
.hasPendingDeletedBB());
304 TEST(DomTreeUpdater
, LazyUpdateDTInheritedPreds
) {
305 StringRef FuncName
= "f";
306 StringRef ModuleString
= R
"(
307 define i32 @f(i32 %i, i32 *%p) {
309 store i32 %i, i32 *%p
310 switch i32 %i, label %bb1 [
324 std::unique_ptr
<Module
> M
= makeLLVMModule(Context
, ModuleString
);
325 Function
*F
= M
->getFunction(FuncName
);
328 DominatorTree
DT(*F
);
329 PostDominatorTree
*PDT
= nullptr;
330 DomTreeUpdater
DTU(&DT
, PDT
, DomTreeUpdater::UpdateStrategy::Lazy
);
331 ASSERT_TRUE(DTU
.hasDomTree());
332 ASSERT_FALSE(DTU
.hasPostDomTree());
333 ASSERT_FALSE(DTU
.isEager());
334 ASSERT_TRUE(DTU
.isLazy());
335 ASSERT_TRUE(DTU
.getDomTree().verify());
337 Function::iterator FI
= F
->begin();
338 BasicBlock
*BB0
= &*FI
++;
339 BasicBlock
*BB1
= &*FI
++;
340 BasicBlock
*BB2
= &*FI
++;
341 BasicBlock
*BB3
= &*FI
++;
343 // There are several CFG locations where we have:
347 // +> curr <+ converted into: pred1..predN curr
352 // There is a specific shape of this we have to be careful of:
356 // |+> curr <+ converted into: pred1..predN curr
361 // While the final CFG form is functionally identical the updates to
362 // DTU are not. In the first case we must have
363 // DTU.applyUpdates({{DominatorTree::Insert, Pred1, Succ}}) while in
364 // the latter case we must *NOT* have
365 // DTU.applyUpdates({{DominatorTree::Insert, Pred1, Succ}}).
367 // CFG Change: bb0 now only has bb0 -> bb1 and bb0 -> bb3. We are preparing to
369 EXPECT_EQ(BB0
->getTerminator()->getNumSuccessors(), 3u);
370 BB0
->getTerminator()->eraseFromParent();
371 BranchInst::Create(BB1
, BB3
, ConstantInt::getTrue(F
->getContext()), BB0
);
372 EXPECT_EQ(BB0
->getTerminator()->getNumSuccessors(), 2u);
374 // Test callback utils.
375 std::vector
<BasicBlock
*> BasicBlocks
;
376 BasicBlocks
.push_back(BB1
);
377 BasicBlocks
.push_back(BB2
);
378 auto Eraser
= [&](BasicBlock
*BB
) { llvm::erase(BasicBlocks
, BB
); };
379 ASSERT_EQ(BasicBlocks
.size(), static_cast<size_t>(2));
380 // Remove bb2 from F. This has to happen before the call to
381 // applyUpdates() for DTU to detect there is no longer an edge between
382 // bb2 -> bb3. The deleteBB() method converts bb2's TI into "unreachable".
383 ASSERT_FALSE(isa
<UnreachableInst
>(BB2
->getTerminator()));
384 EXPECT_FALSE(DTU
.isBBPendingDeletion(BB2
));
385 DTU
.callbackDeleteBB(BB2
, Eraser
);
386 EXPECT_TRUE(DTU
.isBBPendingDeletion(BB2
));
387 ASSERT_TRUE(isa
<UnreachableInst
>(BB2
->getTerminator()));
388 EXPECT_EQ(BB2
->getParent(), F
);
390 // Queue up the DTU updates.
391 std::vector
<DominatorTree::UpdateType
> Updates
;
393 Updates
.push_back({DominatorTree::Delete
, BB0
, BB2
});
394 Updates
.push_back({DominatorTree::Delete
, BB2
, BB3
});
396 // Handle the specific shape case next.
397 // CFG Change: bb0 now only branches to bb3. We are preparing to remove bb1.
398 EXPECT_EQ(BB0
->getTerminator()->getNumSuccessors(), 2u);
399 BB0
->getTerminator()->eraseFromParent();
400 BranchInst::Create(BB3
, BB0
);
401 EXPECT_EQ(BB0
->getTerminator()->getNumSuccessors(), 1u);
403 // Remove bb1 from F. This has to happen before the call to
404 // applyUpdates() for DTU to detect there is no longer an edge between
405 // bb1 -> bb3. The deleteBB() method converts bb1's TI into "unreachable".
406 ASSERT_FALSE(isa
<UnreachableInst
>(BB1
->getTerminator()));
407 EXPECT_FALSE(DTU
.isBBPendingDeletion(BB1
));
408 DTU
.callbackDeleteBB(BB1
, Eraser
);
409 EXPECT_TRUE(DTU
.isBBPendingDeletion(BB1
));
410 ASSERT_TRUE(isa
<UnreachableInst
>(BB1
->getTerminator()));
411 EXPECT_EQ(BB1
->getParent(), F
);
413 // Update the DTU. In this case we don't submit {DominatorTree::Insert, BB0,
414 // BB3} because the edge previously existed at the start of this test when DT
415 // was first created.
416 Updates
.push_back({DominatorTree::Delete
, BB0
, BB1
});
417 Updates
.push_back({DominatorTree::Delete
, BB1
, BB3
});
419 // Verify everything.
420 DTU
.applyUpdatesPermissive(Updates
);
421 ASSERT_EQ(BasicBlocks
.size(), static_cast<size_t>(2));
423 ASSERT_EQ(BasicBlocks
.size(), static_cast<size_t>(0));
424 ASSERT_TRUE(DT
.verify());
427 TEST(DomTreeUpdater
, LazyUpdateBasicOperations
) {
428 StringRef FuncName
= "f";
429 StringRef ModuleString
= R
"(
430 define i32 @f(i32 %i, i32 *%p) {
432 store i32 %i, i32 *%p
433 switch i32 %i, label %bb1 [
448 std::unique_ptr
<Module
> M
= makeLLVMModule(Context
, ModuleString
);
449 Function
*F
= M
->getFunction(FuncName
);
452 DominatorTree
DT(*F
);
453 PostDominatorTree
PDT(*F
);
454 DomTreeUpdater
DTU(&DT
, &PDT
, DomTreeUpdater::UpdateStrategy::Lazy
);
455 ASSERT_TRUE(DTU
.hasDomTree());
456 ASSERT_TRUE(DTU
.hasPostDomTree());
457 ASSERT_FALSE(DTU
.isEager());
458 ASSERT_TRUE(DTU
.isLazy());
459 ASSERT_TRUE(DTU
.getDomTree().verify());
460 ASSERT_TRUE(DTU
.getPostDomTree().verify());
462 Function::iterator FI
= F
->begin();
463 BasicBlock
*BB0
= &*FI
++;
464 BasicBlock
*BB1
= &*FI
++;
465 BasicBlock
*BB2
= &*FI
++;
466 BasicBlock
*BB3
= &*FI
++;
467 // Test discards of self-domination update.
468 DTU
.applyUpdates({{DominatorTree::Delete
, BB0
, BB0
}});
470 // Delete edge bb0 -> bb3 and push the update twice to verify duplicate
471 // entries are discarded.
472 std::vector
<DominatorTree::UpdateType
> Updates
;
474 Updates
.push_back({DominatorTree::Delete
, BB0
, BB3
});
475 Updates
.push_back({DominatorTree::Delete
, BB0
, BB3
});
477 // Unnecessary Insert: no edge bb1 -> bb2 after change to bb0.
478 Updates
.push_back({DominatorTree::Insert
, BB1
, BB2
});
479 // Unnecessary Delete: edge exists bb0 -> bb1 after change to bb0.
480 Updates
.push_back({DominatorTree::Delete
, BB0
, BB1
});
482 // CFG Change: remove edge bb0 -> bb3 and one duplicate edge bb0 -> bb2.
483 EXPECT_EQ(BB0
->getTerminator()->getNumSuccessors(), 4u);
484 BB0
->getTerminator()->eraseFromParent();
485 BranchInst::Create(BB1
, BB2
, ConstantInt::getTrue(F
->getContext()), BB0
);
486 EXPECT_EQ(BB0
->getTerminator()->getNumSuccessors(), 2u);
488 // Deletion of a BasicBlock is an immediate event. We remove all uses to the
489 // contained Instructions and change the Terminator to "unreachable" when
490 // queued for deletion. Its parent is still F until DTU.flushDomTree is
491 // called. We don't defer this action because it can cause problems for other
492 // transforms or analysis as it's part of the actual CFG. We only defer
493 // updates to the DominatorTree. This code will crash if it is placed before
494 // the BranchInst::Create() call above.
495 bool CallbackFlag
= false;
496 ASSERT_FALSE(isa
<UnreachableInst
>(BB3
->getTerminator()));
497 EXPECT_FALSE(DTU
.isBBPendingDeletion(BB3
));
498 DTU
.callbackDeleteBB(BB3
, [&](BasicBlock
*) { CallbackFlag
= true; });
499 EXPECT_TRUE(DTU
.isBBPendingDeletion(BB3
));
500 ASSERT_TRUE(isa
<UnreachableInst
>(BB3
->getTerminator()));
501 EXPECT_EQ(BB3
->getParent(), F
);
503 // Verify. Updates to DTU must be applied *after* all changes to the CFG
504 // (including block deletion).
505 DTU
.applyUpdatesPermissive(Updates
);
506 ASSERT_TRUE(DTU
.getDomTree().verify());
507 ASSERT_TRUE(DTU
.hasPendingUpdates());
508 ASSERT_TRUE(DTU
.hasPendingPostDomTreeUpdates());
509 ASSERT_FALSE(DTU
.hasPendingDomTreeUpdates());
510 ASSERT_TRUE(DTU
.hasPendingDeletedBB());
511 ASSERT_TRUE(DTU
.getPostDomTree().verify());
512 ASSERT_FALSE(DTU
.hasPendingUpdates());
513 ASSERT_FALSE(DTU
.hasPendingPostDomTreeUpdates());
514 ASSERT_FALSE(DTU
.hasPendingDomTreeUpdates());
515 ASSERT_FALSE(DTU
.hasPendingDeletedBB());
516 ASSERT_EQ(CallbackFlag
, true);
519 TEST(DomTreeUpdater
, LazyUpdateReplaceEntryBB
) {
520 StringRef FuncName
= "f";
521 StringRef ModuleString
= R
"(
531 std::unique_ptr
<Module
> M
= makeLLVMModule(Context
, ModuleString
);
532 Function
*F
= M
->getFunction(FuncName
);
535 DominatorTree
DT(*F
);
536 PostDominatorTree
PDT(*F
);
537 DomTreeUpdater
DTU(DT
, PDT
, DomTreeUpdater::UpdateStrategy::Lazy
);
538 ASSERT_TRUE(DTU
.hasDomTree());
539 ASSERT_TRUE(DTU
.hasPostDomTree());
540 ASSERT_FALSE(DTU
.isEager());
541 ASSERT_TRUE(DTU
.isLazy());
542 ASSERT_TRUE(DTU
.getDomTree().verify());
543 ASSERT_TRUE(DTU
.getPostDomTree().verify());
545 Function::iterator FI
= F
->begin();
546 BasicBlock
*BB0
= &*FI
++;
547 BasicBlock
*BB1
= &*FI
++;
549 // Add a block as the new function entry BB. We also link it to BB0.
550 BasicBlock
*NewEntry
=
551 BasicBlock::Create(F
->getContext(), "new_entry", F
, BB0
);
552 BranchInst::Create(BB0
, NewEntry
);
553 EXPECT_EQ(F
->begin()->getName(), NewEntry
->getName());
554 EXPECT_TRUE(&F
->getEntryBlock() == NewEntry
);
556 // Insert the new edge between new_entry -> bb0. Without this the
557 // recalculate() call below will not actually recalculate the DT as there
558 // are no changes pending and no blocks deleted.
559 DTU
.applyUpdates({{DominatorTree::Insert
, NewEntry
, BB0
}});
561 // Changing the Entry BB requires a full recalculation.
563 ASSERT_TRUE(DTU
.getDomTree().verify());
564 ASSERT_TRUE(DTU
.getPostDomTree().verify());
566 // CFG Change: remove new_edge -> bb0 and redirect to new_edge -> bb1.
567 EXPECT_EQ(NewEntry
->getTerminator()->getNumSuccessors(), 1u);
568 NewEntry
->getTerminator()->eraseFromParent();
569 BranchInst::Create(BB1
, NewEntry
);
570 EXPECT_EQ(BB0
->getTerminator()->getNumSuccessors(), 1u);
572 // Update the DTU. At this point bb0 now has no predecessors but is still a
574 DTU
.applyUpdates({{DominatorTree::Delete
, NewEntry
, BB0
},
575 {DominatorTree::Insert
, NewEntry
, BB1
}});
577 ASSERT_TRUE(DT
.verify());
578 ASSERT_TRUE(PDT
.verify());
580 // Now remove bb0 from F.
581 ASSERT_FALSE(isa
<UnreachableInst
>(BB0
->getTerminator()));
582 EXPECT_FALSE(DTU
.isBBPendingDeletion(BB0
));
584 EXPECT_TRUE(DTU
.isBBPendingDeletion(BB0
));
585 ASSERT_TRUE(isa
<UnreachableInst
>(BB0
->getTerminator()));
586 EXPECT_EQ(BB0
->getParent(), F
);
588 // Perform a full recalculation of the DTU. It is not necessary here but we
589 // do this to test the case when there are no pending DT updates but there are
590 // pending deleted BBs.
591 ASSERT_TRUE(DTU
.hasPendingDeletedBB());
593 ASSERT_FALSE(DTU
.hasPendingDeletedBB());
596 TEST(DomTreeUpdater
, LazyUpdateStepTest
) {
597 // This test focus on testing a DTU holding both trees applying multiple
598 // updates and DT/PDT not flushed together.
599 StringRef FuncName
= "f";
600 StringRef ModuleString
= R
"(
601 define i32 @f(i32 %i, i32 *%p) {
603 store i32 %i, i32 *%p
604 switch i32 %i, label %bb1 [
620 std::unique_ptr
<Module
> M
= makeLLVMModule(Context
, ModuleString
);
621 Function
*F
= M
->getFunction(FuncName
);
623 // Make the DomTreeUpdater.
624 DominatorTree
DT(*F
);
625 PostDominatorTree
PDT(*F
);
626 DomTreeUpdater
DTU(DT
, PDT
, DomTreeUpdater::UpdateStrategy::Lazy
);
628 ASSERT_TRUE(DTU
.hasDomTree());
629 ASSERT_TRUE(DTU
.hasPostDomTree());
630 ASSERT_FALSE(DTU
.isEager());
631 ASSERT_TRUE(DTU
.isLazy());
632 ASSERT_TRUE(DTU
.getDomTree().verify());
633 ASSERT_TRUE(DTU
.getPostDomTree().verify());
634 ASSERT_FALSE(DTU
.hasPendingUpdates());
636 Function::iterator FI
= F
->begin();
637 BasicBlock
*BB0
= &*FI
++;
639 BasicBlock
*BB2
= &*FI
++;
640 BasicBlock
*BB3
= &*FI
++;
641 SwitchInst
*SI
= dyn_cast
<SwitchInst
>(BB0
->getTerminator());
642 ASSERT_NE(SI
, nullptr) << "Couldn't get SwitchInst.";
644 // Delete edge bb0 -> bb3.
645 std::vector
<DominatorTree::UpdateType
> Updates
;
647 Updates
.push_back({DominatorTree::Delete
, BB0
, BB3
});
649 // CFG Change: remove edge bb0 -> bb3.
650 EXPECT_EQ(BB0
->getTerminator()->getNumSuccessors(), 5u);
651 BB3
->removePredecessor(BB0
);
652 for (auto i
= SI
->case_begin(), e
= SI
->case_end(); i
!= e
; ++i
) {
653 if (i
->getCaseIndex() == 2) {
658 EXPECT_EQ(BB0
->getTerminator()->getNumSuccessors(), 4u);
659 // Deletion of a BasicBlock is an immediate event. We remove all uses to the
660 // contained Instructions and change the Terminator to "unreachable" when
661 // queued for deletion.
662 ASSERT_FALSE(isa
<UnreachableInst
>(BB3
->getTerminator()));
663 EXPECT_FALSE(DTU
.isBBPendingDeletion(BB3
));
664 DTU
.applyUpdates(Updates
);
666 // Only flush DomTree.
667 ASSERT_TRUE(DTU
.getDomTree().verify());
668 ASSERT_TRUE(DTU
.hasPendingPostDomTreeUpdates());
669 ASSERT_FALSE(DTU
.hasPendingDomTreeUpdates());
671 ASSERT_EQ(BB3
->getParent(), F
);
676 // Remove all case branch to BB2 to test Eager recalculation.
677 // Code section from llvm::ConstantFoldTerminator
678 for (auto i
= SI
->case_begin(), e
= SI
->case_end(); i
!= e
;) {
679 if (i
->getCaseSuccessor() == BB2
) {
680 // Remove this entry.
681 BB2
->removePredecessor(BB0
);
682 i
= SI
->removeCase(i
);
684 Updates
.push_back({DominatorTree::Delete
, BB0
, BB2
});
689 DTU
.applyUpdatesPermissive(Updates
);
691 ASSERT_TRUE(DTU
.getPostDomTree().verify());
692 ASSERT_FALSE(DTU
.hasPendingPostDomTreeUpdates());
693 ASSERT_TRUE(DTU
.hasPendingDomTreeUpdates());
696 ASSERT_TRUE(DT
.verify());
699 TEST(DomTreeUpdater
, NoTreeTest
) {
700 StringRef FuncName
= "f";
701 StringRef ModuleString
= R
"(
709 std::unique_ptr
<Module
> M
= makeLLVMModule(Context
, ModuleString
);
710 Function
*F
= M
->getFunction(FuncName
);
713 DomTreeUpdater
DTU(nullptr, nullptr, DomTreeUpdater::UpdateStrategy::Lazy
);
714 ASSERT_FALSE(DTU
.hasDomTree());
715 ASSERT_FALSE(DTU
.hasPostDomTree());
716 Function::iterator FI
= F
->begin();
717 BasicBlock
*BB0
= &*FI
++;
718 // Test whether PendingDeletedBB is flushed after the recalculation.
720 ASSERT_TRUE(DTU
.hasPendingDeletedBB());
722 ASSERT_FALSE(DTU
.hasPendingDeletedBB());
725 TEST(DomTreeUpdater
, LazyUpdateDeduplicationTest
) {
726 StringRef FuncName
= "f";
727 StringRef ModuleString
= R
"(
739 std::unique_ptr
<Module
> M
= makeLLVMModule(Context
, ModuleString
);
740 Function
*F
= M
->getFunction(FuncName
);
743 DominatorTree
DT(*F
);
744 DomTreeUpdater
DTU(&DT
, nullptr, DomTreeUpdater::UpdateStrategy::Lazy
);
745 ASSERT_TRUE(DTU
.getDomTree().verify());
747 Function::iterator FI
= F
->begin();
748 BasicBlock
*BB0
= &*FI
++;
749 BasicBlock
*BB1
= &*FI
++;
750 BasicBlock
*BB2
= &*FI
++;
752 // CFG Change: remove bb0 -> bb1 and add back bb0 -> bb1.
753 EXPECT_EQ(BB0
->getTerminator()->getNumSuccessors(), 1u);
754 BB0
->getTerminator()->eraseFromParent();
755 BranchInst::Create(BB1
, BB0
);
756 EXPECT_EQ(BB0
->getTerminator()->getNumSuccessors(), 1u);
758 // Update the DTU and simulate duplicates.
759 DTU
.applyUpdatesPermissive({{DominatorTree::Delete
, BB0
, BB1
},
760 {DominatorTree::Delete
, BB0
, BB1
},
761 {DominatorTree::Insert
, BB0
, BB1
},
762 {DominatorTree::Insert
, BB0
, BB1
},
763 {DominatorTree::Insert
, BB0
, BB1
}});
765 // The above operations result in a no-op.
766 ASSERT_FALSE(DTU
.hasPendingUpdates());
768 // Update the DTU. Simulate an invalid update.
769 DTU
.applyUpdatesPermissive({{DominatorTree::Delete
, BB0
, BB1
}});
770 ASSERT_FALSE(DTU
.hasPendingUpdates());
772 // CFG Change: remove bb0 -> bb1.
773 EXPECT_EQ(BB0
->getTerminator()->getNumSuccessors(), 1u);
774 BB0
->getTerminator()->eraseFromParent();
776 // Update the DTU and simulate invalid updates.
777 DTU
.applyUpdatesPermissive({{DominatorTree::Delete
, BB0
, BB1
},
778 {DominatorTree::Insert
, BB0
, BB1
},
779 {DominatorTree::Delete
, BB0
, BB1
},
780 {DominatorTree::Insert
, BB0
, BB1
},
781 {DominatorTree::Insert
, BB0
, BB1
}});
782 ASSERT_TRUE(DTU
.hasPendingUpdates());
784 // CFG Change: add bb0 -> bb2.
785 BranchInst::Create(BB2
, BB0
);
786 EXPECT_EQ(BB0
->getTerminator()->getNumSuccessors(), 1u);
787 DTU
.applyUpdates({{DominatorTree::Insert
, BB0
, BB2
}});
788 ASSERT_TRUE(DTU
.getDomTree().verify());