blob: 85308685e5dd10033480ebbb44ab3182c56195f3 [file] [log] [blame]
Jakub Kuderski624463a2017-08-16 16:12:52 +00001//===- llvm/unittests/IR/DominatorTreeBatchUpdatesTest.cpp ----------------===//
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 <random>
11#include "CFGBuilder.h"
12#include "gtest/gtest.h"
13#include "llvm/Analysis/PostDominators.h"
14#include "llvm/IR/Dominators.h"
15#include "llvm/Support/GenericDomTreeConstruction.h"
16
17#define DEBUG_TYPE "batch-update-tests"
18
19using namespace llvm;
20
21namespace {
22const auto CFGInsert = CFGBuilder::ActionKind::Insert;
23const auto CFGDelete = CFGBuilder::ActionKind::Delete;
24
Jakub Kuderski624463a2017-08-16 16:12:52 +000025
26using DomUpdate = DominatorTree::UpdateType;
27static_assert(
Jakub Kuderskief33edd2018-05-23 17:29:21 +000028 std::is_same<DomUpdate, PostDominatorTree::UpdateType>::value,
Jakub Kuderski624463a2017-08-16 16:12:52 +000029 "Trees differing only in IsPostDom should have the same update types");
30using DomSNCA = DomTreeBuilder::SemiNCAInfo<DomTreeBuilder::BBDomTree>;
31using PostDomSNCA = DomTreeBuilder::SemiNCAInfo<DomTreeBuilder::BBPostDomTree>;
32const auto Insert = DominatorTree::Insert;
33const auto Delete = DominatorTree::Delete;
34
35std::vector<DomUpdate> ToDomUpdates(CFGBuilder &B,
36 std::vector<CFGBuilder::Update> &In) {
37 std::vector<DomUpdate> Res;
38 Res.reserve(In.size());
39
40 for (const auto &CFGU : In)
41 Res.push_back({CFGU.Action == CFGInsert ? Insert : Delete,
42 B.getOrAddBlock(CFGU.Edge.From),
43 B.getOrAddBlock(CFGU.Edge.To)});
44 return Res;
45}
46} // namespace
47
48TEST(DominatorTreeBatchUpdates, LegalizeDomUpdates) {
49 CFGHolder Holder;
50 CFGBuilder Builder(Holder.F, {{"A", "B"}}, {});
51
52 BasicBlock *A = Builder.getOrAddBlock("A");
53 BasicBlock *B = Builder.getOrAddBlock("B");
54 BasicBlock *C = Builder.getOrAddBlock("C");
55 BasicBlock *D = Builder.getOrAddBlock("D");
56
57 std::vector<DomUpdate> Updates = {
58 {Insert, B, C}, {Insert, C, D}, {Delete, B, C}, {Insert, B, C},
59 {Insert, B, D}, {Delete, C, D}, {Delete, A, B}};
60 SmallVector<DomUpdate, 4> Legalized;
61 DomSNCA::LegalizeUpdates(Updates, Legalized);
Nicola Zaghend34e60c2018-05-14 12:53:11 +000062 LLVM_DEBUG(dbgs() << "Legalized updates:\t");
63 LLVM_DEBUG(for (auto &U : Legalized) dbgs() << U << ", ");
64 LLVM_DEBUG(dbgs() << "\n");
Jakub Kuderski624463a2017-08-16 16:12:52 +000065 EXPECT_EQ(Legalized.size(), 3UL);
66 EXPECT_NE(llvm::find(Legalized, DomUpdate{Insert, B, C}), Legalized.end());
67 EXPECT_NE(llvm::find(Legalized, DomUpdate{Insert, B, D}), Legalized.end());
68 EXPECT_NE(llvm::find(Legalized, DomUpdate{Delete, A, B}), Legalized.end());
69}
70
71TEST(DominatorTreeBatchUpdates, LegalizePostDomUpdates) {
72 CFGHolder Holder;
73 CFGBuilder Builder(Holder.F, {{"A", "B"}}, {});
74
75 BasicBlock *A = Builder.getOrAddBlock("A");
76 BasicBlock *B = Builder.getOrAddBlock("B");
77 BasicBlock *C = Builder.getOrAddBlock("C");
78 BasicBlock *D = Builder.getOrAddBlock("D");
79
80 std::vector<DomUpdate> Updates = {
81 {Insert, B, C}, {Insert, C, D}, {Delete, B, C}, {Insert, B, C},
82 {Insert, B, D}, {Delete, C, D}, {Delete, A, B}};
83 SmallVector<DomUpdate, 4> Legalized;
84 PostDomSNCA::LegalizeUpdates(Updates, Legalized);
Nicola Zaghend34e60c2018-05-14 12:53:11 +000085 LLVM_DEBUG(dbgs() << "Legalized postdom updates:\t");
86 LLVM_DEBUG(for (auto &U : Legalized) dbgs() << U << ", ");
87 LLVM_DEBUG(dbgs() << "\n");
Jakub Kuderski624463a2017-08-16 16:12:52 +000088 EXPECT_EQ(Legalized.size(), 3UL);
89 EXPECT_NE(llvm::find(Legalized, DomUpdate{Insert, C, B}), Legalized.end());
90 EXPECT_NE(llvm::find(Legalized, DomUpdate{Insert, D, B}), Legalized.end());
91 EXPECT_NE(llvm::find(Legalized, DomUpdate{Delete, B, A}), Legalized.end());
92}
93
94TEST(DominatorTreeBatchUpdates, SingleInsertion) {
95 CFGHolder Holder;
96 CFGBuilder Builder(Holder.F, {{"A", "B"}}, {{CFGInsert, {"B", "C"}}});
97
98 DominatorTree DT(*Holder.F);
99 EXPECT_TRUE(DT.verify());
Jakub Kuderskief33edd2018-05-23 17:29:21 +0000100 PostDominatorTree PDT(*Holder.F);
Jakub Kuderski0cbc1b02018-05-11 09:30:29 +0000101 EXPECT_TRUE(PDT.verify());
Jakub Kuderski624463a2017-08-16 16:12:52 +0000102
103 BasicBlock *B = Builder.getOrAddBlock("B");
104 BasicBlock *C = Builder.getOrAddBlock("C");
105 std::vector<DomUpdate> Updates = {{Insert, B, C}};
106
107 ASSERT_TRUE(Builder.applyUpdate());
108
109 DT.applyUpdates(Updates);
110 EXPECT_TRUE(DT.verify());
111 PDT.applyUpdates(Updates);
112 EXPECT_TRUE(PDT.verify());
113}
114
115TEST(DominatorTreeBatchUpdates, SingleDeletion) {
116 CFGHolder Holder;
117 CFGBuilder Builder(Holder.F, {{"A", "B"}, {"B", "C"}},
118 {{CFGDelete, {"B", "C"}}});
119
120 DominatorTree DT(*Holder.F);
121 EXPECT_TRUE(DT.verify());
Jakub Kuderskief33edd2018-05-23 17:29:21 +0000122 PostDominatorTree PDT(*Holder.F);
Jakub Kuderski0cbc1b02018-05-11 09:30:29 +0000123 EXPECT_TRUE(PDT.verify());
Jakub Kuderski624463a2017-08-16 16:12:52 +0000124
125 BasicBlock *B = Builder.getOrAddBlock("B");
126 BasicBlock *C = Builder.getOrAddBlock("C");
127 std::vector<DomUpdate> Updates = {{Delete, B, C}};
128
129 ASSERT_TRUE(Builder.applyUpdate());
130
131 DT.applyUpdates(Updates);
132 EXPECT_TRUE(DT.verify());
133 PDT.applyUpdates(Updates);
134 EXPECT_TRUE(PDT.verify());
135}
136
137TEST(DominatorTreeBatchUpdates, FewInsertion) {
138 std::vector<CFGBuilder::Update> CFGUpdates = {{CFGInsert, {"B", "C"}},
139 {CFGInsert, {"C", "B"}},
140 {CFGInsert, {"C", "D"}},
141 {CFGInsert, {"D", "E"}}};
142
143 CFGHolder Holder;
144 CFGBuilder Builder(Holder.F, {{"A", "B"}}, CFGUpdates);
145
146 DominatorTree DT(*Holder.F);
147 EXPECT_TRUE(DT.verify());
Jakub Kuderskief33edd2018-05-23 17:29:21 +0000148 PostDominatorTree PDT(*Holder.F);
Jakub Kuderski624463a2017-08-16 16:12:52 +0000149 EXPECT_TRUE(PDT.verify());
150
151 BasicBlock *B = Builder.getOrAddBlock("B");
152 BasicBlock *C = Builder.getOrAddBlock("C");
153 BasicBlock *D = Builder.getOrAddBlock("D");
154 BasicBlock *E = Builder.getOrAddBlock("E");
155
156 std::vector<DomUpdate> Updates = {
157 {Insert, B, C}, {Insert, C, B}, {Insert, C, D}, {Insert, D, E}};
158
159 while (Builder.applyUpdate())
160 ;
161
162 DT.applyUpdates(Updates);
163 EXPECT_TRUE(DT.verify());
164 PDT.applyUpdates(Updates);
165 EXPECT_TRUE(PDT.verify());
166}
167
168TEST(DominatorTreeBatchUpdates, FewDeletions) {
169 std::vector<CFGBuilder::Update> CFGUpdates = {{CFGDelete, {"B", "C"}},
170 {CFGDelete, {"C", "B"}},
171 {CFGDelete, {"B", "D"}},
172 {CFGDelete, {"D", "E"}}};
173
174 CFGHolder Holder;
175 CFGBuilder Builder(
176 Holder.F, {{"A", "B"}, {"B", "C"}, {"B", "D"}, {"D", "E"}, {"C", "B"}},
177 CFGUpdates);
178
179 DominatorTree DT(*Holder.F);
180 EXPECT_TRUE(DT.verify());
Jakub Kuderskief33edd2018-05-23 17:29:21 +0000181 PostDominatorTree PDT(*Holder.F);
Jakub Kuderski624463a2017-08-16 16:12:52 +0000182 EXPECT_TRUE(PDT.verify());
183
184 auto Updates = ToDomUpdates(Builder, CFGUpdates);
185
186 while (Builder.applyUpdate())
187 ;
188
189 DT.applyUpdates(Updates);
190 EXPECT_TRUE(DT.verify());
191 PDT.applyUpdates(Updates);
192 EXPECT_TRUE(PDT.verify());
193}
194
195TEST(DominatorTreeBatchUpdates, InsertDelete) {
196 std::vector<CFGBuilder::Arc> Arcs = {
197 {"1", "2"}, {"2", "3"}, {"3", "4"}, {"4", "5"}, {"5", "6"}, {"5", "7"},
198 {"3", "8"}, {"8", "9"}, {"9", "10"}, {"8", "11"}, {"11", "12"}};
199
200 std::vector<CFGBuilder::Update> Updates = {
201 {CFGInsert, {"2", "4"}}, {CFGInsert, {"12", "10"}},
202 {CFGInsert, {"10", "9"}}, {CFGInsert, {"7", "6"}},
203 {CFGInsert, {"7", "5"}}, {CFGDelete, {"3", "8"}},
204 {CFGInsert, {"10", "7"}}, {CFGInsert, {"2", "8"}},
205 {CFGDelete, {"3", "4"}}, {CFGDelete, {"8", "9"}},
206 {CFGDelete, {"11", "12"}}};
207
208 CFGHolder Holder;
209 CFGBuilder B(Holder.F, Arcs, Updates);
210 DominatorTree DT(*Holder.F);
211 EXPECT_TRUE(DT.verify());
Jakub Kuderskief33edd2018-05-23 17:29:21 +0000212 PostDominatorTree PDT(*Holder.F);
Jakub Kuderski624463a2017-08-16 16:12:52 +0000213 EXPECT_TRUE(PDT.verify());
214
215 while (B.applyUpdate())
216 ;
217
218 auto DomUpdates = ToDomUpdates(B, Updates);
219 DT.applyUpdates(DomUpdates);
220 EXPECT_TRUE(DT.verify());
221 PDT.applyUpdates(DomUpdates);
222 EXPECT_TRUE(PDT.verify());
223}
224
225TEST(DominatorTreeBatchUpdates, InsertDeleteExhaustive) {
226 std::vector<CFGBuilder::Arc> Arcs = {
227 {"1", "2"}, {"2", "3"}, {"3", "4"}, {"4", "5"}, {"5", "6"}, {"5", "7"},
228 {"3", "8"}, {"8", "9"}, {"9", "10"}, {"8", "11"}, {"11", "12"}};
229
230 std::vector<CFGBuilder::Update> Updates = {
231 {CFGInsert, {"2", "4"}}, {CFGInsert, {"12", "10"}},
232 {CFGInsert, {"10", "9"}}, {CFGInsert, {"7", "6"}},
233 {CFGInsert, {"7", "5"}}, {CFGDelete, {"3", "8"}},
234 {CFGInsert, {"10", "7"}}, {CFGInsert, {"2", "8"}},
235 {CFGDelete, {"3", "4"}}, {CFGDelete, {"8", "9"}},
236 {CFGDelete, {"11", "12"}}};
237
238 std::mt19937 Generator(0);
239 for (unsigned i = 0; i < 16; ++i) {
240 std::shuffle(Updates.begin(), Updates.end(), Generator);
241 CFGHolder Holder;
242 CFGBuilder B(Holder.F, Arcs, Updates);
243 DominatorTree DT(*Holder.F);
244 EXPECT_TRUE(DT.verify());
Jakub Kuderskief33edd2018-05-23 17:29:21 +0000245 PostDominatorTree PDT(*Holder.F);
Jakub Kuderski624463a2017-08-16 16:12:52 +0000246 EXPECT_TRUE(PDT.verify());
247
248 while (B.applyUpdate())
249 ;
250
251 auto DomUpdates = ToDomUpdates(B, Updates);
252 DT.applyUpdates(DomUpdates);
253 EXPECT_TRUE(DT.verify());
254 PDT.applyUpdates(DomUpdates);
255 EXPECT_TRUE(PDT.verify());
256 }
257}
David Green990eb1f2018-01-20 10:29:37 +0000258
259// These are some odd flowgraphs, usually generated from csmith cases,
260// which are difficult on post dom trees.
261TEST(DominatorTreeBatchUpdates, InfiniteLoop) {
262 std::vector<CFGBuilder::Arc> Arcs = {
263 {"1", "2"},
264 {"2", "3"},
265 {"3", "6"}, {"3", "5"},
266 {"4", "5"},
267 {"5", "2"},
268 {"6", "3"}, {"6", "4"}};
269
270 // SplitBlock on 3 -> 5
271 std::vector<CFGBuilder::Update> Updates = {
272 {CFGInsert, {"N", "5"}}, {CFGInsert, {"3", "N"}}, {CFGDelete, {"3", "5"}}};
273
274 CFGHolder Holder;
275 CFGBuilder B(Holder.F, Arcs, Updates);
276 DominatorTree DT(*Holder.F);
277 EXPECT_TRUE(DT.verify());
Jakub Kuderskief33edd2018-05-23 17:29:21 +0000278 PostDominatorTree PDT(*Holder.F);
David Green990eb1f2018-01-20 10:29:37 +0000279 EXPECT_TRUE(PDT.verify());
280
281 while (B.applyUpdate())
282 ;
283
284 auto DomUpdates = ToDomUpdates(B, Updates);
285 DT.applyUpdates(DomUpdates);
286 EXPECT_TRUE(DT.verify());
287 PDT.applyUpdates(DomUpdates);
288 EXPECT_TRUE(PDT.verify());
289}
290
291TEST(DominatorTreeBatchUpdates, DeadBlocks) {
292 std::vector<CFGBuilder::Arc> Arcs = {
293 {"1", "2"},
294 {"2", "3"},
295 {"3", "4"}, {"3", "7"},
296 {"4", "4"},
297 {"5", "6"}, {"5", "7"},
298 {"6", "7"},
299 {"7", "2"}, {"7", "8"}};
300
301 // Remove dead 5 and 7,
302 // plus SplitBlock on 7 -> 8
303 std::vector<CFGBuilder::Update> Updates = {
304 {CFGDelete, {"6", "7"}}, {CFGDelete, {"5", "7"}}, {CFGDelete, {"5", "6"}},
305 {CFGInsert, {"N", "8"}}, {CFGInsert, {"7", "N"}}, {CFGDelete, {"7", "8"}}};
306
307 CFGHolder Holder;
308 CFGBuilder B(Holder.F, Arcs, Updates);
309 DominatorTree DT(*Holder.F);
310 EXPECT_TRUE(DT.verify());
Jakub Kuderskief33edd2018-05-23 17:29:21 +0000311 PostDominatorTree PDT(*Holder.F);
David Green990eb1f2018-01-20 10:29:37 +0000312 EXPECT_TRUE(PDT.verify());
313
314 while (B.applyUpdate())
315 ;
316
317 auto DomUpdates = ToDomUpdates(B, Updates);
318 DT.applyUpdates(DomUpdates);
319 EXPECT_TRUE(DT.verify());
320 PDT.applyUpdates(DomUpdates);
321 EXPECT_TRUE(PDT.verify());
322}
323
324TEST(DominatorTreeBatchUpdates, InfiniteLoop2) {
325 std::vector<CFGBuilder::Arc> Arcs = {
326 {"1", "2"},
327 {"2", "6"}, {"2", "3"},
328 {"3", "4"},
329 {"4", "5"}, {"4", "6"},
330 {"5", "4"},
331 {"6", "2"}};
332
333 // SplitBlock on 4 -> 6
334 std::vector<CFGBuilder::Update> Updates = {
335 {CFGInsert, {"N", "6"}}, {CFGInsert, {"4", "N"}}, {CFGDelete, {"4", "6"}}};
336
337 CFGHolder Holder;
338 CFGBuilder B(Holder.F, Arcs, Updates);
339 DominatorTree DT(*Holder.F);
340 EXPECT_TRUE(DT.verify());
Jakub Kuderskief33edd2018-05-23 17:29:21 +0000341 PostDominatorTree PDT(*Holder.F);
David Green990eb1f2018-01-20 10:29:37 +0000342 EXPECT_TRUE(PDT.verify());
343
344 while (B.applyUpdate())
345 ;
346
347 auto DomUpdates = ToDomUpdates(B, Updates);
348 DT.applyUpdates(DomUpdates);
349 EXPECT_TRUE(DT.verify());
350 PDT.applyUpdates(DomUpdates);
351 EXPECT_TRUE(PDT.verify());
352}