Jlm
Loading...
Searching...
No Matches
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>
15
16TEST(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
57TEST(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
141TEST(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
165 bb1.append_last(AssignmentOperation::create(v2, v3));
166 bb2.append_last(AssignmentOperation::create(v1, v3));
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
225TEST(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
288TEST(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
305 tl_cb1.append_last(AssignmentOperation::create(v1, v3));
306 tl_cb1.append_last(ThreeAddressCode::create(TestOperation::create({ vt }, { vt }), { v1 }));
307 auto v4 = tl_cb1.last()->result(0);
308
309 tl_cb2.append_last(AssignmentOperation::create(v1, v3));
310 tl_cb2.append_last(AssignmentOperation::create(v4, v3));
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
373TEST(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
386 bb.append_last(AssignmentOperation::create(v1, v2));
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
410TEST(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
429 tlb1.append_last(AssignmentOperation::create(v1, v2));
430 tlb1.append_last(AssignmentOperation::create(v1, v3));
431 tlb2.append_last(AssignmentOperation::create(v1, v3));
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 void print(const jlm::util::DisjointSet< int >::Set &set)
static const auto vt
Definition PullTests.cpp:16
Function argument.
Definition cfg.hpp:28
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::shared_ptr< const TestType > createValueType()
Definition TestType.cpp:67
Global memory state passed between functions.