blob: a6d768920bc965117de2d0432bcbc953b3fe7562 [file] [log] [blame]
Jakub Kuderski5e3ab7a2018-07-03 02:06:23 +00001//==- llvm/unittests/IR/DomTreeUpdaterTest.cpp - DomTreeUpdater unit tests ===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
10#include "llvm/IR/DomTreeUpdater.h"
11#include "llvm/Analysis/PostDominators.h"
12#include "llvm/AsmParser/Parser.h"
13#include "llvm/IR/Constants.h"
14#include "llvm/IR/Dominators.h"
15#include "llvm/IR/Instructions.h"
16#include "llvm/IR/LLVMContext.h"
17#include "llvm/IR/Module.h"
18#include "llvm/Support/SourceMgr.h"
19#include "gtest/gtest.h"
20#include <algorithm>
21
22using namespace llvm;
23
24static std::unique_ptr<Module> makeLLVMModule(LLVMContext &Context,
25 StringRef ModuleStr) {
26 SMDiagnostic Err;
27 std::unique_ptr<Module> M = parseAssemblyString(ModuleStr, Err, Context);
28 assert(M && "Bad LLVM IR?");
29 return M;
30}
31
32TEST(DomTreeUpdater, EagerUpdateBasicOperations) {
33 StringRef FuncName = "f";
34 StringRef ModuleString = R"(
35 define i32 @f(i32 %i, i32 *%p) {
36 bb0:
37 store i32 %i, i32 *%p
38 switch i32 %i, label %bb1 [
39 i32 1, label %bb2
40 i32 2, label %bb3
41 ]
42 bb1:
43 ret i32 1
44 bb2:
45 ret i32 2
46 bb3:
47 ret i32 3
48 })";
49 // Make the module.
50 LLVMContext Context;
51 std::unique_ptr<Module> M = makeLLVMModule(Context, ModuleString);
52 Function *F = M->getFunction(FuncName);
53
54 // Make the DomTreeUpdater.
55 DominatorTree DT(*F);
56 PostDominatorTree PDT(*F);
57 DomTreeUpdater DTU(DT, PDT, DomTreeUpdater::UpdateStrategy::Eager);
58
59 ASSERT_TRUE(DTU.hasDomTree());
60 ASSERT_TRUE(DTU.hasPostDomTree());
61 ASSERT_EQ(DTU.getUpdateStrategy(), DomTreeUpdater::UpdateStrategy::Eager);
62 ASSERT_TRUE(DTU.getDomTree().verify());
63 ASSERT_TRUE(DTU.getPostDomTree().verify());
64 ASSERT_FALSE(DTU.hasPendingUpdates());
65
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.";
73
74 ASSERT_FALSE(DTU.insertEdgeRelaxed(BB0, BB0));
75 ASSERT_TRUE(DTU.deleteEdgeRelaxed(BB0, BB0));
76
77 // Delete edge bb0 -> bb3 and push the update twice to verify duplicate
78 // entries are discarded.
79 std::vector<DominatorTree::UpdateType> Updates;
80 Updates.reserve(4);
81 Updates.push_back({DominatorTree::Delete, BB0, BB3});
82 Updates.push_back({DominatorTree::Delete, BB0, BB3});
83
84 // Invalid Insert: no edge bb1 -> bb2 after change to bb0.
85 Updates.push_back({DominatorTree::Insert, BB1, BB2});
86 // Invalid Delete: edge exists bb0 -> bb1 after change to bb0.
87 Updates.push_back({DominatorTree::Delete, BB0, BB1});
88
89 // CFG Change: remove edge bb0 -> bb3.
90 EXPECT_EQ(BB0->getTerminator()->getNumSuccessors(), 3u);
91 BB3->removePredecessor(BB0);
92 for (auto i = SI->case_begin(), e = SI->case_end(); i != e; ++i) {
93 if (i->getCaseSuccessor() == BB3) {
94 SI->removeCase(i);
95 break;
96 }
97 }
98 EXPECT_EQ(BB0->getTerminator()->getNumSuccessors(), 2u);
99 // Deletion of a BasicBlock is an immediate event. We remove all uses to the
100 // contained Instructions and change the Terminator to "unreachable" when
101 // queued for deletion.
102 ASSERT_FALSE(isa<UnreachableInst>(BB3->getTerminator()));
103 EXPECT_FALSE(DTU.isBBPendingDeletion(BB3));
104 DTU.applyUpdates(Updates, /*ForceRemoveDuplicates*/ true);
105 ASSERT_FALSE(DTU.hasPendingUpdates());
106
107 // Invalid Insert: no edge bb1 -> bb2 after change to bb0.
108 ASSERT_FALSE(DTU.insertEdgeRelaxed(BB1, BB2));
109 // Invalid Delete: edge exists bb0 -> bb1 after change to bb0.
110 ASSERT_FALSE(DTU.deleteEdgeRelaxed(BB0, BB1));
111
112 // DTU working with Eager UpdateStrategy does not need to flush.
113 ASSERT_TRUE(DT.verify());
114 ASSERT_TRUE(PDT.verify());
115
116 // Test callback utils.
117 ASSERT_EQ(BB3->getParent(), F);
118 DTU.callbackDeleteBB(BB3,
119 [&F](BasicBlock *BB) { ASSERT_NE(BB->getParent(), F); });
120
121 ASSERT_TRUE(DT.verify());
122 ASSERT_TRUE(PDT.verify());
123 ASSERT_FALSE(DTU.hasPendingUpdates());
124
125 // Unnecessary flush() test
126 DTU.flush();
127 EXPECT_TRUE(DT.verify());
128 EXPECT_TRUE(PDT.verify());
129
130 // Remove all case branch to BB2 to test Eager recalculation.
131 // Code section from llvm::ConstantFoldTerminator
132 for (auto i = SI->case_begin(), e = SI->case_end(); i != e;) {
133 if (i->getCaseSuccessor() == BB2) {
134 // Remove this entry.
135 BB2->removePredecessor(BB0);
136 i = SI->removeCase(i);
137 e = SI->case_end();
138 } else
139 ++i;
140 }
141 ASSERT_FALSE(DT.verify());
142 ASSERT_FALSE(PDT.verify());
143 DTU.recalculate(*F);
144 ASSERT_TRUE(DT.verify());
145 ASSERT_TRUE(PDT.verify());
146}
147
148TEST(DomTreeUpdater, EagerUpdateReplaceEntryBB) {
149 StringRef FuncName = "f";
150 StringRef ModuleString = R"(
151 define i32 @f() {
152 bb0:
153 br label %bb1
154 bb1:
155 ret i32 1
156 }
157 )";
158 // Make the module.
159 LLVMContext Context;
160 std::unique_ptr<Module> M = makeLLVMModule(Context, ModuleString);
161 Function *F = M->getFunction(FuncName);
162
163 // Make the DTU.
164 DominatorTree DT(*F);
165 PostDominatorTree PDT(*F);
166 DomTreeUpdater DTU(DT, PDT, DomTreeUpdater::UpdateStrategy::Eager);
167 ASSERT_TRUE(DTU.hasDomTree());
168 ASSERT_TRUE(DTU.hasPostDomTree());
169 ASSERT_EQ(DTU.getUpdateStrategy(), DomTreeUpdater::UpdateStrategy::Eager);
170 ASSERT_TRUE(DT.verify());
171 ASSERT_TRUE(PDT.verify());
172
173 Function::iterator FI = F->begin();
174 BasicBlock *BB0 = &*FI++;
175 BasicBlock *BB1 = &*FI++;
176
177 // Add a block as the new function entry BB. We also link it to BB0.
178 BasicBlock *NewEntry =
179 BasicBlock::Create(F->getContext(), "new_entry", F, BB0);
180 BranchInst::Create(BB0, NewEntry);
181 EXPECT_EQ(F->begin()->getName(), NewEntry->getName());
182 EXPECT_TRUE(&F->getEntryBlock() == NewEntry);
183
184 ASSERT_TRUE(DTU.insertEdgeRelaxed(NewEntry, BB0));
185
186 // Changing the Entry BB requires a full recalculation of DomTree.
187 DTU.recalculate(*F);
188 ASSERT_TRUE(DT.verify());
189 ASSERT_TRUE(PDT.verify());
190
191 // CFG Change: remove new_edge -> bb0 and redirect to new_edge -> bb1.
192 EXPECT_EQ(NewEntry->getTerminator()->getNumSuccessors(), 1u);
193 NewEntry->getTerminator()->eraseFromParent();
194 BranchInst::Create(BB1, NewEntry);
195 EXPECT_EQ(BB0->getTerminator()->getNumSuccessors(), 1u);
196
197 // Update the DTU. At this point bb0 now has no predecessors but is still a
198 // Child of F.
199 DTU.applyUpdates({{DominatorTree::Delete, NewEntry, BB0},
200 {DominatorTree::Insert, NewEntry, BB1}});
201 ASSERT_TRUE(DT.verify());
202 ASSERT_TRUE(PDT.verify());
203
204 // Now remove bb0 from F.
205 ASSERT_FALSE(isa<UnreachableInst>(BB0->getTerminator()));
206 EXPECT_FALSE(DTU.isBBPendingDeletion(BB0));
207 DTU.deleteBB(BB0);
208 ASSERT_TRUE(DT.verify());
209 ASSERT_TRUE(PDT.verify());
210}
211
212TEST(DomTreeUpdater, LazyUpdateDTBasicOperations) {
213 StringRef FuncName = "f";
214 StringRef ModuleString = R"(
215 define i32 @f(i32 %i, i32 *%p) {
216 bb0:
217 store i32 %i, i32 *%p
218 switch i32 %i, label %bb1 [
219 i32 0, label %bb2
220 i32 1, label %bb2
221 i32 2, label %bb3
222 ]
223 bb1:
224 ret i32 1
225 bb2:
226 ret i32 2
227 bb3:
228 ret i32 3
229 }
230 )";
231 // Make the module.
232 LLVMContext Context;
233 std::unique_ptr<Module> M = makeLLVMModule(Context, ModuleString);
234 Function *F = M->getFunction(FuncName);
235
236 // Make the DTU.
237 DominatorTree DT(*F);
238 DomTreeUpdater DTU(DT, DomTreeUpdater::UpdateStrategy::Lazy);
239 ASSERT_TRUE(DTU.hasDomTree());
240 ASSERT_FALSE(DTU.hasPostDomTree());
241 ASSERT_EQ(DTU.getUpdateStrategy(), DomTreeUpdater::UpdateStrategy::Lazy);
242 ASSERT_TRUE(DTU.getDomTree().verify());
243
244 Function::iterator FI = F->begin();
245 BasicBlock *BB0 = &*FI++;
246 BasicBlock *BB1 = &*FI++;
247 BasicBlock *BB2 = &*FI++;
248 BasicBlock *BB3 = &*FI++;
249
250 // Test discards of self-domination update.
251 DTU.deleteEdge(BB0, BB0);
252 ASSERT_FALSE(DTU.hasPendingDomTreeUpdates());
253
254 // Delete edge bb0 -> bb3 and push the update twice to verify duplicate
255 // entries are discarded.
256 std::vector<DominatorTree::UpdateType> Updates;
257 Updates.reserve(4);
258 Updates.push_back({DominatorTree::Delete, BB0, BB3});
259 Updates.push_back({DominatorTree::Delete, BB0, BB3});
260
261 // Invalid Insert: no edge bb1 -> bb2 after change to bb0.
262 Updates.push_back({DominatorTree::Insert, BB1, BB2});
263 // Invalid Delete: edge exists bb0 -> bb1 after change to bb0.
264 Updates.push_back({DominatorTree::Delete, BB0, BB1});
265
266 // CFG Change: remove edge bb0 -> bb3 and one duplicate edge bb0 -> bb2.
267 EXPECT_EQ(BB0->getTerminator()->getNumSuccessors(), 4u);
268 BB0->getTerminator()->eraseFromParent();
269 BranchInst::Create(BB1, BB2, ConstantInt::getTrue(F->getContext()), BB0);
270 EXPECT_EQ(BB0->getTerminator()->getNumSuccessors(), 2u);
271
272 // Verify. Updates to DTU must be applied *after* all changes to the CFG
273 // (including block deletion).
274 DTU.applyUpdates(Updates);
275 ASSERT_TRUE(DTU.getDomTree().verify());
276
277 // Deletion of a BasicBlock is an immediate event. We remove all uses to the
278 // contained Instructions and change the Terminator to "unreachable" when
279 // queued for deletion. Its parent is still F until all the pending updates
280 // are applied to all trees held by the DomTreeUpdater (DomTree/PostDomTree).
281 // We don't defer this action because it can cause problems for other
282 // transforms or analysis as it's part of the actual CFG. We only defer
283 // updates to the DominatorTrees. This code will crash if it is placed before
284 // the BranchInst::Create() call above. After a deletion of a BasicBlock. Only
285 // an explicit flush event can trigger the flushing of deleteBBs. Because some
286 // passes using Lazy UpdateStrategy rely on this behavior.
287
288 ASSERT_FALSE(isa<UnreachableInst>(BB3->getTerminator()));
289 EXPECT_FALSE(DTU.isBBPendingDeletion(BB3));
290 EXPECT_FALSE(DTU.hasPendingDeletedBB());
291 DTU.deleteBB(BB3);
292 EXPECT_TRUE(DTU.isBBPendingDeletion(BB3));
293 EXPECT_TRUE(DTU.hasPendingDeletedBB());
294 ASSERT_TRUE(isa<UnreachableInst>(BB3->getTerminator()));
295 EXPECT_EQ(BB3->getParent(), F);
296 DTU.recalculate(*F);
297
298 EXPECT_FALSE(DTU.hasPendingDeletedBB());
299}
300
301TEST(DomTreeUpdater, LazyUpdateDTInheritedPreds) {
302 StringRef FuncName = "f";
303 StringRef ModuleString = R"(
304 define i32 @f(i32 %i, i32 *%p) {
305 bb0:
306 store i32 %i, i32 *%p
307 switch i32 %i, label %bb1 [
308 i32 2, label %bb2
309 i32 3, label %bb3
310 ]
311 bb1:
312 br label %bb3
313 bb2:
314 br label %bb3
315 bb3:
316 ret i32 3
317 }
318 )";
319 // Make the module.
320 LLVMContext Context;
321 std::unique_ptr<Module> M = makeLLVMModule(Context, ModuleString);
322 Function *F = M->getFunction(FuncName);
323
324 // Make the DTU.
325 DominatorTree DT(*F);
326 DomTreeUpdater DTU(DT, DomTreeUpdater::UpdateStrategy::Lazy);
327 ASSERT_TRUE(DTU.hasDomTree());
328 ASSERT_FALSE(DTU.hasPostDomTree());
329 ASSERT_EQ(DTU.getUpdateStrategy(), DomTreeUpdater::UpdateStrategy::Lazy);
330 ASSERT_TRUE(DTU.getDomTree().verify());
331
332 Function::iterator FI = F->begin();
333 BasicBlock *BB0 = &*FI++;
334 BasicBlock *BB1 = &*FI++;
335 BasicBlock *BB2 = &*FI++;
336 BasicBlock *BB3 = &*FI++;
337
338 // There are several CFG locations where we have:
339 //
340 // pred1..predN
341 // | |
342 // +> curr <+ converted into: pred1..predN curr
343 // | | |
344 // v +> succ <+
345 // succ
346 //
347 // There is a specific shape of this we have to be careful of:
348 //
349 // pred1..predN
350 // || |
351 // |+> curr <+ converted into: pred1..predN curr
352 // | | | |
353 // | v +> succ <+
354 // +-> succ
355 //
356 // While the final CFG form is functionally identical the updates to
357 // DTU are not. In the first case we must have DTU.insertEdge(Pred1, Succ)
358 // while in the latter case we must *NOT* have DTU.insertEdge(Pred1, Succ).
359
360 // CFG Change: bb0 now only has bb0 -> bb1 and bb0 -> bb3. We are preparing to
361 // remove bb2.
362 EXPECT_EQ(BB0->getTerminator()->getNumSuccessors(), 3u);
363 BB0->getTerminator()->eraseFromParent();
364 BranchInst::Create(BB1, BB3, ConstantInt::getTrue(F->getContext()), BB0);
365 EXPECT_EQ(BB0->getTerminator()->getNumSuccessors(), 2u);
366
367 // Test callback utils.
368 std::vector<BasicBlock *> BasicBlocks;
369 BasicBlocks.push_back(BB1);
370 BasicBlocks.push_back(BB2);
371 auto Eraser = [&](BasicBlock *BB) {
372 BasicBlocks.erase(
373 std::remove_if(BasicBlocks.begin(), BasicBlocks.end(),
374 [&](const BasicBlock *i) { return i == BB; }),
375 BasicBlocks.end());
376 };
377 ASSERT_EQ(BasicBlocks.size(), static_cast<size_t>(2));
378 // Remove bb2 from F. This has to happen before the call to applyUpdates() for
379 // DTU to detect there is no longer an edge between bb2 -> bb3. The deleteBB()
380 // method converts bb2's TI into "unreachable".
381 ASSERT_FALSE(isa<UnreachableInst>(BB2->getTerminator()));
382 EXPECT_FALSE(DTU.isBBPendingDeletion(BB2));
383 DTU.callbackDeleteBB(BB2, Eraser);
384 EXPECT_TRUE(DTU.isBBPendingDeletion(BB2));
385 ASSERT_TRUE(isa<UnreachableInst>(BB2->getTerminator()));
386 EXPECT_EQ(BB2->getParent(), F);
387
388 // Queue up the DTU updates.
389 std::vector<DominatorTree::UpdateType> Updates;
390 Updates.reserve(4);
391 Updates.push_back({DominatorTree::Delete, BB0, BB2});
392 Updates.push_back({DominatorTree::Delete, BB2, BB3});
393
394 // Handle the specific shape case next.
395 // CFG Change: bb0 now only branches to bb3. We are preparing to remove bb1.
396 EXPECT_EQ(BB0->getTerminator()->getNumSuccessors(), 2u);
397 BB0->getTerminator()->eraseFromParent();
398 BranchInst::Create(BB3, BB0);
399 EXPECT_EQ(BB0->getTerminator()->getNumSuccessors(), 1u);
400
401 // Remove bb1 from F. This has to happen before the call to applyUpdates() for
402 // DTU to detect there is no longer an edge between bb1 -> bb3. The deleteBB()
403 // method converts bb1's TI into "unreachable".
404 ASSERT_FALSE(isa<UnreachableInst>(BB1->getTerminator()));
405 EXPECT_FALSE(DTU.isBBPendingDeletion(BB1));
406 DTU.callbackDeleteBB(BB1, Eraser);
407 EXPECT_TRUE(DTU.isBBPendingDeletion(BB1));
408 ASSERT_TRUE(isa<UnreachableInst>(BB1->getTerminator()));
409 EXPECT_EQ(BB1->getParent(), F);
410
411 // Update the DTU. In this case we don't call DTU.insertEdge(BB0, BB3) because
412 // the edge previously existed at the start of this test when DT was first
413 // created.
414 Updates.push_back({DominatorTree::Delete, BB0, BB1});
415 Updates.push_back({DominatorTree::Delete, BB1, BB3});
416
417 // Verify everything.
418 DTU.applyUpdates(Updates);
419 ASSERT_EQ(BasicBlocks.size(), static_cast<size_t>(2));
420 DTU.flush();
421 ASSERT_EQ(BasicBlocks.size(), static_cast<size_t>(0));
422 ASSERT_TRUE(DT.verify());
423}
424
425TEST(DomTreeUpdater, LazyUpdateBasicOperations) {
426 StringRef FuncName = "f";
427 StringRef ModuleString = R"(
428 define i32 @f(i32 %i, i32 *%p) {
429 bb0:
430 store i32 %i, i32 *%p
431 switch i32 %i, label %bb1 [
432 i32 0, label %bb2
433 i32 1, label %bb2
434 i32 2, label %bb3
435 ]
436 bb1:
437 ret i32 1
438 bb2:
439 ret i32 2
440 bb3:
441 ret i32 3
442 }
443 )";
444 // Make the module.
445 LLVMContext Context;
446 std::unique_ptr<Module> M = makeLLVMModule(Context, ModuleString);
447 Function *F = M->getFunction(FuncName);
448
449 // Make the DTU.
450 DominatorTree DT(*F);
451 PostDominatorTree PDT(*F);
452 DomTreeUpdater DTU(DT, PDT, DomTreeUpdater::UpdateStrategy::Lazy);
453 ASSERT_TRUE(DTU.hasDomTree());
454 ASSERT_TRUE(DTU.hasPostDomTree());
455 ASSERT_EQ(DTU.getUpdateStrategy(), DomTreeUpdater::UpdateStrategy::Lazy);
456 ASSERT_TRUE(DTU.getDomTree().verify());
457 ASSERT_TRUE(DTU.getPostDomTree().verify());
458
459 Function::iterator FI = F->begin();
460 BasicBlock *BB0 = &*FI++;
461 BasicBlock *BB1 = &*FI++;
462 BasicBlock *BB2 = &*FI++;
463 BasicBlock *BB3 = &*FI++;
464 // Test discards of self-domination update.
465 DTU.deleteEdge(BB0, BB0);
466
467 // Delete edge bb0 -> bb3 and push the update twice to verify duplicate
468 // entries are discarded.
469 std::vector<DominatorTree::UpdateType> Updates;
470 Updates.reserve(4);
471 Updates.push_back({DominatorTree::Delete, BB0, BB3});
472 Updates.push_back({DominatorTree::Delete, BB0, BB3});
473
474 // Unnecessary Insert: no edge bb1 -> bb2 after change to bb0.
475 Updates.push_back({DominatorTree::Insert, BB1, BB2});
476 // Unnecessary Delete: edge exists bb0 -> bb1 after change to bb0.
477 Updates.push_back({DominatorTree::Delete, BB0, BB1});
478
479 // CFG Change: remove edge bb0 -> bb3 and one duplicate edge bb0 -> bb2.
480 EXPECT_EQ(BB0->getTerminator()->getNumSuccessors(), 4u);
481 BB0->getTerminator()->eraseFromParent();
482 BranchInst::Create(BB1, BB2, ConstantInt::getTrue(F->getContext()), BB0);
483 EXPECT_EQ(BB0->getTerminator()->getNumSuccessors(), 2u);
484
485 // Deletion of a BasicBlock is an immediate event. We remove all uses to the
486 // contained Instructions and change the Terminator to "unreachable" when
487 // queued for deletion. Its parent is still F until DTU.flushDomTree is
488 // called. We don't defer this action because it can cause problems for other
489 // transforms or analysis as it's part of the actual CFG. We only defer
490 // updates to the DominatorTree. This code will crash if it is placed before
491 // the BranchInst::Create() call above.
492 bool CallbackFlag = false;
493 ASSERT_FALSE(isa<UnreachableInst>(BB3->getTerminator()));
494 EXPECT_FALSE(DTU.isBBPendingDeletion(BB3));
495 DTU.callbackDeleteBB(BB3, [&](BasicBlock *) { CallbackFlag = true; });
496 EXPECT_TRUE(DTU.isBBPendingDeletion(BB3));
497 ASSERT_TRUE(isa<UnreachableInst>(BB3->getTerminator()));
498 EXPECT_EQ(BB3->getParent(), F);
499
500 // Verify. Updates to DTU must be applied *after* all changes to the CFG
501 // (including block deletion).
502 DTU.applyUpdates(Updates);
503 ASSERT_TRUE(DTU.getDomTree().verify());
504 ASSERT_TRUE(DTU.hasPendingUpdates());
505 ASSERT_TRUE(DTU.hasPendingPostDomTreeUpdates());
506 ASSERT_FALSE(DTU.hasPendingDomTreeUpdates());
507 ASSERT_TRUE(DTU.hasPendingDeletedBB());
508 ASSERT_TRUE(DTU.getPostDomTree().verify());
509 ASSERT_FALSE(DTU.hasPendingUpdates());
510 ASSERT_FALSE(DTU.hasPendingPostDomTreeUpdates());
511 ASSERT_FALSE(DTU.hasPendingDomTreeUpdates());
512 ASSERT_FALSE(DTU.hasPendingDeletedBB());
513 ASSERT_EQ(CallbackFlag, true);
514}
515
516TEST(DomTreeUpdater, LazyUpdateReplaceEntryBB) {
517 StringRef FuncName = "f";
518 StringRef ModuleString = R"(
519 define i32 @f() {
520 bb0:
521 br label %bb1
522 bb1:
523 ret i32 1
524 }
525 )";
526 // Make the module.
527 LLVMContext Context;
528 std::unique_ptr<Module> M = makeLLVMModule(Context, ModuleString);
529 Function *F = M->getFunction(FuncName);
530
531 // Make the DTU.
532 DominatorTree DT(*F);
533 PostDominatorTree PDT(*F);
534 DomTreeUpdater DTU(DT, PDT, DomTreeUpdater::UpdateStrategy::Lazy);
535 ASSERT_TRUE(DTU.hasDomTree());
536 ASSERT_TRUE(DTU.hasPostDomTree());
537 ASSERT_EQ(DTU.getUpdateStrategy(), DomTreeUpdater::UpdateStrategy::Lazy);
538 ASSERT_TRUE(DTU.getDomTree().verify());
539 ASSERT_TRUE(DTU.getPostDomTree().verify());
540
541 Function::iterator FI = F->begin();
542 BasicBlock *BB0 = &*FI++;
543 BasicBlock *BB1 = &*FI++;
544
545 // Add a block as the new function entry BB. We also link it to BB0.
546 BasicBlock *NewEntry =
547 BasicBlock::Create(F->getContext(), "new_entry", F, BB0);
548 BranchInst::Create(BB0, NewEntry);
549 EXPECT_EQ(F->begin()->getName(), NewEntry->getName());
550 EXPECT_TRUE(&F->getEntryBlock() == NewEntry);
551
552 // Insert the new edge between new_entry -> bb0. Without this the
553 // recalculate() call below will not actually recalculate the DT as there
554 // are no changes pending and no blocks deleted.
555 DTU.insertEdge(NewEntry, BB0);
556
557 // Changing the Entry BB requires a full recalculation.
558 DTU.recalculate(*F);
559 ASSERT_TRUE(DTU.getDomTree().verify());
560 ASSERT_TRUE(DTU.getPostDomTree().verify());
561
562 // CFG Change: remove new_edge -> bb0 and redirect to new_edge -> bb1.
563 EXPECT_EQ(NewEntry->getTerminator()->getNumSuccessors(), 1u);
564 NewEntry->getTerminator()->eraseFromParent();
565 BranchInst::Create(BB1, NewEntry);
566 EXPECT_EQ(BB0->getTerminator()->getNumSuccessors(), 1u);
567
568 // Update the DTU. At this point bb0 now has no predecessors but is still a
569 // Child of F.
570 DTU.applyUpdates({{DominatorTree::Delete, NewEntry, BB0},
571 {DominatorTree::Insert, NewEntry, BB1}});
572 DTU.flush();
573 ASSERT_TRUE(DT.verify());
574 ASSERT_TRUE(PDT.verify());
575
576 // Now remove bb0 from F.
577 ASSERT_FALSE(isa<UnreachableInst>(BB0->getTerminator()));
578 EXPECT_FALSE(DTU.isBBPendingDeletion(BB0));
579 DTU.deleteBB(BB0);
580 EXPECT_TRUE(DTU.isBBPendingDeletion(BB0));
581 ASSERT_TRUE(isa<UnreachableInst>(BB0->getTerminator()));
582 EXPECT_EQ(BB0->getParent(), F);
583
584 // Perform a full recalculation of the DTU. It is not necessary here but we
585 // do this to test the case when there are no pending DT updates but there are
586 // pending deleted BBs.
587 ASSERT_TRUE(DTU.hasPendingDeletedBB());
588 DTU.recalculate(*F);
589 ASSERT_FALSE(DTU.hasPendingDeletedBB());
590}
591
592TEST(DomTreeUpdater, LazyUpdateStepTest) {
593 // This test focus on testing a DTU holding both trees applying multiple
594 // updates and DT/PDT not flushed together.
595 StringRef FuncName = "f";
596 StringRef ModuleString = R"(
597 define i32 @f(i32 %i, i32 *%p) {
598 bb0:
599 store i32 %i, i32 *%p
600 switch i32 %i, label %bb1 [
601 i32 0, label %bb1
602 i32 1, label %bb2
603 i32 2, label %bb3
604 i32 3, label %bb1
605 ]
606 bb1:
607 ret i32 1
608 bb2:
609 ret i32 2
610 bb3:
611 ret i32 3
612 }
613 )";
614 // Make the module.
615 LLVMContext Context;
616 std::unique_ptr<Module> M = makeLLVMModule(Context, ModuleString);
617 Function *F = M->getFunction(FuncName);
618
619 // Make the DomTreeUpdater.
620 DominatorTree DT(*F);
621 PostDominatorTree PDT(*F);
622 DomTreeUpdater DTU(DT, PDT, DomTreeUpdater::UpdateStrategy::Lazy);
623
624 ASSERT_TRUE(DTU.hasDomTree());
625 ASSERT_TRUE(DTU.hasPostDomTree());
626 ASSERT_EQ(DTU.getUpdateStrategy(), DomTreeUpdater::UpdateStrategy::Lazy);
627 ASSERT_TRUE(DTU.getDomTree().verify());
628 ASSERT_TRUE(DTU.getPostDomTree().verify());
629 ASSERT_FALSE(DTU.hasPendingUpdates());
630
631 Function::iterator FI = F->begin();
632 BasicBlock *BB0 = &*FI++;
633 FI++;
634 BasicBlock *BB2 = &*FI++;
635 BasicBlock *BB3 = &*FI++;
636 SwitchInst *SI = dyn_cast<SwitchInst>(BB0->getTerminator());
637 ASSERT_NE(SI, nullptr) << "Couldn't get SwitchInst.";
638
639 // Delete edge bb0 -> bb3 and push the update twice to verify duplicate
640 // entries are discarded.
641 std::vector<DominatorTree::UpdateType> Updates;
642 Updates.reserve(1);
643 Updates.push_back({DominatorTree::Delete, BB0, BB3});
644
645 // CFG Change: remove edge bb0 -> bb3.
646 EXPECT_EQ(BB0->getTerminator()->getNumSuccessors(), 5u);
647 BB3->removePredecessor(BB0);
648 for (auto i = SI->case_begin(), e = SI->case_end(); i != e; ++i) {
649 if (i->getCaseIndex() == 2) {
650 SI->removeCase(i);
651 break;
652 }
653 }
654 EXPECT_EQ(BB0->getTerminator()->getNumSuccessors(), 4u);
655 // Deletion of a BasicBlock is an immediate event. We remove all uses to the
656 // contained Instructions and change the Terminator to "unreachable" when
657 // queued for deletion.
658 ASSERT_FALSE(isa<UnreachableInst>(BB3->getTerminator()));
659 EXPECT_FALSE(DTU.isBBPendingDeletion(BB3));
660 DTU.applyUpdates(Updates);
661
662 // Only flush DomTree.
663 ASSERT_TRUE(DTU.getDomTree().verify());
664 ASSERT_TRUE(DTU.hasPendingPostDomTreeUpdates());
665 ASSERT_FALSE(DTU.hasPendingDomTreeUpdates());
666
667 ASSERT_EQ(BB3->getParent(), F);
668 DTU.deleteBB(BB3);
669
670 Updates.clear();
671
672 // Remove all case branch to BB2 to test Eager recalculation.
673 // Code section from llvm::ConstantFoldTerminator
674 for (auto i = SI->case_begin(), e = SI->case_end(); i != e;) {
675 if (i->getCaseSuccessor() == BB2) {
676 // Remove this entry.
677 BB2->removePredecessor(BB0);
678 i = SI->removeCase(i);
679 e = SI->case_end();
680 Updates.push_back({DominatorTree::Delete, BB0, BB2});
681 } else
682 ++i;
683 }
684
685 DTU.applyUpdates(Updates);
686 // flush PostDomTree
687 ASSERT_TRUE(DTU.getPostDomTree().verify());
688 ASSERT_FALSE(DTU.hasPendingPostDomTreeUpdates());
689 ASSERT_TRUE(DTU.hasPendingDomTreeUpdates());
690 // flush both trees
691 DTU.flush();
692 ASSERT_TRUE(DT.verify());
693}