blob: aa9042a84c255986fda7059554e4cd5c16dd085b [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"
Chandler Carruth9aca9182014-01-07 12:34:26 +000012#include "llvm/AsmParser/Parser.h"
Daniel Berlin8f8174c2015-04-14 19:49:26 +000013#include "llvm/IR/Constants.h"
Adam Nemet7fa6dee2017-05-27 04:05:50 +000014#include "llvm/IR/Dominators.h"
Chandler Carruth9fb823b2013-01-02 11:36:10 +000015#include "llvm/IR/Instructions.h"
16#include "llvm/IR/LLVMContext.h"
Adam Nemet7fa6dee2017-05-27 04:05:50 +000017#include "llvm/IR/Module.h"
Rafael Espindolaa53c46a2012-03-30 16:46:21 +000018#include "llvm/Support/SourceMgr.h"
Jakub Kuderski13e9ef12017-07-14 21:17:33 +000019#include "CFGBuilder.h"
Rafael Espindolaa53c46a2012-03-30 16:46:21 +000020#include "gtest/gtest.h"
21
22using namespace llvm;
23
Jakub Kuderskib292c222017-07-14 18:26:09 +000024struct PostDomTree : PostDomTreeBase<BasicBlock> {
25 PostDomTree(Function &F) { recalculate(F); }
26};
27
Adam Nemet147ede92017-05-27 04:05:52 +000028/// Build the dominator tree for the function and run the Test.
Jakub Kuderskib292c222017-07-14 18:26:09 +000029static void runWithDomTree(
30 Module &M, StringRef FuncName,
31 function_ref<void(Function &F, DominatorTree *DT, PostDomTree *PDT)> Test) {
Adam Nemet147ede92017-05-27 04:05:52 +000032 auto *F = M.getFunction(FuncName);
33 ASSERT_NE(F, nullptr) << "Could not find " << FuncName;
34 // Compute the dominator tree for the function.
35 DominatorTree DT(*F);
Jakub Kuderskib292c222017-07-14 18:26:09 +000036 PostDomTree PDT(*F);
Adam Nemet147ede92017-05-27 04:05:52 +000037 Test(*F, &DT, &PDT);
38}
Rafael Espindolaa53c46a2012-03-30 16:46:21 +000039
Adam Nemet147ede92017-05-27 04:05:52 +000040static std::unique_ptr<Module> makeLLVMModule(LLVMContext &Context,
41 StringRef ModuleStr) {
42 SMDiagnostic Err;
43 std::unique_ptr<Module> M = parseAssemblyString(ModuleStr, Err, Context);
44 assert(M && "Bad assembly?");
45 return M;
46}
Rafael Espindolaa53c46a2012-03-30 16:46:21 +000047
Adam Nemet147ede92017-05-27 04:05:52 +000048TEST(DominatorTree, Unreachable) {
49 StringRef ModuleString =
Adam Nemet7fa6dee2017-05-27 04:05:50 +000050 "declare i32 @g()\n"
51 "define void @f(i32 %x) personality i32 ()* @g {\n"
52 "bb0:\n"
53 " %y1 = add i32 %x, 1\n"
54 " %y2 = add i32 %x, 1\n"
55 " %y3 = invoke i32 @g() to label %bb1 unwind label %bb2\n"
56 "bb1:\n"
57 " %y4 = add i32 %x, 1\n"
58 " br label %bb4\n"
59 "bb2:\n"
60 " %y5 = landingpad i32\n"
61 " cleanup\n"
62 " br label %bb4\n"
63 "bb3:\n"
64 " %y6 = add i32 %x, 1\n"
65 " %y7 = add i32 %x, 1\n"
66 " ret void\n"
67 "bb4:\n"
68 " %y8 = phi i32 [0, %bb2], [%y4, %bb1]\n"
69 " %y9 = phi i32 [0, %bb2], [%y4, %bb1]\n"
70 " ret void\n"
71 "}\n";
Rafael Espindolaa53c46a2012-03-30 16:46:21 +000072
Adam Nemet147ede92017-05-27 04:05:52 +000073 // Parse the module.
Adam Nemet7fa6dee2017-05-27 04:05:50 +000074 LLVMContext Context;
Adam Nemet147ede92017-05-27 04:05:52 +000075 std::unique_ptr<Module> M = makeLLVMModule(Context, ModuleString);
Adam Nemet7fa6dee2017-05-27 04:05:50 +000076
Adam Nemet147ede92017-05-27 04:05:52 +000077 runWithDomTree(
Jakub Kuderskib292c222017-07-14 18:26:09 +000078 *M, "f", [&](Function &F, DominatorTree *DT, PostDomTree *PDT) {
Adam Nemet147ede92017-05-27 04:05:52 +000079 Function::iterator FI = F.begin();
80
81 BasicBlock *BB0 = &*FI++;
82 BasicBlock::iterator BBI = BB0->begin();
83 Instruction *Y1 = &*BBI++;
84 Instruction *Y2 = &*BBI++;
85 Instruction *Y3 = &*BBI++;
86
87 BasicBlock *BB1 = &*FI++;
88 BBI = BB1->begin();
89 Instruction *Y4 = &*BBI++;
90
91 BasicBlock *BB2 = &*FI++;
92 BBI = BB2->begin();
93 Instruction *Y5 = &*BBI++;
94
95 BasicBlock *BB3 = &*FI++;
96 BBI = BB3->begin();
97 Instruction *Y6 = &*BBI++;
98 Instruction *Y7 = &*BBI++;
99
100 BasicBlock *BB4 = &*FI++;
101 BBI = BB4->begin();
102 Instruction *Y8 = &*BBI++;
103 Instruction *Y9 = &*BBI++;
104
105 // Reachability
106 EXPECT_TRUE(DT->isReachableFromEntry(BB0));
107 EXPECT_TRUE(DT->isReachableFromEntry(BB1));
108 EXPECT_TRUE(DT->isReachableFromEntry(BB2));
109 EXPECT_FALSE(DT->isReachableFromEntry(BB3));
110 EXPECT_TRUE(DT->isReachableFromEntry(BB4));
111
112 // BB dominance
113 EXPECT_TRUE(DT->dominates(BB0, BB0));
114 EXPECT_TRUE(DT->dominates(BB0, BB1));
115 EXPECT_TRUE(DT->dominates(BB0, BB2));
116 EXPECT_TRUE(DT->dominates(BB0, BB3));
117 EXPECT_TRUE(DT->dominates(BB0, BB4));
118
119 EXPECT_FALSE(DT->dominates(BB1, BB0));
120 EXPECT_TRUE(DT->dominates(BB1, BB1));
121 EXPECT_FALSE(DT->dominates(BB1, BB2));
122 EXPECT_TRUE(DT->dominates(BB1, BB3));
123 EXPECT_FALSE(DT->dominates(BB1, BB4));
124
125 EXPECT_FALSE(DT->dominates(BB2, BB0));
126 EXPECT_FALSE(DT->dominates(BB2, BB1));
127 EXPECT_TRUE(DT->dominates(BB2, BB2));
128 EXPECT_TRUE(DT->dominates(BB2, BB3));
129 EXPECT_FALSE(DT->dominates(BB2, BB4));
130
131 EXPECT_FALSE(DT->dominates(BB3, BB0));
132 EXPECT_FALSE(DT->dominates(BB3, BB1));
133 EXPECT_FALSE(DT->dominates(BB3, BB2));
134 EXPECT_TRUE(DT->dominates(BB3, BB3));
135 EXPECT_FALSE(DT->dominates(BB3, BB4));
136
137 // BB proper dominance
138 EXPECT_FALSE(DT->properlyDominates(BB0, BB0));
139 EXPECT_TRUE(DT->properlyDominates(BB0, BB1));
140 EXPECT_TRUE(DT->properlyDominates(BB0, BB2));
141 EXPECT_TRUE(DT->properlyDominates(BB0, BB3));
142
143 EXPECT_FALSE(DT->properlyDominates(BB1, BB0));
144 EXPECT_FALSE(DT->properlyDominates(BB1, BB1));
145 EXPECT_FALSE(DT->properlyDominates(BB1, BB2));
146 EXPECT_TRUE(DT->properlyDominates(BB1, BB3));
147
148 EXPECT_FALSE(DT->properlyDominates(BB2, BB0));
149 EXPECT_FALSE(DT->properlyDominates(BB2, BB1));
150 EXPECT_FALSE(DT->properlyDominates(BB2, BB2));
151 EXPECT_TRUE(DT->properlyDominates(BB2, BB3));
152
153 EXPECT_FALSE(DT->properlyDominates(BB3, BB0));
154 EXPECT_FALSE(DT->properlyDominates(BB3, BB1));
155 EXPECT_FALSE(DT->properlyDominates(BB3, BB2));
156 EXPECT_FALSE(DT->properlyDominates(BB3, BB3));
157
158 // Instruction dominance in the same reachable BB
159 EXPECT_FALSE(DT->dominates(Y1, Y1));
160 EXPECT_TRUE(DT->dominates(Y1, Y2));
161 EXPECT_FALSE(DT->dominates(Y2, Y1));
162 EXPECT_FALSE(DT->dominates(Y2, Y2));
163
164 // Instruction dominance in the same unreachable BB
165 EXPECT_TRUE(DT->dominates(Y6, Y6));
166 EXPECT_TRUE(DT->dominates(Y6, Y7));
167 EXPECT_TRUE(DT->dominates(Y7, Y6));
168 EXPECT_TRUE(DT->dominates(Y7, Y7));
169
170 // Invoke
171 EXPECT_TRUE(DT->dominates(Y3, Y4));
172 EXPECT_FALSE(DT->dominates(Y3, Y5));
173
174 // Phi
175 EXPECT_TRUE(DT->dominates(Y2, Y9));
176 EXPECT_FALSE(DT->dominates(Y3, Y9));
177 EXPECT_FALSE(DT->dominates(Y8, Y9));
178
179 // Anything dominates unreachable
180 EXPECT_TRUE(DT->dominates(Y1, Y6));
181 EXPECT_TRUE(DT->dominates(Y3, Y6));
182
183 // Unreachable doesn't dominate reachable
184 EXPECT_FALSE(DT->dominates(Y6, Y1));
185
186 // Instruction, BB dominance
187 EXPECT_FALSE(DT->dominates(Y1, BB0));
188 EXPECT_TRUE(DT->dominates(Y1, BB1));
189 EXPECT_TRUE(DT->dominates(Y1, BB2));
190 EXPECT_TRUE(DT->dominates(Y1, BB3));
191 EXPECT_TRUE(DT->dominates(Y1, BB4));
192
193 EXPECT_FALSE(DT->dominates(Y3, BB0));
194 EXPECT_TRUE(DT->dominates(Y3, BB1));
195 EXPECT_FALSE(DT->dominates(Y3, BB2));
196 EXPECT_TRUE(DT->dominates(Y3, BB3));
197 EXPECT_FALSE(DT->dominates(Y3, BB4));
198
199 EXPECT_TRUE(DT->dominates(Y6, BB3));
200
201 // Post dominance.
202 EXPECT_TRUE(PDT->dominates(BB0, BB0));
203 EXPECT_FALSE(PDT->dominates(BB1, BB0));
204 EXPECT_FALSE(PDT->dominates(BB2, BB0));
205 EXPECT_FALSE(PDT->dominates(BB3, BB0));
206 EXPECT_TRUE(PDT->dominates(BB4, BB1));
207
208 // Dominance descendants.
209 SmallVector<BasicBlock *, 8> DominatedBBs, PostDominatedBBs;
210
211 DT->getDescendants(BB0, DominatedBBs);
212 PDT->getDescendants(BB0, PostDominatedBBs);
213 EXPECT_EQ(DominatedBBs.size(), 4UL);
214 EXPECT_EQ(PostDominatedBBs.size(), 1UL);
215
216 // BB3 is unreachable. It should have no dominators nor postdominators.
217 DominatedBBs.clear();
218 PostDominatedBBs.clear();
219 DT->getDescendants(BB3, DominatedBBs);
220 DT->getDescendants(BB3, PostDominatedBBs);
221 EXPECT_EQ(DominatedBBs.size(), 0UL);
222 EXPECT_EQ(PostDominatedBBs.size(), 0UL);
223
224 // Check DFS Numbers before
Jakub Kuderski837755c2017-06-30 01:28:21 +0000225 DT->updateDFSNumbers();
Adam Nemet147ede92017-05-27 04:05:52 +0000226 EXPECT_EQ(DT->getNode(BB0)->getDFSNumIn(), 0UL);
227 EXPECT_EQ(DT->getNode(BB0)->getDFSNumOut(), 7UL);
228 EXPECT_EQ(DT->getNode(BB1)->getDFSNumIn(), 1UL);
229 EXPECT_EQ(DT->getNode(BB1)->getDFSNumOut(), 2UL);
230 EXPECT_EQ(DT->getNode(BB2)->getDFSNumIn(), 5UL);
231 EXPECT_EQ(DT->getNode(BB2)->getDFSNumOut(), 6UL);
232 EXPECT_EQ(DT->getNode(BB4)->getDFSNumIn(), 3UL);
233 EXPECT_EQ(DT->getNode(BB4)->getDFSNumOut(), 4UL);
234
Jakub Kuderski604a22b2017-07-01 00:23:01 +0000235 // Check levels before
236 EXPECT_EQ(DT->getNode(BB0)->getLevel(), 0U);
237 EXPECT_EQ(DT->getNode(BB1)->getLevel(), 1U);
238 EXPECT_EQ(DT->getNode(BB2)->getLevel(), 1U);
239 EXPECT_EQ(DT->getNode(BB4)->getLevel(), 1U);
240
Adam Nemet147ede92017-05-27 04:05:52 +0000241 // Reattach block 3 to block 1 and recalculate
242 BB1->getTerminator()->eraseFromParent();
243 BranchInst::Create(BB4, BB3, ConstantInt::getTrue(F.getContext()), BB1);
244 DT->recalculate(F);
245
246 // Check DFS Numbers after
Jakub Kuderski837755c2017-06-30 01:28:21 +0000247 DT->updateDFSNumbers();
Adam Nemet147ede92017-05-27 04:05:52 +0000248 EXPECT_EQ(DT->getNode(BB0)->getDFSNumIn(), 0UL);
249 EXPECT_EQ(DT->getNode(BB0)->getDFSNumOut(), 9UL);
250 EXPECT_EQ(DT->getNode(BB1)->getDFSNumIn(), 1UL);
251 EXPECT_EQ(DT->getNode(BB1)->getDFSNumOut(), 4UL);
252 EXPECT_EQ(DT->getNode(BB2)->getDFSNumIn(), 7UL);
253 EXPECT_EQ(DT->getNode(BB2)->getDFSNumOut(), 8UL);
254 EXPECT_EQ(DT->getNode(BB3)->getDFSNumIn(), 2UL);
255 EXPECT_EQ(DT->getNode(BB3)->getDFSNumOut(), 3UL);
256 EXPECT_EQ(DT->getNode(BB4)->getDFSNumIn(), 5UL);
257 EXPECT_EQ(DT->getNode(BB4)->getDFSNumOut(), 6UL);
258
Jakub Kuderski604a22b2017-07-01 00:23:01 +0000259 // Check levels after
260 EXPECT_EQ(DT->getNode(BB0)->getLevel(), 0U);
261 EXPECT_EQ(DT->getNode(BB1)->getLevel(), 1U);
262 EXPECT_EQ(DT->getNode(BB2)->getLevel(), 1U);
263 EXPECT_EQ(DT->getNode(BB3)->getLevel(), 2U);
264 EXPECT_EQ(DT->getNode(BB4)->getLevel(), 1U);
265
Adam Nemet147ede92017-05-27 04:05:52 +0000266 // Change root node
267 DT->verifyDomTree();
268 BasicBlock *NewEntry =
269 BasicBlock::Create(F.getContext(), "new_entry", &F, BB0);
270 BranchInst::Create(BB0, NewEntry);
271 EXPECT_EQ(F.begin()->getName(), NewEntry->getName());
272 EXPECT_TRUE(&F.getEntryBlock() == NewEntry);
273 DT->setNewRoot(NewEntry);
274 DT->verifyDomTree();
275 });
276}
Adam Nemet4ef096b2017-06-05 16:27:09 +0000277
278TEST(DominatorTree, NonUniqueEdges) {
279 StringRef ModuleString =
280 "define i32 @f(i32 %i, i32 *%p) {\n"
281 "bb0:\n"
282 " store i32 %i, i32 *%p\n"
283 " switch i32 %i, label %bb2 [\n"
284 " i32 0, label %bb1\n"
285 " i32 1, label %bb1\n"
286 " ]\n"
287 " bb1:\n"
288 " ret i32 1\n"
289 " bb2:\n"
290 " ret i32 4\n"
291 "}\n";
292
293 // Parse the module.
294 LLVMContext Context;
295 std::unique_ptr<Module> M = makeLLVMModule(Context, ModuleString);
296
297 runWithDomTree(
Jakub Kuderskib292c222017-07-14 18:26:09 +0000298 *M, "f", [&](Function &F, DominatorTree *DT, PostDomTree *PDT) {
Adam Nemet4ef096b2017-06-05 16:27:09 +0000299 Function::iterator FI = F.begin();
300
301 BasicBlock *BB0 = &*FI++;
302 BasicBlock *BB1 = &*FI++;
303 BasicBlock *BB2 = &*FI++;
304
305 const TerminatorInst *TI = BB0->getTerminator();
306 assert(TI->getNumSuccessors() == 3 && "Switch has three successors");
307
308 BasicBlockEdge Edge_BB0_BB2(BB0, TI->getSuccessor(0));
309 assert(Edge_BB0_BB2.getEnd() == BB2 &&
310 "Default label is the 1st successor");
311
312 BasicBlockEdge Edge_BB0_BB1_a(BB0, TI->getSuccessor(1));
313 assert(Edge_BB0_BB1_a.getEnd() == BB1 && "BB1 is the 2nd successor");
314
315 BasicBlockEdge Edge_BB0_BB1_b(BB0, TI->getSuccessor(2));
316 assert(Edge_BB0_BB1_b.getEnd() == BB1 && "BB1 is the 3rd successor");
317
318 EXPECT_TRUE(DT->dominates(Edge_BB0_BB2, BB2));
319 EXPECT_FALSE(DT->dominates(Edge_BB0_BB2, BB1));
320
321 EXPECT_FALSE(DT->dominates(Edge_BB0_BB1_a, BB1));
322 EXPECT_FALSE(DT->dominates(Edge_BB0_BB1_b, BB1));
323
324 EXPECT_FALSE(DT->dominates(Edge_BB0_BB1_a, BB2));
325 EXPECT_FALSE(DT->dominates(Edge_BB0_BB1_b, BB2));
326 });
327}
Jakub Kuderski13e9ef12017-07-14 21:17:33 +0000328
329namespace {
330const auto Insert = CFGBuilder::ActionKind::Insert;
Jakub Kuderskieb59ff22017-07-14 21:58:53 +0000331const auto Delete = CFGBuilder::ActionKind::Delete;
Jakub Kuderski13e9ef12017-07-14 21:17:33 +0000332
333bool CompUpdates(const CFGBuilder::Update &A, const CFGBuilder::Update &B) {
334 return std::tie(A.Action, A.Edge.From, A.Edge.To) <
335 std::tie(B.Action, B.Edge.From, B.Edge.To);
Jakub Kuderski23497b42017-07-14 22:24:15 +0000336}
Jakub Kuderski13e9ef12017-07-14 21:17:33 +0000337} // namespace
338
339TEST(DominatorTree, InsertReachable) {
340 CFGHolder Holder;
341 std::vector<CFGBuilder::Arc> Arcs = {
342 {"1", "2"}, {"2", "3"}, {"3", "4"}, {"4", "5"}, {"5", "6"}, {"5", "7"},
343 {"3", "8"}, {"8", "9"}, {"9", "10"}, {"8", "11"}, {"11", "12"}};
344
345 std::vector<CFGBuilder::Update> Updates = {{Insert, {"12", "10"}},
346 {Insert, {"10", "9"}},
347 {Insert, {"7", "6"}},
348 {Insert, {"7", "5"}}};
349 CFGBuilder B(Holder.F, Arcs, Updates);
350 DominatorTree DT(*Holder.F);
351 EXPECT_TRUE(DT.verify());
352 PostDomTree PDT(*Holder.F);
353 EXPECT_TRUE(PDT.verify());
354
355 Optional<CFGBuilder::Update> LastUpdate;
356 while ((LastUpdate = B.applyUpdate())) {
357 EXPECT_EQ(LastUpdate->Action, Insert);
358 BasicBlock *From = B.getOrAddBlock(LastUpdate->Edge.From);
359 BasicBlock *To = B.getOrAddBlock(LastUpdate->Edge.To);
360 DT.insertEdge(From, To);
361 EXPECT_TRUE(DT.verify());
362 PDT.insertEdge(From, To);
363 EXPECT_TRUE(PDT.verify());
364 }
365}
366
367TEST(DominatorTree, InsertUnreachable) {
368 CFGHolder Holder;
369 std::vector<CFGBuilder::Arc> Arcs = {{"1", "2"}, {"2", "3"}, {"3", "4"},
370 {"5", "6"}, {"5", "7"}, {"3", "8"},
371 {"9", "10"}, {"11", "12"}};
372
373 std::vector<CFGBuilder::Update> Updates = {{Insert, {"4", "5"}},
374 {Insert, {"8", "9"}},
375 {Insert, {"10", "12"}},
376 {Insert, {"10", "11"}}};
377 CFGBuilder B(Holder.F, Arcs, Updates);
378 DominatorTree DT(*Holder.F);
379 EXPECT_TRUE(DT.verify());
380 PostDomTree PDT(*Holder.F);
381 EXPECT_TRUE(PDT.verify());
382
383 Optional<CFGBuilder::Update> LastUpdate;
384 while ((LastUpdate = B.applyUpdate())) {
385 EXPECT_EQ(LastUpdate->Action, Insert);
386 BasicBlock *From = B.getOrAddBlock(LastUpdate->Edge.From);
387 BasicBlock *To = B.getOrAddBlock(LastUpdate->Edge.To);
388 DT.insertEdge(From, To);
389 EXPECT_TRUE(DT.verify());
390 PDT.insertEdge(From, To);
391 EXPECT_TRUE(PDT.verify());
392 }
393}
394
395TEST(DominatorTree, InsertMixed) {
396 CFGHolder Holder;
397 std::vector<CFGBuilder::Arc> Arcs = {
398 {"1", "2"}, {"2", "3"}, {"3", "4"}, {"5", "6"}, {"5", "7"},
399 {"8", "9"}, {"9", "10"}, {"8", "11"}, {"11", "12"}, {"7", "3"}};
400
401 std::vector<CFGBuilder::Update> Updates = {
402 {Insert, {"4", "5"}}, {Insert, {"2", "5"}}, {Insert, {"10", "9"}},
403 {Insert, {"12", "10"}}, {Insert, {"12", "10"}}, {Insert, {"7", "8"}},
404 {Insert, {"7", "5"}}};
405 CFGBuilder B(Holder.F, Arcs, Updates);
406 DominatorTree DT(*Holder.F);
407 EXPECT_TRUE(DT.verify());
408 PostDomTree PDT(*Holder.F);
409 EXPECT_TRUE(PDT.verify());
410
411 Optional<CFGBuilder::Update> LastUpdate;
412 while ((LastUpdate = B.applyUpdate())) {
413 EXPECT_EQ(LastUpdate->Action, Insert);
414 BasicBlock *From = B.getOrAddBlock(LastUpdate->Edge.From);
415 BasicBlock *To = B.getOrAddBlock(LastUpdate->Edge.To);
416 DT.insertEdge(From, To);
417 EXPECT_TRUE(DT.verify());
418 PDT.insertEdge(From, To);
419 EXPECT_TRUE(PDT.verify());
420 }
421}
422
423TEST(DominatorTree, InsertPermut) {
424 std::vector<CFGBuilder::Arc> Arcs = {
425 {"1", "2"}, {"2", "3"}, {"3", "4"}, {"5", "6"}, {"5", "7"},
426 {"8", "9"}, {"9", "10"}, {"8", "11"}, {"11", "12"}, {"7", "3"}};
427
428 std::vector<CFGBuilder::Update> Updates = {{Insert, {"4", "5"}},
429 {Insert, {"2", "5"}},
430 {Insert, {"10", "9"}},
431 {Insert, {"12", "10"}}};
432
433 while (std::next_permutation(Updates.begin(), Updates.end(), CompUpdates)) {
434 CFGHolder Holder;
435 CFGBuilder B(Holder.F, Arcs, Updates);
436 DominatorTree DT(*Holder.F);
437 EXPECT_TRUE(DT.verify());
438 PostDomTree PDT(*Holder.F);
439 EXPECT_TRUE(PDT.verify());
440
441 Optional<CFGBuilder::Update> LastUpdate;
442 while ((LastUpdate = B.applyUpdate())) {
443 EXPECT_EQ(LastUpdate->Action, Insert);
444 BasicBlock *From = B.getOrAddBlock(LastUpdate->Edge.From);
445 BasicBlock *To = B.getOrAddBlock(LastUpdate->Edge.To);
446 DT.insertEdge(From, To);
447 EXPECT_TRUE(DT.verify());
448 PDT.insertEdge(From, To);
449 EXPECT_TRUE(PDT.verify());
450 }
451 }
452}
Jakub Kuderskieb59ff22017-07-14 21:58:53 +0000453
454TEST(DominatorTree, DeleteReachable) {
455 CFGHolder Holder;
456 std::vector<CFGBuilder::Arc> Arcs = {
457 {"1", "2"}, {"2", "3"}, {"2", "4"}, {"3", "4"}, {"4", "5"}, {"5", "6"},
458 {"5", "7"}, {"7", "8"}, {"3", "8"}, {"8", "9"}, {"9", "10"}, {"10", "2"}};
459
460 std::vector<CFGBuilder::Update> Updates = {
461 {Delete, {"2", "4"}}, {Delete, {"7", "8"}}, {Delete, {"10", "2"}}};
462 CFGBuilder B(Holder.F, Arcs, Updates);
463 DominatorTree DT(*Holder.F);
464 EXPECT_TRUE(DT.verify());
465 PostDomTree PDT(*Holder.F);
466 EXPECT_TRUE(PDT.verify());
467
468 Optional<CFGBuilder::Update> LastUpdate;
469 while ((LastUpdate = B.applyUpdate())) {
470 EXPECT_EQ(LastUpdate->Action, Delete);
471 BasicBlock *From = B.getOrAddBlock(LastUpdate->Edge.From);
472 BasicBlock *To = B.getOrAddBlock(LastUpdate->Edge.To);
473 DT.deleteEdge(From, To);
474 EXPECT_TRUE(DT.verify());
475 PDT.deleteEdge(From, To);
476 EXPECT_TRUE(PDT.verify());
477 }
478}
479
480TEST(DominatorTree, DeleteUnreachable) {
481 CFGHolder Holder;
482 std::vector<CFGBuilder::Arc> Arcs = {
483 {"1", "2"}, {"2", "3"}, {"3", "4"}, {"4", "5"}, {"5", "6"}, {"5", "7"},
484 {"7", "8"}, {"3", "8"}, {"8", "9"}, {"9", "10"}, {"10", "2"}};
485
486 std::vector<CFGBuilder::Update> Updates = {
487 {Delete, {"8", "9"}}, {Delete, {"7", "8"}}, {Delete, {"3", "4"}}};
488 CFGBuilder B(Holder.F, Arcs, Updates);
489 DominatorTree DT(*Holder.F);
490 EXPECT_TRUE(DT.verify());
491 PostDomTree PDT(*Holder.F);
492 EXPECT_TRUE(PDT.verify());
493
494 Optional<CFGBuilder::Update> LastUpdate;
495 while ((LastUpdate = B.applyUpdate())) {
496 EXPECT_EQ(LastUpdate->Action, Delete);
497 BasicBlock *From = B.getOrAddBlock(LastUpdate->Edge.From);
498 BasicBlock *To = B.getOrAddBlock(LastUpdate->Edge.To);
499 DT.deleteEdge(From, To);
500 EXPECT_TRUE(DT.verify());
501 PDT.deleteEdge(From, To);
502 EXPECT_TRUE(PDT.verify());
503 }
504}
505
506TEST(DominatorTree, InsertDelete) {
507 std::vector<CFGBuilder::Arc> Arcs = {
508 {"1", "2"}, {"2", "3"}, {"3", "4"}, {"4", "5"}, {"5", "6"}, {"5", "7"},
509 {"3", "8"}, {"8", "9"}, {"9", "10"}, {"8", "11"}, {"11", "12"}};
510
511 std::vector<CFGBuilder::Update> Updates = {
512 {Insert, {"2", "4"}}, {Insert, {"12", "10"}}, {Insert, {"10", "9"}},
513 {Insert, {"7", "6"}}, {Insert, {"7", "5"}}, {Delete, {"3", "8"}},
514 {Insert, {"10", "7"}}, {Insert, {"2", "8"}}, {Delete, {"3", "4"}},
515 {Delete, {"8", "9"}}, {Delete, {"11", "12"}}};
516
517 CFGHolder Holder;
518 CFGBuilder B(Holder.F, Arcs, Updates);
519 DominatorTree DT(*Holder.F);
520 EXPECT_TRUE(DT.verify());
521 PostDomTree PDT(*Holder.F);
522 EXPECT_TRUE(PDT.verify());
523
524 Optional<CFGBuilder::Update> LastUpdate;
525 while ((LastUpdate = B.applyUpdate())) {
526 BasicBlock *From = B.getOrAddBlock(LastUpdate->Edge.From);
527 BasicBlock *To = B.getOrAddBlock(LastUpdate->Edge.To);
528 if (LastUpdate->Action == Insert) {
529 DT.insertEdge(From, To);
530 PDT.insertEdge(From, To);
531 } else {
532 DT.deleteEdge(From, To);
533 PDT.deleteEdge(From, To);
534 }
535
536 EXPECT_TRUE(DT.verify());
537 EXPECT_TRUE(PDT.verify());
538 }
539}
540
541TEST(DominatorTree, InsertDeleteExhaustive) {
542 std::vector<CFGBuilder::Arc> Arcs = {
543 {"1", "2"}, {"2", "3"}, {"3", "4"}, {"4", "5"}, {"5", "6"}, {"5", "7"},
544 {"3", "8"}, {"8", "9"}, {"9", "10"}, {"8", "11"}, {"11", "12"}};
545
546 std::vector<CFGBuilder::Update> Updates = {
547 {Insert, {"2", "4"}}, {Insert, {"12", "10"}}, {Insert, {"10", "9"}},
548 {Insert, {"7", "6"}}, {Insert, {"7", "5"}}, {Delete, {"3", "8"}},
549 {Insert, {"10", "7"}}, {Insert, {"2", "8"}}, {Delete, {"3", "4"}},
550 {Delete, {"8", "9"}}, {Delete, {"11", "12"}}};
551
552 std::mt19937 Generator(0);
553 for (unsigned i = 0; i < 16; ++i) {
554 std::shuffle(Updates.begin(), Updates.end(), Generator);
555 CFGHolder Holder;
556 CFGBuilder B(Holder.F, Arcs, Updates);
557 DominatorTree DT(*Holder.F);
558 EXPECT_TRUE(DT.verify());
559 PostDomTree PDT(*Holder.F);
560 EXPECT_TRUE(PDT.verify());
561
562 Optional<CFGBuilder::Update> LastUpdate;
563 while ((LastUpdate = B.applyUpdate())) {
564 BasicBlock *From = B.getOrAddBlock(LastUpdate->Edge.From);
565 BasicBlock *To = B.getOrAddBlock(LastUpdate->Edge.To);
566 if (LastUpdate->Action == Insert) {
567 DT.insertEdge(From, To);
568 PDT.insertEdge(From, To);
569 } else {
570 DT.deleteEdge(From, To);
571 PDT.deleteEdge(From, To);
572 }
573
574 EXPECT_TRUE(DT.verify());
575 EXPECT_TRUE(PDT.verify());
576 }
577 }
578}