Jlm
Loading...
Searching...
No Matches
AndersenTests.cpp
Go to the documentation of this file.
1/*
2 * Copyright 2023 HÃ¥vard Krogstie <krogstie.havard@gmail.com>
3 * See COPYING for terms of redistribution.
4 */
5
6#include <gtest/gtest.h>
7
12
13#include <cassert>
14
15static std::unique_ptr<jlm::llvm::aa::PointsToGraph>
17{
18 using namespace jlm::llvm;
19
20 aa::Andersen andersen;
21 return andersen.Analyze(module);
22}
23
31[[nodiscard]] static bool
33 const jlm::llvm::aa::PointsToGraph & pointsToGraph,
35 const std::unordered_set<jlm::llvm::aa::PointsToGraph::NodeIndex> & expectedTargets)
36{
37 using namespace jlm::llvm::aa;
38
39 std::unordered_set<PointsToGraph::NodeIndex> actualTargets;
40 for (const auto target : pointsToGraph.getExplicitTargets(ptgNode).Items())
41 actualTargets.insert(target);
42
43 // If the node targets all externally available memory, add those nodes
44 if (pointsToGraph.isTargetingAllExternallyAvailable(ptgNode))
45 for (const auto target : pointsToGraph.getExternallyAvailableNodes())
46 actualTargets.insert(target);
47
48 return actualTargets == expectedTargets;
49}
50
58[[nodiscard]] static bool
60 const jlm::llvm::aa::PointsToGraph & pointsToGraph,
61 const std::unordered_set<jlm::llvm::aa::PointsToGraph::NodeIndex> & nodes)
62{
64 expected.insert(pointsToGraph.getExternalMemoryNode());
65
67 for (const auto escaped : pointsToGraph.getExternallyAvailableNodes())
68 actual.insert(escaped);
69
70 return expected == actual;
71}
72
73TEST(AndersenTests, TestStore1)
74{
76 const auto ptg = RunAndersen(test.module());
77
78 // std::unordered_map<const jlm::rvsdg::output*, std::string> outputMap;
79 // std::cout << jlm::rvsdg::view(test.graph().GetRootRegion(), outputMap) << std::endl;
80 // std::cout << jlm::llvm::aa::PointsToGraph::dumpGraph(*ptg, outputMap) << std::endl;
81
82 EXPECT_EQ(ptg->numAllocaNodes(), 4u);
83 EXPECT_EQ(ptg->numLambdaNodes(), 1u);
84 EXPECT_EQ(ptg->numMappedRegisters(), 5u);
85
86 auto alloca_a = ptg->getNodeForAlloca(*test.alloca_a);
87 auto alloca_b = ptg->getNodeForAlloca(*test.alloca_b);
88 auto alloca_c = ptg->getNodeForAlloca(*test.alloca_c);
89 auto alloca_d = ptg->getNodeForAlloca(*test.alloca_d);
90
91 auto palloca_a = ptg->getNodeForRegister(*test.alloca_a->output(0));
92 auto palloca_b = ptg->getNodeForRegister(*test.alloca_b->output(0));
93 auto palloca_c = ptg->getNodeForRegister(*test.alloca_c->output(0));
94 auto palloca_d = ptg->getNodeForRegister(*test.alloca_d->output(0));
95
96 auto lambda = ptg->getNodeForLambda(*test.lambda);
97 auto plambda = ptg->getNodeForRegister(*test.lambda->output());
98
99 EXPECT_TRUE(TargetsExactly(*ptg, alloca_a, { alloca_b }));
100 EXPECT_TRUE(TargetsExactly(*ptg, alloca_b, { alloca_c }));
101 EXPECT_TRUE(TargetsExactly(*ptg, alloca_c, { alloca_d }));
102 EXPECT_TRUE(TargetsExactly(*ptg, alloca_d, {}));
103
104 EXPECT_TRUE(TargetsExactly(*ptg, palloca_a, { alloca_a }));
105 EXPECT_TRUE(TargetsExactly(*ptg, palloca_b, { alloca_b }));
106 EXPECT_TRUE(TargetsExactly(*ptg, palloca_c, { alloca_c }));
107 EXPECT_TRUE(TargetsExactly(*ptg, palloca_d, { alloca_d }));
108
109 EXPECT_TRUE(TargetsExactly(*ptg, lambda, {}));
110 EXPECT_TRUE(TargetsExactly(*ptg, plambda, { lambda }));
111
112 EXPECT_TRUE(EscapedIsExactly(*ptg, { lambda }));
113}
114
115TEST(AndersenTests, TestStore2)
116{
118 const auto ptg = RunAndersen(test.module());
119
120 EXPECT_EQ(ptg->numAllocaNodes(), 5u);
121 EXPECT_EQ(ptg->numLambdaNodes(), 1u);
122 EXPECT_EQ(ptg->numMappedRegisters(), 6u);
123
124 auto alloca_a = ptg->getNodeForAlloca(*test.alloca_a);
125 auto alloca_b = ptg->getNodeForAlloca(*test.alloca_b);
126 auto alloca_x = ptg->getNodeForAlloca(*test.alloca_x);
127 auto alloca_y = ptg->getNodeForAlloca(*test.alloca_y);
128 auto alloca_p = ptg->getNodeForAlloca(*test.alloca_p);
129
130 auto palloca_a = ptg->getNodeForRegister(*test.alloca_a->output(0));
131 auto palloca_b = ptg->getNodeForRegister(*test.alloca_b->output(0));
132 auto palloca_x = ptg->getNodeForRegister(*test.alloca_x->output(0));
133 auto palloca_y = ptg->getNodeForRegister(*test.alloca_y->output(0));
134 auto palloca_p = ptg->getNodeForRegister(*test.alloca_p->output(0));
135
136 auto lambda = ptg->getNodeForLambda(*test.lambda);
137 auto plambda = ptg->getNodeForRegister(*test.lambda->output());
138
139 EXPECT_TRUE(TargetsExactly(*ptg, alloca_a, {}));
140 EXPECT_TRUE(TargetsExactly(*ptg, alloca_b, {}));
141 EXPECT_TRUE(TargetsExactly(*ptg, alloca_x, { alloca_a }));
142 EXPECT_TRUE(TargetsExactly(*ptg, alloca_y, { alloca_b }));
143 EXPECT_TRUE(TargetsExactly(*ptg, alloca_p, { alloca_x, alloca_y }));
144
145 EXPECT_TRUE(TargetsExactly(*ptg, palloca_a, { alloca_a }));
146 EXPECT_TRUE(TargetsExactly(*ptg, palloca_b, { alloca_b }));
147 EXPECT_TRUE(TargetsExactly(*ptg, palloca_x, { alloca_x }));
148 EXPECT_TRUE(TargetsExactly(*ptg, palloca_y, { alloca_y }));
149 EXPECT_TRUE(TargetsExactly(*ptg, palloca_p, { alloca_p }));
150
151 EXPECT_TRUE(TargetsExactly(*ptg, lambda, {}));
152 EXPECT_TRUE(TargetsExactly(*ptg, plambda, { lambda }));
153
154 EXPECT_TRUE(EscapedIsExactly(*ptg, { lambda }));
155}
156
157TEST(AndersenTests, TestLoad1)
158{
160 const auto ptg = RunAndersen(test.module());
161
162 EXPECT_EQ(ptg->numLambdaNodes(), 1u);
163 EXPECT_EQ(ptg->numMappedRegisters(), 3u);
164
165 auto loadResult = ptg->getNodeForRegister(*test.load_p->output(0));
166
167 auto lambda = ptg->getNodeForLambda(*test.lambda);
168 auto lambdaOutput = ptg->getNodeForRegister(*test.lambda->output());
169 auto lambdaArgument0 = ptg->getNodeForRegister(*test.lambda->GetFunctionArguments()[0]);
170
171 EXPECT_TRUE(TargetsExactly(*ptg, loadResult, { lambda, ptg->getExternalMemoryNode() }));
172
173 EXPECT_TRUE(TargetsExactly(*ptg, lambdaOutput, { lambda }));
174 EXPECT_TRUE(TargetsExactly(*ptg, lambdaArgument0, { lambda, ptg->getExternalMemoryNode() }));
175
176 EXPECT_TRUE(EscapedIsExactly(*ptg, { lambda }));
177}
178
179TEST(AndersenTests, TestLoad2)
180{
182 const auto ptg = RunAndersen(test.module());
183
184 EXPECT_EQ(ptg->numAllocaNodes(), 5u);
185 EXPECT_EQ(ptg->numLambdaNodes(), 1u);
186 EXPECT_EQ(ptg->numMappedRegisters(), 8u);
187
188 auto alloca_a = ptg->getNodeForAlloca(*test.alloca_a);
189 auto alloca_b = ptg->getNodeForAlloca(*test.alloca_b);
190 auto alloca_x = ptg->getNodeForAlloca(*test.alloca_x);
191 auto alloca_y = ptg->getNodeForAlloca(*test.alloca_y);
192 auto alloca_p = ptg->getNodeForAlloca(*test.alloca_p);
193
194 auto pload_x = ptg->getNodeForRegister(*test.load_x->output(0));
195 auto pload_a = ptg->getNodeForRegister(*test.load_a->output(0));
196
197 auto lambdaMemoryNode = ptg->getNodeForLambda(*test.lambda);
198
199 EXPECT_TRUE(TargetsExactly(*ptg, alloca_x, { alloca_a }));
200 EXPECT_TRUE(TargetsExactly(*ptg, alloca_y, { alloca_a, alloca_b }));
201 EXPECT_TRUE(TargetsExactly(*ptg, alloca_p, { alloca_x }));
202
203 EXPECT_TRUE(TargetsExactly(*ptg, pload_x, { alloca_x }));
204 EXPECT_TRUE(TargetsExactly(*ptg, pload_a, { alloca_a }));
205
206 EXPECT_TRUE(EscapedIsExactly(*ptg, { lambdaMemoryNode }));
207}
208
209TEST(AndersenTests, TestLoadFromUndef)
210{
212 const auto ptg = RunAndersen(test.module());
213
214 EXPECT_EQ(ptg->numLambdaNodes(), 1u);
215 EXPECT_EQ(ptg->numMappedRegisters(), 2u);
216
217 auto lambdaMemoryNode = ptg->getNodeForLambda(test.Lambda());
218 auto undefValueNode = ptg->getNodeForRegister(*test.UndefValueNode()->output(0));
219
220 EXPECT_TRUE(TargetsExactly(*ptg, undefValueNode, {}));
221 EXPECT_TRUE(EscapedIsExactly(*ptg, { lambdaMemoryNode }));
222}
223
224TEST(AndersenTests, TestGetElementPtr)
225{
227 const auto ptg = RunAndersen(test.module());
228
229 EXPECT_EQ(ptg->numLambdaNodes(), 1u);
230 EXPECT_EQ(ptg->numMappedRegisters(), 4u);
231
232 // We only care about the getelemenptr's in this test, skipping the validation for all other nodes
233 auto lambda = ptg->getNodeForLambda(*test.lambda);
234 auto gepX = ptg->getNodeForRegister(*test.getElementPtrX->output(0));
235 auto gepY = ptg->getNodeForRegister(*test.getElementPtrY->output(0));
236
237 // The RegisterNode is the same
238 EXPECT_EQ(gepX, gepY);
239
240 EXPECT_TRUE(TargetsExactly(*ptg, gepX, { lambda, ptg->getExternalMemoryNode() }));
241
242 EXPECT_TRUE(EscapedIsExactly(*ptg, { lambda }));
243}
244
245TEST(AndersenTests, TestBitCast)
246{
248 const auto ptg = RunAndersen(test.module());
249
250 EXPECT_EQ(ptg->numLambdaNodes(), 1u);
251 EXPECT_EQ(ptg->numMappedRegisters(), 3u);
252
253 auto lambda = ptg->getNodeForLambda(*test.lambda);
254 auto lambdaOut = ptg->getNodeForRegister(*test.lambda->output());
255 auto lambdaArg = ptg->getNodeForRegister(*test.lambda->GetFunctionArguments()[0]);
256 auto bitCast = ptg->getNodeForRegister(*test.bitCast->output(0));
257
258 EXPECT_TRUE(TargetsExactly(*ptg, lambdaOut, { lambda }));
259 EXPECT_TRUE(TargetsExactly(*ptg, lambdaArg, { lambda, ptg->getExternalMemoryNode() }));
260 EXPECT_TRUE(TargetsExactly(*ptg, bitCast, { lambda, ptg->getExternalMemoryNode() }));
261
262 EXPECT_TRUE(EscapedIsExactly(*ptg, { lambda }));
263}
264
265TEST(AndersenTests, TestConstantPointerNull)
266{
268 const auto ptg = RunAndersen(test.module());
269
270 EXPECT_EQ(ptg->numLambdaNodes(), 1u);
271 EXPECT_EQ(ptg->numMappedRegisters(), 3u);
272
273 auto lambda = ptg->getNodeForLambda(*test.lambda);
274 auto lambdaOut = ptg->getNodeForRegister(*test.lambda->output());
275 auto lambdaArg = ptg->getNodeForRegister(*test.lambda->GetFunctionArguments()[0]);
276
277 auto constantPointerNull = ptg->getNodeForRegister(*test.constantPointerNullNode->output(0));
278
279 EXPECT_TRUE(TargetsExactly(*ptg, lambdaOut, { lambda }));
280 EXPECT_TRUE(TargetsExactly(*ptg, lambdaArg, { lambda, ptg->getExternalMemoryNode() }));
281 EXPECT_TRUE(TargetsExactly(*ptg, constantPointerNull, {}));
282
283 EXPECT_TRUE(EscapedIsExactly(*ptg, { lambda }));
284}
285
286TEST(AndersenTests, TestBits2Ptr)
287{
289 const auto ptg = RunAndersen(test.module());
290
291 EXPECT_EQ(ptg->numLambdaNodes(), 2u);
292 EXPECT_EQ(ptg->numMappedRegisters(), 5u);
293
294 auto lambdaTestMemoryNode = ptg->getNodeForLambda(test.GetLambdaTest());
295 auto externalMemoryNode = ptg->getExternalMemoryNode();
296
297 auto callOutput0 = ptg->getNodeForRegister(*test.GetCallNode().output(0));
298 auto bits2ptr = ptg->getNodeForRegister(*test.GetBitsToPtrNode().output(0));
299
300 EXPECT_TRUE(TargetsExactly(*ptg, callOutput0, { lambdaTestMemoryNode, externalMemoryNode }));
301 EXPECT_TRUE(TargetsExactly(*ptg, bits2ptr, { lambdaTestMemoryNode, externalMemoryNode }));
302
303 EXPECT_TRUE(EscapedIsExactly(*ptg, { lambdaTestMemoryNode }));
304}
305
306TEST(AndersenTests, TestCall1)
307{
309 const auto ptg = RunAndersen(test.module());
310
311 EXPECT_EQ(ptg->numAllocaNodes(), 3u);
312 EXPECT_EQ(ptg->numLambdaNodes(), 3u);
313 EXPECT_EQ(ptg->numMappedRegisters(), 12u);
314
315 auto alloca_x = ptg->getNodeForAlloca(*test.alloca_x);
316 auto alloca_y = ptg->getNodeForAlloca(*test.alloca_y);
317 auto alloca_z = ptg->getNodeForAlloca(*test.alloca_z);
318
319 auto palloca_x = ptg->getNodeForRegister(*test.alloca_x->output(0));
320 auto palloca_y = ptg->getNodeForRegister(*test.alloca_y->output(0));
321 auto palloca_z = ptg->getNodeForRegister(*test.alloca_z->output(0));
322
323 auto lambda_f = ptg->getNodeForLambda(*test.lambda_f);
324 auto lambda_g = ptg->getNodeForLambda(*test.lambda_g);
325 auto lambda_h = ptg->getNodeForLambda(*test.lambda_h);
326
327 auto plambda_f = ptg->getNodeForRegister(*test.lambda_f->output());
328 auto plambda_g = ptg->getNodeForRegister(*test.lambda_g->output());
329 auto plambda_h = ptg->getNodeForRegister(*test.lambda_h->output());
330
331 auto lambda_f_arg0 = ptg->getNodeForRegister(*test.lambda_f->GetFunctionArguments()[0]);
332 auto lambda_f_arg1 = ptg->getNodeForRegister(*test.lambda_f->GetFunctionArguments()[1]);
333
334 auto lambda_g_arg0 = ptg->getNodeForRegister(*test.lambda_g->GetFunctionArguments()[0]);
335 auto lambda_g_arg1 = ptg->getNodeForRegister(*test.lambda_g->GetFunctionArguments()[1]);
336
337 auto lambda_h_cv0 = ptg->getNodeForRegister(*test.lambda_h->GetContextVars()[0].inner);
338 auto lambda_h_cv1 = ptg->getNodeForRegister(*test.lambda_h->GetContextVars()[1].inner);
339
340 EXPECT_TRUE(TargetsExactly(*ptg, palloca_x, { alloca_x }));
341 EXPECT_TRUE(TargetsExactly(*ptg, palloca_y, { alloca_y }));
342 EXPECT_TRUE(TargetsExactly(*ptg, palloca_z, { alloca_z }));
343
344 EXPECT_TRUE(TargetsExactly(*ptg, plambda_f, { lambda_f }));
345 EXPECT_TRUE(TargetsExactly(*ptg, plambda_g, { lambda_g }));
346 EXPECT_TRUE(TargetsExactly(*ptg, plambda_h, { lambda_h }));
347
348 EXPECT_TRUE(TargetsExactly(*ptg, lambda_f_arg0, { alloca_x }));
349 EXPECT_TRUE(TargetsExactly(*ptg, lambda_f_arg1, { alloca_y }));
350
351 EXPECT_TRUE(TargetsExactly(*ptg, lambda_g_arg0, { alloca_z }));
352 EXPECT_TRUE(TargetsExactly(*ptg, lambda_g_arg1, { alloca_z }));
353
354 EXPECT_TRUE(TargetsExactly(*ptg, lambda_h_cv0, { lambda_f }));
355 EXPECT_TRUE(TargetsExactly(*ptg, lambda_h_cv1, { lambda_g }));
356
357 EXPECT_TRUE(EscapedIsExactly(*ptg, { lambda_h }));
358}
359
360TEST(AndersenTests, TestCall2)
361{
363 const auto ptg = RunAndersen(test.module());
364
365 EXPECT_EQ(ptg->numLambdaNodes(), 3u);
366 EXPECT_EQ(ptg->numMallocNodes(), 1u);
367 EXPECT_EQ(ptg->numImportNodes(), 0u);
368 EXPECT_EQ(ptg->numMappedRegisters(), 11u);
369
370 auto lambda_create = ptg->getNodeForLambda(*test.lambda_create);
371 auto lambda_create_out = ptg->getNodeForRegister(*test.lambda_create->output());
372
373 auto lambda_destroy = ptg->getNodeForLambda(*test.lambda_destroy);
374 auto lambda_destroy_out = ptg->getNodeForRegister(*test.lambda_destroy->output());
375 auto lambda_destroy_arg =
376 ptg->getNodeForRegister(*test.lambda_destroy->GetFunctionArguments()[0]);
377
378 auto lambda_test = ptg->getNodeForLambda(*test.lambda_test);
379 auto lambda_test_out = ptg->getNodeForRegister(*test.lambda_test->output());
380 auto lambda_test_cv1 = ptg->getNodeForRegister(*test.lambda_test->GetContextVars()[0].inner);
381 auto lambda_test_cv2 = ptg->getNodeForRegister(*test.lambda_test->GetContextVars()[1].inner);
382
383 auto call_create1_out = ptg->getNodeForRegister(*test.CallCreate1().output(0));
384 auto call_create2_out = ptg->getNodeForRegister(*test.CallCreate2().output(0));
385
386 auto malloc = ptg->getNodeForMalloc(*test.malloc);
387 auto malloc_out = ptg->getNodeForRegister(*test.malloc->output(0));
388
389 EXPECT_TRUE(TargetsExactly(*ptg, lambda_create_out, { lambda_create }));
390
391 EXPECT_TRUE(TargetsExactly(*ptg, lambda_destroy_out, { lambda_destroy }));
392 EXPECT_TRUE(TargetsExactly(*ptg, lambda_destroy_arg, { malloc }));
393
394 EXPECT_TRUE(TargetsExactly(*ptg, lambda_test_out, { lambda_test }));
395 EXPECT_TRUE(TargetsExactly(*ptg, lambda_test_cv1, { lambda_create }));
396 EXPECT_TRUE(TargetsExactly(*ptg, lambda_test_cv2, { lambda_destroy }));
397
398 EXPECT_TRUE(TargetsExactly(*ptg, call_create1_out, { malloc }));
399 EXPECT_TRUE(TargetsExactly(*ptg, call_create2_out, { malloc }));
400
401 EXPECT_TRUE(TargetsExactly(*ptg, malloc_out, { malloc }));
402
403 EXPECT_TRUE(EscapedIsExactly(*ptg, { lambda_test }));
404}
405
406TEST(AndersenTests, TestIndirectCall1)
407{
409 const auto ptg = RunAndersen(test.module());
410
411 EXPECT_EQ(ptg->numLambdaNodes(), 4u);
412 EXPECT_EQ(ptg->numImportNodes(), 0u);
413 EXPECT_EQ(ptg->numMappedRegisters(), 11u);
414
415 auto lambda_three = ptg->getNodeForLambda(test.GetLambdaThree());
416 auto lambda_three_out = ptg->getNodeForRegister(*test.GetLambdaThree().output());
417
418 auto lambda_four = ptg->getNodeForLambda(test.GetLambdaFour());
419 auto lambda_four_out = ptg->getNodeForRegister(*test.GetLambdaFour().output());
420
421 auto lambda_indcall = ptg->getNodeForLambda(test.GetLambdaIndcall());
422 auto lambda_indcall_out = ptg->getNodeForRegister(*test.GetLambdaIndcall().output());
423 auto lambda_indcall_arg =
424 ptg->getNodeForRegister(*test.GetLambdaIndcall().GetFunctionArguments()[0]);
425
426 auto lambda_test = ptg->getNodeForLambda(test.GetLambdaTest());
427 auto lambda_test_out = ptg->getNodeForRegister(*test.GetLambdaTest().output());
428 auto lambda_test_cv0 = ptg->getNodeForRegister(*test.GetLambdaTest().GetContextVars()[0].inner);
429 auto lambda_test_cv1 = ptg->getNodeForRegister(*test.GetLambdaTest().GetContextVars()[1].inner);
430 auto lambda_test_cv2 = ptg->getNodeForRegister(*test.GetLambdaTest().GetContextVars()[2].inner);
431
432 EXPECT_TRUE(TargetsExactly(*ptg, lambda_three_out, { lambda_three }));
433
434 EXPECT_TRUE(TargetsExactly(*ptg, lambda_four_out, { lambda_four }));
435
436 EXPECT_TRUE(TargetsExactly(*ptg, lambda_indcall_out, { lambda_indcall }));
437 EXPECT_TRUE(TargetsExactly(*ptg, lambda_indcall_arg, { lambda_three, lambda_four }));
438
439 EXPECT_TRUE(TargetsExactly(*ptg, lambda_test_out, { lambda_test }));
440 EXPECT_TRUE(TargetsExactly(*ptg, lambda_test_cv0, { lambda_indcall }));
441 EXPECT_TRUE(TargetsExactly(*ptg, lambda_test_cv1, { lambda_four }));
442 EXPECT_TRUE(TargetsExactly(*ptg, lambda_test_cv2, { lambda_three }));
443
444 EXPECT_TRUE(EscapedIsExactly(*ptg, { lambda_test }));
445}
446
447TEST(AndersenTests, TestIndirectCall2)
448{
450 const auto ptg = RunAndersen(test.module());
451
452 EXPECT_EQ(ptg->numAllocaNodes(), 3u);
453 EXPECT_EQ(ptg->numLambdaNodes(), 7u);
454 EXPECT_EQ(ptg->numDeltaNodes(), 2u);
455 EXPECT_EQ(ptg->numMappedRegisters(), 27u);
456
457 auto lambdaThree = ptg->getNodeForLambda(test.GetLambdaThree());
458 auto lambdaThreeOutput = ptg->getNodeForRegister(*test.GetLambdaThree().output());
459
460 auto lambdaFour = ptg->getNodeForLambda(test.GetLambdaFour());
461 auto lambdaFourOutput = ptg->getNodeForRegister(*test.GetLambdaFour().output());
462
463 EXPECT_TRUE(TargetsExactly(*ptg, lambdaThreeOutput, { lambdaThree }));
464 EXPECT_TRUE(TargetsExactly(*ptg, lambdaFourOutput, { lambdaFour }));
465}
466
467TEST(AndersenTests, TestExternalCall1)
468{
470 const auto ptg = RunAndersen(test.module());
471
472 EXPECT_EQ(ptg->numAllocaNodes(), 2u);
473 EXPECT_EQ(ptg->numLambdaNodes(), 1u);
474 EXPECT_EQ(ptg->numImportNodes(), 1u);
475 EXPECT_EQ(ptg->numMappedRegisters(), 10u);
476
477 auto lambdaF = ptg->getNodeForLambda(test.LambdaF());
478 auto lambdaFArgument0 = ptg->getNodeForRegister(*test.LambdaF().GetFunctionArguments()[0]);
479 auto lambdaFArgument1 = ptg->getNodeForRegister(*test.LambdaF().GetFunctionArguments()[1]);
480 auto importG = ptg->getNodeForImport(test.ExternalGArgument());
481
482 auto callResult = ptg->getNodeForRegister(*test.CallG().output(0));
483
484 auto externalMemory = ptg->getExternalMemoryNode();
485
486 EXPECT_TRUE(TargetsExactly(*ptg, lambdaFArgument0, { lambdaF, importG, externalMemory }));
487 EXPECT_TRUE(TargetsExactly(*ptg, lambdaFArgument1, { lambdaF, importG, externalMemory }));
488 EXPECT_TRUE(TargetsExactly(*ptg, callResult, { lambdaF, importG, externalMemory }));
489}
490
491TEST(AndersenTests, TestGamma)
492{
494 const auto ptg = RunAndersen(test.module());
495
496 EXPECT_EQ(ptg->numLambdaNodes(), 1u);
497 EXPECT_EQ(ptg->numMappedRegisters(), 15u);
498
499 auto lambda = ptg->getNodeForLambda(*test.lambda);
500
501 for (size_t n = 1; n < 5; n++)
502 {
503 auto lambdaArgument = ptg->getNodeForRegister(*test.lambda->GetFunctionArguments()[n]);
504 EXPECT_TRUE(TargetsExactly(*ptg, lambdaArgument, { lambda, ptg->getExternalMemoryNode() }));
505 }
506
507 auto entryvars = test.gamma->GetEntryVars();
508 EXPECT_EQ(entryvars.size(), 4u);
509 for (const auto & entryvar : entryvars)
510 {
511 auto argument0 = ptg->getNodeForRegister(*entryvar.branchArgument[0]);
512 auto argument1 = ptg->getNodeForRegister(*entryvar.branchArgument[1]);
513
514 EXPECT_TRUE(TargetsExactly(*ptg, argument0, { lambda, ptg->getExternalMemoryNode() }));
515 EXPECT_TRUE(TargetsExactly(*ptg, argument1, { lambda, ptg->getExternalMemoryNode() }));
516 }
517
518 for (size_t n = 0; n < 4; n++)
519 {
520 auto gammaOutput = ptg->getNodeForRegister(*test.gamma->GetExitVars()[0].output);
521 EXPECT_TRUE(TargetsExactly(*ptg, gammaOutput, { lambda, ptg->getExternalMemoryNode() }));
522 }
523
524 EXPECT_TRUE(EscapedIsExactly(*ptg, { lambda }));
525}
526
527TEST(AndersenTests, TestTheta)
528{
530 const auto ptg = RunAndersen(test.module());
531
532 EXPECT_EQ(ptg->numLambdaNodes(), 1u);
533 EXPECT_EQ(ptg->numMappedRegisters(), 5u);
534
535 auto lambda = ptg->getNodeForLambda(*test.lambda);
536 auto lambdaArgument1 = ptg->getNodeForRegister(*test.lambda->GetFunctionArguments()[1]);
537 auto lambdaOutput = ptg->getNodeForRegister(*test.lambda->output());
538
539 auto gepOutput = ptg->getNodeForRegister(*test.gep->output(0));
540
541 auto thetaArgument2 = ptg->getNodeForRegister(*test.theta->GetLoopVars()[2].pre);
542 auto thetaOutput2 = ptg->getNodeForRegister(*test.theta->output(2));
543
544 EXPECT_TRUE(TargetsExactly(*ptg, lambdaArgument1, { lambda, ptg->getExternalMemoryNode() }));
545 EXPECT_TRUE(TargetsExactly(*ptg, lambdaOutput, { lambda }));
546
547 EXPECT_TRUE(TargetsExactly(*ptg, gepOutput, { lambda, ptg->getExternalMemoryNode() }));
548
549 EXPECT_TRUE(TargetsExactly(*ptg, thetaArgument2, { lambda, ptg->getExternalMemoryNode() }));
550 EXPECT_TRUE(TargetsExactly(*ptg, thetaOutput2, { lambda, ptg->getExternalMemoryNode() }));
551
552 EXPECT_TRUE(EscapedIsExactly(*ptg, { lambda }));
553}
554
555TEST(AndersenTests, TestDelta1)
556{
558 const auto ptg = RunAndersen(test.module());
559
560 EXPECT_EQ(ptg->numDeltaNodes(), 1u);
561 EXPECT_EQ(ptg->numLambdaNodes(), 2u);
562 EXPECT_EQ(ptg->numMappedRegisters(), 6u);
563
564 auto delta_f = ptg->getNodeForDelta(*test.delta_f);
565 auto pdelta_f = ptg->getNodeForRegister(test.delta_f->output());
566
567 auto lambda_g = ptg->getNodeForLambda(*test.lambda_g);
568 auto plambda_g = ptg->getNodeForRegister(*test.lambda_g->output());
569 auto lambda_g_arg0 = ptg->getNodeForRegister(*test.lambda_g->GetFunctionArguments()[0]);
570
571 auto lambda_h = ptg->getNodeForLambda(*test.lambda_h);
572 auto plambda_h = ptg->getNodeForRegister(*test.lambda_h->output());
573 auto lambda_h_cv0 = ptg->getNodeForRegister(*test.lambda_h->GetContextVars()[0].inner);
574 auto lambda_h_cv1 = ptg->getNodeForRegister(*test.lambda_h->GetContextVars()[1].inner);
575
576 EXPECT_TRUE(TargetsExactly(*ptg, pdelta_f, { delta_f }));
577
578 EXPECT_TRUE(TargetsExactly(*ptg, plambda_g, { lambda_g }));
579 EXPECT_TRUE(TargetsExactly(*ptg, plambda_h, { lambda_h }));
580
581 EXPECT_TRUE(TargetsExactly(*ptg, lambda_g_arg0, { delta_f }));
582
583 EXPECT_TRUE(TargetsExactly(*ptg, lambda_h_cv0, { delta_f }));
584 EXPECT_TRUE(TargetsExactly(*ptg, lambda_h_cv1, { lambda_g }));
585
586 EXPECT_TRUE(EscapedIsExactly(*ptg, { lambda_h }));
587}
588
589TEST(AndersenTests, TestDelta2)
590{
592 const auto ptg = RunAndersen(test.module());
593
594 EXPECT_EQ(ptg->numDeltaNodes(), 2u);
595 EXPECT_EQ(ptg->numLambdaNodes(), 2u);
596 EXPECT_EQ(ptg->numMappedRegisters(), 8u);
597
598 auto delta_d1 = ptg->getNodeForDelta(*test.delta_d1);
599 auto delta_d1_out = ptg->getNodeForRegister(test.delta_d1->output());
600
601 auto delta_d2 = ptg->getNodeForDelta(*test.delta_d2);
602 auto delta_d2_out = ptg->getNodeForRegister(test.delta_d2->output());
603
604 auto lambda_f1 = ptg->getNodeForLambda(*test.lambda_f1);
605 auto lambda_f1_out = ptg->getNodeForRegister(*test.lambda_f1->output());
606 auto lambda_f1_cvd1 = ptg->getNodeForRegister(*test.lambda_f1->GetContextVars()[0].inner);
607
608 auto lambda_f2 = ptg->getNodeForLambda(*test.lambda_f2);
609 auto lambda_f2_out = ptg->getNodeForRegister(*test.lambda_f2->output());
610 auto lambda_f2_cvd1 = ptg->getNodeForRegister(*test.lambda_f2->GetContextVars()[0].inner);
611 auto lambda_f2_cvd2 = ptg->getNodeForRegister(*test.lambda_f2->GetContextVars()[1].inner);
612 auto lambda_f2_cvf1 = ptg->getNodeForRegister(*test.lambda_f2->GetContextVars()[2].inner);
613
614 EXPECT_TRUE(TargetsExactly(*ptg, delta_d1_out, { delta_d1 }));
615 EXPECT_TRUE(TargetsExactly(*ptg, delta_d2_out, { delta_d2 }));
616
617 EXPECT_TRUE(TargetsExactly(*ptg, lambda_f1_out, { lambda_f1 }));
618 EXPECT_TRUE(TargetsExactly(*ptg, lambda_f2_out, { lambda_f2 }));
619
620 EXPECT_EQ(lambda_f1_cvd1, delta_d1_out);
621 EXPECT_EQ(lambda_f2_cvd1, delta_d1_out);
622 EXPECT_EQ(lambda_f2_cvd2, delta_d2_out);
623 EXPECT_EQ(lambda_f2_cvf1, lambda_f1_out);
624
625 EXPECT_TRUE(EscapedIsExactly(*ptg, { lambda_f2 }));
626}
627
628TEST(AndersenTests, TestImports)
629{
631 const auto ptg = RunAndersen(test.module());
632
633 EXPECT_EQ(ptg->numLambdaNodes(), 2u);
634 EXPECT_EQ(ptg->numImportNodes(), 2u);
635 EXPECT_EQ(ptg->numMappedRegisters(), 8u);
636
637 auto d1 = ptg->getNodeForImport(*test.import_d1);
638 auto import_d1 = ptg->getNodeForRegister(*test.import_d1);
639
640 auto d2 = ptg->getNodeForImport(*test.import_d2);
641 auto import_d2 = ptg->getNodeForRegister(*test.import_d2);
642
643 auto lambda_f1 = ptg->getNodeForLambda(*test.lambda_f1);
644 auto lambda_f1_out = ptg->getNodeForRegister(*test.lambda_f1->output());
645 auto lambda_f1_cvd1 = ptg->getNodeForRegister(*test.lambda_f1->GetContextVars()[0].inner);
646
647 auto lambda_f2 = ptg->getNodeForLambda(*test.lambda_f2);
648 auto lambda_f2_out = ptg->getNodeForRegister(*test.lambda_f2->output());
649 auto lambda_f2_cvd1 = ptg->getNodeForRegister(*test.lambda_f2->GetContextVars()[0].inner);
650 auto lambda_f2_cvd2 = ptg->getNodeForRegister(*test.lambda_f2->GetContextVars()[1].inner);
651 auto lambda_f2_cvf1 = ptg->getNodeForRegister(*test.lambda_f2->GetContextVars()[2].inner);
652
653 EXPECT_TRUE(TargetsExactly(*ptg, import_d1, { d1 }));
654 EXPECT_TRUE(TargetsExactly(*ptg, import_d2, { d2 }));
655
656 EXPECT_TRUE(TargetsExactly(*ptg, lambda_f1_out, { lambda_f1 }));
657 EXPECT_TRUE(TargetsExactly(*ptg, lambda_f2_out, { lambda_f2 }));
658
659 EXPECT_EQ(lambda_f1_cvd1, import_d1);
660 EXPECT_EQ(lambda_f2_cvd1, import_d1);
661 EXPECT_EQ(lambda_f2_cvd2, import_d2);
662 EXPECT_EQ(lambda_f2_cvf1, lambda_f1_out);
663
664 EXPECT_TRUE(EscapedIsExactly(*ptg, { lambda_f2, d1, d2 }));
665}
666
667TEST(AndersenTests, TestPhi1)
668{
670 const auto ptg = RunAndersen(test.module());
671
672 EXPECT_EQ(ptg->numAllocaNodes(), 1u);
673 EXPECT_EQ(ptg->numLambdaNodes(), 2u);
674 EXPECT_EQ(ptg->numMappedRegisters(), 16u);
675
676 auto lambda_fib = ptg->getNodeForLambda(*test.lambda_fib);
677 auto lambda_fib_out = ptg->getNodeForRegister(*test.lambda_fib->output());
678 auto lambda_fib_arg1 = ptg->getNodeForRegister(*test.lambda_fib->GetFunctionArguments()[1]);
679
680 auto lambda_test = ptg->getNodeForLambda(*test.lambda_test);
681 auto lambda_test_out = ptg->getNodeForRegister(*test.lambda_test->output());
682
683 auto phi_rv = ptg->getNodeForRegister(*test.phi->GetFixVars()[0].output);
684 auto phi_rv_arg = ptg->getNodeForRegister(*test.phi->GetFixVars()[0].recref);
685
686 auto gamma_result = ptg->getNodeForRegister(*test.gamma->GetEntryVars()[1].branchArgument[0]);
687 auto gamma_fib = ptg->getNodeForRegister(*test.gamma->GetEntryVars()[2].branchArgument[0]);
688
689 auto alloca = ptg->getNodeForAlloca(*test.alloca);
690 auto alloca_out = ptg->getNodeForRegister(*test.alloca->output(0));
691
692 EXPECT_TRUE(TargetsExactly(*ptg, lambda_fib_out, { lambda_fib }));
693 EXPECT_TRUE(TargetsExactly(*ptg, lambda_fib_arg1, { alloca }));
694
695 EXPECT_TRUE(TargetsExactly(*ptg, lambda_test_out, { lambda_test }));
696
697 EXPECT_EQ(phi_rv, lambda_fib_out);
698 EXPECT_TRUE(TargetsExactly(*ptg, phi_rv_arg, { lambda_fib }));
699
700 EXPECT_TRUE(TargetsExactly(*ptg, gamma_result, { alloca }));
701 EXPECT_TRUE(TargetsExactly(*ptg, gamma_fib, { lambda_fib }));
702
703 EXPECT_TRUE(TargetsExactly(*ptg, alloca_out, { alloca }));
704
705 EXPECT_TRUE(EscapedIsExactly(*ptg, { lambda_test }));
706}
707
708TEST(AndersenTests, TestExternalMemory)
709{
711 const auto ptg = RunAndersen(test.module());
712
713 EXPECT_EQ(ptg->numLambdaNodes(), 1u);
714 EXPECT_EQ(ptg->numMappedRegisters(), 3u);
715
716 auto lambdaF = ptg->getNodeForLambda(*test.LambdaF);
717 auto lambdaFArgument0 = ptg->getNodeForRegister(*test.LambdaF->GetFunctionArguments()[0]);
718 auto lambdaFArgument1 = ptg->getNodeForRegister(*test.LambdaF->GetFunctionArguments()[1]);
719
720 EXPECT_TRUE(TargetsExactly(*ptg, lambdaFArgument0, { lambdaF, ptg->getExternalMemoryNode() }));
721 EXPECT_TRUE(TargetsExactly(*ptg, lambdaFArgument1, { lambdaF, ptg->getExternalMemoryNode() }));
722
723 EXPECT_TRUE(EscapedIsExactly(*ptg, { lambdaF }));
724}
725
726TEST(AndersenTests, TestEscapedMemory1)
727{
729 const auto ptg = RunAndersen(test.module());
730
731 EXPECT_EQ(ptg->numDeltaNodes(), 4u);
732 EXPECT_EQ(ptg->numLambdaNodes(), 1u);
733 EXPECT_EQ(ptg->numMappedRegisters(), 10u);
734
735 auto lambdaTestArgument0 = ptg->getNodeForRegister(*test.LambdaTest->GetFunctionArguments()[0]);
736 auto lambdaTestCv0 = ptg->getNodeForRegister(*test.LambdaTest->GetContextVars()[0].inner);
737 auto loadNode1Output = ptg->getNodeForRegister(*test.LoadNode1->output(0));
738
739 auto deltaA = ptg->getNodeForDelta(*test.DeltaA);
740 auto deltaB = ptg->getNodeForDelta(*test.DeltaB);
741 auto deltaX = ptg->getNodeForDelta(*test.DeltaX);
742 auto deltaY = ptg->getNodeForDelta(*test.DeltaY);
743 auto lambdaTest = ptg->getNodeForLambda(*test.LambdaTest);
744 auto externalMemory = ptg->getExternalMemoryNode();
745
746 EXPECT_TRUE(TargetsExactly(
747 *ptg,
748 lambdaTestArgument0,
749 { deltaA, deltaX, deltaY, lambdaTest, externalMemory }));
750 EXPECT_TRUE(TargetsExactly(*ptg, lambdaTestCv0, { deltaB }));
751 EXPECT_TRUE(TargetsExactly(
752 *ptg,
753 loadNode1Output,
754 { deltaA, deltaX, deltaY, lambdaTest, externalMemory }));
755
756 EXPECT_TRUE(EscapedIsExactly(*ptg, { lambdaTest, deltaA, deltaX, deltaY }));
757}
758
759TEST(AndersenTests, TestEscapedMemory2)
760{
762 const auto ptg = RunAndersen(test.module());
763
764 EXPECT_EQ(ptg->numImportNodes(), 2u);
765 EXPECT_EQ(ptg->numLambdaNodes(), 3u);
766 EXPECT_EQ(ptg->numMallocNodes(), 2u);
767 EXPECT_EQ(ptg->numMappedRegisters(), 10u);
768
769 auto returnAddressFunction = ptg->getNodeForLambda(*test.ReturnAddressFunction);
770 auto callExternalFunction1 = ptg->getNodeForLambda(*test.CallExternalFunction1);
771 auto callExternalFunction2 = ptg->getNodeForLambda(*test.CallExternalFunction2);
772 auto returnAddressMalloc = ptg->getNodeForMalloc(*test.ReturnAddressMalloc);
773 auto callExternalFunction1Malloc = ptg->getNodeForMalloc(*test.CallExternalFunction1Malloc);
774 auto externalMemory = ptg->getExternalMemoryNode();
775 auto externalFunction1Import = ptg->getNodeForImport(*test.ExternalFunction1Import);
776 auto externalFunction2Import = ptg->getNodeForImport(*test.ExternalFunction2Import);
777
778 auto externalFunction2CallResult =
779 ptg->getNodeForRegister(*test.ExternalFunction2Call->output(0));
780
781 EXPECT_TRUE(TargetsExactly(
782 *ptg,
783 externalFunction2CallResult,
784 { returnAddressFunction,
785 callExternalFunction1,
786 callExternalFunction2,
787 externalMemory,
788 returnAddressMalloc,
789 callExternalFunction1Malloc,
790 externalFunction1Import,
791 externalFunction2Import }));
792
793 EXPECT_TRUE(EscapedIsExactly(
794 *ptg,
795 { returnAddressFunction,
796 callExternalFunction1,
797 callExternalFunction2,
798 returnAddressMalloc,
799 callExternalFunction1Malloc,
800 externalFunction1Import,
801 externalFunction2Import }));
802}
803
804TEST(AndersenTests, TestEscapedMemory3)
805{
807 const auto ptg = RunAndersen(test.module());
808
809 EXPECT_EQ(ptg->numDeltaNodes(), 1u);
810 EXPECT_EQ(ptg->numImportNodes(), 1u);
811 EXPECT_EQ(ptg->numLambdaNodes(), 1u);
812 EXPECT_EQ(ptg->numMappedRegisters(), 5u);
813
814 auto lambdaTest = ptg->getNodeForLambda(*test.LambdaTest);
815 auto deltaGlobal = ptg->getNodeForDelta(*test.DeltaGlobal);
816 auto importExternalFunction = ptg->getNodeForImport(*test.ImportExternalFunction);
817 auto externalMemory = ptg->getExternalMemoryNode();
818
819 auto callExternalFunctionResult = ptg->getNodeForRegister(*test.CallExternalFunction->output(0));
820
821 EXPECT_TRUE(TargetsExactly(
822 *ptg,
823 callExternalFunctionResult,
824 { lambdaTest, deltaGlobal, importExternalFunction, externalMemory }));
825
826 EXPECT_TRUE(EscapedIsExactly(*ptg, { lambdaTest, deltaGlobal, importExternalFunction }));
827}
828
829TEST(AndersenTests, TestMemcpy)
830{
832 const auto ptg = RunAndersen(test.module());
833
834 EXPECT_EQ(ptg->numDeltaNodes(), 2u);
835 EXPECT_EQ(ptg->numLambdaNodes(), 2u);
836 EXPECT_EQ(ptg->numMappedRegisters(), 11u);
837
838 auto initArray = ptg->getNodeForDelta(test.InitArray());
839 auto globalArray = ptg->getNodeForDelta(test.GlobalArray());
840
841 auto memCpyDest = ptg->getNodeForRegister(*test.Memcpy().input(0)->origin());
842 auto memCpySrc = ptg->getNodeForRegister(*test.Memcpy().input(1)->origin());
843
844 auto lambdaF = ptg->getNodeForLambda(test.LambdaF());
845 auto lambdaG = ptg->getNodeForLambda(test.LambdaG());
846
847 EXPECT_TRUE(TargetsExactly(*ptg, memCpyDest, { globalArray }));
848 EXPECT_TRUE(TargetsExactly(*ptg, memCpySrc, { initArray }));
849
850 EXPECT_TRUE(EscapedIsExactly(*ptg, { globalArray, initArray, lambdaF, lambdaG }));
851}
852
853TEST(AndersenTests, TestLinkedList)
854{
856 const auto ptg = RunAndersen(test.module());
857
858 EXPECT_EQ(ptg->numAllocaNodes(), 1u);
859 EXPECT_EQ(ptg->numDeltaNodes(), 1u);
860 EXPECT_EQ(ptg->numLambdaNodes(), 1u);
861
862 auto allocaNode = ptg->getNodeForAlloca(test.GetAlloca());
863 auto deltaMyListNode = ptg->getNodeForDelta(test.GetDeltaMyList());
864 auto lambdaNextNode = ptg->getNodeForLambda(test.GetLambdaNext());
865 auto externalMemoryNode = ptg->getExternalMemoryNode();
866
867 EXPECT_TRUE(
868 TargetsExactly(*ptg, allocaNode, { deltaMyListNode, lambdaNextNode, externalMemoryNode }));
869 EXPECT_TRUE(TargetsExactly(
870 *ptg,
871 deltaMyListNode,
872 { deltaMyListNode, lambdaNextNode, externalMemoryNode }));
873}
874
875TEST(AndersenTests, TestStatistics)
876{
877 // Arrange
879 jlm::util::StatisticsCollectorSettings statisticsCollectorSettings(
881 jlm::util::StatisticsCollector statisticsCollector(statisticsCollectorSettings);
882
883 // Act
885 auto ptg = andersen.Analyze(test.module(), statisticsCollector);
886
887 // Assert
889 const auto & statistics = *statisticsCollector.CollectedStatistics().begin();
890
891 EXPECT_EQ(statistics.GetMeasurementValue<uint64_t>("#StoreConstraints"), 0u);
892 EXPECT_EQ(statistics.GetMeasurementValue<uint64_t>("#LoadConstraints"), 1u);
893 EXPECT_EQ(statistics.GetMeasurementValue<uint64_t>("#PointsToGraphNodes"), ptg->numNodes());
894 EXPECT_GT(statistics.GetTimerElapsedNanoseconds("AnalysisTimer"), 0u);
895}
896
897TEST(AndersenTests, TestConfiguration)
898{
899 using namespace jlm::llvm::aa;
900 auto config = Andersen::Configuration::NaiveSolverConfiguration();
901
902 // Arrange
903 config.EnableOfflineVariableSubstitution(false);
904 config.EnableOfflineConstraintNormalization(true);
905 config.SetSolver(Andersen::Configuration::Solver::Naive);
906
907 // Act
908 auto configString = config.ToString();
909
910 // Assert
911 EXPECT_FALSE(config.IsOfflineVariableSubstitutionEnabled());
912 EXPECT_TRUE(config.IsOfflineConstraintNormalizationEnabled());
913 EXPECT_EQ(config.GetSolver(), Andersen::Configuration::Solver::Naive);
914 EXPECT_EQ(configString.find("OVS"), std::string::npos);
915 EXPECT_NE(configString.find("NORM"), std::string::npos);
916 EXPECT_NE(configString.find("Solver=Naive"), std::string::npos);
917
918 // Arrange some more
919 auto policy = PointerObjectConstraintSet::WorklistSolverPolicy::TwoPhaseLeastRecentlyFired;
920 config.SetSolver(Andersen::Configuration::Solver::Worklist);
921 config.SetWorklistSolverPolicy(policy);
922 config.EnableOfflineVariableSubstitution(false);
923 config.EnableOnlineCycleDetection(true);
924
925 // Act
926 configString = config.ToString();
927
928 // Assert
929 EXPECT_NE(configString.find("Solver=Worklist"), std::string::npos);
930 EXPECT_NE(configString.find("Policy=TwoPhaseLeastRecentlyFired"), std::string::npos);
931 EXPECT_EQ(configString.find("OVS"), std::string::npos);
932 EXPECT_NE(configString.find("OnlineCD"), std::string::npos);
933
934 // Arrange some more
935 config.EnableOnlineCycleDetection(false);
936 config.EnableHybridCycleDetection(true);
937
938 // Act
939 configString = config.ToString();
940
941 // Assert
942 EXPECT_EQ(configString.find("OnlineCD"), std::string::npos);
943 EXPECT_NE(configString.find("HybridCD"), std::string::npos);
944}
945
946TEST(AndersenTests, TestConstructPointsToGraph)
947{
948 using namespace jlm::llvm::aa;
949
951 rvsdg.InitializeTest();
952
953 // Arrange a very standard set of memory objects and registers
955 auto alloca0 = set.CreateAllocaMemoryObject(rvsdg.GetAllocaNode(), true);
956 auto allocaR = set.CreateRegisterPointerObject(rvsdg.GetAllocaOutput());
957 auto import0 = set.CreateImportMemoryObject(rvsdg.GetImportOutput(), true);
958 auto importR = set.CreateRegisterPointerObject(rvsdg.GetImportOutput());
959 auto lambda0 = set.CreateFunctionMemoryObject(rvsdg.GetLambdaNode());
960 auto lambdaR = set.CreateRegisterPointerObject(rvsdg.GetLambdaOutput());
961 auto malloc0 = set.CreateMallocMemoryObject(rvsdg.GetMallocNode(), true);
962 auto mallocR = set.CreateRegisterPointerObject(rvsdg.GetMallocOutput());
963 set.AddToPointsToSet(allocaR, alloca0);
964 set.AddToPointsToSet(importR, import0);
965 set.AddToPointsToSet(lambdaR, lambda0);
966 set.AddToPointsToSet(mallocR, malloc0);
967
968 // Make an exception for the delta node: Map its output to importR's PointerObject instead
969 [[maybe_unused]] auto delta0 = set.CreateGlobalMemoryObject(rvsdg.GetDeltaNode(), true);
971
972 // Make alloca0 point to lambda0
973 set.AddToPointsToSet(alloca0, lambda0);
974
975 // create a dummy node
976 auto dummy = set.CreateDummyRegisterPointerObject();
977
978 // Unify allocaR with dummy, and importR with dummy
979 set.UnifyPointerObjects(dummy, allocaR);
980 set.UnifyPointerObjects(dummy, importR);
981
982 // Unify a register and a memory object
983 set.UnifyPointerObjects(lambdaR, malloc0);
984
985 // Mark a register as pointing to external
986 set.MarkAsPointingToExternal(mallocR);
987 // And a memory object as escaped
988 set.MarkAsEscaped(delta0);
989
990 auto ptg = Andersen::ConstructPointsToGraphFromPointerObjectSet(set);
991
992 // Assert
993 auto allocaNode = ptg->getNodeForAlloca(rvsdg.GetAllocaNode());
994 auto allocaRNode = ptg->getNodeForRegister(rvsdg.GetAllocaOutput());
995 auto importNode = ptg->getNodeForImport(rvsdg.GetImportOutput());
996 auto importRNode = ptg->getNodeForRegister(rvsdg.GetImportOutput());
997 auto lambdaNode = ptg->getNodeForLambda(rvsdg.GetLambdaNode());
998 auto lambdaRNode = ptg->getNodeForRegister(rvsdg.GetLambdaOutput());
999 auto mallocNode = ptg->getNodeForMalloc(rvsdg.GetMallocNode());
1000 auto mallocRNode = ptg->getNodeForRegister(rvsdg.GetMallocOutput());
1001 auto deltaNode = ptg->getNodeForDelta(rvsdg.GetDeltaNode());
1002 auto deltaRNode = ptg->getNodeForRegister(rvsdg.GetDeltaOutput());
1003
1004 auto externalMemory = ptg->getExternalMemoryNode();
1005
1006 // ==== Targets of allocaR, importR and deltaR ==== (2 explicit, 2 total)
1007 // Make sure unification causes allocaR to point to all of its pointees
1008 EXPECT_TRUE(TargetsExactly(*ptg, allocaRNode, { allocaNode, importNode }));
1009 // The unified registers should share RegisterNode
1010 EXPECT_EQ(allocaRNode, importRNode);
1011 // deltaR was mapped to importR, so it too should share RegisterNode
1012 EXPECT_EQ(allocaRNode, deltaRNode);
1013
1014 // ==== Targets of lambdaR ==== (1 explicit, 1 total)
1015 EXPECT_TRUE(TargetsExactly(*ptg, lambdaRNode, { lambdaNode }));
1016
1017 // ==== Targets of mallocR ==== (1 explicit, 4 total)
1018 // mallocR points to mallocNode, as well as everything that has escaped
1019 EXPECT_TRUE(
1020 TargetsExactly(*ptg, mallocRNode, { mallocNode, deltaNode, importNode, externalMemory }));
1021
1022 // ==== Targets of alloca0 ==== (1 explicit, 1 total)
1023 EXPECT_TRUE(TargetsExactly(*ptg, allocaNode, { lambdaNode }));
1024
1025 // ==== Targets of malloc0 ==== (1 explicit, 1 total)
1026 // Because malloc0 was unified with lambdaR, they have the same targets, but are not the same node
1027 EXPECT_NE(lambdaRNode, mallocNode);
1028 EXPECT_TRUE(TargetsExactly(*ptg, mallocNode, { lambdaNode }));
1029
1030 // ==== Targets of delta0 ==== (0 explicit, 3 total)
1031 // deltaNode points to everything that has escaped, but only implicitly
1032 EXPECT_TRUE(ptg->isExternallyAvailable(deltaNode));
1033 EXPECT_TRUE(ptg->isTargetingAllExternallyAvailable(deltaNode));
1034 EXPECT_TRUE(TargetsExactly(*ptg, deltaNode, { deltaNode, importNode, externalMemory }));
1035
1036 // ==== Targets of import0 ==== (0 explicit, 3 total)
1037 // The importNode should be flagged as targeting everything externally available
1038 EXPECT_TRUE(ptg->isExternallyAvailable(importNode));
1039 EXPECT_TRUE(ptg->isTargetingAllExternallyAvailable(importNode));
1040 EXPECT_TRUE(TargetsExactly(*ptg, importNode, { deltaNode, importNode, externalMemory }));
1041
1042 // ==== Targets of lambda0 ==== (0 explicit, 0 total)
1043 // Because lambda nodes are marked as CanPoint()=false, they have no targets
1044 EXPECT_FALSE(ptg->isTargetingAllExternallyAvailable(lambdaNode));
1045 EXPECT_FALSE(ptg->isExternallyAvailable(lambdaNode));
1046 EXPECT_TRUE(TargetsExactly(*ptg, lambdaNode, {}));
1047
1048 // ==== Targets of externalMemoryNode ==== (0 explicit, 3 total)
1049 // While the external node has no explicit targets, it targets everything externally available
1050 EXPECT_EQ(ptg->getExplicitTargets(externalMemory).Size(), 0u);
1051 EXPECT_TRUE(TargetsExactly(*ptg, externalMemory, { deltaNode, importNode, externalMemory }));
1052
1053 // 5 memory node + register pairs, plus one external memory node,
1054 // minus two registers that have been unified into allocaRNode
1055 unsigned int expectedNumNodes = 5 * 2 + 1 - 2;
1056 EXPECT_EQ(ptg->numNodes(), expectedNumNodes);
1057
1058 // Adding up the out-edges for all nodes
1059 auto [numExplicitEdges, numTotalEdges] = ptg->numEdges();
1060 unsigned int expectedNumExplicitEdges = 2 + 1 + 1 + 1 + 1;
1061 EXPECT_EQ(numExplicitEdges, expectedNumExplicitEdges);
1062 // total edges also includes the outgoing implicit edges from the external node
1063 unsigned int expectedNumTotalEdges = 2 + 1 + 4 + 1 + 1 + 3 + 3 + 0 + 3;
1064 EXPECT_EQ(numTotalEdges, expectedNumTotalEdges);
1065}
static bool TargetsExactly(const jlm::llvm::aa::PointsToGraph &pointsToGraph, const jlm::llvm::aa::PointsToGraph::NodeIndex ptgNode, const std::unordered_set< jlm::llvm::aa::PointsToGraph::NodeIndex > &expectedTargets)
Checks that the given PointsToGraph node points to exactly the given set of target nodes.
TEST(AndersenTests, TestStore1)
static bool EscapedIsExactly(const jlm::llvm::aa::PointsToGraph &pointsToGraph, const std::unordered_set< jlm::llvm::aa::PointsToGraph::NodeIndex > &nodes)
Checks that the set of Memory Nodes escaping the PointsToGraph is exactly equal to the given set of n...
static std::unique_ptr< jlm::llvm::aa::PointsToGraph > RunAndersen(jlm::llvm::LlvmRvsdgModule &module)
static jlm::util::StatisticsCollector statisticsCollector
std::int64_t expected
std::vector< rvsdg::Node * > nodes
RVSDG module with one of each memory node type.
const rvsdg::SimpleNode & GetMallocNode() const noexcept
const jlm::rvsdg::Output & GetMallocOutput() const noexcept
const jlm::rvsdg::DeltaNode & GetDeltaNode() const noexcept
const rvsdg::SimpleNode & GetAllocaNode() const noexcept
const rvsdg::Output & GetDeltaOutput() const noexcept
const jlm::rvsdg::Output & GetAllocaOutput() const noexcept
const llvm::LlvmGraphImport & GetImportOutput() const noexcept
const jlm::rvsdg::LambdaNode & GetLambdaNode() const noexcept
const rvsdg::Output & GetLambdaOutput() const noexcept
BitCastTest class.
jlm::rvsdg::LambdaNode * lambda
Bits2PtrTest class.
const rvsdg::Node & GetBitsToPtrNode() const noexcept
const jlm::rvsdg::LambdaNode & GetLambdaTest() const noexcept
const rvsdg::SimpleNode & GetCallNode() const noexcept
CallTest1 class.
rvsdg::SimpleNode * alloca_y
rvsdg::SimpleNode * alloca_z
jlm::rvsdg::LambdaNode * lambda_g
jlm::rvsdg::LambdaNode * lambda_f
rvsdg::SimpleNode * alloca_x
jlm::rvsdg::LambdaNode * lambda_h
CallTest2 class.
jlm::rvsdg::LambdaNode * lambda_test
const rvsdg::SimpleNode & CallCreate2() const noexcept
jlm::rvsdg::LambdaNode * lambda_create
jlm::rvsdg::LambdaNode * lambda_destroy
const rvsdg::SimpleNode & CallCreate1() const noexcept
rvsdg::SimpleNode * malloc
ConstantPointerNullTest class.
jlm::rvsdg::LambdaNode * lambda
DeltaTest1 class.
jlm::rvsdg::DeltaNode * delta_f
jlm::rvsdg::LambdaNode * lambda_h
jlm::rvsdg::LambdaNode * lambda_g
DeltaTest2 class.
jlm::rvsdg::LambdaNode * lambda_f2
jlm::rvsdg::LambdaNode * lambda_f1
jlm::rvsdg::DeltaNode * delta_d2
jlm::rvsdg::DeltaNode * delta_d1
EscapedMemoryTest1 class.
jlm::rvsdg::DeltaNode * DeltaX
jlm::rvsdg::DeltaNode * DeltaA
jlm::rvsdg::DeltaNode * DeltaB
jlm::rvsdg::LambdaNode * LambdaTest
rvsdg::SimpleNode * LoadNode1
jlm::rvsdg::DeltaNode * DeltaY
EscapedMemoryTest2 class.
jlm::rvsdg::LambdaNode * CallExternalFunction2
rvsdg::SimpleNode * ReturnAddressMalloc
jlm::rvsdg::LambdaNode * CallExternalFunction1
rvsdg::SimpleNode * ExternalFunction2Call
jlm::rvsdg::LambdaNode * ReturnAddressFunction
jlm::rvsdg::GraphImport * ExternalFunction1Import
jlm::rvsdg::GraphImport * ExternalFunction2Import
rvsdg::SimpleNode * CallExternalFunction1Malloc
EscapedMemoryTest3 class.
rvsdg::SimpleNode * CallExternalFunction
jlm::rvsdg::GraphImport * ImportExternalFunction
jlm::rvsdg::DeltaNode * DeltaGlobal
jlm::rvsdg::LambdaNode * LambdaTest
const rvsdg::SimpleNode & CallG() const noexcept
const jlm::rvsdg::GraphImport & ExternalGArgument() const noexcept
const jlm::rvsdg::LambdaNode & LambdaF() const noexcept
ExternalMemoryTest class.
jlm::rvsdg::LambdaNode * LambdaF
GammaTest class.
rvsdg::GammaNode * gamma
jlm::rvsdg::LambdaNode * lambda
GetElementPtrTest class.
jlm::rvsdg::LambdaNode * lambda
ImportTest class.
jlm::rvsdg::LambdaNode * lambda_f1
jlm::rvsdg::LambdaNode * lambda_f2
jlm::rvsdg::GraphImport * import_d2
jlm::rvsdg::GraphImport * import_d1
IndirectCallTest1 class.
const jlm::rvsdg::LambdaNode & GetLambdaFour() const noexcept
const jlm::rvsdg::LambdaNode & GetLambdaThree() const noexcept
const jlm::rvsdg::LambdaNode & GetLambdaTest() const noexcept
const jlm::rvsdg::LambdaNode & GetLambdaIndcall() const noexcept
IndirectCallTest2 class.
jlm::rvsdg::LambdaNode & GetLambdaFour() const noexcept
jlm::rvsdg::LambdaNode & GetLambdaThree() const noexcept
LinkedListTest class.
const jlm::rvsdg::DeltaNode & GetDeltaMyList() const noexcept
const rvsdg::SimpleNode & GetAlloca() const noexcept
const jlm::rvsdg::LambdaNode & GetLambdaNext() const noexcept
LoadFromUndefTest class.
const jlm::rvsdg::LambdaNode & Lambda() const noexcept
const rvsdg::Node * UndefValueNode() const noexcept
LoadTest1 class.
jlm::rvsdg::LambdaNode * lambda
rvsdg::Node * load_p
LoadTest2 class.
rvsdg::SimpleNode * load_a
rvsdg::SimpleNode * alloca_p
jlm::rvsdg::LambdaNode * lambda
rvsdg::SimpleNode * alloca_y
rvsdg::SimpleNode * load_x
rvsdg::SimpleNode * alloca_a
rvsdg::SimpleNode * alloca_x
rvsdg::SimpleNode * alloca_b
MemcpyTest class.
const jlm::rvsdg::DeltaNode & GlobalArray() const noexcept
const jlm::rvsdg::LambdaNode & LambdaG() const noexcept
const rvsdg::SimpleNode & Memcpy() const noexcept
const jlm::rvsdg::DeltaNode & InitArray() const noexcept
const jlm::rvsdg::LambdaNode & LambdaF() const noexcept
PhiTest1 class.
rvsdg::GammaNode * gamma
rvsdg::SimpleNode * alloca
jlm::rvsdg::LambdaNode * lambda_test
jlm::rvsdg::LambdaNode * lambda_fib
jlm::rvsdg::PhiNode * phi
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
std::unique_ptr< PointsToGraph > Analyze(const rvsdg::RvsdgModule &module, util::StatisticsCollector &statisticsCollector) override
PointerObjectIndex CreateMallocMemoryObject(const rvsdg::SimpleNode &mallocNode, bool canPoint)
PointerObjectIndex UnifyPointerObjects(PointerObjectIndex object1, PointerObjectIndex object2)
PointerObjectIndex CreateDummyRegisterPointerObject()
PointerObjectIndex CreateGlobalMemoryObject(const rvsdg::DeltaNode &deltaNode, bool canPoint)
void MapRegisterToExistingPointerObject(const rvsdg::Output &rvsdgOutput, PointerObjectIndex pointerObject)
PointerObjectIndex CreateRegisterPointerObject(const rvsdg::Output &rvsdgOutput)
bool AddToPointsToSet(PointerObjectIndex pointer, PointerObjectIndex pointee)
PointerObjectIndex CreateAllocaMemoryObject(const rvsdg::SimpleNode &allocaNode, bool canPoint)
bool MarkAsPointingToExternal(PointerObjectIndex index)
PointerObjectIndex CreateFunctionMemoryObject(const rvsdg::LambdaNode &lambdaNode)
PointerObjectIndex CreateImportMemoryObject(const LlvmGraphImport &importNode, bool canPoint)
bool MarkAsEscaped(PointerObjectIndex index)
bool isTargetingAllExternallyAvailable(NodeIndex index) const
NodeIndex getExternalMemoryNode() const noexcept
const std::vector< NodeIndex > & getExternallyAvailableNodes() const noexcept
const util::HashSet< NodeIndex > & getExplicitTargets(NodeIndex index) const
rvsdg::Output & output() const noexcept
Definition delta.cpp:110
std::vector< ExitVar > GetExitVars() const
Gets all exit variables for this gamma.
Definition gamma.cpp:381
std::vector< EntryVar > GetEntryVars() const
Gets all entry variables for this gamma.
Definition gamma.cpp:305
Output * origin() const noexcept
Definition node.hpp:58
std::vector< rvsdg::Output * > GetFunctionArguments() const
Definition lambda.cpp:58
rvsdg::Output * output() const noexcept
Definition lambda.cpp:177
std::vector< ContextVar > GetContextVars() const noexcept
Gets all bound context variables.
Definition lambda.cpp:120
NodeOutput * output(size_t index) const noexcept
Definition node.hpp:650
std::vector< FixVar > GetFixVars() const noexcept
Gets all fixpoint variables.
Definition Phi.cpp:63
NodeInput * input(size_t index) const noexcept
NodeOutput * output(size_t index) const noexcept
StructuralOutput * output(size_t index) const noexcept
std::vector< LoopVar > GetLoopVars() const
Returns all loop variables.
Definition theta.cpp:176
bool insert(ItemType item)
Definition HashSet.hpp:210
StatisticsRange CollectedStatistics() const noexcept
size_t NumCollectedStatistics() const noexcept
Global memory state passed between functions.