Jlm
AnnotationTests.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 
12 #include <jlm/llvm/ir/print.hpp>
14 #include <jlm/rvsdg/TestType.hpp>
15 
16 TEST(AnnotationTests, TestBasicBlockAnnotation)
17 {
18  using namespace jlm::llvm;
19  using namespace jlm::rvsdg;
20 
21  // Arrange
22  auto SetupAggregationTree = [](InterProceduralGraphModule & module)
23  {
25 
26  auto v0 = module.create_variable(vt, "v0");
27 
29  bb.append_last(ThreeAddressCode::create(TestOperation::create({ vt }, { vt }), { v0 }));
30  auto v1 = bb.last()->result(0);
31 
32  bb.append_last(ThreeAddressCode::create(TestOperation::create({ vt }, { vt }), { v1 }));
33  auto v2 = bb.last()->result(0);
34 
35  auto root = BasicBlockAggregationNode::create(std::move(bb));
36 
37  return std::make_tuple(std::move(root), v0, v1, v2);
38  };
39 
41  auto [aggregationTreeRoot, v0, v1, v2] = SetupAggregationTree(module);
42 
43  /*
44  * Act
45  */
46  auto demandMap = Annotate(*aggregationTreeRoot);
47  print(*aggregationTreeRoot, *demandMap, stdout);
48 
49  /*
50  * Assert
51  */
52  EXPECT_EQ(
53  demandMap->Lookup<BasicBlockAnnotationSet>(*aggregationTreeRoot),
54  BasicBlockAnnotationSet({ v0 }, { v1, v2 }, { v1, v2 }));
55 }
56 
57 TEST(AnnotationTests, TestLinearSubgraphAnnotation)
58 {
59  using namespace jlm::llvm;
60  using namespace jlm::rvsdg;
61 
62  // Arrange
63  auto SetupAggregationTree = [](InterProceduralGraphModule &, jlm::llvm::Argument & argument)
64  {
65  /*
66  * Setup simple linear CFG: Entry -> B1 -> B2 -> Exit
67  */
69 
70  ThreeAddressCodeList bb1, bb2;
71  bb1.append_last(ThreeAddressCode::create(TestOperation::create({ vt }, { vt }), { &argument }));
72  auto v1 = bb1.last()->result(0);
73 
74  bb2.append_last(ThreeAddressCode::create(TestOperation::create({ vt }, { vt }), { v1 }));
75  auto v2 = bb2.last()->result(0);
76 
77  auto entryNode = EntryAggregationNode::create({ &argument });
78  auto basicBlockNode1 = BasicBlockAggregationNode::create(std::move(bb1));
79  auto basicBlockNode2 = BasicBlockAggregationNode::create(std::move(bb2));
80  auto exitNode = ExitAggregationNode::create({ v2 });
81 
82  auto linearNode1 =
83  LinearAggregationNode::create(std::move(entryNode), std::move(basicBlockNode1));
84  auto linearNode2 =
85  LinearAggregationNode::create(std::move(basicBlockNode2), std::move(exitNode));
86 
87  auto root = LinearAggregationNode::create(std::move(linearNode1), std::move(linearNode2));
88 
89  return std::make_tuple(std::move(root), v1, v2);
90  };
91 
94  auto [aggregationTreeRoot, v1, v2] = SetupAggregationTree(module, argument);
95 
96  /*
97  * Act
98  */
99  auto demandMap = Annotate(*aggregationTreeRoot);
100  print(*aggregationTreeRoot, *demandMap, stdout);
101 
102  /*
103  * Assert
104  */
105  EXPECT_EQ(
106  demandMap->Lookup<LinearAnnotationSet>(*aggregationTreeRoot),
107  LinearAnnotationSet({}, { v1, &argument, v2 }, { v1, &argument, v2 }));
108  {
109  auto linearNode1 = aggregationTreeRoot->child(0);
110  EXPECT_EQ(
111  demandMap->Lookup<LinearAnnotationSet>(*linearNode1),
112  LinearAnnotationSet({}, { v1, &argument }, { v1, &argument }));
113  {
114  auto entryNode = linearNode1->child(0);
115  EXPECT_EQ(
116  demandMap->Lookup<EntryAnnotationSet>(*entryNode),
117  EntryAnnotationSet({}, { &argument }, { &argument }, {}));
118 
119  auto basicBlockNode1 = linearNode1->child(1);
120  EXPECT_EQ(
121  demandMap->Lookup<BasicBlockAnnotationSet>(*basicBlockNode1),
122  BasicBlockAnnotationSet({ &argument }, { v1 }, { v1 }));
123  }
124 
125  auto linearNode2 = aggregationTreeRoot->child(1);
126  EXPECT_EQ(
127  demandMap->Lookup<LinearAnnotationSet>(*linearNode2),
128  LinearAnnotationSet({ v1 }, { v2 }, { v2 }));
129  {
130  auto basicBlockNode2 = linearNode2->child(0);
131  EXPECT_EQ(
132  demandMap->Lookup<BasicBlockAnnotationSet>(*basicBlockNode2),
133  BasicBlockAnnotationSet({ v1 }, { v2 }, { v2 }));
134 
135  auto exitNode = linearNode2->child(1);
136  EXPECT_EQ(demandMap->Lookup<ExitAnnotationSet>(*exitNode), ExitAnnotationSet({ v2 }, {}, {}));
137  }
138  }
139 }
140 
141 TEST(AnnotationTests, TestBranchAnnotation)
142 {
143  using namespace jlm::llvm;
144  using namespace jlm::rvsdg;
145 
146  // Arrange
147  auto SetupAggregationTree = [](InterProceduralGraphModule & module)
148  {
149  /*
150  * Setup conditional CFG with nodes bbs, b1, b2, and edges bbs -> b1 and bbs -> b2.
151  */
153 
154  auto argument = module.create_variable(vt, "arg");
155  auto v3 = module.create_variable(vt, "v3");
156 
157  ThreeAddressCodeList splitTacList, bb1, bb2;
158  splitTacList.append_last(
159  ThreeAddressCode::create(TestOperation::create({ vt }, { vt }), { argument }));
160  auto v1 = splitTacList.last()->result(0);
161 
162  bb2.append_last(ThreeAddressCode::create(TestOperation::create({ vt }, { vt }), { v1 }));
163  auto v2 = bb2.last()->result(0);
164 
167  bb2.append_last(ThreeAddressCode::create(TestOperation::create({ vt }, { vt }), { v3 }));
168  auto v4 = bb2.last()->result(0);
169 
170  auto basicBlockSplit = BasicBlockAggregationNode::create(std::move(splitTacList));
171  auto basicBlock1 = BasicBlockAggregationNode::create(std::move(bb1));
172  auto basicBlock2 = BasicBlockAggregationNode::create(std::move(bb2));
173 
174  auto branch = BranchAggregationNode::create();
175  branch->add_child(std::move(basicBlock1));
176  branch->add_child(std::move(basicBlock2));
177 
178  auto root = LinearAggregationNode::create(std::move(basicBlockSplit), std::move(branch));
179 
180  return std::make_tuple(std::move(root), argument, v1, v2, v3, v4);
181  };
182 
184  TestOperation op({ vt }, { vt });
185 
187  auto [aggregationTreeRoot, argument, v1, v2, v3, v4] = SetupAggregationTree(module);
188 
189  /*
190  * Act
191  */
192  auto demandMap = Annotate(*aggregationTreeRoot);
193  print(*aggregationTreeRoot, *demandMap, stdout);
194 
195  /*
196  * Assert
197  */
198  EXPECT_EQ(
199  demandMap->Lookup<LinearAnnotationSet>(*aggregationTreeRoot),
200  LinearAnnotationSet({ argument, v2 }, { v1, v2, v3, v4 }, { v1, v3 }));
201  {
202  auto splitNode = aggregationTreeRoot->child(0);
203  EXPECT_EQ(
204  demandMap->Lookup<BasicBlockAnnotationSet>(*splitNode),
205  BasicBlockAnnotationSet({ argument }, { v1 }, { v1 }));
206 
207  auto branchNode = aggregationTreeRoot->child(1);
208  EXPECT_EQ(
209  demandMap->Lookup<BranchAnnotationSet>(*branchNode),
210  BranchAnnotationSet({ v1, v2 }, { v2, v3, v4 }, { v3 }, { v1, v2 }, {}));
211  {
212  auto basicBlockNode1 = branchNode->child(0);
213  EXPECT_EQ(
214  demandMap->Lookup<BasicBlockAnnotationSet>(*basicBlockNode1),
215  BasicBlockAnnotationSet({ v2 }, { v3 }, { v3 }));
216 
217  auto basicBlockNode2 = branchNode->child(1);
218  EXPECT_EQ(
219  demandMap->Lookup<BasicBlockAnnotationSet>(*basicBlockNode2),
220  BasicBlockAnnotationSet({ v1 }, { v2, v4, v3 }, { v2, v4, v3 }));
221  }
222  }
223 }
224 
225 TEST(AnnotationTests, TestLoopAnnotation)
226 {
227  using namespace jlm::llvm;
228  using namespace jlm::rvsdg;
229 
230  // Arrange
231  auto SetupAggregationTree = [](InterProceduralGraphModule & module)
232  {
234 
235  auto v1 = module.create_variable(vt, "v1");
236  auto v4 = module.create_variable(vt, "v4");
237 
239  bb.append_last(ThreeAddressCode::create(TestOperation::create({ vt }, { vt }), { v1 }));
240  auto v2 = bb.last()->result(0);
241 
242  bb.append_last(ThreeAddressCode::create(TestOperation::create({ vt }, { vt }), { v2 }));
243  auto v3 = bb.last()->result(0);
244 
245  auto exitNode = ExitAggregationNode::create({ v3, v4 });
246  auto basicBlockNode = BasicBlockAggregationNode::create(std::move(bb));
247 
248  auto loopNode = LoopAggregationNode::create(std::move(basicBlockNode));
249  auto root = LinearAggregationNode::create(std::move(loopNode), std::move(exitNode));
250 
251  return std::make_tuple(std::move(root), v1, v2, v3, v4);
252  };
253 
255  auto [aggregationTreeRoot, v1, v2, v3, v4] = SetupAggregationTree(module);
256 
257  /*
258  * Assert
259  */
260  auto demandMap = Annotate(*aggregationTreeRoot);
261  print(*aggregationTreeRoot, *demandMap, stdout);
262 
263  /*
264  * Act
265  */
266  EXPECT_EQ(
267  demandMap->Lookup<LinearAnnotationSet>(*aggregationTreeRoot),
268  LinearAnnotationSet({ v1, v4 }, { v2, v3 }, { v2, v3 }));
269  {
270  auto loopNode = aggregationTreeRoot->child(0);
271  EXPECT_EQ(
272  demandMap->Lookup<LoopAnnotationSet>(*loopNode),
273  LoopAnnotationSet({ v1 }, { v2, v3 }, { v2, v3 }, { v1, v3, v4 }));
274  {
275  auto basicBlockNode = loopNode->child(0);
276  EXPECT_EQ(
277  demandMap->Lookup<BasicBlockAnnotationSet>(*basicBlockNode),
278  BasicBlockAnnotationSet({ v1 }, { v2, v3 }, { v2, v3 }));
279  }
280 
281  auto exitNode = aggregationTreeRoot->child(1);
282  EXPECT_EQ(
283  demandMap->Lookup<ExitAnnotationSet>(*exitNode),
284  ExitAnnotationSet({ v3, v4 }, {}, {}));
285  }
286 }
287 
288 TEST(AnnotationTests, TestBranchInLoopAnnotation)
289 {
290  using namespace jlm::llvm;
291  using namespace jlm::rvsdg;
292 
293  // Arrange
294  auto SetupAggregationTree = [](InterProceduralGraphModule & module)
295  {
297 
298  auto v1 = module.create_variable(vt, "v1");
299  auto v3 = module.create_variable(vt, "v3");
300 
301  ThreeAddressCodeList tl_cb1, tl_cb2;
302  tl_cb1.append_last(ThreeAddressCode::create(TestOperation::create({ vt }, { vt }), { v1 }));
303  auto v2 = tl_cb1.last()->result(0);
304 
306  tl_cb1.append_last(ThreeAddressCode::create(TestOperation::create({ vt }, { vt }), { v1 }));
307  auto v4 = tl_cb1.last()->result(0);
308 
311 
312  auto exitNode = ExitAggregationNode::create({ v2, v3 });
313 
314  auto basicBlock1 = BasicBlockAggregationNode::create(std::move(tl_cb1));
315  auto basicBlock2 = BasicBlockAggregationNode::create(std::move(tl_cb2));
316 
317  auto branchNode = BranchAggregationNode::create();
318  branchNode->add_child(std::move(basicBlock1));
319  branchNode->add_child(std::move(basicBlock2));
320 
321  auto loopNode = LoopAggregationNode::create(std::move(branchNode));
322 
323  auto root = LinearAggregationNode::create(std::move(loopNode), std::move(exitNode));
324 
325  return std::make_tuple(std::move(root), v1, v2, v3, v4);
326  };
327 
329  auto [aggregationTreeRoot, v1, v2, v3, v4] = SetupAggregationTree(module);
330 
331  /*
332  * Act
333  */
334  auto demandMap = Annotate(*aggregationTreeRoot);
335  print(*aggregationTreeRoot, *demandMap, stdout);
336 
337  /*
338  * Assert
339  */
340  EXPECT_EQ(
341  demandMap->Lookup<LinearAnnotationSet>(*aggregationTreeRoot),
342  LinearAnnotationSet({ v1, v2, v4 }, { v2, v3, v4 }, { v3 }));
343  {
344  auto loopNode = aggregationTreeRoot->child(0);
345  EXPECT_EQ(
346  demandMap->Lookup<LoopAnnotationSet>(*loopNode),
347  LoopAnnotationSet({ v1, v4 }, { v2, v3, v4 }, { v3 }, { v1, v2, v3, v4 }));
348  {
349  auto branchNode = loopNode->child(0);
350  EXPECT_EQ(
351  demandMap->Lookup<BranchAnnotationSet>(*branchNode),
352  BranchAnnotationSet({ v1, v4 }, { v2, v3, v4 }, { v3 }, { v1, v2, v4 }, { v2, v3, v4 }));
353  {
354  auto basicBlockNode1 = branchNode->child(0);
355  EXPECT_EQ(
356  demandMap->Lookup<BasicBlockAnnotationSet>(*basicBlockNode1),
357  BasicBlockAnnotationSet({ v1 }, { v2, v3, v4 }, { v2, v3, v4 }));
358 
359  auto basicBlockNode2 = branchNode->child(1);
360  EXPECT_EQ(
361  demandMap->Lookup<BasicBlockAnnotationSet>(*basicBlockNode2),
362  BasicBlockAnnotationSet({ v1, v4 }, { v3 }, { v3 }));
363  }
364  }
365 
366  auto exitNode = aggregationTreeRoot->child(1);
367  EXPECT_EQ(
368  demandMap->Lookup<ExitAnnotationSet>(*exitNode),
369  ExitAnnotationSet({ v2, v3 }, {}, {}));
370  }
371 }
372 
373 TEST(AnnotationTests, TestAssignmentAnnotation)
374 {
375  using namespace jlm::llvm;
376 
377  // Arrange
378  auto SetupAggregationTree = [](InterProceduralGraphModule & module)
379  {
381 
382  auto v1 = module.create_variable(vt, "v1");
383  auto v2 = module.create_variable(vt, "v2");
384 
387 
388  auto root = BasicBlockAggregationNode::create(std::move(bb));
389 
390  return std::make_tuple(std::move(root), v1, v2);
391  };
392 
394  auto [aggregationTreeRoot, v1, v2] = SetupAggregationTree(module);
395 
396  /*
397  * Act
398  */
399  auto demandMap = Annotate(*aggregationTreeRoot);
400  print(*aggregationTreeRoot, *demandMap, stdout);
401 
402  /*
403  * Assert
404  */
405  EXPECT_EQ(
406  demandMap->Lookup<BasicBlockAnnotationSet>(*aggregationTreeRoot),
407  BasicBlockAnnotationSet({ v1 }, { v2 }, { v2 }));
408 }
409 
410 TEST(AnnotationTests, TestBranchPassByAnnotation)
411 {
412  using namespace jlm::llvm;
413  using namespace jlm::rvsdg;
414 
415  // Arrange
416  auto SetupAggregationTree = [](InterProceduralGraphModule & module)
417  {
419 
420  auto v3 = module.create_variable(vt, "v3");
421 
422  ThreeAddressCodeList tlsplit, tlb1, tlb2;
423  tlsplit.append_last(ThreeAddressCode::create(TestOperation::create({}, { vt }), {}));
424  auto v1 = tlsplit.last()->result(0);
425 
426  tlsplit.append_last(ThreeAddressCode::create(TestOperation::create({}, { vt }), {}));
427  auto v2 = tlsplit.last()->result(0);
428 
432 
433  auto splitNode = BasicBlockAggregationNode::create(std::move(tlsplit));
434 
435  auto basicBlockNode1 = BasicBlockAggregationNode::create(std::move(tlb1));
436  auto basicBlockNode2 = BasicBlockAggregationNode::create(std::move(tlb2));
437 
438  auto branchNode = BranchAggregationNode::create();
439  branchNode->add_child(std::move(basicBlockNode1));
440  branchNode->add_child(std::move(basicBlockNode2));
441 
442  auto joinNode = BasicBlockAggregationNode::create();
443 
444  auto exitNode = ExitAggregationNode::create({ v1, v2, v3 });
445 
446  auto root = LinearAggregationNode::create(std::move(splitNode), std::move(branchNode));
447  root->add_child(std::move(joinNode));
448  root->add_child(std::move(exitNode));
449 
450  return std::make_tuple(std::move(root), v1, v2, v3);
451  };
452 
454  auto [aggregationTreeRoot, v1, v2, v3] = SetupAggregationTree(module);
455 
456  /*
457  * Act
458  */
459  auto demandMap = Annotate(*aggregationTreeRoot);
460  print(*aggregationTreeRoot, *demandMap, stdout);
461 
462  /*
463  * Assert
464  */
465  EXPECT_EQ(
466  demandMap->Lookup<LinearAnnotationSet>(*aggregationTreeRoot),
467  LinearAnnotationSet({}, { v1, v2, v3 }, { v1, v2, v3 }));
468  {
469  auto splitNode = aggregationTreeRoot->child(0);
470  EXPECT_EQ(
471  demandMap->Lookup<BasicBlockAnnotationSet>(*splitNode),
472  BasicBlockAnnotationSet({}, { v1, v2 }, { v1, v2 }));
473 
474  auto branchNode = aggregationTreeRoot->child(1);
475  EXPECT_EQ(
476  demandMap->Lookup<BranchAnnotationSet>(*branchNode),
477  BranchAnnotationSet({ v1 }, { v2, v3 }, { v3 }, { v1, v2 }, { v2, v3 }));
478  {
479  auto basicBlockNode1 = branchNode->child(0);
480  EXPECT_EQ(
481  demandMap->Lookup<BasicBlockAnnotationSet>(*basicBlockNode1),
482  BasicBlockAnnotationSet({ v1 }, { v2, v3 }, { v2, v3 }));
483 
484  auto basicBlockNode2 = branchNode->child(1);
485  EXPECT_EQ(
486  demandMap->Lookup<BasicBlockAnnotationSet>(*basicBlockNode2),
487  BasicBlockAnnotationSet({ v1 }, { v3 }, { v3 }));
488  }
489 
490  auto joinNode = aggregationTreeRoot->child(2);
491  EXPECT_EQ(
492  demandMap->Lookup<BasicBlockAnnotationSet>(*joinNode),
493  BasicBlockAnnotationSet({}, {}, {}));
494 
495  auto exitNode = aggregationTreeRoot->child(3);
496  EXPECT_EQ(
497  demandMap->Lookup<ExitAnnotationSet>(*exitNode),
498  ExitAnnotationSet({ v1, v2, v3 }, {}, {}));
499  }
500 }
TEST(AnnotationTests, TestBasicBlockAnnotation)
static const auto vt
Definition: PullTests.cpp:16
Function argument.
Definition: cfg.hpp:28
static std::unique_ptr< llvm::ThreeAddressCode > create(const Variable *rhs, const Variable *lhs)
Definition: operators.hpp:119
static std::unique_ptr< AggregationNode > create()
static std::unique_ptr< AggregationNode > create()
static std::unique_ptr< AggregationNode > create(const std::vector< llvm::Argument * > &arguments)
static std::unique_ptr< AggregationNode > create(const std::vector< const Variable * > &results)
static std::unique_ptr< AggregationNode > create(std::unique_ptr< AggregationNode > n1, std::unique_ptr< AggregationNode > n2)
static std::unique_ptr< AggregationNode > create(std::unique_ptr< AggregationNode > body)
ThreeAddressCode * last() const noexcept
Definition: tac.hpp:306
void append_last(std::unique_ptr< llvm::ThreeAddressCode > tac)
Definition: tac.hpp:275
const ThreeAddressCodeVariable * result(size_t index) const noexcept
Definition: tac.hpp:109
static std::unique_ptr< llvm::ThreeAddressCode > create(std::unique_ptr< rvsdg::SimpleOperation > operation, const std::vector< const Variable * > &operands)
Definition: tac.hpp:135
static std::shared_ptr< const TestType > createValueType()
Definition: TestType.cpp:67
Global memory state passed between functions.
void print(const AggregationNode &n, const AnnotationMap &dm, FILE *out)
Definition: print.cpp:120
std::unique_ptr< AnnotationMap > Annotate(const AggregationNode &aggregationTreeRoot)
Definition: Annotation.cpp:492