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