blob: 6a8cc55e5d50c85513feaf870c45e79135119a8c [file] [log] [blame]
NAKAMURA Takumiafda71e2013-01-23 08:30:10 +00001//===- llvm/unittests/IR/DominatorTreeTest.cpp - Constants 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
Jakub Kuderski23497b42017-07-14 22:24:15 +000010#include <random>
Diego Novilloee592422013-12-02 14:08:27 +000011#include "llvm/Analysis/PostDominators.h"
Michael Zolotukhin046da972018-05-12 01:44:32 +000012#include "llvm/Analysis/IteratedDominanceFrontier.h"
Chandler Carruth9aca9182014-01-07 12:34:26 +000013#include "llvm/AsmParser/Parser.h"
Daniel Berlin8f8174c2015-04-14 19:49:26 +000014#include "llvm/IR/Constants.h"
Adam Nemet7fa6dee2017-05-27 04:05:50 +000015#include "llvm/IR/Dominators.h"
Chandler Carruth9fb823b2013-01-02 11:36:10 +000016#include "llvm/IR/Instructions.h"
17#include "llvm/IR/LLVMContext.h"
Adam Nemet7fa6dee2017-05-27 04:05:50 +000018#include "llvm/IR/Module.h"
Rafael Espindolaa53c46a2012-03-30 16:46:21 +000019#include "llvm/Support/SourceMgr.h"
Jakub Kuderski13e9ef12017-07-14 21:17:33 +000020#include "CFGBuilder.h"
Rafael Espindolaa53c46a2012-03-30 16:46:21 +000021#include "gtest/gtest.h"
22
23using namespace llvm;
24
Jakub Kuderskib292c222017-07-14 18:26:09 +000025struct PostDomTree : PostDomTreeBase<BasicBlock> {
26 PostDomTree(Function &F) { recalculate(F); }
27};
28
Adam Nemet147ede92017-05-27 04:05:52 +000029/// Build the dominator tree for the function and run the Test.
Jakub Kuderskib292c222017-07-14 18:26:09 +000030static void runWithDomTree(
31 Module &M, StringRef FuncName,
32 function_ref<void(Function &F, DominatorTree *DT, PostDomTree *PDT)> Test) {
Adam Nemet147ede92017-05-27 04:05:52 +000033 auto *F = M.getFunction(FuncName);
34 ASSERT_NE(F, nullptr) << "Could not find " << FuncName;
35 // Compute the dominator tree for the function.
36 DominatorTree DT(*F);
Jakub Kuderskib292c222017-07-14 18:26:09 +000037 PostDomTree PDT(*F);
Adam Nemet147ede92017-05-27 04:05:52 +000038 Test(*F, &DT, &PDT);
39}
Rafael Espindolaa53c46a2012-03-30 16:46:21 +000040
Adam Nemet147ede92017-05-27 04:05:52 +000041static std::unique_ptr<Module> makeLLVMModule(LLVMContext &Context,
42 StringRef ModuleStr) {
43 SMDiagnostic Err;
44 std::unique_ptr<Module> M = parseAssemblyString(ModuleStr, Err, Context);
45 assert(M && "Bad assembly?");
46 return M;
47}
Rafael Espindolaa53c46a2012-03-30 16:46:21 +000048
Adam Nemet147ede92017-05-27 04:05:52 +000049TEST(DominatorTree, Unreachable) {
50 StringRef ModuleString =
Adam Nemet7fa6dee2017-05-27 04:05:50 +000051 "declare i32 @g()\n"
52 "define void @f(i32 %x) personality i32 ()* @g {\n"
53 "bb0:\n"
54 " %y1 = add i32 %x, 1\n"
55 " %y2 = add i32 %x, 1\n"
56 " %y3 = invoke i32 @g() to label %bb1 unwind label %bb2\n"
57 "bb1:\n"
58 " %y4 = add i32 %x, 1\n"
59 " br label %bb4\n"
60 "bb2:\n"
61 " %y5 = landingpad i32\n"
62 " cleanup\n"
63 " br label %bb4\n"
64 "bb3:\n"
65 " %y6 = add i32 %x, 1\n"
66 " %y7 = add i32 %x, 1\n"
67 " ret void\n"
68 "bb4:\n"
69 " %y8 = phi i32 [0, %bb2], [%y4, %bb1]\n"
70 " %y9 = phi i32 [0, %bb2], [%y4, %bb1]\n"
71 " ret void\n"
72 "}\n";
Rafael Espindolaa53c46a2012-03-30 16:46:21 +000073
Adam Nemet147ede92017-05-27 04:05:52 +000074 // Parse the module.
Adam Nemet7fa6dee2017-05-27 04:05:50 +000075 LLVMContext Context;
Adam Nemet147ede92017-05-27 04:05:52 +000076 std::unique_ptr<Module> M = makeLLVMModule(Context, ModuleString);
Adam Nemet7fa6dee2017-05-27 04:05:50 +000077
Adam Nemet147ede92017-05-27 04:05:52 +000078 runWithDomTree(
Jakub Kuderskib292c222017-07-14 18:26:09 +000079 *M, "f", [&](Function &F, DominatorTree *DT, PostDomTree *PDT) {
Adam Nemet147ede92017-05-27 04:05:52 +000080 Function::iterator FI = F.begin();
81
82 BasicBlock *BB0 = &*FI++;
83 BasicBlock::iterator BBI = BB0->begin();
84 Instruction *Y1 = &*BBI++;
85 Instruction *Y2 = &*BBI++;
86 Instruction *Y3 = &*BBI++;
87
88 BasicBlock *BB1 = &*FI++;
89 BBI = BB1->begin();
90 Instruction *Y4 = &*BBI++;
91
92 BasicBlock *BB2 = &*FI++;
93 BBI = BB2->begin();
94 Instruction *Y5 = &*BBI++;
95
96 BasicBlock *BB3 = &*FI++;
97 BBI = BB3->begin();
98 Instruction *Y6 = &*BBI++;
99 Instruction *Y7 = &*BBI++;
100
101 BasicBlock *BB4 = &*FI++;
102 BBI = BB4->begin();
103 Instruction *Y8 = &*BBI++;
104 Instruction *Y9 = &*BBI++;
105
106 // Reachability
107 EXPECT_TRUE(DT->isReachableFromEntry(BB0));
108 EXPECT_TRUE(DT->isReachableFromEntry(BB1));
109 EXPECT_TRUE(DT->isReachableFromEntry(BB2));
110 EXPECT_FALSE(DT->isReachableFromEntry(BB3));
111 EXPECT_TRUE(DT->isReachableFromEntry(BB4));
112
113 // BB dominance
114 EXPECT_TRUE(DT->dominates(BB0, BB0));
115 EXPECT_TRUE(DT->dominates(BB0, BB1));
116 EXPECT_TRUE(DT->dominates(BB0, BB2));
117 EXPECT_TRUE(DT->dominates(BB0, BB3));
118 EXPECT_TRUE(DT->dominates(BB0, BB4));
119
120 EXPECT_FALSE(DT->dominates(BB1, BB0));
121 EXPECT_TRUE(DT->dominates(BB1, BB1));
122 EXPECT_FALSE(DT->dominates(BB1, BB2));
123 EXPECT_TRUE(DT->dominates(BB1, BB3));
124 EXPECT_FALSE(DT->dominates(BB1, BB4));
125
126 EXPECT_FALSE(DT->dominates(BB2, BB0));
127 EXPECT_FALSE(DT->dominates(BB2, BB1));
128 EXPECT_TRUE(DT->dominates(BB2, BB2));
129 EXPECT_TRUE(DT->dominates(BB2, BB3));
130 EXPECT_FALSE(DT->dominates(BB2, BB4));
131
132 EXPECT_FALSE(DT->dominates(BB3, BB0));
133 EXPECT_FALSE(DT->dominates(BB3, BB1));
134 EXPECT_FALSE(DT->dominates(BB3, BB2));
135 EXPECT_TRUE(DT->dominates(BB3, BB3));
136 EXPECT_FALSE(DT->dominates(BB3, BB4));
137
138 // BB proper dominance
139 EXPECT_FALSE(DT->properlyDominates(BB0, BB0));
140 EXPECT_TRUE(DT->properlyDominates(BB0, BB1));
141 EXPECT_TRUE(DT->properlyDominates(BB0, BB2));
142 EXPECT_TRUE(DT->properlyDominates(BB0, BB3));
143
144 EXPECT_FALSE(DT->properlyDominates(BB1, BB0));
145 EXPECT_FALSE(DT->properlyDominates(BB1, BB1));
146 EXPECT_FALSE(DT->properlyDominates(BB1, BB2));
147 EXPECT_TRUE(DT->properlyDominates(BB1, BB3));
148
149 EXPECT_FALSE(DT->properlyDominates(BB2, BB0));
150 EXPECT_FALSE(DT->properlyDominates(BB2, BB1));
151 EXPECT_FALSE(DT->properlyDominates(BB2, BB2));
152 EXPECT_TRUE(DT->properlyDominates(BB2, BB3));
153
154 EXPECT_FALSE(DT->properlyDominates(BB3, BB0));
155 EXPECT_FALSE(DT->properlyDominates(BB3, BB1));
156 EXPECT_FALSE(DT->properlyDominates(BB3, BB2));
157 EXPECT_FALSE(DT->properlyDominates(BB3, BB3));
158
159 // Instruction dominance in the same reachable BB
160 EXPECT_FALSE(DT->dominates(Y1, Y1));
161 EXPECT_TRUE(DT->dominates(Y1, Y2));
162 EXPECT_FALSE(DT->dominates(Y2, Y1));
163 EXPECT_FALSE(DT->dominates(Y2, Y2));
164
165 // Instruction dominance in the same unreachable BB
166 EXPECT_TRUE(DT->dominates(Y6, Y6));
167 EXPECT_TRUE(DT->dominates(Y6, Y7));
168 EXPECT_TRUE(DT->dominates(Y7, Y6));
169 EXPECT_TRUE(DT->dominates(Y7, Y7));
170
171 // Invoke
172 EXPECT_TRUE(DT->dominates(Y3, Y4));
173 EXPECT_FALSE(DT->dominates(Y3, Y5));
174
175 // Phi
176 EXPECT_TRUE(DT->dominates(Y2, Y9));
177 EXPECT_FALSE(DT->dominates(Y3, Y9));
178 EXPECT_FALSE(DT->dominates(Y8, Y9));
179
180 // Anything dominates unreachable
181 EXPECT_TRUE(DT->dominates(Y1, Y6));
182 EXPECT_TRUE(DT->dominates(Y3, Y6));
183
184 // Unreachable doesn't dominate reachable
185 EXPECT_FALSE(DT->dominates(Y6, Y1));
186
187 // Instruction, BB dominance
188 EXPECT_FALSE(DT->dominates(Y1, BB0));
189 EXPECT_TRUE(DT->dominates(Y1, BB1));
190 EXPECT_TRUE(DT->dominates(Y1, BB2));
191 EXPECT_TRUE(DT->dominates(Y1, BB3));
192 EXPECT_TRUE(DT->dominates(Y1, BB4));
193
194 EXPECT_FALSE(DT->dominates(Y3, BB0));
195 EXPECT_TRUE(DT->dominates(Y3, BB1));
196 EXPECT_FALSE(DT->dominates(Y3, BB2));
197 EXPECT_TRUE(DT->dominates(Y3, BB3));
198 EXPECT_FALSE(DT->dominates(Y3, BB4));
199
200 EXPECT_TRUE(DT->dominates(Y6, BB3));
201
202 // Post dominance.
203 EXPECT_TRUE(PDT->dominates(BB0, BB0));
204 EXPECT_FALSE(PDT->dominates(BB1, BB0));
205 EXPECT_FALSE(PDT->dominates(BB2, BB0));
206 EXPECT_FALSE(PDT->dominates(BB3, BB0));
207 EXPECT_TRUE(PDT->dominates(BB4, BB1));
208
209 // Dominance descendants.
210 SmallVector<BasicBlock *, 8> DominatedBBs, PostDominatedBBs;
211
212 DT->getDescendants(BB0, DominatedBBs);
213 PDT->getDescendants(BB0, PostDominatedBBs);
214 EXPECT_EQ(DominatedBBs.size(), 4UL);
215 EXPECT_EQ(PostDominatedBBs.size(), 1UL);
216
217 // BB3 is unreachable. It should have no dominators nor postdominators.
218 DominatedBBs.clear();
219 PostDominatedBBs.clear();
220 DT->getDescendants(BB3, DominatedBBs);
221 DT->getDescendants(BB3, PostDominatedBBs);
222 EXPECT_EQ(DominatedBBs.size(), 0UL);
223 EXPECT_EQ(PostDominatedBBs.size(), 0UL);
224
225 // Check DFS Numbers before
Jakub Kuderski837755c2017-06-30 01:28:21 +0000226 DT->updateDFSNumbers();
Adam Nemet147ede92017-05-27 04:05:52 +0000227 EXPECT_EQ(DT->getNode(BB0)->getDFSNumIn(), 0UL);
228 EXPECT_EQ(DT->getNode(BB0)->getDFSNumOut(), 7UL);
229 EXPECT_EQ(DT->getNode(BB1)->getDFSNumIn(), 1UL);
230 EXPECT_EQ(DT->getNode(BB1)->getDFSNumOut(), 2UL);
231 EXPECT_EQ(DT->getNode(BB2)->getDFSNumIn(), 5UL);
232 EXPECT_EQ(DT->getNode(BB2)->getDFSNumOut(), 6UL);
233 EXPECT_EQ(DT->getNode(BB4)->getDFSNumIn(), 3UL);
234 EXPECT_EQ(DT->getNode(BB4)->getDFSNumOut(), 4UL);
235
Jakub Kuderski604a22b2017-07-01 00:23:01 +0000236 // Check levels before
237 EXPECT_EQ(DT->getNode(BB0)->getLevel(), 0U);
238 EXPECT_EQ(DT->getNode(BB1)->getLevel(), 1U);
239 EXPECT_EQ(DT->getNode(BB2)->getLevel(), 1U);
240 EXPECT_EQ(DT->getNode(BB4)->getLevel(), 1U);
241
Adam Nemet147ede92017-05-27 04:05:52 +0000242 // Reattach block 3 to block 1 and recalculate
243 BB1->getTerminator()->eraseFromParent();
244 BranchInst::Create(BB4, BB3, ConstantInt::getTrue(F.getContext()), BB1);
245 DT->recalculate(F);
246
247 // Check DFS Numbers after
Jakub Kuderski837755c2017-06-30 01:28:21 +0000248 DT->updateDFSNumbers();
Adam Nemet147ede92017-05-27 04:05:52 +0000249 EXPECT_EQ(DT->getNode(BB0)->getDFSNumIn(), 0UL);
250 EXPECT_EQ(DT->getNode(BB0)->getDFSNumOut(), 9UL);
251 EXPECT_EQ(DT->getNode(BB1)->getDFSNumIn(), 1UL);
252 EXPECT_EQ(DT->getNode(BB1)->getDFSNumOut(), 4UL);
253 EXPECT_EQ(DT->getNode(BB2)->getDFSNumIn(), 7UL);
254 EXPECT_EQ(DT->getNode(BB2)->getDFSNumOut(), 8UL);
255 EXPECT_EQ(DT->getNode(BB3)->getDFSNumIn(), 2UL);
256 EXPECT_EQ(DT->getNode(BB3)->getDFSNumOut(), 3UL);
257 EXPECT_EQ(DT->getNode(BB4)->getDFSNumIn(), 5UL);
258 EXPECT_EQ(DT->getNode(BB4)->getDFSNumOut(), 6UL);
259
Jakub Kuderski604a22b2017-07-01 00:23:01 +0000260 // Check levels after
261 EXPECT_EQ(DT->getNode(BB0)->getLevel(), 0U);
262 EXPECT_EQ(DT->getNode(BB1)->getLevel(), 1U);
263 EXPECT_EQ(DT->getNode(BB2)->getLevel(), 1U);
264 EXPECT_EQ(DT->getNode(BB3)->getLevel(), 2U);
265 EXPECT_EQ(DT->getNode(BB4)->getLevel(), 1U);
266
Adam Nemet147ede92017-05-27 04:05:52 +0000267 // Change root node
David Green7c35de12018-02-28 11:00:08 +0000268 EXPECT_TRUE(DT->verify());
Adam Nemet147ede92017-05-27 04:05:52 +0000269 BasicBlock *NewEntry =
270 BasicBlock::Create(F.getContext(), "new_entry", &F, BB0);
271 BranchInst::Create(BB0, NewEntry);
272 EXPECT_EQ(F.begin()->getName(), NewEntry->getName());
273 EXPECT_TRUE(&F.getEntryBlock() == NewEntry);
274 DT->setNewRoot(NewEntry);
David Green7c35de12018-02-28 11:00:08 +0000275 EXPECT_TRUE(DT->verify());
Adam Nemet147ede92017-05-27 04:05:52 +0000276 });
277}
Adam Nemet4ef096b2017-06-05 16:27:09 +0000278
279TEST(DominatorTree, NonUniqueEdges) {
280 StringRef ModuleString =
281 "define i32 @f(i32 %i, i32 *%p) {\n"
282 "bb0:\n"
283 " store i32 %i, i32 *%p\n"
284 " switch i32 %i, label %bb2 [\n"
285 " i32 0, label %bb1\n"
286 " i32 1, label %bb1\n"
287 " ]\n"
288 " bb1:\n"
289 " ret i32 1\n"
290 " bb2:\n"
291 " ret i32 4\n"
292 "}\n";
293
294 // Parse the module.
295 LLVMContext Context;
296 std::unique_ptr<Module> M = makeLLVMModule(Context, ModuleString);
297
298 runWithDomTree(
Jakub Kuderskib292c222017-07-14 18:26:09 +0000299 *M, "f", [&](Function &F, DominatorTree *DT, PostDomTree *PDT) {
Adam Nemet4ef096b2017-06-05 16:27:09 +0000300 Function::iterator FI = F.begin();
301
302 BasicBlock *BB0 = &*FI++;
303 BasicBlock *BB1 = &*FI++;
304 BasicBlock *BB2 = &*FI++;
305
306 const TerminatorInst *TI = BB0->getTerminator();
307 assert(TI->getNumSuccessors() == 3 && "Switch has three successors");
308
309 BasicBlockEdge Edge_BB0_BB2(BB0, TI->getSuccessor(0));
310 assert(Edge_BB0_BB2.getEnd() == BB2 &&
311 "Default label is the 1st successor");
312
313 BasicBlockEdge Edge_BB0_BB1_a(BB0, TI->getSuccessor(1));
314 assert(Edge_BB0_BB1_a.getEnd() == BB1 && "BB1 is the 2nd successor");
315
316 BasicBlockEdge Edge_BB0_BB1_b(BB0, TI->getSuccessor(2));
317 assert(Edge_BB0_BB1_b.getEnd() == BB1 && "BB1 is the 3rd successor");
318
319 EXPECT_TRUE(DT->dominates(Edge_BB0_BB2, BB2));
320 EXPECT_FALSE(DT->dominates(Edge_BB0_BB2, BB1));
321
322 EXPECT_FALSE(DT->dominates(Edge_BB0_BB1_a, BB1));
323 EXPECT_FALSE(DT->dominates(Edge_BB0_BB1_b, BB1));
324
325 EXPECT_FALSE(DT->dominates(Edge_BB0_BB1_a, BB2));
326 EXPECT_FALSE(DT->dominates(Edge_BB0_BB1_b, BB2));
327 });
328}
Jakub Kuderski13e9ef12017-07-14 21:17:33 +0000329
Tobias Grosser3d0ba4b02017-08-01 14:40:55 +0000330// Verify that the PDT is correctly updated in case an edge removal results
Jakub Kuderski638c0852017-08-15 18:14:57 +0000331// in a new unreachable CFG node. Also make sure that the updated PDT is the
332// same as a freshly recalculated one.
Tobias Grosser3d0ba4b02017-08-01 14:40:55 +0000333//
334// For the following input code and initial PDT:
335//
336// CFG PDT
337//
338// A Exit
339// | |
340// _B D
341// / | \ |
342// ^ v \ B
343// \ / D / \
344// C \ C A
345// v
346// Exit
347//
348// we verify that CFG' and PDT-updated is obtained after removal of edge C -> B.
349//
350// CFG' PDT-updated
351//
352// A Exit
Jakub Kuderski638c0852017-08-15 18:14:57 +0000353// | / | \
354// B C B D
Tobias Grosser3d0ba4b02017-08-01 14:40:55 +0000355// | \ |
Jakub Kuderski638c0852017-08-15 18:14:57 +0000356// v \ A
357// / D
358// C \
359// | \
Tobias Grosser3d0ba4b02017-08-01 14:40:55 +0000360// unreachable Exit
361//
Jakub Kuderski638c0852017-08-15 18:14:57 +0000362// Both the blocks that end with ret and with unreachable become trivial
363// PostDomTree roots, as they have no successors.
Tobias Grosser3d0ba4b02017-08-01 14:40:55 +0000364//
Tobias Grosser3d0ba4b02017-08-01 14:40:55 +0000365TEST(DominatorTree, DeletingEdgesIntroducesUnreachables) {
366 StringRef ModuleString =
367 "define void @f() {\n"
368 "A:\n"
369 " br label %B\n"
370 "B:\n"
371 " br i1 undef, label %D, label %C\n"
372 "C:\n"
373 " br label %B\n"
374 "D:\n"
375 " ret void\n"
376 "}\n";
377
378 // Parse the module.
379 LLVMContext Context;
380 std::unique_ptr<Module> M = makeLLVMModule(Context, ModuleString);
381
382 runWithDomTree(
383 *M, "f", [&](Function &F, DominatorTree *DT, PostDomTree *PDT) {
384 Function::iterator FI = F.begin();
385
386 FI++;
387 BasicBlock *B = &*FI++;
388 BasicBlock *C = &*FI++;
389 BasicBlock *D = &*FI++;
390
Jakub Kuderski638c0852017-08-15 18:14:57 +0000391 ASSERT_TRUE(PDT->dominates(PDT->getNode(D), PDT->getNode(B)));
392 EXPECT_TRUE(DT->verify());
393 EXPECT_TRUE(PDT->verify());
Tobias Grosser3d0ba4b02017-08-01 14:40:55 +0000394
395 C->getTerminator()->eraseFromParent();
396 new UnreachableInst(C->getContext(), C);
397
398 DT->deleteEdge(C, B);
399 PDT->deleteEdge(C, B);
400
Jakub Kuderski638c0852017-08-15 18:14:57 +0000401 EXPECT_TRUE(DT->verify());
402 EXPECT_TRUE(PDT->verify());
Tobias Grosser3d0ba4b02017-08-01 14:40:55 +0000403
404 EXPECT_FALSE(PDT->dominates(PDT->getNode(D), PDT->getNode(B)));
405 EXPECT_NE(PDT->getNode(C), nullptr);
Jakub Kuderski638c0852017-08-15 18:14:57 +0000406
407 DominatorTree NDT(F);
408 EXPECT_EQ(DT->compare(NDT), 0);
409
410 PostDomTree NPDT(F);
411 EXPECT_EQ(PDT->compare(NPDT), 0);
Tobias Grosser3d0ba4b02017-08-01 14:40:55 +0000412 });
413}
414
415// Verify that the PDT is correctly updated in case an edge removal results
Jakub Kuderski638c0852017-08-15 18:14:57 +0000416// in an infinite loop. Also make sure that the updated PDT is the
417// same as a freshly recalculated one.
Tobias Grosser3d0ba4b02017-08-01 14:40:55 +0000418//
419// Test case:
420//
421// CFG PDT
422//
423// A Exit
424// | |
425// _B D
426// / | \ |
427// ^ v \ B
428// \ / D / \
429// C \ C A
430// / \ v
431// ^ v Exit
432// \_/
433//
434// After deleting the edge C->B, C is part of an infinite reverse-unreachable
435// loop:
436//
Jakub Kuderski638c0852017-08-15 18:14:57 +0000437// CFG' PDT'
Tobias Grosser3d0ba4b02017-08-01 14:40:55 +0000438//
439// A Exit
Jakub Kuderski638c0852017-08-15 18:14:57 +0000440// | / | \
441// B C B D
Tobias Grosser3d0ba4b02017-08-01 14:40:55 +0000442// | \ |
Jakub Kuderski638c0852017-08-15 18:14:57 +0000443// v \ A
444// / D
445// C \
Tobias Grosser3d0ba4b02017-08-01 14:40:55 +0000446// / \ v
447// ^ v Exit
448// \_/
449//
Jakub Kuderski638c0852017-08-15 18:14:57 +0000450// As C now becomes reverse-unreachable, it forms a new non-trivial root and
451// gets connected to the virtual exit.
452// D does not postdominate B anymore, because there are two forward paths from
453// B to the virtual exit:
454// - B -> C -> VirtualExit
455// - B -> D -> VirtualExit.
Tobias Grosser3d0ba4b02017-08-01 14:40:55 +0000456//
Tobias Grosser3d0ba4b02017-08-01 14:40:55 +0000457TEST(DominatorTree, DeletingEdgesIntroducesInfiniteLoop) {
458 StringRef ModuleString =
459 "define void @f() {\n"
460 "A:\n"
461 " br label %B\n"
462 "B:\n"
463 " br i1 undef, label %D, label %C\n"
464 "C:\n"
465 " switch i32 undef, label %C [\n"
466 " i32 0, label %B\n"
467 " ]\n"
468 "D:\n"
469 " ret void\n"
470 "}\n";
471
472 // Parse the module.
473 LLVMContext Context;
474 std::unique_ptr<Module> M = makeLLVMModule(Context, ModuleString);
475
476 runWithDomTree(
477 *M, "f", [&](Function &F, DominatorTree *DT, PostDomTree *PDT) {
478 Function::iterator FI = F.begin();
479
480 FI++;
481 BasicBlock *B = &*FI++;
482 BasicBlock *C = &*FI++;
483 BasicBlock *D = &*FI++;
484
Jakub Kuderski638c0852017-08-15 18:14:57 +0000485 ASSERT_TRUE(PDT->dominates(PDT->getNode(D), PDT->getNode(B)));
486 EXPECT_TRUE(DT->verify());
487 EXPECT_TRUE(PDT->verify());
Tobias Grosser3d0ba4b02017-08-01 14:40:55 +0000488
489 auto SwitchC = cast<SwitchInst>(C->getTerminator());
490 SwitchC->removeCase(SwitchC->case_begin());
491 DT->deleteEdge(C, B);
Jakub Kuderski638c0852017-08-15 18:14:57 +0000492 EXPECT_TRUE(DT->verify());
Tobias Grosser3d0ba4b02017-08-01 14:40:55 +0000493 PDT->deleteEdge(C, B);
Jakub Kuderski638c0852017-08-15 18:14:57 +0000494 EXPECT_TRUE(PDT->verify());
Tobias Grosser3d0ba4b02017-08-01 14:40:55 +0000495
Jakub Kuderski638c0852017-08-15 18:14:57 +0000496 EXPECT_FALSE(PDT->dominates(PDT->getNode(D), PDT->getNode(B)));
497 EXPECT_NE(PDT->getNode(C), nullptr);
Tobias Grosser3d0ba4b02017-08-01 14:40:55 +0000498
Jakub Kuderski638c0852017-08-15 18:14:57 +0000499 DominatorTree NDT(F);
500 EXPECT_EQ(DT->compare(NDT), 0);
Tobias Grosser3d0ba4b02017-08-01 14:40:55 +0000501
Jakub Kuderski638c0852017-08-15 18:14:57 +0000502 PostDomTree NPDT(F);
503 EXPECT_EQ(PDT->compare(NPDT), 0);
Tobias Grosser3d0ba4b02017-08-01 14:40:55 +0000504 });
505}
506
507// Verify that the PDT is correctly updated in case an edge removal results
508// in an infinite loop.
509//
510// Test case:
511//
512// CFG PDT
513//
514// A Exit
515// | / | \
Jakub Kuderski638c0852017-08-15 18:14:57 +0000516// B-- C2 B D
517// | \ / |
518// v \ C A
Tobias Grosser3d0ba4b02017-08-01 14:40:55 +0000519// / D
520// C--C2 \
521// / \ \ v
522// ^ v --Exit
523// \_/
524//
525// After deleting the edge C->E, C is part of an infinite reverse-unreachable
526// loop:
527//
Jakub Kuderski638c0852017-08-15 18:14:57 +0000528// CFG' PDT'
Tobias Grosser3d0ba4b02017-08-01 14:40:55 +0000529//
530// A Exit
Jakub Kuderski638c0852017-08-15 18:14:57 +0000531// | / | \
532// B C B D
Tobias Grosser3d0ba4b02017-08-01 14:40:55 +0000533// | \ |
Jakub Kuderski638c0852017-08-15 18:14:57 +0000534// v \ A
535// / D
536// C \
Tobias Grosser3d0ba4b02017-08-01 14:40:55 +0000537// / \ v
538// ^ v Exit
539// \_/
540//
Jakub Kuderski638c0852017-08-15 18:14:57 +0000541// In PDT, D does not post-dominate B. After the edge C -> C2 is removed,
542// C becomes a new nontrivial PDT root.
Tobias Grosser3d0ba4b02017-08-01 14:40:55 +0000543//
Tobias Grosser3d0ba4b02017-08-01 14:40:55 +0000544TEST(DominatorTree, DeletingEdgesIntroducesInfiniteLoop2) {
545 StringRef ModuleString =
546 "define void @f() {\n"
547 "A:\n"
548 " br label %B\n"
549 "B:\n"
550 " br i1 undef, label %D, label %C\n"
551 "C:\n"
552 " switch i32 undef, label %C [\n"
553 " i32 0, label %C2\n"
554 " ]\n"
555 "C2:\n"
556 " ret void\n"
557 "D:\n"
558 " ret void\n"
559 "}\n";
560
561 // Parse the module.
562 LLVMContext Context;
563 std::unique_ptr<Module> M = makeLLVMModule(Context, ModuleString);
564
565 runWithDomTree(
566 *M, "f", [&](Function &F, DominatorTree *DT, PostDomTree *PDT) {
567 Function::iterator FI = F.begin();
568
569 FI++;
570 BasicBlock *B = &*FI++;
571 BasicBlock *C = &*FI++;
572 BasicBlock *C2 = &*FI++;
573 BasicBlock *D = &*FI++;
574
Jakub Kuderski638c0852017-08-15 18:14:57 +0000575 EXPECT_TRUE(DT->verify());
576 EXPECT_TRUE(PDT->verify());
577
Tobias Grosser3d0ba4b02017-08-01 14:40:55 +0000578 auto SwitchC = cast<SwitchInst>(C->getTerminator());
579 SwitchC->removeCase(SwitchC->case_begin());
580 DT->deleteEdge(C, C2);
581 PDT->deleteEdge(C, C2);
Jakub Kuderski638c0852017-08-15 18:14:57 +0000582 C2->removeFromParent();
Tobias Grosser3d0ba4b02017-08-01 14:40:55 +0000583
584 EXPECT_EQ(DT->getNode(C2), nullptr);
585 PDT->eraseNode(C2);
Jakub Kuderski638c0852017-08-15 18:14:57 +0000586 delete C2;
Tobias Grosser3d0ba4b02017-08-01 14:40:55 +0000587
Jakub Kuderski638c0852017-08-15 18:14:57 +0000588 EXPECT_TRUE(DT->verify());
589 EXPECT_TRUE(PDT->verify());
Tobias Grosser3d0ba4b02017-08-01 14:40:55 +0000590
Jakub Kuderski638c0852017-08-15 18:14:57 +0000591 EXPECT_FALSE(PDT->dominates(PDT->getNode(D), PDT->getNode(B)));
592 EXPECT_NE(PDT->getNode(C), nullptr);
Tobias Grosser3d0ba4b02017-08-01 14:40:55 +0000593
Jakub Kuderski638c0852017-08-15 18:14:57 +0000594 DominatorTree NDT(F);
595 EXPECT_EQ(DT->compare(NDT), 0);
596
597 PostDomTree NPDT(F);
598 EXPECT_EQ(PDT->compare(NPDT), 0);
Tobias Grosser3d0ba4b02017-08-01 14:40:55 +0000599 });
600}
601
Michael Zolotukhin046da972018-05-12 01:44:32 +0000602// Verify that the IDF returns blocks in a deterministic way.
603//
604// Test case:
605//
606// CFG
607//
608// (A)
609// / \
610// / \
611// (B) (C)
612// |\ /|
613// | X |
614// |/ \|
615// (D) (E)
616//
617// IDF for block B is {D, E}, and the order of blocks in this list is defined by
618// their 1) level in dom-tree and 2) DFSIn number if the level is the same.
619//
620TEST(DominatorTree, IDFDeterminismTest) {
621 StringRef ModuleString =
622 "define void @f() {\n"
623 "A:\n"
624 " br i1 undef, label %B, label %C\n"
625 "B:\n"
626 " br i1 undef, label %D, label %E\n"
627 "C:\n"
628 " br i1 undef, label %D, label %E\n"
629 "D:\n"
630 " ret void\n"
631 "E:\n"
632 " ret void\n"
633 "}\n";
634
635 // Parse the module.
636 LLVMContext Context;
637 std::unique_ptr<Module> M = makeLLVMModule(Context, ModuleString);
638
639 runWithDomTree(
640 *M, "f", [&](Function &F, DominatorTree *DT, PostDomTree *PDT) {
641 Function::iterator FI = F.begin();
642
643 BasicBlock *A = &*FI++;
644 BasicBlock *B = &*FI++;
645 BasicBlock *C = &*FI++;
646 BasicBlock *D = &*FI++;
647 BasicBlock *E = &*FI++;
648 (void)C;
649
650 DT->updateDFSNumbers();
651 ForwardIDFCalculator IDF(*DT);
652 SmallPtrSet<BasicBlock *, 1> DefBlocks;
653 DefBlocks.insert(B);
654 IDF.setDefiningBlocks(DefBlocks);
655
656 SmallVector<BasicBlock *, 32> IDFBlocks;
657 SmallPtrSet<BasicBlock *, 32> LiveInBlocks;
658 IDF.resetLiveInBlocks();
659 IDF.calculate(IDFBlocks);
660
661
662 EXPECT_EQ(IDFBlocks.size(), 2UL);
663 EXPECT_EQ(DT->getNode(A)->getDFSNumIn(), 0UL);
664 EXPECT_EQ(IDFBlocks[0], D);
665 EXPECT_EQ(IDFBlocks[1], E);
666 EXPECT_TRUE(DT->getNode(IDFBlocks[0])->getDFSNumIn() <
667 DT->getNode(IDFBlocks[1])->getDFSNumIn());
668 });
669}
670
Jakub Kuderski13e9ef12017-07-14 21:17:33 +0000671namespace {
672const auto Insert = CFGBuilder::ActionKind::Insert;
Jakub Kuderskieb59ff22017-07-14 21:58:53 +0000673const auto Delete = CFGBuilder::ActionKind::Delete;
Jakub Kuderski13e9ef12017-07-14 21:17:33 +0000674
675bool CompUpdates(const CFGBuilder::Update &A, const CFGBuilder::Update &B) {
676 return std::tie(A.Action, A.Edge.From, A.Edge.To) <
677 std::tie(B.Action, B.Edge.From, B.Edge.To);
Jakub Kuderski23497b42017-07-14 22:24:15 +0000678}
Jakub Kuderski13e9ef12017-07-14 21:17:33 +0000679} // namespace
680
681TEST(DominatorTree, InsertReachable) {
682 CFGHolder Holder;
683 std::vector<CFGBuilder::Arc> Arcs = {
684 {"1", "2"}, {"2", "3"}, {"3", "4"}, {"4", "5"}, {"5", "6"}, {"5", "7"},
685 {"3", "8"}, {"8", "9"}, {"9", "10"}, {"8", "11"}, {"11", "12"}};
686
687 std::vector<CFGBuilder::Update> Updates = {{Insert, {"12", "10"}},
688 {Insert, {"10", "9"}},
689 {Insert, {"7", "6"}},
690 {Insert, {"7", "5"}}};
691 CFGBuilder B(Holder.F, Arcs, Updates);
692 DominatorTree DT(*Holder.F);
693 EXPECT_TRUE(DT.verify());
694 PostDomTree PDT(*Holder.F);
695 EXPECT_TRUE(PDT.verify());
696
697 Optional<CFGBuilder::Update> LastUpdate;
698 while ((LastUpdate = B.applyUpdate())) {
699 EXPECT_EQ(LastUpdate->Action, Insert);
700 BasicBlock *From = B.getOrAddBlock(LastUpdate->Edge.From);
701 BasicBlock *To = B.getOrAddBlock(LastUpdate->Edge.To);
702 DT.insertEdge(From, To);
703 EXPECT_TRUE(DT.verify());
704 PDT.insertEdge(From, To);
705 EXPECT_TRUE(PDT.verify());
706 }
707}
708
Jakub Kuderski66360342017-07-15 01:27:16 +0000709TEST(DominatorTree, InsertReachable2) {
710 CFGHolder Holder;
711 std::vector<CFGBuilder::Arc> Arcs = {
712 {"1", "2"}, {"2", "3"}, {"3", "4"}, {"4", "5"}, {"5", "6"}, {"5", "7"},
713 {"7", "5"}, {"2", "8"}, {"8", "11"}, {"11", "12"}, {"12", "10"},
714 {"10", "9"}, {"9", "10"}};
715
716 std::vector<CFGBuilder::Update> Updates = {{Insert, {"10", "7"}}};
717 CFGBuilder B(Holder.F, Arcs, Updates);
718 DominatorTree DT(*Holder.F);
719 EXPECT_TRUE(DT.verify());
720 PostDomTree PDT(*Holder.F);
721 EXPECT_TRUE(PDT.verify());
722
723 Optional<CFGBuilder::Update> LastUpdate = B.applyUpdate();
724 EXPECT_TRUE(LastUpdate);
725
726 EXPECT_EQ(LastUpdate->Action, Insert);
727 BasicBlock *From = B.getOrAddBlock(LastUpdate->Edge.From);
728 BasicBlock *To = B.getOrAddBlock(LastUpdate->Edge.To);
729 DT.insertEdge(From, To);
730 EXPECT_TRUE(DT.verify());
731 PDT.insertEdge(From, To);
732 EXPECT_TRUE(PDT.verify());
733}
734
Jakub Kuderski13e9ef12017-07-14 21:17:33 +0000735TEST(DominatorTree, InsertUnreachable) {
736 CFGHolder Holder;
737 std::vector<CFGBuilder::Arc> Arcs = {{"1", "2"}, {"2", "3"}, {"3", "4"},
738 {"5", "6"}, {"5", "7"}, {"3", "8"},
739 {"9", "10"}, {"11", "12"}};
740
741 std::vector<CFGBuilder::Update> Updates = {{Insert, {"4", "5"}},
742 {Insert, {"8", "9"}},
743 {Insert, {"10", "12"}},
744 {Insert, {"10", "11"}}};
745 CFGBuilder B(Holder.F, Arcs, Updates);
746 DominatorTree DT(*Holder.F);
747 EXPECT_TRUE(DT.verify());
748 PostDomTree PDT(*Holder.F);
749 EXPECT_TRUE(PDT.verify());
750
751 Optional<CFGBuilder::Update> LastUpdate;
752 while ((LastUpdate = B.applyUpdate())) {
753 EXPECT_EQ(LastUpdate->Action, Insert);
754 BasicBlock *From = B.getOrAddBlock(LastUpdate->Edge.From);
755 BasicBlock *To = B.getOrAddBlock(LastUpdate->Edge.To);
756 DT.insertEdge(From, To);
757 EXPECT_TRUE(DT.verify());
758 PDT.insertEdge(From, To);
759 EXPECT_TRUE(PDT.verify());
760 }
761}
762
Jakub Kuderski638c0852017-08-15 18:14:57 +0000763TEST(DominatorTree, InsertFromUnreachable) {
764 CFGHolder Holder;
765 std::vector<CFGBuilder::Arc> Arcs = {{"1", "2"}, {"2", "3"}, {"3", "4"}};
766
767 std::vector<CFGBuilder::Update> Updates = {{Insert, {"3", "5"}}};
768 CFGBuilder B(Holder.F, Arcs, Updates);
769 PostDomTree PDT(*Holder.F);
770 EXPECT_TRUE(PDT.verify());
771
772 Optional<CFGBuilder::Update> LastUpdate = B.applyUpdate();
773 EXPECT_TRUE(LastUpdate);
774
775 EXPECT_EQ(LastUpdate->Action, Insert);
776 BasicBlock *From = B.getOrAddBlock(LastUpdate->Edge.From);
777 BasicBlock *To = B.getOrAddBlock(LastUpdate->Edge.To);
778 PDT.insertEdge(From, To);
779 EXPECT_TRUE(PDT.verify());
780 EXPECT_TRUE(PDT.getRoots().size() == 2);
781 EXPECT_NE(PDT.getNode(B.getOrAddBlock("5")), nullptr);
782}
783
Jakub Kuderski13e9ef12017-07-14 21:17:33 +0000784TEST(DominatorTree, InsertMixed) {
785 CFGHolder Holder;
786 std::vector<CFGBuilder::Arc> Arcs = {
787 {"1", "2"}, {"2", "3"}, {"3", "4"}, {"5", "6"}, {"5", "7"},
788 {"8", "9"}, {"9", "10"}, {"8", "11"}, {"11", "12"}, {"7", "3"}};
789
790 std::vector<CFGBuilder::Update> Updates = {
791 {Insert, {"4", "5"}}, {Insert, {"2", "5"}}, {Insert, {"10", "9"}},
792 {Insert, {"12", "10"}}, {Insert, {"12", "10"}}, {Insert, {"7", "8"}},
793 {Insert, {"7", "5"}}};
794 CFGBuilder B(Holder.F, Arcs, Updates);
795 DominatorTree DT(*Holder.F);
796 EXPECT_TRUE(DT.verify());
797 PostDomTree PDT(*Holder.F);
798 EXPECT_TRUE(PDT.verify());
799
800 Optional<CFGBuilder::Update> LastUpdate;
801 while ((LastUpdate = B.applyUpdate())) {
802 EXPECT_EQ(LastUpdate->Action, Insert);
803 BasicBlock *From = B.getOrAddBlock(LastUpdate->Edge.From);
804 BasicBlock *To = B.getOrAddBlock(LastUpdate->Edge.To);
805 DT.insertEdge(From, To);
806 EXPECT_TRUE(DT.verify());
807 PDT.insertEdge(From, To);
808 EXPECT_TRUE(PDT.verify());
809 }
810}
811
812TEST(DominatorTree, InsertPermut) {
813 std::vector<CFGBuilder::Arc> Arcs = {
814 {"1", "2"}, {"2", "3"}, {"3", "4"}, {"5", "6"}, {"5", "7"},
815 {"8", "9"}, {"9", "10"}, {"8", "11"}, {"11", "12"}, {"7", "3"}};
816
817 std::vector<CFGBuilder::Update> Updates = {{Insert, {"4", "5"}},
818 {Insert, {"2", "5"}},
819 {Insert, {"10", "9"}},
820 {Insert, {"12", "10"}}};
821
822 while (std::next_permutation(Updates.begin(), Updates.end(), CompUpdates)) {
823 CFGHolder Holder;
824 CFGBuilder B(Holder.F, Arcs, Updates);
825 DominatorTree DT(*Holder.F);
826 EXPECT_TRUE(DT.verify());
827 PostDomTree PDT(*Holder.F);
828 EXPECT_TRUE(PDT.verify());
829
830 Optional<CFGBuilder::Update> LastUpdate;
831 while ((LastUpdate = B.applyUpdate())) {
832 EXPECT_EQ(LastUpdate->Action, Insert);
833 BasicBlock *From = B.getOrAddBlock(LastUpdate->Edge.From);
834 BasicBlock *To = B.getOrAddBlock(LastUpdate->Edge.To);
835 DT.insertEdge(From, To);
836 EXPECT_TRUE(DT.verify());
837 PDT.insertEdge(From, To);
838 EXPECT_TRUE(PDT.verify());
839 }
840 }
841}
Jakub Kuderskieb59ff22017-07-14 21:58:53 +0000842
843TEST(DominatorTree, DeleteReachable) {
844 CFGHolder Holder;
845 std::vector<CFGBuilder::Arc> Arcs = {
846 {"1", "2"}, {"2", "3"}, {"2", "4"}, {"3", "4"}, {"4", "5"}, {"5", "6"},
847 {"5", "7"}, {"7", "8"}, {"3", "8"}, {"8", "9"}, {"9", "10"}, {"10", "2"}};
848
849 std::vector<CFGBuilder::Update> Updates = {
850 {Delete, {"2", "4"}}, {Delete, {"7", "8"}}, {Delete, {"10", "2"}}};
851 CFGBuilder B(Holder.F, Arcs, Updates);
852 DominatorTree DT(*Holder.F);
853 EXPECT_TRUE(DT.verify());
854 PostDomTree PDT(*Holder.F);
855 EXPECT_TRUE(PDT.verify());
856
857 Optional<CFGBuilder::Update> LastUpdate;
858 while ((LastUpdate = B.applyUpdate())) {
859 EXPECT_EQ(LastUpdate->Action, Delete);
860 BasicBlock *From = B.getOrAddBlock(LastUpdate->Edge.From);
861 BasicBlock *To = B.getOrAddBlock(LastUpdate->Edge.To);
862 DT.deleteEdge(From, To);
863 EXPECT_TRUE(DT.verify());
864 PDT.deleteEdge(From, To);
865 EXPECT_TRUE(PDT.verify());
866 }
867}
868
869TEST(DominatorTree, DeleteUnreachable) {
870 CFGHolder Holder;
871 std::vector<CFGBuilder::Arc> Arcs = {
872 {"1", "2"}, {"2", "3"}, {"3", "4"}, {"4", "5"}, {"5", "6"}, {"5", "7"},
873 {"7", "8"}, {"3", "8"}, {"8", "9"}, {"9", "10"}, {"10", "2"}};
874
875 std::vector<CFGBuilder::Update> Updates = {
876 {Delete, {"8", "9"}}, {Delete, {"7", "8"}}, {Delete, {"3", "4"}}};
877 CFGBuilder B(Holder.F, Arcs, Updates);
878 DominatorTree DT(*Holder.F);
879 EXPECT_TRUE(DT.verify());
880 PostDomTree PDT(*Holder.F);
881 EXPECT_TRUE(PDT.verify());
882
883 Optional<CFGBuilder::Update> LastUpdate;
884 while ((LastUpdate = B.applyUpdate())) {
885 EXPECT_EQ(LastUpdate->Action, Delete);
886 BasicBlock *From = B.getOrAddBlock(LastUpdate->Edge.From);
887 BasicBlock *To = B.getOrAddBlock(LastUpdate->Edge.To);
888 DT.deleteEdge(From, To);
889 EXPECT_TRUE(DT.verify());
890 PDT.deleteEdge(From, To);
891 EXPECT_TRUE(PDT.verify());
892 }
893}
894
895TEST(DominatorTree, InsertDelete) {
896 std::vector<CFGBuilder::Arc> Arcs = {
897 {"1", "2"}, {"2", "3"}, {"3", "4"}, {"4", "5"}, {"5", "6"}, {"5", "7"},
898 {"3", "8"}, {"8", "9"}, {"9", "10"}, {"8", "11"}, {"11", "12"}};
899
900 std::vector<CFGBuilder::Update> Updates = {
901 {Insert, {"2", "4"}}, {Insert, {"12", "10"}}, {Insert, {"10", "9"}},
902 {Insert, {"7", "6"}}, {Insert, {"7", "5"}}, {Delete, {"3", "8"}},
903 {Insert, {"10", "7"}}, {Insert, {"2", "8"}}, {Delete, {"3", "4"}},
904 {Delete, {"8", "9"}}, {Delete, {"11", "12"}}};
905
906 CFGHolder Holder;
907 CFGBuilder B(Holder.F, Arcs, Updates);
908 DominatorTree DT(*Holder.F);
909 EXPECT_TRUE(DT.verify());
910 PostDomTree PDT(*Holder.F);
911 EXPECT_TRUE(PDT.verify());
912
913 Optional<CFGBuilder::Update> LastUpdate;
914 while ((LastUpdate = B.applyUpdate())) {
915 BasicBlock *From = B.getOrAddBlock(LastUpdate->Edge.From);
916 BasicBlock *To = B.getOrAddBlock(LastUpdate->Edge.To);
917 if (LastUpdate->Action == Insert) {
918 DT.insertEdge(From, To);
919 PDT.insertEdge(From, To);
920 } else {
921 DT.deleteEdge(From, To);
922 PDT.deleteEdge(From, To);
923 }
924
925 EXPECT_TRUE(DT.verify());
926 EXPECT_TRUE(PDT.verify());
927 }
928}
929
Jakub Kuderski66360342017-07-15 01:27:16 +0000930TEST(DominatorTree, InsertDeleteExhaustive) {
Jakub Kuderskieb59ff22017-07-14 21:58:53 +0000931 std::vector<CFGBuilder::Arc> Arcs = {
932 {"1", "2"}, {"2", "3"}, {"3", "4"}, {"4", "5"}, {"5", "6"}, {"5", "7"},
933 {"3", "8"}, {"8", "9"}, {"9", "10"}, {"8", "11"}, {"11", "12"}};
934
935 std::vector<CFGBuilder::Update> Updates = {
936 {Insert, {"2", "4"}}, {Insert, {"12", "10"}}, {Insert, {"10", "9"}},
937 {Insert, {"7", "6"}}, {Insert, {"7", "5"}}, {Delete, {"3", "8"}},
938 {Insert, {"10", "7"}}, {Insert, {"2", "8"}}, {Delete, {"3", "4"}},
939 {Delete, {"8", "9"}}, {Delete, {"11", "12"}}};
940
941 std::mt19937 Generator(0);
942 for (unsigned i = 0; i < 16; ++i) {
943 std::shuffle(Updates.begin(), Updates.end(), Generator);
944 CFGHolder Holder;
945 CFGBuilder B(Holder.F, Arcs, Updates);
946 DominatorTree DT(*Holder.F);
947 EXPECT_TRUE(DT.verify());
948 PostDomTree PDT(*Holder.F);
949 EXPECT_TRUE(PDT.verify());
950
951 Optional<CFGBuilder::Update> LastUpdate;
952 while ((LastUpdate = B.applyUpdate())) {
953 BasicBlock *From = B.getOrAddBlock(LastUpdate->Edge.From);
954 BasicBlock *To = B.getOrAddBlock(LastUpdate->Edge.To);
955 if (LastUpdate->Action == Insert) {
956 DT.insertEdge(From, To);
957 PDT.insertEdge(From, To);
958 } else {
959 DT.deleteEdge(From, To);
960 PDT.deleteEdge(From, To);
961 }
962
963 EXPECT_TRUE(DT.verify());
964 EXPECT_TRUE(PDT.verify());
965 }
966 }
967}
Jakub Kuderskid2e371f2018-01-19 21:27:24 +0000968
969TEST(DominatorTree, InsertIntoIrreducible) {
970 std::vector<CFGBuilder::Arc> Arcs = {
971 {"0", "1"},
972 {"1", "27"}, {"1", "7"},
973 {"10", "18"},
974 {"13", "10"},
975 {"18", "13"}, {"18", "23"},
976 {"23", "13"}, {"23", "24"},
977 {"24", "1"}, {"24", "18"},
978 {"27", "24"}};
979
980 CFGHolder Holder;
981 CFGBuilder B(Holder.F, Arcs, {{Insert, {"7", "23"}}});
982 DominatorTree DT(*Holder.F);
983 EXPECT_TRUE(DT.verify());
984
985 B.applyUpdate();
986 BasicBlock *From = B.getOrAddBlock("7");
987 BasicBlock *To = B.getOrAddBlock("23");
988 DT.insertEdge(From, To);
989
990 EXPECT_TRUE(DT.verify());
991}
992