[ARM] MVE big endian loads/stores
[llvm-complete.git] / unittests / Analysis / DomTreeUpdaterTest.cpp
blob4a5e2d73f962ca652632c4d5448f2b2171156853
1 //===- DomTreeUpdaterTest.cpp - DomTreeUpdater unit tests -----------------===//
2 //
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
6 //
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"
19 #include <algorithm>
21 using namespace llvm;
23 static std::unique_ptr<Module> makeLLVMModule(LLVMContext &Context,
24 StringRef ModuleStr) {
25 SMDiagnostic Err;
26 std::unique_ptr<Module> M = parseAssemblyString(ModuleStr, Err, Context);
27 assert(M && "Bad LLVM IR?");
28 return M;
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
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<Module> M = makeLLVMModule(Context, ModuleString);
51 Function *F = M->getFunction(FuncName);
53 // Make the DomTreeUpdater.
54 DominatorTree DT(*F);
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;
81 Updates.reserve(4);
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) {
95 SI->removeCase(i);
96 break;
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
127 DTU.flush();
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);
138 e = SI->case_end();
139 } else
140 ++i;
142 ASSERT_FALSE(DT.verify());
143 ASSERT_FALSE(PDT.verify());
144 DTU.recalculate(*F);
145 ASSERT_TRUE(DT.verify());
146 ASSERT_TRUE(PDT.verify());
149 TEST(DomTreeUpdater, EagerUpdateReplaceEntryBB) {
150 StringRef FuncName = "f";
151 StringRef ModuleString = R"(
152 define i32 @f() {
153 bb0:
154 br label %bb1
155 bb1:
156 ret i32 1
159 // Make the module.
160 LLVMContext Context;
161 std::unique_ptr<Module> M = makeLLVMModule(Context, ModuleString);
162 Function *F = M->getFunction(FuncName);
164 // Make the DTU.
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.
189 DTU.recalculate(*F);
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
200 // Child of F.
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));
209 DTU.deleteBB(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) {
218 bb0:
219 store i32 %i, i32 *%p
220 switch i32 %i, label %bb1 [
221 i32 0, label %bb2
222 i32 1, label %bb2
223 i32 2, label %bb3
225 bb1:
226 ret i32 1
227 bb2:
228 ret i32 2
229 bb3:
230 ret i32 3
233 // Make the module.
234 LLVMContext Context;
235 std::unique_ptr<Module> M = makeLLVMModule(Context, ModuleString);
236 Function *F = M->getFunction(FuncName);
238 // Make the DTU.
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;
261 Updates.reserve(4);
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());
295 DTU.deleteBB(BB3);
296 EXPECT_TRUE(DTU.isBBPendingDeletion(BB3));
297 EXPECT_TRUE(DTU.hasPendingDeletedBB());
298 ASSERT_TRUE(isa<UnreachableInst>(BB3->getTerminator()));
299 EXPECT_EQ(BB3->getParent(), F);
300 DTU.recalculate(*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) {
308 bb0:
309 store i32 %i, i32 *%p
310 switch i32 %i, label %bb1 [
311 i32 2, label %bb2
312 i32 3, label %bb3
314 bb1:
315 br label %bb3
316 bb2:
317 br label %bb3
318 bb3:
319 ret i32 3
322 // Make the module.
323 LLVMContext Context;
324 std::unique_ptr<Module> M = makeLLVMModule(Context, ModuleString);
325 Function *F = M->getFunction(FuncName);
327 // Make the DTU.
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:
345 // pred1..predN
346 // | |
347 // +> curr <+ converted into: pred1..predN curr
348 // | | |
349 // v +> succ <+
350 // succ
352 // There is a specific shape of this we have to be careful of:
354 // pred1..predN
355 // || |
356 // |+> curr <+ converted into: pred1..predN curr
357 // | | | |
358 // | v +> succ <+
359 // +-> succ
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
368 // remove bb2.
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) {
379 BasicBlocks.erase(
380 std::remove_if(BasicBlocks.begin(), BasicBlocks.end(),
381 [&](const BasicBlock *i) { return i == BB; }),
382 BasicBlocks.end());
384 ASSERT_EQ(BasicBlocks.size(), static_cast<size_t>(2));
385 // Remove bb2 from F. This has to happen before the call to
386 // applyUpdates() for DTU to detect there is no longer an edge between
387 // bb2 -> bb3. The deleteBB() method converts bb2's TI into "unreachable".
388 ASSERT_FALSE(isa<UnreachableInst>(BB2->getTerminator()));
389 EXPECT_FALSE(DTU.isBBPendingDeletion(BB2));
390 DTU.callbackDeleteBB(BB2, Eraser);
391 EXPECT_TRUE(DTU.isBBPendingDeletion(BB2));
392 ASSERT_TRUE(isa<UnreachableInst>(BB2->getTerminator()));
393 EXPECT_EQ(BB2->getParent(), F);
395 // Queue up the DTU updates.
396 std::vector<DominatorTree::UpdateType> Updates;
397 Updates.reserve(4);
398 Updates.push_back({DominatorTree::Delete, BB0, BB2});
399 Updates.push_back({DominatorTree::Delete, BB2, BB3});
401 // Handle the specific shape case next.
402 // CFG Change: bb0 now only branches to bb3. We are preparing to remove bb1.
403 EXPECT_EQ(BB0->getTerminator()->getNumSuccessors(), 2u);
404 BB0->getTerminator()->eraseFromParent();
405 BranchInst::Create(BB3, BB0);
406 EXPECT_EQ(BB0->getTerminator()->getNumSuccessors(), 1u);
408 // Remove bb1 from F. This has to happen before the call to
409 // applyUpdates() for DTU to detect there is no longer an edge between
410 // bb1 -> bb3. The deleteBB() method converts bb1's TI into "unreachable".
411 ASSERT_FALSE(isa<UnreachableInst>(BB1->getTerminator()));
412 EXPECT_FALSE(DTU.isBBPendingDeletion(BB1));
413 DTU.callbackDeleteBB(BB1, Eraser);
414 EXPECT_TRUE(DTU.isBBPendingDeletion(BB1));
415 ASSERT_TRUE(isa<UnreachableInst>(BB1->getTerminator()));
416 EXPECT_EQ(BB1->getParent(), F);
418 // Update the DTU. In this case we don't submit {DominatorTree::Insert, BB0,
419 // BB3} because the edge previously existed at the start of this test when DT
420 // was first created.
421 Updates.push_back({DominatorTree::Delete, BB0, BB1});
422 Updates.push_back({DominatorTree::Delete, BB1, BB3});
424 // Verify everything.
425 DTU.applyUpdatesPermissive(Updates);
426 ASSERT_EQ(BasicBlocks.size(), static_cast<size_t>(2));
427 DTU.flush();
428 ASSERT_EQ(BasicBlocks.size(), static_cast<size_t>(0));
429 ASSERT_TRUE(DT.verify());
432 TEST(DomTreeUpdater, LazyUpdateBasicOperations) {
433 StringRef FuncName = "f";
434 StringRef ModuleString = R"(
435 define i32 @f(i32 %i, i32 *%p) {
436 bb0:
437 store i32 %i, i32 *%p
438 switch i32 %i, label %bb1 [
439 i32 0, label %bb2
440 i32 1, label %bb2
441 i32 2, label %bb3
443 bb1:
444 ret i32 1
445 bb2:
446 ret i32 2
447 bb3:
448 ret i32 3
451 // Make the module.
452 LLVMContext Context;
453 std::unique_ptr<Module> M = makeLLVMModule(Context, ModuleString);
454 Function *F = M->getFunction(FuncName);
456 // Make the DTU.
457 DominatorTree DT(*F);
458 PostDominatorTree PDT(*F);
459 DomTreeUpdater DTU(&DT, &PDT, DomTreeUpdater::UpdateStrategy::Lazy);
460 ASSERT_TRUE(DTU.hasDomTree());
461 ASSERT_TRUE(DTU.hasPostDomTree());
462 ASSERT_FALSE(DTU.isEager());
463 ASSERT_TRUE(DTU.isLazy());
464 ASSERT_TRUE(DTU.getDomTree().verify());
465 ASSERT_TRUE(DTU.getPostDomTree().verify());
467 Function::iterator FI = F->begin();
468 BasicBlock *BB0 = &*FI++;
469 BasicBlock *BB1 = &*FI++;
470 BasicBlock *BB2 = &*FI++;
471 BasicBlock *BB3 = &*FI++;
472 // Test discards of self-domination update.
473 DTU.applyUpdates({{DominatorTree::Delete, BB0, BB0}});
475 // Delete edge bb0 -> bb3 and push the update twice to verify duplicate
476 // entries are discarded.
477 std::vector<DominatorTree::UpdateType> Updates;
478 Updates.reserve(4);
479 Updates.push_back({DominatorTree::Delete, BB0, BB3});
480 Updates.push_back({DominatorTree::Delete, BB0, BB3});
482 // Unnecessary Insert: no edge bb1 -> bb2 after change to bb0.
483 Updates.push_back({DominatorTree::Insert, BB1, BB2});
484 // Unnecessary Delete: edge exists bb0 -> bb1 after change to bb0.
485 Updates.push_back({DominatorTree::Delete, BB0, BB1});
487 // CFG Change: remove edge bb0 -> bb3 and one duplicate edge bb0 -> bb2.
488 EXPECT_EQ(BB0->getTerminator()->getNumSuccessors(), 4u);
489 BB0->getTerminator()->eraseFromParent();
490 BranchInst::Create(BB1, BB2, ConstantInt::getTrue(F->getContext()), BB0);
491 EXPECT_EQ(BB0->getTerminator()->getNumSuccessors(), 2u);
493 // Deletion of a BasicBlock is an immediate event. We remove all uses to the
494 // contained Instructions and change the Terminator to "unreachable" when
495 // queued for deletion. Its parent is still F until DTU.flushDomTree is
496 // called. We don't defer this action because it can cause problems for other
497 // transforms or analysis as it's part of the actual CFG. We only defer
498 // updates to the DominatorTree. This code will crash if it is placed before
499 // the BranchInst::Create() call above.
500 bool CallbackFlag = false;
501 ASSERT_FALSE(isa<UnreachableInst>(BB3->getTerminator()));
502 EXPECT_FALSE(DTU.isBBPendingDeletion(BB3));
503 DTU.callbackDeleteBB(BB3, [&](BasicBlock *) { CallbackFlag = true; });
504 EXPECT_TRUE(DTU.isBBPendingDeletion(BB3));
505 ASSERT_TRUE(isa<UnreachableInst>(BB3->getTerminator()));
506 EXPECT_EQ(BB3->getParent(), F);
508 // Verify. Updates to DTU must be applied *after* all changes to the CFG
509 // (including block deletion).
510 DTU.applyUpdatesPermissive(Updates);
511 ASSERT_TRUE(DTU.getDomTree().verify());
512 ASSERT_TRUE(DTU.hasPendingUpdates());
513 ASSERT_TRUE(DTU.hasPendingPostDomTreeUpdates());
514 ASSERT_FALSE(DTU.hasPendingDomTreeUpdates());
515 ASSERT_TRUE(DTU.hasPendingDeletedBB());
516 ASSERT_TRUE(DTU.getPostDomTree().verify());
517 ASSERT_FALSE(DTU.hasPendingUpdates());
518 ASSERT_FALSE(DTU.hasPendingPostDomTreeUpdates());
519 ASSERT_FALSE(DTU.hasPendingDomTreeUpdates());
520 ASSERT_FALSE(DTU.hasPendingDeletedBB());
521 ASSERT_EQ(CallbackFlag, true);
524 TEST(DomTreeUpdater, LazyUpdateReplaceEntryBB) {
525 StringRef FuncName = "f";
526 StringRef ModuleString = R"(
527 define i32 @f() {
528 bb0:
529 br label %bb1
530 bb1:
531 ret i32 1
534 // Make the module.
535 LLVMContext Context;
536 std::unique_ptr<Module> M = makeLLVMModule(Context, ModuleString);
537 Function *F = M->getFunction(FuncName);
539 // Make the DTU.
540 DominatorTree DT(*F);
541 PostDominatorTree PDT(*F);
542 DomTreeUpdater DTU(DT, PDT, DomTreeUpdater::UpdateStrategy::Lazy);
543 ASSERT_TRUE(DTU.hasDomTree());
544 ASSERT_TRUE(DTU.hasPostDomTree());
545 ASSERT_FALSE(DTU.isEager());
546 ASSERT_TRUE(DTU.isLazy());
547 ASSERT_TRUE(DTU.getDomTree().verify());
548 ASSERT_TRUE(DTU.getPostDomTree().verify());
550 Function::iterator FI = F->begin();
551 BasicBlock *BB0 = &*FI++;
552 BasicBlock *BB1 = &*FI++;
554 // Add a block as the new function entry BB. We also link it to BB0.
555 BasicBlock *NewEntry =
556 BasicBlock::Create(F->getContext(), "new_entry", F, BB0);
557 BranchInst::Create(BB0, NewEntry);
558 EXPECT_EQ(F->begin()->getName(), NewEntry->getName());
559 EXPECT_TRUE(&F->getEntryBlock() == NewEntry);
561 // Insert the new edge between new_entry -> bb0. Without this the
562 // recalculate() call below will not actually recalculate the DT as there
563 // are no changes pending and no blocks deleted.
564 DTU.applyUpdates({{DominatorTree::Insert, NewEntry, BB0}});
566 // Changing the Entry BB requires a full recalculation.
567 DTU.recalculate(*F);
568 ASSERT_TRUE(DTU.getDomTree().verify());
569 ASSERT_TRUE(DTU.getPostDomTree().verify());
571 // CFG Change: remove new_edge -> bb0 and redirect to new_edge -> bb1.
572 EXPECT_EQ(NewEntry->getTerminator()->getNumSuccessors(), 1u);
573 NewEntry->getTerminator()->eraseFromParent();
574 BranchInst::Create(BB1, NewEntry);
575 EXPECT_EQ(BB0->getTerminator()->getNumSuccessors(), 1u);
577 // Update the DTU. At this point bb0 now has no predecessors but is still a
578 // Child of F.
579 DTU.applyUpdates({{DominatorTree::Delete, NewEntry, BB0},
580 {DominatorTree::Insert, NewEntry, BB1}});
581 DTU.flush();
582 ASSERT_TRUE(DT.verify());
583 ASSERT_TRUE(PDT.verify());
585 // Now remove bb0 from F.
586 ASSERT_FALSE(isa<UnreachableInst>(BB0->getTerminator()));
587 EXPECT_FALSE(DTU.isBBPendingDeletion(BB0));
588 DTU.deleteBB(BB0);
589 EXPECT_TRUE(DTU.isBBPendingDeletion(BB0));
590 ASSERT_TRUE(isa<UnreachableInst>(BB0->getTerminator()));
591 EXPECT_EQ(BB0->getParent(), F);
593 // Perform a full recalculation of the DTU. It is not necessary here but we
594 // do this to test the case when there are no pending DT updates but there are
595 // pending deleted BBs.
596 ASSERT_TRUE(DTU.hasPendingDeletedBB());
597 DTU.recalculate(*F);
598 ASSERT_FALSE(DTU.hasPendingDeletedBB());
601 TEST(DomTreeUpdater, LazyUpdateStepTest) {
602 // This test focus on testing a DTU holding both trees applying multiple
603 // updates and DT/PDT not flushed together.
604 StringRef FuncName = "f";
605 StringRef ModuleString = R"(
606 define i32 @f(i32 %i, i32 *%p) {
607 bb0:
608 store i32 %i, i32 *%p
609 switch i32 %i, label %bb1 [
610 i32 0, label %bb1
611 i32 1, label %bb2
612 i32 2, label %bb3
613 i32 3, label %bb1
615 bb1:
616 ret i32 1
617 bb2:
618 ret i32 2
619 bb3:
620 ret i32 3
623 // Make the module.
624 LLVMContext Context;
625 std::unique_ptr<Module> M = makeLLVMModule(Context, ModuleString);
626 Function *F = M->getFunction(FuncName);
628 // Make the DomTreeUpdater.
629 DominatorTree DT(*F);
630 PostDominatorTree PDT(*F);
631 DomTreeUpdater DTU(DT, PDT, DomTreeUpdater::UpdateStrategy::Lazy);
633 ASSERT_TRUE(DTU.hasDomTree());
634 ASSERT_TRUE(DTU.hasPostDomTree());
635 ASSERT_FALSE(DTU.isEager());
636 ASSERT_TRUE(DTU.isLazy());
637 ASSERT_TRUE(DTU.getDomTree().verify());
638 ASSERT_TRUE(DTU.getPostDomTree().verify());
639 ASSERT_FALSE(DTU.hasPendingUpdates());
641 Function::iterator FI = F->begin();
642 BasicBlock *BB0 = &*FI++;
643 FI++;
644 BasicBlock *BB2 = &*FI++;
645 BasicBlock *BB3 = &*FI++;
646 SwitchInst *SI = dyn_cast<SwitchInst>(BB0->getTerminator());
647 ASSERT_NE(SI, nullptr) << "Couldn't get SwitchInst.";
649 // Delete edge bb0 -> bb3.
650 std::vector<DominatorTree::UpdateType> Updates;
651 Updates.reserve(1);
652 Updates.push_back({DominatorTree::Delete, BB0, BB3});
654 // CFG Change: remove edge bb0 -> bb3.
655 EXPECT_EQ(BB0->getTerminator()->getNumSuccessors(), 5u);
656 BB3->removePredecessor(BB0);
657 for (auto i = SI->case_begin(), e = SI->case_end(); i != e; ++i) {
658 if (i->getCaseIndex() == 2) {
659 SI->removeCase(i);
660 break;
663 EXPECT_EQ(BB0->getTerminator()->getNumSuccessors(), 4u);
664 // Deletion of a BasicBlock is an immediate event. We remove all uses to the
665 // contained Instructions and change the Terminator to "unreachable" when
666 // queued for deletion.
667 ASSERT_FALSE(isa<UnreachableInst>(BB3->getTerminator()));
668 EXPECT_FALSE(DTU.isBBPendingDeletion(BB3));
669 DTU.applyUpdates(Updates);
671 // Only flush DomTree.
672 ASSERT_TRUE(DTU.getDomTree().verify());
673 ASSERT_TRUE(DTU.hasPendingPostDomTreeUpdates());
674 ASSERT_FALSE(DTU.hasPendingDomTreeUpdates());
676 ASSERT_EQ(BB3->getParent(), F);
677 DTU.deleteBB(BB3);
679 Updates.clear();
681 // Remove all case branch to BB2 to test Eager recalculation.
682 // Code section from llvm::ConstantFoldTerminator
683 for (auto i = SI->case_begin(), e = SI->case_end(); i != e;) {
684 if (i->getCaseSuccessor() == BB2) {
685 // Remove this entry.
686 BB2->removePredecessor(BB0);
687 i = SI->removeCase(i);
688 e = SI->case_end();
689 Updates.push_back({DominatorTree::Delete, BB0, BB2});
690 } else
691 ++i;
694 DTU.applyUpdatesPermissive(Updates);
695 // flush PostDomTree
696 ASSERT_TRUE(DTU.getPostDomTree().verify());
697 ASSERT_FALSE(DTU.hasPendingPostDomTreeUpdates());
698 ASSERT_TRUE(DTU.hasPendingDomTreeUpdates());
699 // flush both trees
700 DTU.flush();
701 ASSERT_TRUE(DT.verify());
704 TEST(DomTreeUpdater, NoTreeTest) {
705 StringRef FuncName = "f";
706 StringRef ModuleString = R"(
707 define i32 @f() {
708 bb0:
709 ret i32 0
712 // Make the module.
713 LLVMContext Context;
714 std::unique_ptr<Module> M = makeLLVMModule(Context, ModuleString);
715 Function *F = M->getFunction(FuncName);
717 // Make the DTU.
718 DomTreeUpdater DTU(nullptr, nullptr, DomTreeUpdater::UpdateStrategy::Lazy);
719 ASSERT_FALSE(DTU.hasDomTree());
720 ASSERT_FALSE(DTU.hasPostDomTree());
721 Function::iterator FI = F->begin();
722 BasicBlock *BB0 = &*FI++;
723 // Test whether PendingDeletedBB is flushed after the recalculation.
724 DTU.deleteBB(BB0);
725 ASSERT_TRUE(DTU.hasPendingDeletedBB());
726 DTU.recalculate(*F);
727 ASSERT_FALSE(DTU.hasPendingDeletedBB());
730 TEST(DomTreeUpdater, LazyUpdateDeduplicationTest) {
731 StringRef FuncName = "f";
732 StringRef ModuleString = R"(
733 define i32 @f() {
734 bb0:
735 br label %bb1
736 bb1:
737 ret i32 1
738 bb2:
739 ret i32 1
742 // Make the module.
743 LLVMContext Context;
744 std::unique_ptr<Module> M = makeLLVMModule(Context, ModuleString);
745 Function *F = M->getFunction(FuncName);
747 // Make the DTU.
748 DominatorTree DT(*F);
749 DomTreeUpdater DTU(&DT, nullptr, DomTreeUpdater::UpdateStrategy::Lazy);
750 ASSERT_TRUE(DTU.getDomTree().verify());
752 Function::iterator FI = F->begin();
753 BasicBlock *BB0 = &*FI++;
754 BasicBlock *BB1 = &*FI++;
755 BasicBlock *BB2 = &*FI++;
757 // CFG Change: remove bb0 -> bb1 and add back bb0 -> bb1.
758 EXPECT_EQ(BB0->getTerminator()->getNumSuccessors(), 1u);
759 BB0->getTerminator()->eraseFromParent();
760 BranchInst::Create(BB1, BB0);
761 EXPECT_EQ(BB0->getTerminator()->getNumSuccessors(), 1u);
763 // Update the DTU and simulate duplicates.
764 DTU.applyUpdatesPermissive({{DominatorTree::Delete, BB0, BB1},
765 {DominatorTree::Delete, BB0, BB1},
766 {DominatorTree::Insert, BB0, BB1},
767 {DominatorTree::Insert, BB0, BB1},
768 {DominatorTree::Insert, BB0, BB1}});
770 // The above operations result in a no-op.
771 ASSERT_FALSE(DTU.hasPendingUpdates());
773 // Update the DTU. Simulate an invalid update.
774 DTU.applyUpdatesPermissive({{DominatorTree::Delete, BB0, BB1}});
775 ASSERT_FALSE(DTU.hasPendingUpdates());
777 // CFG Change: remove bb0 -> bb1.
778 EXPECT_EQ(BB0->getTerminator()->getNumSuccessors(), 1u);
779 BB0->getTerminator()->eraseFromParent();
781 // Update the DTU and simulate invalid updates.
782 DTU.applyUpdatesPermissive({{DominatorTree::Delete, BB0, BB1},
783 {DominatorTree::Insert, BB0, BB1},
784 {DominatorTree::Delete, BB0, BB1},
785 {DominatorTree::Insert, BB0, BB1},
786 {DominatorTree::Insert, BB0, BB1}});
787 ASSERT_TRUE(DTU.hasPendingUpdates());
789 // CFG Change: add bb0 -> bb2.
790 BranchInst::Create(BB2, BB0);
791 EXPECT_EQ(BB0->getTerminator()->getNumSuccessors(), 1u);
792 DTU.applyUpdates({{DominatorTree::Insert, BB0, BB2}});
793 ASSERT_TRUE(DTU.getDomTree().verify());