Jlm
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 
12 static bool
14 {
15  return jlm::llvm::is<jlm::llvm::EntryAggregationNode>(node) && node->nchildren() == 0;
16 }
17 
18 static bool
20 {
21  return jlm::llvm::is<jlm::llvm::ExitAggregationNode>(node) && node->nchildren() == 0;
22 }
23 
24 static bool
26 {
27  return jlm::llvm::is<jlm::llvm::BasicBlockAggregationNode>(node) && node->nchildren() == 0;
28 }
29 
30 static bool
31 is_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 
48 static bool
50 {
51  return jlm::llvm::is<jlm::llvm::LoopAggregationNode>(node) && node->nchildren() == 1
52  && node->child(0)->parent() == node;
53 }
54 
55 static bool
56 is_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 
73 TEST(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 
108 TEST(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 
158 TEST(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 
225 TEST(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 
301 TEST(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 
367 TEST(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 
427 TEST(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)
size_t nchildren() const noexcept
Definition: aggregation.hpp:69
static void normalize(AggregationNode &node)
Definition: aggregation.cpp:19
AggregationNode * parent() noexcept
Definition: aggregation.hpp:91
AggregationNode * child(size_t n) const noexcept
Definition: aggregation.hpp:84
static BasicBlock * create(ControlFlowGraph &cfg)
Definition: basic-block.cpp:37
static std::unique_ptr< ControlFlowGraph > create(InterProceduralGraphModule &im)
Definition: cfg.hpp:267
Global memory state passed between functions.
static ControlFlowGraphNode * aggregate(ControlFlowGraphNode *, ControlFlowGraphNode *, AggregationMap &)
static bool is_loop(const jlm::llvm::ControlFlowGraphNode *node) noexcept
static bool is_linear(const ControlFlowGraphNode *node) noexcept
void print(const AggregationNode &n, const AnnotationMap &dm, FILE *out)
Definition: print.cpp:120
static bool is_branch(const ControlFlowGraphNode *split) noexcept