Jlm
Loading...
Searching...
No Matches
AggregationTests.cpp
Go to the documentation of this file.
1/*
2 * Copyright 2017 Nico Reißmann <nico.reissmann@gmail.com>
3 * See COPYING for terms of redistribution.
4 */
5
6#include <gtest/gtest.h>
7
10#include <jlm/llvm/ir/print.hpp>
11
12static bool
14{
15 return jlm::llvm::is<jlm::llvm::EntryAggregationNode>(node) && node->nchildren() == 0;
16}
17
18static bool
20{
21 return jlm::llvm::is<jlm::llvm::ExitAggregationNode>(node) && node->nchildren() == 0;
22}
23
24static bool
26{
27 return jlm::llvm::is<jlm::llvm::BasicBlockAggregationNode>(node) && node->nchildren() == 0;
28}
29
30static bool
31is_linear(const jlm::llvm::AggregationNode * node, size_t nchildren)
32{
33 if (!jlm::llvm::is<jlm::llvm::LinearAggregationNode>(node))
34 return false;
35
36 if (node->nchildren() != nchildren)
37 return false;
38
39 for (auto & child : *node)
40 {
41 if (child.parent() != node)
42 return false;
43 }
44
45 return true;
46}
47
48static bool
50{
51 return jlm::llvm::is<jlm::llvm::LoopAggregationNode>(node) && node->nchildren() == 1
52 && node->child(0)->parent() == node;
53}
54
55static bool
56is_branch(const jlm::llvm::AggregationNode * node, size_t nchildren)
57{
58 if (!jlm::llvm::is<jlm::llvm::BranchAggregationNode>(node))
59 return false;
60
61 if (node->nchildren() != nchildren)
62 return false;
63
64 for (auto & child : *node)
65 {
66 if (child.parent() != node)
67 return false;
68 }
69
70 return true;
71}
72
73TEST(ViewTests, test_linear_reduction)
74{
75 using namespace jlm::llvm;
76
77 auto setup_cfg = [](jlm::llvm::InterProceduralGraphModule & module)
78 {
79 auto cfg = ControlFlowGraph::create(module);
80
81 auto bb = jlm::llvm::BasicBlock::create(*cfg);
82 cfg->exit()->divert_inedges(bb);
83 bb->add_outedge(cfg->exit());
84
85 return cfg;
86 };
87
88 auto verify_aggtree = [](const jlm::llvm::AggregationNode & root)
89 {
90 EXPECT_TRUE(is_linear(&root, 3));
91 {
92 EXPECT_TRUE(is_entry(root.child(0)));
93 EXPECT_TRUE(is_block(root.child(1)));
94 EXPECT_TRUE(is_exit(root.child(2)));
95 }
96 };
97
99 auto cfg = setup_cfg(module);
100
101 auto root = jlm::llvm::aggregate(*cfg);
103 jlm::llvm::print(*root, stdout);
104
105 verify_aggtree(*root);
106}
107
108TEST(ViewTests, test_loop_reduction)
109{
110 using namespace jlm::llvm;
111
112 auto setup_cfg = [](jlm::llvm::InterProceduralGraphModule & module)
113 {
114 auto cfg = ControlFlowGraph::create(module);
115
116 auto bb1 = jlm::llvm::BasicBlock::create(*cfg);
117 auto bb2 = jlm::llvm::BasicBlock::create(*cfg);
118
119 cfg->exit()->divert_inedges(bb1);
120 bb1->add_outedge(bb2);
121 bb2->add_outedge(cfg->exit());
122 bb2->add_outedge(bb1);
123
124 return cfg;
125 };
126
127 auto verify_aggtree = [](const jlm::llvm::AggregationNode & root)
128 {
129 EXPECT_TRUE(is_linear(&root, 3));
130 {
131 EXPECT_TRUE(is_entry(root.child(0)));
132
133 auto loop = root.child(1);
134 EXPECT_TRUE(is_loop(loop));
135 {
136 auto linear = loop->child(0);
137 EXPECT_TRUE(is_linear(linear, 2));
138 {
139 EXPECT_TRUE(is_block(linear->child(0)));
140 EXPECT_TRUE(is_block(linear->child(1)));
141 }
142 }
143
144 EXPECT_TRUE(is_exit(root.child(2)));
145 }
146 };
147
149 auto cfg = setup_cfg(module);
150
151 auto root = jlm::llvm::aggregate(*cfg);
153 jlm::llvm::print(*root, stdout);
154
155 verify_aggtree(*root);
156}
157
158TEST(ViewTests, test_branch_reduction)
159{
160 using namespace jlm::llvm;
161
162 auto setup_cfg = [](jlm::llvm::InterProceduralGraphModule & module)
163 {
164 auto cfg = ControlFlowGraph::create(module);
165
166 auto split = jlm::llvm::BasicBlock::create(*cfg);
167 auto bb1 = jlm::llvm::BasicBlock::create(*cfg);
168 auto bb2 = jlm::llvm::BasicBlock::create(*cfg);
169 auto bb3 = jlm::llvm::BasicBlock::create(*cfg);
170 auto bb4 = jlm::llvm::BasicBlock::create(*cfg);
171 auto join = jlm::llvm::BasicBlock::create(*cfg);
172
173 cfg->exit()->divert_inedges(split);
174 split->add_outedge(bb1);
175 split->add_outedge(bb3);
176 bb1->add_outedge(bb2);
177 bb2->add_outedge(join);
178 bb3->add_outedge(bb4);
179 bb4->add_outedge(join);
180 join->add_outedge(cfg->exit());
181
182 return cfg;
183 };
184
185 auto verify_aggtree = [](const jlm::llvm::AggregationNode & root)
186 {
187 EXPECT_TRUE(is_linear(&root, 5));
188 {
189 EXPECT_TRUE(is_entry(root.child(0)));
190 EXPECT_TRUE(is_block(root.child(1)));
191
192 auto branch = root.child(2);
193 EXPECT_TRUE(is_branch(branch, 2));
194 {
195 auto linear = branch->child(0);
196 EXPECT_TRUE(is_linear(linear, 2));
197 {
198 EXPECT_TRUE(is_block(linear->child(0)));
199 EXPECT_TRUE(is_block(linear->child(1)));
200 }
201
202 linear = branch->child(1);
203 EXPECT_TRUE(is_linear(linear, 2));
204 {
205 EXPECT_TRUE(is_block(linear->child(0)));
206 EXPECT_TRUE(is_block(linear->child(1)));
207 }
208 }
209
210 EXPECT_TRUE(is_block(root.child(3)));
211 EXPECT_TRUE(is_exit(root.child(4)));
212 }
213 };
214
216 auto cfg = setup_cfg(module);
217
218 auto root = jlm::llvm::aggregate(*cfg);
220 jlm::llvm::print(*root, stdout);
221
222 verify_aggtree(*root);
223}
224
225TEST(ViewTests, test_branch_loop_reduction)
226{
227 using namespace jlm::llvm;
228
229 auto setup_cfg = [](jlm::llvm::InterProceduralGraphModule & module)
230 {
231 auto cfg = ControlFlowGraph::create(module);
232 auto split = jlm::llvm::BasicBlock::create(*cfg);
233 auto bb1 = jlm::llvm::BasicBlock::create(*cfg);
234 auto bb2 = jlm::llvm::BasicBlock::create(*cfg);
235 auto bb3 = jlm::llvm::BasicBlock::create(*cfg);
236 auto bb4 = jlm::llvm::BasicBlock::create(*cfg);
237 auto join = jlm::llvm::BasicBlock::create(*cfg);
238
239 cfg->exit()->divert_inedges(split);
240 split->add_outedge(bb1);
241 split->add_outedge(bb3);
242 bb1->add_outedge(bb2);
243 bb2->add_outedge(join);
244 bb2->add_outedge(bb1);
245 bb3->add_outedge(bb4);
246 bb4->add_outedge(join);
247 bb4->add_outedge(bb3);
248 join->add_outedge(cfg->exit());
249
250 return cfg;
251 };
252
253 auto verify_aggtree = [](const jlm::llvm::AggregationNode & root)
254 {
255 EXPECT_TRUE(is_linear(&root, 5));
256 {
257 EXPECT_TRUE(is_entry(root.child(0)));
258 EXPECT_TRUE(is_block(root.child(1)));
259
260 auto branch = root.child(2);
261 EXPECT_TRUE(is_branch(branch, 2));
262 {
263 auto loop = branch->child(0);
264 EXPECT_TRUE(is_loop(loop));
265 {
266 auto linear = loop->child(0);
267 EXPECT_TRUE(is_linear(linear, 2));
268 {
269 EXPECT_TRUE(is_block(linear->child(0)));
270 EXPECT_TRUE(is_block(linear->child(1)));
271 }
272 }
273
274 loop = branch->child(1);
275 EXPECT_TRUE(is_loop(loop));
276 {
277 auto linear = loop->child(0);
278 EXPECT_TRUE(is_linear(linear, 2));
279 {
280 EXPECT_TRUE(is_block(linear->child(0)));
281 EXPECT_TRUE(is_block(linear->child(1)));
282 }
283 }
284 }
285
286 EXPECT_TRUE(is_block(root.child(3)));
287 EXPECT_TRUE(is_exit(root.child(4)));
288 }
289 };
290
292 auto cfg = setup_cfg(module);
293
294 auto root = jlm::llvm::aggregate(*cfg);
296 jlm::llvm::print(*root, stdout);
297
298 verify_aggtree(*root);
299}
300
301TEST(ViewTests, test_loop_branch_reduction)
302{
303 using namespace jlm::llvm;
304
305 auto setup_cfg = [](jlm::llvm::InterProceduralGraphModule & module)
306 {
307 auto cfg = ControlFlowGraph::create(module);
308
309 auto split = jlm::llvm::BasicBlock::create(*cfg);
310 auto bb1 = jlm::llvm::BasicBlock::create(*cfg);
311 auto bb2 = jlm::llvm::BasicBlock::create(*cfg);
312 auto join = jlm::llvm::BasicBlock::create(*cfg);
313 auto bb3 = jlm::llvm::BasicBlock::create(*cfg);
314
315 cfg->exit()->divert_inedges(split);
316 split->add_outedge(bb1);
317 split->add_outedge(bb2);
318 bb1->add_outedge(join);
319 bb2->add_outedge(join);
320 join->add_outedge(bb3);
321 bb3->add_outedge(cfg->exit());
322 bb3->add_outedge(split);
323
324 return cfg;
325 };
326
327 auto verify_aggtree = [](const jlm::llvm::AggregationNode & root)
328 {
329 EXPECT_TRUE(is_linear(&root, 3));
330 {
331 EXPECT_TRUE(is_entry(root.child(0)));
332
333 auto loop = root.child(1);
334 EXPECT_TRUE(is_loop(loop));
335 {
336 auto linear = loop->child(0);
337 EXPECT_TRUE(is_linear(linear, 4));
338 {
339 EXPECT_TRUE(is_block(linear->child(0)));
340
341 auto branch = linear->child(1);
342 EXPECT_TRUE(is_branch(branch, 2));
343 {
344 EXPECT_TRUE(is_block(branch->child(0)));
345 EXPECT_TRUE(is_block(branch->child(1)));
346 }
347
348 EXPECT_TRUE(is_block(linear->child(2)));
349 EXPECT_TRUE(is_block(linear->child(3)));
350 }
351 }
352
353 EXPECT_TRUE(is_exit(root.child(2)));
354 }
355 };
356
358 auto cfg = setup_cfg(module);
359
360 auto root = jlm::llvm::aggregate(*cfg);
362 jlm::llvm::print(*root, stdout);
363
364 verify_aggtree(*root);
365}
366
367TEST(ViewTests, test_ifthen_reduction)
368{
369 using namespace jlm::llvm;
370
371 auto setup_cfg = [](jlm::llvm::InterProceduralGraphModule & module)
372 {
373 auto cfg = ControlFlowGraph::create(module);
374
375 auto split = jlm::llvm::BasicBlock::create(*cfg);
376 auto bb1 = jlm::llvm::BasicBlock::create(*cfg);
377 auto bb2 = jlm::llvm::BasicBlock::create(*cfg);
378 auto bb3 = jlm::llvm::BasicBlock::create(*cfg);
379 auto join = jlm::llvm::BasicBlock::create(*cfg);
380
381 cfg->exit()->divert_inedges(split);
382 split->add_outedge(bb3);
383 split->add_outedge(bb1);
384 bb1->add_outedge(bb2);
385 bb2->add_outedge(join);
386 bb3->add_outedge(join);
387 join->add_outedge(cfg->exit());
388
389 return cfg;
390 };
391
392 auto verify_aggtree = [](const jlm::llvm::AggregationNode & root)
393 {
394 EXPECT_TRUE(is_linear(&root, 5));
395 {
396 EXPECT_TRUE(is_entry(root.child(0)));
397 EXPECT_TRUE(is_block(root.child(1)));
398
399 auto branch = root.child(2);
400 EXPECT_TRUE(is_branch(branch, 2));
401 {
402 EXPECT_TRUE(is_block(branch->child(0)));
403
404 auto linear = branch->child(1);
405 EXPECT_TRUE(is_linear(linear, 2));
406 {
407 EXPECT_TRUE(is_block(linear->child(0)));
408 EXPECT_TRUE(is_block(linear->child(1)));
409 }
410 }
411
412 EXPECT_TRUE(is_block(root.child(3)));
413 EXPECT_TRUE(is_exit(root.child(4)));
414 }
415 };
416
418 auto cfg = setup_cfg(module);
419
420 auto root = jlm::llvm::aggregate(*cfg);
422 jlm::llvm::print(*root, stdout);
423
424 verify_aggtree(*root);
425}
426
427TEST(AggregationTests, test_branch_and_loop)
428{
429 using namespace jlm::llvm;
430
431 auto setup_cfg = [](jlm::llvm::InterProceduralGraphModule & module)
432 {
433 auto cfg = ControlFlowGraph::create(module);
434
435 auto split = jlm::llvm::BasicBlock::create(*cfg);
436 auto bb1 = jlm::llvm::BasicBlock::create(*cfg);
437 auto bb2 = jlm::llvm::BasicBlock::create(*cfg);
438 auto loop = jlm::llvm::BasicBlock::create(*cfg);
439
440 cfg->exit()->divert_inedges(split);
441 split->add_outedge(bb1);
442 split->add_outedge(bb2);
443 bb1->add_outedge(loop);
444 bb2->add_outedge(loop);
445 loop->add_outedge(cfg->exit());
446 loop->add_outedge(loop);
447
448 return cfg;
449 };
450
451 auto verify_aggtree = [](const jlm::llvm::AggregationNode & root)
452 {
453 EXPECT_TRUE(is_linear(&root, 5));
454 {
455 EXPECT_TRUE(is_entry(root.child(0)));
456 EXPECT_TRUE(is_block(root.child(1)));
457
458 auto branch = root.child(2);
459 EXPECT_TRUE(is_branch(branch, 2));
460 {
461 EXPECT_TRUE(is_block(branch->child(0)));
462 EXPECT_TRUE(is_block(branch->child(1)));
463 }
464
465 auto loop = root.child(3);
466 EXPECT_TRUE(is_loop(loop));
467 {
468 EXPECT_TRUE(is_block(loop->child(0)));
469 }
470
471 EXPECT_TRUE(is_exit(root.child(4)));
472 }
473 };
474
476 auto cfg = setup_cfg(module);
477
478 auto root = jlm::llvm::aggregate(*cfg);
480 jlm::llvm::print(*root, stdout);
481
482 verify_aggtree(*root);
483}
static bool is_block(const jlm::llvm::AggregationNode *node)
static bool is_linear(const jlm::llvm::AggregationNode *node, size_t nchildren)
static bool is_loop(const jlm::llvm::AggregationNode *node)
static bool is_entry(const jlm::llvm::AggregationNode *node)
TEST(ViewTests, test_linear_reduction)
static bool is_branch(const jlm::llvm::AggregationNode *node, size_t nchildren)
static bool is_exit(const jlm::llvm::AggregationNode *node)
AggregationNode * parent() noexcept
size_t nchildren() const noexcept
AggregationNode * child(size_t n) const noexcept
static void normalize(AggregationNode &node)
static BasicBlock * create(ControlFlowGraph &cfg)
Global memory state passed between functions.
static ControlFlowGraphNode * aggregate(ControlFlowGraphNode *, ControlFlowGraphNode *, AggregationMap &)
void print(const AggregationNode &n, const AnnotationMap &dm, FILE *out)
Definition print.cpp:120