Jlm
Loading...
Searching...
No Matches
MemoryStateEncoderTests.cpp
Go to the documentation of this file.
1/*
2 * Copyright 2020 Nico Reißmann <nico.reissmann@gmail.com>
3 * See COPYING for terms of redistribution.
4 */
5
6#include <gtest/gtest.h>
7
21#include <jlm/rvsdg/view.hpp>
22
23template<class Analysis, class TModRefSummarizer>
24static void
26{
27 static_assert(
28 std::is_base_of_v<jlm::llvm::aa::PointsToAnalysis, Analysis>,
29 "Analysis should be derived from PointsToAnalysis class.");
30
31 static_assert(
32 std::is_base_of_v<jlm::llvm::aa::ModRefSummarizer, TModRefSummarizer>,
33 "TModRefSummarizer should be derived from ModRefSummarizer class.");
34
35 jlm::rvsdg::view(&rvsdgModule.Rvsdg().GetRootRegion(), stdout);
36
38
39 Analysis aliasAnalysis;
40 auto pointsToGraph = aliasAnalysis.Analyze(rvsdgModule, statisticsCollector);
41 std::cout << jlm::llvm::aa::PointsToGraph::dumpDot(*pointsToGraph);
42
43 TModRefSummarizer summarizer;
44 auto modRefSummary =
45 summarizer.SummarizeModRefs(rvsdgModule, *pointsToGraph, statisticsCollector);
46
48 std::cout << "run encoder\n";
49 encoder.Encode(rvsdgModule, *modRefSummary, statisticsCollector);
50 jlm::rvsdg::view(&rvsdgModule.Rvsdg().GetRootRegion(), stdout);
51}
52
53template<class OP>
54static bool
55is(const jlm::rvsdg::Node & node, size_t numInputs, size_t numOutputs)
56{
57 return jlm::rvsdg::is<OP>(&node) && node.ninputs() == numInputs && node.noutputs() == numOutputs;
58}
59
60TEST(MemoryStateEncoderTests, storeTest1AndersenAgnostic)
61{
62 using namespace jlm::llvm;
63
64 StoreTest1 test;
65 encodeStates<aa::Andersen, aa::AgnosticModRefSummarizer>(test.module());
66
67 EXPECT_EQ(test.lambda->subregion()->numNodes(), 14u);
68
70 *test.lambda->GetFunctionResults()[0]->origin());
71 EXPECT_TRUE(is<LambdaExitMemoryStateMergeOperation>(*lambdaExitMerge, 6, 1));
72
73 // Agnostic ModRef summaries lead to Join operations for all allocas
75 test.alloca_a->output(1)->SingleUser());
77 test.alloca_b->output(1)->SingleUser());
79 test.alloca_c->output(1)->SingleUser());
81 test.alloca_d->output(1)->SingleUser());
82 EXPECT_TRUE(aJoinOp && aJoinNode->output(0)->nusers() == 1);
83 EXPECT_TRUE(bJoinOp && bJoinNode->output(0)->nusers() == 1);
84 EXPECT_TRUE(cJoinOp && cJoinNode->output(0)->nusers() == 1);
85 EXPECT_TRUE(dJoinOp && dJoinNode->output(0)->nusers() == 1);
86
87 // the d alloca is not used by any operation, and goes straight to the call exit
88 EXPECT_EQ(
89 jlm::rvsdg::TryGetOwnerNode<jlm::rvsdg::Node>(dJoinNode->output(0)->SingleUser()),
90 lambdaExitMerge);
91
92 auto storeD = jlm::rvsdg::TryGetOwnerNode<jlm::rvsdg::Node>(cJoinNode->output(0)->SingleUser());
93 EXPECT_TRUE(is<StoreNonVolatileOperation>(*storeD, 3, 1));
94 EXPECT_EQ(storeD->input(0)->origin(), test.alloca_c->output(0));
95 EXPECT_EQ(storeD->input(1)->origin(), test.alloca_d->output(0));
96
97 auto storeC = jlm::rvsdg::TryGetOwnerNode<jlm::rvsdg::Node>(bJoinNode->output(0)->SingleUser());
98 EXPECT_TRUE(is<StoreNonVolatileOperation>(*storeC, 3, 1));
99 EXPECT_EQ(storeC->input(0)->origin(), test.alloca_b->output(0));
100 EXPECT_EQ(storeC->input(1)->origin(), test.alloca_c->output(0));
101
102 auto storeB = jlm::rvsdg::TryGetOwnerNode<jlm::rvsdg::Node>(aJoinNode->output(0)->SingleUser());
103 EXPECT_TRUE(is<StoreNonVolatileOperation>(*storeB, 3, 1));
104 EXPECT_EQ(storeB->input(0)->origin(), test.alloca_a->output(0));
105 EXPECT_EQ(storeB->input(1)->origin(), test.alloca_b->output(0));
106}
107
108TEST(MemoryStateEncoderTests, storeTest1AndersenRegionAware)
109{
110 using namespace jlm::llvm;
111
112 StoreTest1 test;
113 encodeStates<aa::Andersen, aa::RegionAwareModRefSummarizer>(test.module());
114
115 EXPECT_EQ(test.lambda->subregion()->numNodes(), 1u);
116
118 *test.lambda->GetFunctionResults()[0]->origin());
119 EXPECT_TRUE(is<LambdaExitMemoryStateMergeOperation>(*lambdaExitMerge, 0, 1));
120}
121
122TEST(MemoryStateEncoderTests, storeTest2AndersenAgnostic)
123{
124 using namespace jlm::llvm;
125
126 StoreTest2 test;
127 encodeStates<aa::Andersen, aa::AgnosticModRefSummarizer>(test.module());
128
129 EXPECT_EQ(test.lambda->subregion()->numNodes(), 17u);
130
132 *test.lambda->GetFunctionResults()[0]->origin());
133 EXPECT_TRUE(is<LambdaExitMemoryStateMergeOperation>(*lambdaExitMerge, 7, 1));
134
135 // Agnostic ModRef summaries lead to Join operations for all allocas
137 test.alloca_a->output(1)->SingleUser());
139 test.alloca_b->output(1)->SingleUser());
141 test.alloca_x->output(1)->SingleUser());
143 test.alloca_y->output(1)->SingleUser());
145 test.alloca_p->output(1)->SingleUser());
146 EXPECT_TRUE(aJoinOp && aJoinNode->output(0)->nusers() == 1);
147 EXPECT_TRUE(bJoinOp && bJoinNode->output(0)->nusers() == 1);
148 EXPECT_TRUE(xJoinOp && xJoinNode->output(0)->nusers() == 1);
149 EXPECT_TRUE(yJoinOp && yJoinNode->output(0)->nusers() == 1);
150 EXPECT_TRUE(pJoinOp && pJoinNode->output(0)->nusers() == 1);
151
152 EXPECT_EQ(
153 jlm::rvsdg::TryGetOwnerNode<jlm::rvsdg::Node>(aJoinNode->output(0)->SingleUser()),
154 lambdaExitMerge);
155 EXPECT_EQ(
156 jlm::rvsdg::TryGetOwnerNode<jlm::rvsdg::Node>(bJoinNode->output(0)->SingleUser()),
157 lambdaExitMerge);
158
159 auto storeA =
161 EXPECT_TRUE(is<StoreNonVolatileOperation>(*storeA, 3, 1));
162 EXPECT_EQ(storeA->input(0)->origin(), test.alloca_x->output(0));
163 EXPECT_EQ(storeA->input(1)->origin(), test.alloca_a->output(0));
164 EXPECT_TRUE(
166
167 auto storeB =
169 EXPECT_TRUE(is<StoreNonVolatileOperation>(*storeB, 3, 1));
170 EXPECT_EQ(storeB->input(0)->origin(), test.alloca_y->output(0));
171 EXPECT_EQ(storeB->input(1)->origin(), test.alloca_b->output(0));
172 EXPECT_TRUE(
174
175 auto storeX = jlm::rvsdg::TryGetOwnerNode<jlm::rvsdg::Node>(pJoinNode->output(0)->SingleUser());
176 EXPECT_TRUE(is<StoreNonVolatileOperation>(*storeX, 3, 1));
177 EXPECT_EQ(storeX->input(0)->origin(), test.alloca_p->output(0));
178 EXPECT_EQ(storeX->input(1)->origin(), test.alloca_x->output(0));
179 EXPECT_TRUE(
181
182 auto storeY = jlm::rvsdg::TryGetOwnerNode<jlm::rvsdg::Node>(storeX->output(0)->SingleUser());
183 EXPECT_TRUE(is<StoreNonVolatileOperation>(*storeY, 3, 1));
184 EXPECT_EQ(storeY->input(0)->origin(), test.alloca_p->output(0));
185 EXPECT_EQ(storeY->input(1)->origin(), test.alloca_y->output(0));
186 EXPECT_EQ(storeY->input(2)->origin(), storeX->output(0));
187}
188
189TEST(MemoryStateEncoderTests, storeTest2AndersenRegionAware)
190{
191 using namespace jlm::llvm;
192
193 StoreTest1 test;
194 encodeStates<aa::Andersen, aa::RegionAwareModRefSummarizer>(test.module());
195
196 EXPECT_EQ(test.lambda->subregion()->numNodes(), 1u);
197
199 *test.lambda->GetFunctionResults()[0]->origin());
200 EXPECT_TRUE(is<LambdaExitMemoryStateMergeOperation>(*lambdaExitMerge, 0, 1));
201}
202
203TEST(MemoryStateEncoderTests, loadTest1AndersenAgnostic)
204{
205 using namespace jlm::llvm;
206
207 LoadTest1 test;
208 encodeStates<aa::Andersen, aa::AgnosticModRefSummarizer>(test.module());
209
210 EXPECT_EQ(test.lambda->subregion()->numNodes(), 4u);
211
213 *test.lambda->GetFunctionResults()[1]->origin());
214 EXPECT_TRUE(is<LambdaExitMemoryStateMergeOperation>(*lambdaExitMerge, 2, 1));
215
216 auto lambdaEntrySplit = jlm::rvsdg::TryGetOwnerNode<jlm::rvsdg::Node>(
217 test.lambda->GetFunctionArguments()[1]->SingleUser());
218 EXPECT_TRUE(is<LambdaEntryMemoryStateSplitOperation>(*lambdaEntrySplit, 1, 2));
219
221 *test.lambda->GetFunctionResults()[0]->origin());
222 auto loadX = jlm::rvsdg::TryGetOwnerNode<jlm::rvsdg::Node>(*loadA->input(0)->origin());
223
224 EXPECT_TRUE(is<LoadNonVolatileOperation>(*loadA, 3, 3));
225 EXPECT_EQ(jlm::rvsdg::TryGetOwnerNode<jlm::rvsdg::Node>(*loadA->input(1)->origin()), loadX);
226
227 EXPECT_TRUE(is<LoadNonVolatileOperation>(*loadX, 3, 3));
228 EXPECT_EQ(loadX->input(0)->origin(), test.lambda->GetFunctionArguments()[0]);
229 EXPECT_EQ(
230 jlm::rvsdg::TryGetOwnerNode<jlm::rvsdg::Node>(*loadX->input(1)->origin()),
231 lambdaEntrySplit);
232}
233
234TEST(MemoryStateEncoderTests, loadTest1AndersenRegionAware)
235{
236 using namespace jlm::llvm;
237
238 LoadTest1 test;
239 encodeStates<aa::Andersen, aa::RegionAwareModRefSummarizer>(test.module());
240
241 EXPECT_EQ(test.lambda->subregion()->numNodes(), 4u);
242
244 *test.lambda->GetFunctionResults()[1]->origin());
245 EXPECT_TRUE(is<LambdaExitMemoryStateMergeOperation>(*lambdaExitMerge, 1, 1));
246
247 auto lambdaEntrySplit = jlm::rvsdg::TryGetOwnerNode<jlm::rvsdg::Node>(
248 test.lambda->GetFunctionArguments()[1]->SingleUser());
249 EXPECT_TRUE(is<LambdaEntryMemoryStateSplitOperation>(*lambdaEntrySplit, 1, 1));
250
252 *test.lambda->GetFunctionResults()[0]->origin());
253 auto loadX = jlm::rvsdg::TryGetOwnerNode<jlm::rvsdg::Node>(*loadA->input(0)->origin());
254
255 EXPECT_TRUE(is<LoadNonVolatileOperation>(*loadA, 2, 2));
256 EXPECT_EQ(jlm::rvsdg::TryGetOwnerNode<jlm::rvsdg::Node>(*loadA->input(1)->origin()), loadX);
257
258 EXPECT_TRUE(is<LoadNonVolatileOperation>(*loadX, 2, 2));
259 EXPECT_EQ(loadX->input(0)->origin(), test.lambda->GetFunctionArguments()[0]);
260 EXPECT_EQ(
261 jlm::rvsdg::TryGetOwnerNode<jlm::rvsdg::Node>(*loadX->input(1)->origin()),
262 lambdaEntrySplit);
263}
264
265TEST(MemoryStateEncoderTests, loadTest2AndersenAgnostic)
266{
267 using namespace jlm::llvm;
268 LoadTest2 test;
269 encodeStates<aa::Andersen, aa::AgnosticModRefSummarizer>(test.module());
270
271 EXPECT_EQ(test.lambda->subregion()->numNodes(), 19u);
272
274 *test.lambda->GetFunctionResults()[0]->origin());
275 EXPECT_TRUE(is<LambdaExitMemoryStateMergeOperation>(*lambdaExitMerge, 7, 1));
276
277 // Agnostic ModRef summaries lead to Join operations for all allocas
279 test.alloca_a->output(1)->SingleUser());
281 test.alloca_b->output(1)->SingleUser());
283 test.alloca_x->output(1)->SingleUser());
285 test.alloca_y->output(1)->SingleUser());
287 test.alloca_p->output(1)->SingleUser());
288 EXPECT_TRUE(aJoinOp && aJoinNode->output(0)->nusers() == 1);
289 EXPECT_TRUE(bJoinOp && bJoinNode->output(0)->nusers() == 1);
290 EXPECT_TRUE(xJoinOp && xJoinNode->output(0)->nusers() == 1);
291 EXPECT_TRUE(yJoinOp && yJoinNode->output(0)->nusers() == 1);
292 EXPECT_TRUE(pJoinOp && pJoinNode->output(0)->nusers() == 1);
293
294 EXPECT_EQ(
295 jlm::rvsdg::TryGetOwnerNode<jlm::rvsdg::Node>(aJoinNode->output(0)->SingleUser()),
296 lambdaExitMerge);
297 EXPECT_EQ(
298 jlm::rvsdg::TryGetOwnerNode<jlm::rvsdg::Node>(bJoinNode->output(0)->SingleUser()),
299 lambdaExitMerge);
300
301 auto storeA =
303 EXPECT_TRUE(is<StoreNonVolatileOperation>(*storeA, 3, 1));
304 EXPECT_EQ(storeA->input(0)->origin(), test.alloca_x->output(0));
305 EXPECT_TRUE(
307
308 auto storeB =
310 EXPECT_TRUE(is<StoreNonVolatileOperation>(*storeB, 3, 1));
311 EXPECT_EQ(storeB->input(0)->origin(), test.alloca_y->output(0));
312 EXPECT_TRUE(
314
315 auto storeX = jlm::rvsdg::TryGetOwnerNode<jlm::rvsdg::Node>(pJoinNode->output(0)->SingleUser());
316 EXPECT_TRUE(is<StoreNonVolatileOperation>(*storeX, 3, 1));
317 EXPECT_EQ(storeX->input(0)->origin(), test.alloca_p->output(0));
318 EXPECT_EQ(storeX->input(1)->origin(), test.alloca_x->output(0));
319 EXPECT_TRUE(
321
322 auto load1 = jlm::rvsdg::TryGetOwnerNode<jlm::rvsdg::Node>(storeX->output(0)->SingleUser());
323 EXPECT_TRUE(is<LoadNonVolatileOperation>(*load1, 2, 2));
324 EXPECT_EQ(load1->input(0)->origin(), test.alloca_p->output(0));
325 EXPECT_EQ(load1->input(1)->origin(), storeX->output(0));
326
327 auto load2 = jlm::rvsdg::TryGetOwnerNode<jlm::rvsdg::Node>(load1->output(0)->SingleUser());
328 EXPECT_TRUE(is<LoadNonVolatileOperation>(*load2, 2, 2));
329 EXPECT_EQ(load2->input(1)->origin(), storeA->output(0));
330
331 auto storeY = jlm::rvsdg::TryGetOwnerNode<jlm::rvsdg::Node>(load2->output(0)->SingleUser());
332 EXPECT_TRUE(is<StoreNonVolatileOperation>(*storeY, 3, 1));
333 EXPECT_EQ(storeY->input(0)->origin(), test.alloca_y->output(0));
334 EXPECT_EQ(storeY->input(2)->origin(), storeB->output(0));
335}
336
337TEST(MemoryStateEncoderTests, loadTest2AndersenRegionAware)
338{
339 using namespace jlm::llvm;
340
341 LoadTest2 test;
342 encodeStates<aa::Andersen, aa::RegionAwareModRefSummarizer>(test.module());
343
344 EXPECT_EQ(test.lambda->subregion()->numNodes(), 1u);
345
347 *test.lambda->GetFunctionResults()[0]->origin());
348 EXPECT_TRUE(is<LambdaExitMemoryStateMergeOperation>(*lambdaExitMerge, 0, 1));
349}
350
351TEST(MemoryStateEncoderTests, loadFromUndefAndersenAgnostic)
352{
353 using namespace jlm::llvm;
354
356 encodeStates<aa::Andersen, aa::AgnosticModRefSummarizer>(test.module());
357 EXPECT_EQ(test.Lambda().subregion()->numNodes(), 4u);
358
360 *test.Lambda().GetFunctionResults()[1]->origin());
361 EXPECT_TRUE(is<LambdaExitMemoryStateMergeOperation>(*lambdaExitMerge, 2, 1));
362
364 *test.Lambda().GetFunctionResults()[0]->origin());
365 EXPECT_TRUE(is<LoadNonVolatileOperation>(*load, 1, 1));
366
367 auto lambdaEntrySplit = jlm::rvsdg::TryGetOwnerNode<jlm::rvsdg::Node>(
368 test.Lambda().GetFunctionArguments()[0]->SingleUser());
369 EXPECT_TRUE(is<LambdaEntryMemoryStateSplitOperation>(*lambdaEntrySplit, 1, 2));
370}
371
372TEST(MemoryStateEncoderTests, loadFromUndefAndersenRegionAware)
373{
374 using namespace jlm::llvm;
375
377 encodeStates<aa::Andersen, aa::RegionAwareModRefSummarizer>(test.module());
378
379 EXPECT_EQ(test.Lambda().subregion()->numNodes(), 3u);
380
382 *test.Lambda().GetFunctionResults()[1]->origin());
383 EXPECT_TRUE(is<LambdaExitMemoryStateMergeOperation>(*lambdaExitMerge, 0, 1));
384
386 *test.Lambda().GetFunctionResults()[0]->origin());
387 EXPECT_TRUE(is<LoadNonVolatileOperation>(*load, 1, 1));
388}
389
390TEST(MemoryStateEncoderTests, callTest1AndersenAgnostic)
391{
392 using namespace jlm::llvm;
393
394 CallTest1 test;
395 encodeStates<aa::Andersen, aa::AgnosticModRefSummarizer>(test.module());
396
397 /* validate f */
398 {
399 auto lambdaEntrySplit = jlm::rvsdg::TryGetOwnerNode<jlm::rvsdg::Node>(
400 *test.lambda_f->GetFunctionArguments()[3]->Users().begin());
402 *test.lambda_f->GetFunctionResults()[2]->origin());
404 *test.lambda_f->GetFunctionArguments()[0]->Users().begin());
406 *test.lambda_f->GetFunctionArguments()[1]->Users().begin());
407
408 EXPECT_TRUE(is<LambdaExitMemoryStateMergeOperation>(*lambdaExitMerge, 7, 1));
409 EXPECT_TRUE(is<LambdaEntryMemoryStateSplitOperation>(*lambdaEntrySplit, 1, 7));
410
411 EXPECT_TRUE(is<LoadNonVolatileOperation>(*loadX, 2, 2));
412 EXPECT_EQ(
413 jlm::rvsdg::TryGetOwnerNode<jlm::rvsdg::Node>(*loadX->input(1)->origin()),
414 lambdaEntrySplit);
415
416 EXPECT_TRUE(is<LoadNonVolatileOperation>(*loadY, 2, 2));
417 EXPECT_EQ(
418 jlm::rvsdg::TryGetOwnerNode<jlm::rvsdg::Node>(*loadY->input(1)->origin()),
419 lambdaEntrySplit);
420 }
421
422 /* validate g */
423 {
424 auto lambdaEntrySplit = jlm::rvsdg::TryGetOwnerNode<jlm::rvsdg::Node>(
425 *test.lambda_g->GetFunctionArguments()[3]->Users().begin());
427 *test.lambda_g->GetFunctionResults()[2]->origin());
429 *test.lambda_g->GetFunctionArguments()[0]->Users().begin());
431 *test.lambda_g->GetFunctionArguments()[1]->Users().begin());
432
433 EXPECT_TRUE(is<LambdaExitMemoryStateMergeOperation>(*lambdaExitMerge, 7, 1));
434 EXPECT_TRUE(is<LambdaEntryMemoryStateSplitOperation>(*lambdaEntrySplit, 1, 7));
435
436 EXPECT_TRUE(is<LoadNonVolatileOperation>(*loadX, 2, 2));
437 EXPECT_EQ(
438 jlm::rvsdg::TryGetOwnerNode<jlm::rvsdg::Node>(*loadX->input(1)->origin()),
439 lambdaEntrySplit);
440
441 EXPECT_TRUE(is<LoadNonVolatileOperation>(*loadY, 2, 2));
442 EXPECT_TRUE(jlm::rvsdg::TryGetOwnerNode<jlm::rvsdg::Node>(*loadY->input(1)->origin()) == loadX);
443 }
444
445 /* validate h */
446 {
447 auto callEntryMerge =
449 auto callExitSplit =
451
452 EXPECT_TRUE(is<CallEntryMemoryStateMergeOperation>(*callEntryMerge, 7, 1));
453 EXPECT_TRUE(is<CallExitMemoryStateSplitOperation>(*callExitSplit, 1, 7));
454
455 callEntryMerge =
457 callExitSplit =
459
460 EXPECT_TRUE(is<CallEntryMemoryStateMergeOperation>(*callEntryMerge, 7, 1));
461 EXPECT_TRUE(is<CallExitMemoryStateSplitOperation>(*callExitSplit, 1, 7));
462 }
463}
464
465TEST(MemoryStateEncoderTests, callTest1AndersenRegionAware)
466{
467 using namespace jlm::llvm;
468
469 CallTest1 test;
470 encodeStates<aa::Andersen, aa::RegionAwareModRefSummarizer>(test.module());
471
472 /* validate f */
473 {
474 auto lambdaEntrySplit = jlm::rvsdg::TryGetOwnerNode<jlm::rvsdg::Node>(
475 test.lambda_f->GetFunctionArguments()[3]->SingleUser());
477 *test.lambda_f->GetFunctionResults()[2]->origin());
479 test.lambda_f->GetFunctionArguments()[0]->SingleUser());
481 test.lambda_f->GetFunctionArguments()[1]->SingleUser());
482
483 EXPECT_TRUE(is<LambdaExitMemoryStateMergeOperation>(*lambdaExitMerge, 2, 1));
484 EXPECT_TRUE(is<LambdaEntryMemoryStateSplitOperation>(*lambdaEntrySplit, 1, 2));
485
486 EXPECT_TRUE(is<LoadNonVolatileOperation>(*loadX, 2, 2));
487 EXPECT_EQ(
488 jlm::rvsdg::TryGetOwnerNode<jlm::rvsdg::Node>(*loadX->input(1)->origin()),
489 lambdaEntrySplit);
490
491 EXPECT_TRUE(is<LoadNonVolatileOperation>(*loadY, 2, 2));
492 EXPECT_EQ(
493 jlm::rvsdg::TryGetOwnerNode<jlm::rvsdg::Node>(*loadY->input(1)->origin()),
494 lambdaEntrySplit);
495 }
496
497 /* validate g */
498 {
499 auto lambdaEntrySplit = jlm::rvsdg::TryGetOwnerNode<jlm::rvsdg::Node>(
500 test.lambda_g->GetFunctionArguments()[3]->SingleUser());
502 *test.lambda_g->GetFunctionResults()[2]->origin());
504 test.lambda_g->GetFunctionArguments()[0]->SingleUser());
506 test.lambda_g->GetFunctionArguments()[1]->SingleUser());
507
508 EXPECT_TRUE(is<LambdaExitMemoryStateMergeOperation>(*lambdaExitMerge, 1, 1));
509 EXPECT_TRUE(is<LambdaEntryMemoryStateSplitOperation>(*lambdaEntrySplit, 1, 1));
510
511 EXPECT_TRUE(is<LoadNonVolatileOperation>(*loadX, 2, 2));
512 EXPECT_EQ(
513 jlm::rvsdg::TryGetOwnerNode<jlm::rvsdg::Node>(*loadX->input(1)->origin()),
514 lambdaEntrySplit);
515
516 EXPECT_TRUE(is<LoadNonVolatileOperation>(*loadY, 2, 2));
517 EXPECT_EQ(jlm::rvsdg::TryGetOwnerNode<jlm::rvsdg::Node>(*loadY->input(1)->origin()), loadX);
518 }
519
520 /* validate h */
521 {
522 auto callEntryMerge =
524 EXPECT_TRUE(is<CallEntryMemoryStateMergeOperation>(*callEntryMerge, 2, 1));
525 // There is no call exit split, as it has been removed by dead node elimination
526 EXPECT_EQ(test.CallF().output(2)->nusers(), 0u);
527
528 callEntryMerge =
530 EXPECT_TRUE(is<CallEntryMemoryStateMergeOperation>(*callEntryMerge, 1, 1));
531 EXPECT_EQ(test.CallG().output(2)->nusers(), 0u);
532 }
533}
534
535TEST(MemoryStateEncoderTests, callTest2AndersenAgnostic)
536{
537 using namespace jlm::llvm;
538 CallTest2 test;
539 encodeStates<aa::Andersen, aa::AgnosticModRefSummarizer>(test.module());
540
541 /* validate create function */
542 {
543 EXPECT_EQ(test.lambda_create->subregion()->numNodes(), 7u);
544
546 MallocOperation::memoryStateOutput(*test.malloc).SingleUser());
547 EXPECT_TRUE(is<MemoryStateJoinOperation>(*stateJoin, 2, 1));
548
549 auto lambdaEntrySplit =
550 jlm::rvsdg::TryGetOwnerNode<jlm::rvsdg::Node>(*stateJoin->input(1)->origin());
551 EXPECT_TRUE(is<LambdaEntryMemoryStateSplitOperation>(*lambdaEntrySplit, 1, 5));
552
553 auto lambdaExitMerge =
554 jlm::rvsdg::TryGetOwnerNode<jlm::rvsdg::Node>(stateJoin->output(0)->SingleUser());
555 EXPECT_TRUE(is<LambdaExitMemoryStateMergeOperation>(*lambdaExitMerge, 5, 1));
556
557 auto mallocStateLambdaEntryIndex = stateJoin->input(1)->origin()->index();
558 auto mallocStateLambdaExitIndex = stateJoin->output(0)->SingleUser().index();
559 EXPECT_EQ(mallocStateLambdaEntryIndex, mallocStateLambdaExitIndex);
560 }
561
562 /* validate destroy function */
563 {
564 EXPECT_EQ(test.lambda_destroy->subregion()->numNodes(), 4u);
565 }
566
567 /* validate test function */
568 {
569 EXPECT_EQ(test.lambda_test->subregion()->numNodes(), 16u);
570 }
571}
572
573TEST(MemoryStateEncoderTests, callTest2AndersenRegionAware)
574{
575 using namespace jlm::llvm;
576
577 CallTest2 test;
578 encodeStates<aa::Andersen, aa::RegionAwareModRefSummarizer>(test.module());
579
580 /* validate create function */
581 {
582 EXPECT_EQ(test.lambda_create->subregion()->numNodes(), 7u);
583
585 MallocOperation::memoryStateOutput(*test.malloc).SingleUser());
586 EXPECT_TRUE(is<MemoryStateJoinOperation>(*stateJoin, 2, 1));
587
588 auto lambdaEntrySplit =
589 jlm::rvsdg::TryGetOwnerNode<jlm::rvsdg::Node>(*stateJoin->input(1)->origin());
590 EXPECT_TRUE(is<LambdaEntryMemoryStateSplitOperation>(*lambdaEntrySplit, 1, 1));
591
592 auto lambdaExitMerge =
593 jlm::rvsdg::TryGetOwnerNode<jlm::rvsdg::Node>(stateJoin->output(0)->SingleUser());
594 EXPECT_TRUE(is<LambdaExitMemoryStateMergeOperation>(*lambdaExitMerge, 1, 1));
595
596 auto mallocStateLambdaEntryIndex = stateJoin->input(1)->origin()->index();
597 auto mallocStateLambdaExitIndex = stateJoin->output(0)->SingleUser().index();
598 EXPECT_EQ(mallocStateLambdaEntryIndex, mallocStateLambdaExitIndex);
599 }
600
601 /* validate destroy function */
602 {
603 EXPECT_EQ(test.lambda_destroy->subregion()->numNodes(), 4u);
604 }
605
606 /* validate test function */
607 {
608 EXPECT_EQ(test.lambda_test->subregion()->numNodes(), 16u);
609 }
610}
611
612TEST(MemoryStateEncoderTests, indirectCallTest1AndersenAgnostic)
613{
614 using namespace jlm::llvm;
615
617 encodeStates<aa::Andersen, aa::AgnosticModRefSummarizer>(test.module());
618
619 /* validate indcall function */
620 {
621 EXPECT_EQ(test.GetLambdaIndcall().subregion()->numNodes(), 6u);
622
624 *test.GetLambdaIndcall().GetFunctionResults()[2]->origin());
625 EXPECT_TRUE(is<LambdaExitMemoryStateMergeOperation>(*lambda_exit_mux, 5, 1));
626
627 auto call_exit_mux =
628 jlm::rvsdg::TryGetOwnerNode<jlm::rvsdg::Node>(*lambda_exit_mux->input(0)->origin());
629 EXPECT_TRUE(is<CallExitMemoryStateSplitOperation>(*call_exit_mux, 1, 5));
630
631 auto call = jlm::rvsdg::TryGetOwnerNode<jlm::rvsdg::Node>(*call_exit_mux->input(0)->origin());
632 EXPECT_TRUE(is<CallOperation>(*call, 3, 3));
633
634 auto call_entry_mux = jlm::rvsdg::TryGetOwnerNode<jlm::rvsdg::Node>(*call->input(2)->origin());
635 EXPECT_TRUE(is<CallEntryMemoryStateMergeOperation>(*call_entry_mux, 5, 1));
636
637 auto lambda_entry_mux =
638 jlm::rvsdg::TryGetOwnerNode<jlm::rvsdg::Node>(*call_entry_mux->input(2)->origin());
639 EXPECT_TRUE(is<LambdaEntryMemoryStateSplitOperation>(*lambda_entry_mux, 1, 5));
640 }
641
642 /* validate test function */
643 {
644 EXPECT_EQ(test.GetLambdaTest().subregion()->numNodes(), 9u);
645
647 *test.GetLambdaTest().GetFunctionResults()[2]->origin());
648 EXPECT_TRUE(is<LambdaExitMemoryStateMergeOperation>(*lambda_exit_mux, 5, 1));
649
650 auto call_exit_mux =
651 jlm::rvsdg::TryGetOwnerNode<jlm::rvsdg::Node>(*lambda_exit_mux->input(0)->origin());
652 EXPECT_TRUE(is<CallExitMemoryStateSplitOperation>(*call_exit_mux, 1, 5));
653
654 auto call = jlm::rvsdg::TryGetOwnerNode<jlm::rvsdg::Node>(*call_exit_mux->input(0)->origin());
655 EXPECT_TRUE(is<CallOperation>(*call, 4, 3));
656
657 auto call_entry_mux = jlm::rvsdg::TryGetOwnerNode<jlm::rvsdg::Node>(*call->input(3)->origin());
658 EXPECT_TRUE(is<CallEntryMemoryStateMergeOperation>(*call_entry_mux, 5, 1));
659
660 call_exit_mux =
661 jlm::rvsdg::TryGetOwnerNode<jlm::rvsdg::Node>(*call_entry_mux->input(0)->origin());
662 EXPECT_TRUE(is<CallExitMemoryStateSplitOperation>(*call_exit_mux, 1, 5));
663
664 call = jlm::rvsdg::TryGetOwnerNode<jlm::rvsdg::Node>(*call_exit_mux->input(0)->origin());
665 EXPECT_TRUE(is<CallOperation>(*call, 4, 3));
666
667 call_entry_mux = jlm::rvsdg::TryGetOwnerNode<jlm::rvsdg::Node>(*call->input(3)->origin());
668 EXPECT_TRUE(is<CallEntryMemoryStateMergeOperation>(*call_entry_mux, 5, 1));
669
670 auto lambda_entry_mux =
671 jlm::rvsdg::TryGetOwnerNode<jlm::rvsdg::Node>(*call_entry_mux->input(2)->origin());
672 EXPECT_TRUE(is<LambdaEntryMemoryStateSplitOperation>(*lambda_entry_mux, 1, 5));
673 }
674}
675
676TEST(MemoryStateEncoderTests, indirectCallTest1AndersenRegionAware)
677{
678 using namespace jlm::llvm;
679
681 encodeStates<aa::Andersen, aa::RegionAwareModRefSummarizer>(test.module());
682
683 /* validate indcall function */
684 {
685 EXPECT_EQ(test.GetLambdaIndcall().subregion()->numNodes(), 4u);
686
688 *test.GetLambdaIndcall().GetFunctionResults()[2]->origin());
689 EXPECT_TRUE(is<LambdaExitMemoryStateMergeOperation>(*lambdaExitMerge, 0, 1));
690
692 *test.GetLambdaIndcall().GetFunctionResults()[0]->origin());
693 EXPECT_TRUE(is<CallOperation>(*call, 3, 3));
694
695 auto callEntryMerge = jlm::rvsdg::TryGetOwnerNode<jlm::rvsdg::Node>(*call->input(2)->origin());
696 EXPECT_TRUE(is<CallEntryMemoryStateMergeOperation>(*callEntryMerge, 0, 1));
697 }
698
699 /* validate test function */
700 {
701 EXPECT_EQ(test.GetLambdaTest().subregion()->numNodes(), 6u);
702
704 *test.GetLambdaTest().GetFunctionResults()[2]->origin());
705 EXPECT_TRUE(is<LambdaExitMemoryStateMergeOperation>(*lambdaExitMerge, 0, 1));
706
708 *test.GetLambdaTest().GetFunctionResults()[0]->origin());
709 EXPECT_TRUE(is<jlm::rvsdg::BinaryOperation>(*add, 2, 1));
710
711 auto call = jlm::rvsdg::TryGetOwnerNode<jlm::rvsdg::Node>(*add->input(0)->origin());
712 EXPECT_TRUE(is<CallOperation>(*call, 4, 3));
713
714 auto callEntryMerge = jlm::rvsdg::TryGetOwnerNode<jlm::rvsdg::Node>(*call->input(3)->origin());
715 EXPECT_TRUE(is<CallEntryMemoryStateMergeOperation>(*callEntryMerge, 0, 1));
716
717 call = jlm::rvsdg::TryGetOwnerNode<jlm::rvsdg::Node>(*add->input(1)->origin());
718 EXPECT_TRUE(is<CallOperation>(*call, 4, 3));
719
720 callEntryMerge = jlm::rvsdg::TryGetOwnerNode<jlm::rvsdg::Node>(*call->input(3)->origin());
721 EXPECT_TRUE(is<CallEntryMemoryStateMergeOperation>(*callEntryMerge, 0, 1));
722 }
723}
724
725TEST(MemoryStateEncoderTests, indirectCallTest2AndersenAgnostic)
726{
727 using namespace jlm::llvm;
728
730 encodeStates<aa::Andersen, aa::AgnosticModRefSummarizer>(test.module());
731
732 // validate function three()
733 {
734 EXPECT_EQ(test.GetLambdaThree().subregion()->numNodes(), 3u);
735
737 *test.GetLambdaThree().GetFunctionResults()[2]->origin());
738 EXPECT_TRUE(is<LambdaExitMemoryStateMergeOperation>(*lambdaExitMerge, 13, 1));
739
740 auto lambdaEntrySplit = jlm::rvsdg::TryGetOwnerNode<jlm::rvsdg::Node>(
741 test.GetLambdaThree().GetFunctionArguments()[1]->SingleUser());
742 EXPECT_TRUE(is<LambdaEntryMemoryStateSplitOperation>(*lambdaEntrySplit, 1, 13));
743 }
744
745 // validate function four()
746 {
747 EXPECT_EQ(test.GetLambdaFour().subregion()->numNodes(), 3u);
748
750 *test.GetLambdaFour().GetFunctionResults()[2]->origin());
751 EXPECT_TRUE(is<LambdaExitMemoryStateMergeOperation>(*lambdaExitMerge, 13, 1));
752
753 auto lambdaEntrySplit = jlm::rvsdg::TryGetOwnerNode<jlm::rvsdg::Node>(
754 test.GetLambdaFour().GetFunctionArguments()[1]->SingleUser());
755 EXPECT_TRUE(is<LambdaEntryMemoryStateSplitOperation>(*lambdaEntrySplit, 1, 13));
756 }
757
758 // validate function i()
759 {
760 EXPECT_EQ(test.GetLambdaI().subregion()->numNodes(), 6u);
761
763 *test.GetLambdaI().GetFunctionResults()[2]->origin());
764 EXPECT_TRUE(is<LambdaExitMemoryStateMergeOperation>(*lambdaExitMerge, 13, 1));
765
766 auto callExitSplit =
767 jlm::rvsdg::TryGetOwnerNode<jlm::rvsdg::Node>(*lambdaExitMerge->input(0)->origin());
768 EXPECT_TRUE(is<CallExitMemoryStateSplitOperation>(*callExitSplit, 1, 13));
769
770 auto callEntryMerge =
772 EXPECT_TRUE(is<CallEntryMemoryStateMergeOperation>(*callEntryMerge, 13, 1));
773
774 auto lambdaEntrySplit =
775 jlm::rvsdg::TryGetOwnerNode<jlm::rvsdg::Node>(*callEntryMerge->input(0)->origin());
776 EXPECT_TRUE(is<LambdaEntryMemoryStateSplitOperation>(*lambdaEntrySplit, 1, 13));
777 }
778}
779
780TEST(MemoryStateEncoderTests, indirectCallTest2AndersenRegionAware)
781{
782 using namespace jlm::llvm;
783
785 encodeStates<aa::Andersen, aa::RegionAwareModRefSummarizer>(test.module());
786
787 // validate function three()
788 {
789 EXPECT_EQ(test.GetLambdaThree().subregion()->numNodes(), 2u);
790
792 *test.GetLambdaThree().GetFunctionResults()[2]->origin());
793 EXPECT_TRUE(is<LambdaExitMemoryStateMergeOperation>(*lambdaExitMerge, 0, 1));
794 }
795
796 // validate function four()
797 {
798 EXPECT_EQ(test.GetLambdaFour().subregion()->numNodes(), 2u);
799
801 *test.GetLambdaFour().GetFunctionResults()[2]->origin());
802 EXPECT_TRUE(is<LambdaExitMemoryStateMergeOperation>(*lambdaExitMerge, 0, 1));
803 }
804
805 // validate function i()
806 {
807 EXPECT_EQ(test.GetLambdaI().subregion()->numNodes(), 4u);
808
810 *test.GetLambdaI().GetFunctionResults()[2]->origin());
811 EXPECT_TRUE(is<LambdaExitMemoryStateMergeOperation>(*lambdaExitMerge, 0, 1));
812
813 auto callEntryMerge =
815 EXPECT_TRUE(is<CallEntryMemoryStateMergeOperation>(*callEntryMerge, 0, 1));
816 }
817
818 // validate function x()
819 {
820 EXPECT_EQ(test.GetLambdaX().subregion()->numNodes(), 7u);
821
823 *test.GetLambdaX().GetFunctionResults()[2]->origin());
824 EXPECT_TRUE(is<LambdaExitMemoryStateMergeOperation>(*lambdaExitMerge, 2, 1));
825
826 auto callEntryMerge =
828 EXPECT_TRUE(is<CallEntryMemoryStateMergeOperation>(*callEntryMerge, 0, 1));
829 }
830
831 // validate function y()
832 {
833 EXPECT_EQ(test.GetLambdaY().subregion()->numNodes(), 7u);
834
836 *test.GetLambdaY().GetFunctionResults()[2]->origin());
837 EXPECT_TRUE(is<LambdaExitMemoryStateMergeOperation>(*lambdaExitMerge, 1, 1));
838
839 auto callEntryMerge =
841 EXPECT_TRUE(is<CallEntryMemoryStateMergeOperation>(*callEntryMerge, 0, 1));
842 }
843
844 // validate function test()
845 {
846 EXPECT_EQ(test.GetLambdaTest().subregion()->numNodes(), 13u);
847
848 // There is no lambda entry split, as no memory states are routed into the function body
849 EXPECT_TRUE(test.GetLambdaTest().GetFunctionArguments().back()->IsDead());
850
852 *test.GetLambdaTest().GetFunctionResults()[2]->origin());
853 EXPECT_TRUE(is<LambdaExitMemoryStateMergeOperation>(*lambdaExitMerge, 0, 1));
854
855 // The variables g1 and g2 are effectively read-only, since they never get stored to.
856 // This means their loads do not have any memory state edges going through them.
858 test.GetLambdaTest().GetContextVars()[2].inner->SingleUser());
859 EXPECT_TRUE(is<LoadNonVolatileOperation>(*loadG1, 1, 1));
860
862 test.GetLambdaTest().GetContextVars()[3].inner->SingleUser());
863 EXPECT_TRUE(is<LoadNonVolatileOperation>(*loadG2, 1, 1));
864 }
865
866 // validate function test2()
867 {
868 EXPECT_EQ(test.GetLambdaTest2().subregion()->numNodes(), 5u);
869
870 // There is no lambda entry split, as no memory states are routed into the function body
871 EXPECT_TRUE(test.GetLambdaTest2().GetFunctionArguments().back()->IsDead());
872
874 *test.GetLambdaTest2().GetFunctionResults()[2]->origin());
875 EXPECT_TRUE(is<LambdaExitMemoryStateMergeOperation>(*lambdaExitMerge, 0, 1));
876 }
877}
878
879TEST(MemoryStateEncoderTests, gammaTestAndersenAgnostic)
880{
881 using namespace jlm::llvm;
882
883 GammaTest test;
884 encodeStates<aa::Andersen, aa::AgnosticModRefSummarizer>(test.module());
885
887 *test.lambda->GetFunctionResults()[1]->origin());
888 EXPECT_TRUE(is<LambdaExitMemoryStateMergeOperation>(*lambdaExitMerge, 2, 1));
889
890 auto loadTmp2 =
891 jlm::rvsdg::TryGetOwnerNode<jlm::rvsdg::Node>(*lambdaExitMerge->input(0)->origin());
892 EXPECT_TRUE(is<LoadNonVolatileOperation>(*loadTmp2, 3, 3));
893
894 auto loadTmp1 = jlm::rvsdg::TryGetOwnerNode<jlm::rvsdg::Node>(*loadTmp2->input(1)->origin());
895 EXPECT_TRUE(is<LoadNonVolatileOperation>(*loadTmp1, 3, 3));
896
897 auto gamma = jlm::rvsdg::TryGetOwnerNode<jlm::rvsdg::Node>(*loadTmp1->input(1)->origin());
898 EXPECT_EQ(gamma, test.gamma);
899}
900
901TEST(MemoryStateEncoderTests, gammaTestAndersenRegionAware)
902{
903 using namespace jlm::llvm;
904
905 GammaTest test;
906 encodeStates<aa::Andersen, aa::RegionAwareModRefSummarizer>(test.module());
907
909 *test.lambda->GetFunctionResults()[1]->origin());
910 EXPECT_TRUE(is<LambdaExitMemoryStateMergeOperation>(*lambdaExitMerge, 1, 1));
911
912 auto loadTmp2 =
913 jlm::rvsdg::TryGetOwnerNode<jlm::rvsdg::Node>(*lambdaExitMerge->input(0)->origin());
914 EXPECT_TRUE(is<LoadNonVolatileOperation>(*loadTmp2, 2, 2));
915
916 auto loadTmp1 = jlm::rvsdg::TryGetOwnerNode<jlm::rvsdg::Node>(*loadTmp2->input(1)->origin());
917 EXPECT_TRUE(is<LoadNonVolatileOperation>(*loadTmp1, 2, 2));
918
919 auto lambdaEntrySplit =
920 jlm::rvsdg::TryGetOwnerNode<jlm::rvsdg::Node>(*loadTmp1->input(1)->origin());
921 EXPECT_TRUE(is<LambdaEntryMemoryStateSplitOperation>(*lambdaEntrySplit, 1, 1));
922}
923
924TEST(MemoryStateEncoderTests, thetaTestAndersenAgnostic)
925{
926 using namespace jlm::llvm;
927
928 ThetaTest test;
929 encodeStates<aa::Andersen, aa::AgnosticModRefSummarizer>(test.module());
930
931 EXPECT_EQ(test.lambda->subregion()->numNodes(), 4u);
932
934 *test.lambda->GetFunctionResults()[0]->origin());
935 EXPECT_TRUE(is<LambdaExitMemoryStateMergeOperation>(*lambda_exit_mux, 2, 1));
936
937 auto thetaOutput = lambda_exit_mux->input(0)->origin();
939 EXPECT_EQ(theta, test.theta);
940
941 auto loopvar = theta->MapOutputLoopVar(*thetaOutput);
942 auto storeStateOutput = loopvar.post->origin();
943 auto store = jlm::rvsdg::TryGetOwnerNode<jlm::rvsdg::Node>(*storeStateOutput);
944 EXPECT_TRUE(is<StoreNonVolatileOperation>(*store, 4, 2));
945 EXPECT_EQ(store->input(storeStateOutput->index() + 2)->origin(), loopvar.pre);
946
947 auto lambda_entry_mux = jlm::rvsdg::TryGetOwnerNode<jlm::rvsdg::Node>(*loopvar.input->origin());
948 EXPECT_TRUE(is<LambdaEntryMemoryStateSplitOperation>(*lambda_entry_mux, 1, 2));
949}
950
951TEST(MemoryStateEncoderTests, thetaTestAndersenRegionAware)
952{
953 using namespace jlm::llvm;
954
955 ThetaTest test;
956 encodeStates<aa::Andersen, aa::RegionAwareModRefSummarizer>(test.module());
957
958 EXPECT_EQ(test.lambda->subregion()->numNodes(), 4u);
959
961 *test.lambda->GetFunctionResults()[0]->origin());
962 EXPECT_TRUE(is<LambdaExitMemoryStateMergeOperation>(*lambdaExitMerge, 1, 1));
963
964 auto thetaOutput = lambdaExitMerge->input(0)->origin();
966 EXPECT_EQ(theta, test.theta);
967 auto loopvar = theta->MapOutputLoopVar(*thetaOutput);
968
969 auto storeStateOutput = loopvar.post->origin();
970 auto store = jlm::rvsdg::TryGetOwnerNode<jlm::rvsdg::Node>(*storeStateOutput);
971 EXPECT_TRUE(is<StoreNonVolatileOperation>(*store, 3, 1));
972 EXPECT_EQ(store->input(storeStateOutput->index() + 2)->origin(), loopvar.pre);
973
974 auto lambdaEntrySplit = jlm::rvsdg::TryGetOwnerNode<jlm::rvsdg::Node>(*loopvar.input->origin());
975 EXPECT_TRUE(is<LambdaEntryMemoryStateSplitOperation>(*lambdaEntrySplit, 1, 1));
976}
977
978TEST(MemoryStateEncoderTests, deltaTest1AndersenAgnostic)
979{
980 using namespace jlm::llvm;
981
982 DeltaTest1 test;
983 encodeStates<aa::Andersen, aa::AgnosticModRefSummarizer>(test.module());
984
985 EXPECT_EQ(test.lambda_h->subregion()->numNodes(), 7u);
986
987 auto lambdaEntrySplit = jlm::rvsdg::TryGetOwnerNode<jlm::rvsdg::Node>(
988 test.lambda_h->GetFunctionArguments()[1]->SingleUser());
989 EXPECT_TRUE(is<LambdaEntryMemoryStateSplitOperation>(*lambdaEntrySplit, 1, 4));
990
991 auto storeF =
993 EXPECT_TRUE(is<StoreNonVolatileOperation>(*storeF, 3, 1));
994 EXPECT_EQ(
995 jlm::rvsdg::TryGetOwnerNode<jlm::rvsdg::Node>(*storeF->input(2)->origin()),
996 lambdaEntrySplit);
997
998 auto deltaStateIndex = storeF->input(2)->origin()->index();
999
1001 test.lambda_g->GetFunctionArguments()[0]->SingleUser());
1002 EXPECT_TRUE(is<LoadNonVolatileOperation>(*loadF, 2, 2));
1003 EXPECT_EQ(loadF->input(1)->origin()->index(), deltaStateIndex);
1004}
1005
1006TEST(MemoryStateEncoderTests, deltaTest1AndersenRegionAware)
1007{
1008 using namespace jlm::llvm;
1009
1010 DeltaTest1 test;
1011 encodeStates<aa::Andersen, aa::RegionAwareModRefSummarizer>(test.module());
1012
1013 EXPECT_EQ(test.lambda_h->subregion()->numNodes(), 7u);
1014
1015 auto lambdaEntrySplit = jlm::rvsdg::TryGetOwnerNode<jlm::rvsdg::Node>(
1016 test.lambda_h->GetFunctionArguments()[1]->SingleUser());
1017 EXPECT_TRUE(is<LambdaEntryMemoryStateSplitOperation>(*lambdaEntrySplit, 1, 1));
1018
1019 auto storeF =
1021 EXPECT_TRUE(is<StoreNonVolatileOperation>(*storeF, 3, 1));
1022 EXPECT_EQ(
1023 jlm::rvsdg::TryGetOwnerNode<jlm::rvsdg::Node>(*storeF->input(2)->origin()),
1024 lambdaEntrySplit);
1025
1026 auto deltaStateIndex = storeF->input(2)->origin()->index();
1027
1029 test.lambda_g->GetFunctionArguments()[0]->SingleUser());
1030 EXPECT_TRUE(is<LoadNonVolatileOperation>(*loadF, 2, 2));
1031 EXPECT_EQ(loadF->input(1)->origin()->index(), deltaStateIndex);
1032}
1033
1034TEST(MemoryStateEncoderTests, deltaTest2AndersenAgnostic)
1035{
1036 using namespace jlm::llvm;
1037
1038 DeltaTest2 test;
1039 encodeStates<aa::Andersen, aa::AgnosticModRefSummarizer>(test.module());
1040
1041 EXPECT_EQ(test.lambda_f2->subregion()->numNodes(), 9u);
1042
1043 auto lambdaEntrySplit = jlm::rvsdg::TryGetOwnerNode<jlm::rvsdg::Node>(
1044 test.lambda_f2->GetFunctionArguments()[1]->SingleUser());
1045 EXPECT_TRUE(is<LambdaEntryMemoryStateSplitOperation>(*lambdaEntrySplit, 1, 5));
1046
1048 test.lambda_f2->GetContextVars()[0].inner->SingleUser());
1049 EXPECT_TRUE(is<StoreNonVolatileOperation>(*storeD1InF2, 3, 1));
1050 EXPECT_EQ(
1051 jlm::rvsdg::TryGetOwnerNode<jlm::rvsdg::Node>(*storeD1InF2->input(2)->origin()),
1052 lambdaEntrySplit);
1053
1054 auto d1StateIndex = storeD1InF2->input(2)->origin()->index();
1055
1057 test.lambda_f1->GetContextVars()[0].inner->SingleUser());
1058 EXPECT_TRUE(is<StoreNonVolatileOperation>(*storeD1InF1, 3, 1));
1059
1060 EXPECT_EQ(d1StateIndex, storeD1InF1->input(2)->origin()->index());
1061
1063 test.lambda_f2->GetContextVars()[1].inner->SingleUser());
1064 EXPECT_TRUE(is<StoreNonVolatileOperation>(*storeD1InF2, 3, 1));
1065
1066 EXPECT_NE(d1StateIndex, storeD2InF2->input(2)->origin()->index());
1067}
1068
1069TEST(MemoryStateEncoderTests, deltaTest2AndersenRegionAware)
1070{
1071 using namespace jlm::llvm;
1072
1073 DeltaTest2 test;
1074 encodeStates<aa::Andersen, aa::RegionAwareModRefSummarizer>(test.module());
1075
1076 /* Validate f1() */
1077 {
1078 EXPECT_EQ(test.lambda_f1->subregion()->numNodes(), 4u);
1079
1080 auto lambdaExitMerge = jlm::rvsdg::TryGetOwnerNode<jlm::rvsdg::Node>(
1081 *test.lambda_f1->GetFunctionResults()[1]->origin());
1082 EXPECT_TRUE(is<LambdaExitMemoryStateMergeOperation>(*lambdaExitMerge, 1, 1));
1083
1084 auto storeNode =
1085 jlm::rvsdg::TryGetOwnerNode<jlm::rvsdg::Node>(*lambdaExitMerge->input(0)->origin());
1086 EXPECT_TRUE(is<StoreNonVolatileOperation>(*storeNode, 3, 1));
1087
1088 auto lambdaEntrySplit =
1089 jlm::rvsdg::TryGetOwnerNode<jlm::rvsdg::Node>(*storeNode->input(2)->origin());
1090 EXPECT_TRUE(is<LambdaEntryMemoryStateSplitOperation>(*lambdaEntrySplit, 1, 1));
1091 }
1092
1093 /* Validate f2() */
1094 {
1095 EXPECT_EQ(test.lambda_f2->subregion()->numNodes(), 9u);
1096
1097 auto lambdaEntrySplit = jlm::rvsdg::TryGetOwnerNode<jlm::rvsdg::Node>(
1098 test.lambda_f2->GetFunctionArguments()[1]->SingleUser());
1099 EXPECT_TRUE(is<LambdaEntryMemoryStateSplitOperation>(*lambdaEntrySplit, 1, 2));
1100
1102 test.lambda_f2->GetContextVars()[0].inner->SingleUser());
1103 EXPECT_TRUE(is<StoreNonVolatileOperation>(*storeD1, 3, 1));
1104 EXPECT_EQ(
1105 jlm::rvsdg::TryGetOwnerNode<jlm::rvsdg::Node>(*storeD1->input(2)->origin()),
1106 lambdaEntrySplit);
1107
1109 test.lambda_f2->GetContextVars()[1].inner->SingleUser());
1110 EXPECT_TRUE(is<StoreNonVolatileOperation>(*storeD2, 3, 1));
1111 EXPECT_EQ(
1112 jlm::rvsdg::TryGetOwnerNode<jlm::rvsdg::Node>(*storeD2->input(2)->origin()),
1113 lambdaEntrySplit);
1114
1115 auto callEntryMerge =
1116 jlm::rvsdg::TryGetOwnerNode<jlm::rvsdg::Node>(storeD1->output(0)->SingleUser());
1117 EXPECT_TRUE(is<CallEntryMemoryStateMergeOperation>(*callEntryMerge, 1, 1));
1118
1119 auto callF1 =
1120 jlm::rvsdg::TryGetOwnerNode<jlm::rvsdg::Node>(callEntryMerge->output(0)->SingleUser());
1121 EXPECT_TRUE(is<CallOperation>(*callF1, 3, 2));
1122
1123 auto callExitSplit =
1124 jlm::rvsdg::TryGetOwnerNode<jlm::rvsdg::Node>(callF1->output(1)->SingleUser());
1125 EXPECT_TRUE(is<CallExitMemoryStateSplitOperation>(*callExitSplit, 1, 1));
1126
1127 auto lambdaExitMerge =
1128 jlm::rvsdg::TryGetOwnerNode<jlm::rvsdg::Node>(callExitSplit->output(0)->SingleUser());
1129 EXPECT_TRUE(is<LambdaExitMemoryStateMergeOperation>(*lambdaExitMerge, 2, 1));
1130 }
1131}
1132
1133TEST(MemoryStateEncoderTests, deltaTest3AndersenAgnostic)
1134{
1135 using namespace jlm::llvm;
1136
1137 DeltaTest3 test;
1138 encodeStates<aa::Andersen, aa::AgnosticModRefSummarizer>(test.module());
1139
1140 /* validate f() */
1141 {
1142 EXPECT_EQ(test.LambdaF().subregion()->numNodes(), 6u);
1143
1144 auto lambdaExitMerge = jlm::rvsdg::TryGetOwnerNode<jlm::rvsdg::Node>(
1145 *test.LambdaF().GetFunctionResults()[2]->origin());
1146 EXPECT_TRUE(is<LambdaExitMemoryStateMergeOperation>(*lambdaExitMerge, 5, 1));
1147
1149 *test.LambdaF().GetFunctionResults()[0]->origin());
1150 EXPECT_TRUE(is<TruncOperation>(*truncNode, 1, 1));
1151
1152 auto loadG1Node = jlm::rvsdg::TryGetOwnerNode<jlm::rvsdg::Node>(*truncNode->input(0)->origin());
1153 EXPECT_TRUE(is<LoadNonVolatileOperation>(*loadG1Node, 2, 2));
1154
1155 auto lambdaEntrySplit =
1156 jlm::rvsdg::TryGetOwnerNode<jlm::rvsdg::Node>(*loadG1Node->input(1)->origin());
1157 EXPECT_TRUE(is<LambdaEntryMemoryStateSplitOperation>(*lambdaEntrySplit, 1, 5));
1158
1159 jlm::rvsdg::Node * storeG2Node = nullptr;
1160 for (size_t n = 0; n < lambdaExitMerge->ninputs(); n++)
1161 {
1162 auto input = lambdaExitMerge->input(n);
1163 auto node = jlm::rvsdg::TryGetOwnerNode<jlm::rvsdg::Node>(*input->origin());
1164 if (is<StoreNonVolatileOperation>(node))
1165 {
1166 storeG2Node = node;
1167 break;
1168 }
1169 }
1170 EXPECT_NE(storeG2Node, nullptr);
1171
1172 auto loadG2Node =
1174 EXPECT_TRUE(is<LoadNonVolatileOperation>(*loadG2Node, 2, 2));
1175
1176 auto node = jlm::rvsdg::TryGetOwnerNode<jlm::rvsdg::Node>(*loadG2Node->input(1)->origin());
1177 EXPECT_EQ(node, lambdaEntrySplit);
1178 }
1179}
1180
1181TEST(MemoryStateEncoderTests, deltaTest3AndersenRegionAware)
1182{
1183 using namespace jlm::llvm;
1184
1185 DeltaTest3 test;
1186 encodeStates<aa::Andersen, aa::RegionAwareModRefSummarizer>(test.module());
1187
1188 /* validate f() */
1189 {
1190 EXPECT_EQ(test.LambdaF().subregion()->numNodes(), 6u);
1191
1192 auto lambdaExitMerge = jlm::rvsdg::TryGetOwnerNode<jlm::rvsdg::Node>(
1193 *test.LambdaF().GetFunctionResults()[2]->origin());
1194 EXPECT_TRUE(is<LambdaExitMemoryStateMergeOperation>(*lambdaExitMerge, 1, 1));
1195
1197 *test.LambdaF().GetFunctionResults()[0]->origin());
1198 EXPECT_TRUE(is<TruncOperation>(*truncNode, 1, 1));
1199
1200 // g1 is only loaded, making it effectively constant, so no memory states are routed through
1201 auto loadG1Node = jlm::rvsdg::TryGetOwnerNode<jlm::rvsdg::Node>(*truncNode->input(0)->origin());
1202 EXPECT_TRUE(is<LoadNonVolatileOperation>(*loadG1Node, 1, 1));
1203
1204 jlm::rvsdg::Node * storeG2Node = nullptr;
1205 for (size_t n = 0; n < lambdaExitMerge->ninputs(); n++)
1206 {
1207 auto input = lambdaExitMerge->input(n);
1208 auto node = jlm::rvsdg::TryGetOwnerNode<jlm::rvsdg::Node>(*input->origin());
1209 if (is<StoreNonVolatileOperation>(node))
1210 {
1211 storeG2Node = node;
1212 break;
1213 }
1214 }
1215 EXPECT_NE(storeG2Node, nullptr);
1216
1217 auto loadG2Node =
1219 EXPECT_TRUE(is<LoadNonVolatileOperation>(*loadG2Node, 2, 2));
1220
1221 // The load of g2 has a memory state input from the LambdaEntrySplit
1222 auto lambdaEntrySplit =
1223 jlm::rvsdg::TryGetOwnerNode<jlm::rvsdg::Node>(*loadG2Node->input(1)->origin());
1224 EXPECT_TRUE(is<LambdaEntryMemoryStateSplitOperation>(*lambdaEntrySplit, 1, 1));
1225 }
1226}
1227
1228TEST(MemoryStateEncoderTests, importTestAndersenAgnostic)
1229{
1230 using namespace jlm::llvm;
1231
1232 ImportTest test;
1233 encodeStates<aa::Andersen, aa::AgnosticModRefSummarizer>(test.module());
1234
1235 EXPECT_EQ(test.lambda_f2->subregion()->numNodes(), 9u);
1236
1237 auto lambdaEntrySplit = jlm::rvsdg::TryGetOwnerNode<jlm::rvsdg::Node>(
1238 test.lambda_f2->GetFunctionArguments()[1]->SingleUser());
1239 EXPECT_TRUE(is<LambdaEntryMemoryStateSplitOperation>(*lambdaEntrySplit, 1, 5));
1240
1242 test.lambda_f2->GetContextVars()[0].inner->SingleUser());
1243 EXPECT_TRUE(is<StoreNonVolatileOperation>(*storeD1InF2, 3, 1));
1244 EXPECT_EQ(
1245 jlm::rvsdg::TryGetOwnerNode<jlm::rvsdg::Node>(*storeD1InF2->input(2)->origin()),
1246 lambdaEntrySplit);
1247
1248 auto d1StateIndex = storeD1InF2->input(2)->origin()->index();
1249
1251 test.lambda_f1->GetContextVars()[0].inner->SingleUser());
1252 EXPECT_TRUE(is<StoreNonVolatileOperation>(*storeD1InF1, 3, 1));
1253
1254 EXPECT_EQ(d1StateIndex, storeD1InF1->input(2)->origin()->index());
1255
1257 test.lambda_f2->GetContextVars()[1].inner->SingleUser());
1258 EXPECT_TRUE(is<StoreNonVolatileOperation>(*storeD1InF2, 3, 1));
1259
1260 EXPECT_NE(d1StateIndex, storeD2InF2->input(2)->origin()->index());
1261}
1262
1263TEST(MemoryStateEncoderTests, importTestAndersenRegionAware)
1264{
1265 using namespace jlm::llvm;
1266
1267 ImportTest test;
1268 encodeStates<aa::Andersen, aa::RegionAwareModRefSummarizer>(test.module());
1269
1270 /* Validate f1() */
1271 {
1272 EXPECT_EQ(test.lambda_f1->subregion()->numNodes(), 4u);
1273
1274 auto lambdaExitMerge = jlm::rvsdg::TryGetOwnerNode<jlm::rvsdg::Node>(
1275 *test.lambda_f1->GetFunctionResults()[1]->origin());
1276 EXPECT_TRUE(is<LambdaExitMemoryStateMergeOperation>(*lambdaExitMerge, 1, 1));
1277
1278 auto storeNode =
1279 jlm::rvsdg::TryGetOwnerNode<jlm::rvsdg::Node>(*lambdaExitMerge->input(0)->origin());
1280 EXPECT_TRUE(is<StoreNonVolatileOperation>(*storeNode, 3, 1));
1281
1282 auto lambdaEntrySplit =
1283 jlm::rvsdg::TryGetOwnerNode<jlm::rvsdg::Node>(*storeNode->input(2)->origin());
1284 EXPECT_TRUE(is<LambdaEntryMemoryStateSplitOperation>(*lambdaEntrySplit, 1, 1));
1285 }
1286
1287 /* Validate f2() */
1288 {
1289 EXPECT_EQ(test.lambda_f2->subregion()->numNodes(), 9u);
1290
1291 auto lambdaEntrySplit = jlm::rvsdg::TryGetOwnerNode<jlm::rvsdg::Node>(
1292 test.lambda_f2->GetFunctionArguments()[1]->SingleUser());
1293 EXPECT_TRUE(is<LambdaEntryMemoryStateSplitOperation>(*lambdaEntrySplit, 1, 2));
1294
1296 test.lambda_f2->GetContextVars()[0].inner->SingleUser());
1297 EXPECT_TRUE(is<StoreNonVolatileOperation>(*storeD1, 3, 1));
1298 EXPECT_EQ(
1299 jlm::rvsdg::TryGetOwnerNode<jlm::rvsdg::Node>(*storeD1->input(2)->origin()),
1300 lambdaEntrySplit);
1301
1303 test.lambda_f2->GetContextVars()[1].inner->SingleUser());
1304 EXPECT_TRUE(is<StoreNonVolatileOperation>(*storeD2, 3, 1));
1305 EXPECT_EQ(
1306 jlm::rvsdg::TryGetOwnerNode<jlm::rvsdg::Node>(*storeD2->input(2)->origin()),
1307 lambdaEntrySplit);
1308
1309 auto callEntryMerge =
1310 jlm::rvsdg::TryGetOwnerNode<jlm::rvsdg::Node>(storeD1->output(0)->SingleUser());
1311 EXPECT_TRUE(is<CallEntryMemoryStateMergeOperation>(*callEntryMerge, 1, 1));
1312
1313 auto callF1 =
1314 jlm::rvsdg::TryGetOwnerNode<jlm::rvsdg::Node>(callEntryMerge->output(0)->SingleUser());
1315 EXPECT_TRUE(is<CallOperation>(*callF1, 3, 2));
1316
1317 auto callExitSplit =
1318 jlm::rvsdg::TryGetOwnerNode<jlm::rvsdg::Node>(callF1->output(1)->SingleUser());
1319 EXPECT_TRUE(is<CallExitMemoryStateSplitOperation>(*callExitSplit, 1, 1));
1320
1321 auto lambdaExitMerge =
1322 jlm::rvsdg::TryGetOwnerNode<jlm::rvsdg::Node>(callExitSplit->output(0)->SingleUser());
1323 EXPECT_TRUE(is<LambdaExitMemoryStateMergeOperation>(*lambdaExitMerge, 2, 1));
1324 }
1325}
1326
1327TEST(MemoryStateEncoderTests, phiTest1AndersenAgnostic)
1328{
1329 using namespace jlm::llvm;
1330
1331 PhiTest1 test;
1332 encodeStates<aa::Andersen, aa::AgnosticModRefSummarizer>(test.module());
1333
1335 test.alloca->output(1)->SingleUser());
1336 EXPECT_TRUE(joinNode && joinOp);
1337 auto arrayStateIndex = joinNode->output(0)->SingleUser().index();
1338
1339 auto lambdaExitMerge = jlm::rvsdg::TryGetOwnerNode<jlm::rvsdg::Node>(
1340 *test.lambda_fib->GetFunctionResults()[1]->origin());
1341 EXPECT_TRUE(is<LambdaExitMemoryStateMergeOperation>(*lambdaExitMerge, 4, 1));
1342
1344 *lambdaExitMerge->input(arrayStateIndex)->origin());
1345 EXPECT_TRUE(is<StoreNonVolatileOperation>(*store, 3, 1));
1346
1347 auto gamma = jlm::rvsdg::TryGetOwnerNode<jlm::rvsdg::Node>(*store->input(2)->origin());
1348 EXPECT_EQ(gamma, test.gamma);
1349
1350 auto gammaStateIndex = store->input(2)->origin()->index();
1351
1353 *test.gamma->GetExitVars()[gammaStateIndex].branchResult[0]->origin());
1354 EXPECT_TRUE(is<LoadNonVolatileOperation>(*load1, 2, 2));
1355
1356 auto load2 = jlm::rvsdg::TryGetOwnerNode<jlm::rvsdg::Node>(*load1->input(1)->origin());
1357 EXPECT_TRUE(is<LoadNonVolatileOperation>(*load2, 2, 2));
1358
1359 EXPECT_EQ(load2->input(1)->origin()->index(), arrayStateIndex);
1360}
1361
1362TEST(MemoryStateEncoderTests, phiTest1AndersenRegionAware)
1363{
1364 using namespace jlm::llvm;
1365
1366 PhiTest1 test;
1367 encodeStates<aa::Andersen, aa::RegionAwareModRefSummarizer>(test.module());
1368
1369 auto lambdaExitMerge = jlm::rvsdg::TryGetOwnerNode<jlm::rvsdg::Node>(
1370 *test.lambda_fib->GetFunctionResults()[1]->origin());
1371 EXPECT_TRUE(is<LambdaExitMemoryStateMergeOperation>(*lambdaExitMerge, 1, 1));
1372
1374 *test.lambda_fib->GetFunctionResults()[0]->origin());
1375 EXPECT_EQ(gamma, test.gamma);
1376
1377 // In the region aware, we know that the alloca is non-reentrant, so there is no Join
1379 test.alloca->output(1)->SingleUser());
1380 EXPECT_EQ(op, nullptr);
1381}
1382
1383TEST(MemoryStateEncoderTests, memCpyTestAndersenAgnostic)
1384{
1385 using namespace jlm::llvm;
1386
1387 MemcpyTest test;
1388 encodeStates<aa::Andersen, aa::AgnosticModRefSummarizer>(test.module());
1389
1390 /*
1391 * Validate function f
1392 */
1393 {
1394 auto lambdaExitMerge = jlm::rvsdg::TryGetOwnerNode<jlm::rvsdg::Node>(
1395 *test.LambdaF().GetFunctionResults()[2]->origin());
1396 EXPECT_TRUE(is<LambdaExitMemoryStateMergeOperation>(*lambdaExitMerge, 5, 1));
1397
1399 *test.LambdaF().GetFunctionResults()[0]->origin());
1400 EXPECT_TRUE(is<LoadNonVolatileOperation>(*load, 2, 2));
1401
1402 auto store = jlm::rvsdg::TryGetOwnerNode<jlm::rvsdg::Node>(*load->input(1)->origin());
1403 EXPECT_TRUE(is<StoreNonVolatileOperation>(*store, 3, 1));
1404
1405 auto lambdaEntrySplit =
1406 jlm::rvsdg::TryGetOwnerNode<jlm::rvsdg::Node>(*store->input(2)->origin());
1407 EXPECT_TRUE(is<LambdaEntryMemoryStateSplitOperation>(*lambdaEntrySplit, 1, 5));
1408 }
1409
1410 /*
1411 * Validate function g
1412 */
1413 {
1414 auto lambdaExitMerge = jlm::rvsdg::TryGetOwnerNode<jlm::rvsdg::Node>(
1415 *test.LambdaG().GetFunctionResults()[2]->origin());
1416 EXPECT_TRUE(is<LambdaExitMemoryStateMergeOperation>(*lambdaExitMerge, 5, 1));
1417
1418 auto callExitSplit =
1419 jlm::rvsdg::TryGetOwnerNode<jlm::rvsdg::Node>(*lambdaExitMerge->input(0)->origin());
1420 EXPECT_TRUE(is<CallExitMemoryStateSplitOperation>(*callExitSplit, 1, 5));
1421
1422 auto call = jlm::rvsdg::TryGetOwnerNode<jlm::rvsdg::Node>(*callExitSplit->input(0)->origin());
1423 EXPECT_TRUE(is<CallOperation>(*call, 3, 3));
1424
1425 auto callEntryMerge = jlm::rvsdg::TryGetOwnerNode<jlm::rvsdg::Node>(*call->input(2)->origin());
1426 EXPECT_TRUE(is<CallEntryMemoryStateMergeOperation>(*callEntryMerge, 5, 1));
1427
1428 jlm::rvsdg::Node * memcpy = nullptr;
1429 for (size_t n = 0; n < callEntryMerge->ninputs(); n++)
1430 {
1431 auto node =
1432 jlm::rvsdg::TryGetOwnerNode<jlm::rvsdg::Node>(*callEntryMerge->input(n)->origin());
1433 if (is<MemCpyNonVolatileOperation>(node))
1434 memcpy = node;
1435 }
1436 EXPECT_NE(memcpy, nullptr);
1437 EXPECT_TRUE(is<MemCpyNonVolatileOperation>(*memcpy, 5, 2));
1438
1439 auto lambdaEntrySplit =
1441 EXPECT_TRUE(is<LambdaEntryMemoryStateSplitOperation>(*lambdaEntrySplit, 1, 5));
1442 }
1443}
1444
1445TEST(MemoryStateEncoderTests, memCpyAndersenRegionAware)
1446{
1447 using namespace jlm::llvm;
1448
1449 MemcpyTest test;
1450 encodeStates<aa::Andersen, aa::RegionAwareModRefSummarizer>(test.module());
1451
1452 /*
1453 * Validate function f
1454 */
1455 {
1456 auto lambdaExitMerge = jlm::rvsdg::TryGetOwnerNode<jlm::rvsdg::Node>(
1457 *test.LambdaF().GetFunctionResults()[2]->origin());
1458 EXPECT_TRUE(is<LambdaExitMemoryStateMergeOperation>(*lambdaExitMerge, 1, 1));
1459
1461 *test.LambdaF().GetFunctionResults()[0]->origin());
1462 EXPECT_TRUE(is<LoadNonVolatileOperation>(*load, 2, 2));
1463
1464 auto store = jlm::rvsdg::TryGetOwnerNode<jlm::rvsdg::Node>(*load->input(1)->origin());
1465 EXPECT_TRUE(is<StoreNonVolatileOperation>(*store, 3, 1));
1466
1467 auto lambdaEntrySplit =
1468 jlm::rvsdg::TryGetOwnerNode<jlm::rvsdg::Node>(*store->input(2)->origin());
1469 EXPECT_TRUE(is<LambdaEntryMemoryStateSplitOperation>(*lambdaEntrySplit, 1, 1));
1470 }
1471
1472 /*
1473 * Validate function g
1474 */
1475 {
1477 test.LambdaG().GetContextVars()[2].inner->SingleUser());
1478 EXPECT_TRUE(is<CallOperation>(*callNode, 3, 3));
1479
1480 auto callEntryMerge =
1481 jlm::rvsdg::TryGetOwnerNode<jlm::rvsdg::Node>(*callNode->input(2)->origin());
1482 EXPECT_TRUE(is<CallEntryMemoryStateMergeOperation>(*callEntryMerge, 1, 1));
1483
1484 auto callExitSplit =
1485 jlm::rvsdg::TryGetOwnerNode<jlm::rvsdg::Node>(callNode->output(2)->SingleUser());
1486 EXPECT_TRUE(is<CallExitMemoryStateSplitOperation>(*callExitSplit, 1, 1));
1487
1488 auto memcpyNode =
1489 jlm::rvsdg::TryGetOwnerNode<jlm::rvsdg::Node>(*callEntryMerge->input(0)->origin());
1490 EXPECT_TRUE(is<MemCpyNonVolatileOperation>(*memcpyNode, 5, 2));
1491
1492 auto lambdaEntrySplit =
1493 jlm::rvsdg::TryGetOwnerNode<jlm::rvsdg::Node>(*memcpyNode->input(3)->origin());
1494 EXPECT_TRUE(is<LambdaEntryMemoryStateSplitOperation>(*lambdaEntrySplit, 1, 2));
1495 EXPECT_EQ(
1496 jlm::rvsdg::TryGetOwnerNode<jlm::rvsdg::Node>(*memcpyNode->input(4)->origin()),
1497 lambdaEntrySplit);
1498
1499 auto lambdaExitMerge =
1500 jlm::rvsdg::TryGetOwnerNode<jlm::rvsdg::Node>(callExitSplit->output(0)->SingleUser());
1501 EXPECT_TRUE(is<LambdaExitMemoryStateMergeOperation>(*lambdaExitMerge, 2, 1));
1502 }
1503}
1504
1505TEST(MemoryStateEncoderTests, freeNullTestAndersenAgnostic)
1506{
1507 using namespace jlm::llvm;
1508 using namespace jlm::rvsdg;
1509
1510 FreeNullTest test;
1511 encodeStates<aa::Andersen, aa::AgnosticModRefSummarizer>(test.module());
1512
1513 auto lambdaExitMerge = jlm::rvsdg::TryGetOwnerNode<jlm::rvsdg::Node>(
1514 *GetMemoryStateRegionResult(test.LambdaMain()).origin());
1515 EXPECT_TRUE(is<LambdaExitMemoryStateMergeOperation>(*lambdaExitMerge, 2, 1));
1516
1518 *test.LambdaMain().GetFunctionResults()[0]->origin());
1519 EXPECT_TRUE(is<FreeOperation>(*free, 2, 1));
1520
1521 auto lambdaEntrySplit =
1522 jlm::rvsdg::TryGetOwnerNode<jlm::rvsdg::Node>(*lambdaExitMerge->input(0)->origin());
1523 EXPECT_TRUE(is<LambdaEntryMemoryStateSplitOperation>(*lambdaEntrySplit, 1, 2));
1524}
1525
1526TEST(MemoryStateEncoderTests, LambdaMemoryStateArgumentMultipleUsers)
1527{
1528 using namespace jlm::llvm;
1529 using namespace jlm::rvsdg;
1530 using namespace jlm::util;
1531
1532 // Arrange
1533 auto bitType32 = BitType::Create(32);
1534 auto ioStateType = IOStateType::Create();
1535 auto memoryStateType = MemoryStateType::Create();
1536 auto pointerType = PointerType::Create();
1537 auto functionTypeOne = FunctionType::Create(
1538 { ioStateType, memoryStateType },
1539 { bitType32, ioStateType, memoryStateType });
1540 auto functionTypeMain = FunctionType::Create(
1541 { pointerType, ioStateType, memoryStateType },
1542 { bitType32, ioStateType, memoryStateType });
1543
1544 jlm::llvm::LlvmRvsdgModule rvsdgModule(FilePath(""), "", "");
1545 auto & rvsdg = rvsdgModule.Rvsdg();
1546
1547 LambdaNode * lambdaOne = nullptr;
1548 {
1549 lambdaOne = LambdaNode::Create(
1550 rvsdg.GetRootRegion(),
1551 LlvmLambdaOperation::Create(functionTypeOne, "one", Linkage::privateLinkage));
1552 auto ioStateArgument = lambdaOne->GetFunctionArguments()[0];
1553 auto memoryStateArgument = lambdaOne->GetFunctionArguments()[1];
1554
1555 auto & one = IntegerConstantOperation::Create(*lambdaOne->subregion(), 32, 1);
1556
1557 lambdaOne->finalize({ one.output(0), ioStateArgument, memoryStateArgument });
1558 }
1559
1560 LambdaNode * lambdaMain = nullptr;
1561 {
1562 lambdaMain = LambdaNode::Create(
1563 rvsdg.GetRootRegion(),
1564 LlvmLambdaOperation::Create(functionTypeMain, "main", Linkage::externalLinkage));
1565 auto pointerArgument = lambdaMain->GetFunctionArguments()[0];
1566 auto ioStateArgument = lambdaMain->GetFunctionArguments()[1];
1567 auto memoryStateArgument = lambdaMain->GetFunctionArguments()[2];
1568 auto ctxVarOne = lambdaMain->AddContextVar(*lambdaOne->output());
1569
1570 auto callResults = CallOperation::Create(
1571 ctxVarOne.inner,
1572 functionTypeOne,
1573 { ioStateArgument, memoryStateArgument });
1574
1575 auto & loadNode = LoadNonVolatileOperation::CreateNode(
1576 *pointerArgument,
1577 { memoryStateArgument },
1578 bitType32,
1579 4);
1580
1581 auto & addNode = CreateOpNode<IntegerAddOperation>({ callResults[0], loadNode.output(0) }, 32);
1582
1583 lambdaMain->finalize({ addNode.output(0), callResults[1], loadNode.output(1) });
1584 }
1585
1586 GraphExport::Create(*lambdaMain->output(), "main");
1587
1588 view(rvsdg, stdout);
1589
1590 // Act
1591 encodeStates<aa::Andersen, aa::RegionAwareModRefSummarizer>(rvsdgModule);
1592
1593 view(rvsdg, stdout);
1594
1595 // Assert
1596 {
1597 auto lambdaExitMerge =
1598 TryGetOwnerNode<SimpleNode>(*GetMemoryStateRegionResult(*lambdaMain).origin());
1599 EXPECT_TRUE(is<LambdaExitMemoryStateMergeOperation>(*lambdaExitMerge, 1, 1));
1600
1601 auto loadNode = TryGetOwnerNode<SimpleNode>(*lambdaExitMerge->input(0)->origin());
1602 EXPECT_TRUE(is<LoadNonVolatileOperation>(*loadNode, 2, 2));
1603
1604 auto lambdaEntrySplit = TryGetOwnerNode<SimpleNode>(*loadNode->input(1)->origin());
1605 EXPECT_TRUE(is<LambdaEntryMemoryStateSplitOperation>(*lambdaEntrySplit, 1, 1));
1606
1607 auto addNode = TryGetOwnerNode<SimpleNode>(*lambdaMain->GetFunctionResults()[0]->origin());
1608 EXPECT_TRUE(is<IntegerAddOperation>(*addNode, 2, 1));
1609
1610 auto callNode = TryGetOwnerNode<SimpleNode>(*addNode->input(0)->origin());
1611 EXPECT_TRUE(is<CallOperation>(*callNode, 3, 3));
1612 EXPECT_TRUE(CallOperation::GetMemoryStateOutput(*callNode).IsDead());
1613
1614 auto callEntryMergeNode =
1615 TryGetOwnerNode<SimpleNode>(*CallOperation::GetMemoryStateInput(*callNode).origin());
1616 EXPECT_TRUE(is<CallEntryMemoryStateMergeOperation>(*callEntryMergeNode, 0, 1));
1617 }
1618}
static jlm::util::StatisticsCollector statisticsCollector
static void encodeStates(jlm::rvsdg::RvsdgModule &rvsdgModule)
TEST(MemoryStateEncoderTests, storeTest1AndersenAgnostic)
static bool is(const jlm::rvsdg::Node &node, size_t numInputs, size_t numOutputs)
CallTest1 class.
const rvsdg::SimpleNode & CallG() const noexcept
jlm::rvsdg::LambdaNode * lambda_g
jlm::rvsdg::LambdaNode * lambda_f
const rvsdg::SimpleNode & CallF() const noexcept
CallTest2 class.
jlm::rvsdg::LambdaNode * lambda_test
jlm::rvsdg::LambdaNode * lambda_create
jlm::rvsdg::LambdaNode * lambda_destroy
rvsdg::SimpleNode * malloc
DeltaTest1 class.
jlm::rvsdg::LambdaNode * lambda_h
rvsdg::Node * constantFive
jlm::rvsdg::LambdaNode * lambda_g
DeltaTest2 class.
jlm::rvsdg::LambdaNode * lambda_f2
jlm::rvsdg::LambdaNode * lambda_f1
DeltaTest3 class.
const jlm::rvsdg::LambdaNode & LambdaF() const noexcept
RVSDG module with a call to free(NULL).
rvsdg::LambdaNode & LambdaMain() const noexcept
GammaTest class.
rvsdg::GammaNode * gamma
jlm::rvsdg::LambdaNode * lambda
ImportTest class.
jlm::rvsdg::LambdaNode * lambda_f1
jlm::rvsdg::LambdaNode * lambda_f2
IndirectCallTest1 class.
const jlm::rvsdg::LambdaNode & GetLambdaTest() const noexcept
const jlm::rvsdg::LambdaNode & GetLambdaIndcall() const noexcept
IndirectCallTest2 class.
rvsdg::SimpleNode & GetCallIWithThree() const noexcept
jlm::rvsdg::LambdaNode & GetLambdaY() const noexcept
jlm::rvsdg::LambdaNode & GetLambdaTest2() const noexcept
jlm::rvsdg::LambdaNode & GetLambdaTest() const noexcept
jlm::rvsdg::LambdaNode & GetLambdaFour() const noexcept
rvsdg::SimpleNode & GetIndirectCall() const noexcept
jlm::rvsdg::LambdaNode & GetLambdaThree() const noexcept
rvsdg::SimpleNode & GetCallIWithFour() const noexcept
jlm::rvsdg::LambdaNode & GetLambdaX() const noexcept
jlm::rvsdg::LambdaNode & GetLambdaI() const noexcept
LoadFromUndefTest class.
const jlm::rvsdg::LambdaNode & Lambda() const noexcept
LoadTest1 class.
jlm::rvsdg::LambdaNode * lambda
LoadTest2 class.
rvsdg::SimpleNode * alloca_p
jlm::rvsdg::LambdaNode * lambda
rvsdg::SimpleNode * alloca_y
rvsdg::SimpleNode * alloca_a
rvsdg::SimpleNode * alloca_x
rvsdg::SimpleNode * alloca_b
MemcpyTest class.
const jlm::rvsdg::LambdaNode & LambdaG() const noexcept
const jlm::rvsdg::LambdaNode & LambdaF() const noexcept
PhiTest1 class.
rvsdg::GammaNode * gamma
rvsdg::SimpleNode * alloca
jlm::rvsdg::LambdaNode * lambda_fib
jlm::llvm::LlvmRvsdgModule & module()
StoreTest1 class.
rvsdg::SimpleNode * alloca_c
rvsdg::SimpleNode * alloca_a
rvsdg::SimpleNode * alloca_d
jlm::rvsdg::LambdaNode * lambda
rvsdg::SimpleNode * alloca_b
StoreTest2 class.
rvsdg::SimpleNode * alloca_p
jlm::rvsdg::LambdaNode * lambda
rvsdg::SimpleNode * alloca_y
rvsdg::SimpleNode * alloca_x
rvsdg::SimpleNode * alloca_b
rvsdg::SimpleNode * alloca_a
ThetaTest class.
jlm::rvsdg::LambdaNode * lambda
jlm::rvsdg::ThetaNode * theta
void Encode(rvsdg::RvsdgModule &rvsdgModule, const ModRefSummary &modRefSummary, util::StatisticsCollector &statisticsCollector)
static std::string dumpDot(const PointsToGraph &pointsToGraph)
std::vector< ExitVar > GetExitVars() const
Gets all exit variables for this gamma.
Definition gamma.cpp:381
Region & GetRootRegion() const noexcept
Definition graph.hpp:99
Output * origin() const noexcept
Definition node.hpp:58
rvsdg::Output * finalize(const std::vector< jlm::rvsdg::Output * > &results)
Definition lambda.cpp:147
std::vector< rvsdg::Output * > GetFunctionArguments() const
Definition lambda.cpp:58
ContextVar AddContextVar(jlm::rvsdg::Output &origin)
Adds a context/free variable to the lambda node.
Definition lambda.cpp:132
std::vector< rvsdg::Input * > GetFunctionResults() const
Definition lambda.cpp:70
rvsdg::Output * output() const noexcept
Definition lambda.cpp:177
rvsdg::Region * subregion() const noexcept
Definition lambda.hpp:138
std::vector< ContextVar > GetContextVars() const noexcept
Gets all bound context variables.
Definition lambda.cpp:120
NodeInput * input(size_t index) const noexcept
Definition node.hpp:615
NodeOutput * output(size_t index) const noexcept
Definition node.hpp:650
size_t ninputs() const noexcept
Definition node.hpp:609
size_t noutputs() const noexcept
Definition node.hpp:644
rvsdg::Input & SingleUser() noexcept
Definition node.hpp:347
size_t nusers() const noexcept
Definition node.hpp:280
size_t numNodes() const noexcept
Definition region.hpp:510
Graph & Rvsdg() noexcept
NodeInput * input(size_t index) const noexcept
NodeOutput * output(size_t index) const noexcept
Global memory state passed between functions.
std::string view(const rvsdg::Region *region)
Definition view.cpp:142
NodeType * TryGetOwnerNode(const rvsdg::Input &input) noexcept
Checks if this is an input to a node of specified type.
Definition node.hpp:872