Jlm
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 
10 #include <jlm/llvm/TestRvsdgs.hpp>
11 #include <jlm/util/Statistics.hpp>
12 
13 #include <cassert>
14 
15 static 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 {
63  jlm::util::HashSet expected(nodes);
64  expected.insert(pointsToGraph.getExternalMemoryNode());
65 
67  for (const auto escaped : pointsToGraph.getExternallyAvailableNodes())
68  actual.insert(escaped);
69 
70  return expected == actual;
71 }
72 
73 TEST(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 
115 TEST(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 
157 TEST(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 
179 TEST(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 
209 TEST(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 
224 TEST(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 
245 TEST(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 
265 TEST(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 
286 TEST(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 
306 TEST(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 
360 TEST(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 
406 TEST(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 
447 TEST(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 
467 TEST(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 
491 TEST(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 
527 TEST(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 
555 TEST(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 
589 TEST(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 
628 TEST(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 
667 TEST(AndersenTests, TestPhi1)
668 {
669  jlm::llvm::PhiTest1 test;
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 
708 TEST(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 
726 TEST(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 
759 TEST(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 
804 TEST(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 
829 TEST(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 localArray = ptg->getNodeForDelta(test.LocalArray());
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, { localArray }));
849 
850  EXPECT_TRUE(EscapedIsExactly(*ptg, { globalArray, localArray, lambdaF, lambdaG }));
851 }
852 
853 TEST(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 
875 TEST(AndersenTests, TestStatistics)
876 {
877  // Arrange
879  jlm::util::StatisticsCollectorSettings statisticsCollectorSettings(
881  jlm::util::StatisticsCollector statisticsCollector(statisticsCollectorSettings);
882 
883  // Act
884  jlm::llvm::aa::Andersen andersen;
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 
897 TEST(AndersenTests, TestConfiguration)
898 {
899  using namespace jlm::llvm::aa;
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
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 
946 TEST(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
954  PointerObjectSet set;
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 
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
RVSDG module with one of each memory node type.
const rvsdg::SimpleNode & GetAllocaNode() const noexcept
const rvsdg::Output & GetLambdaOutput() const noexcept
const jlm::rvsdg::LambdaNode & GetLambdaNode() const noexcept
const jlm::rvsdg::Output & GetAllocaOutput() const noexcept
const rvsdg::Output & GetDeltaOutput() const noexcept
const llvm::LlvmGraphImport & GetImportOutput() const noexcept
const rvsdg::SimpleNode & GetMallocNode() const noexcept
const jlm::rvsdg::DeltaNode & GetDeltaNode() const noexcept
const jlm::rvsdg::Output & GetMallocOutput() const noexcept
BitCastTest class.
Definition: TestRvsdgs.hpp:303
rvsdg::Node * bitCast
Definition: TestRvsdgs.hpp:311
jlm::rvsdg::LambdaNode * lambda
Definition: TestRvsdgs.hpp:309
Bits2PtrTest class.
Definition: TestRvsdgs.hpp:335
const jlm::rvsdg::LambdaNode & GetLambdaTest() const noexcept
Definition: TestRvsdgs.hpp:344
const rvsdg::Node & GetBitsToPtrNode() const noexcept
Definition: TestRvsdgs.hpp:356
const rvsdg::SimpleNode & GetCallNode() const noexcept
Definition: TestRvsdgs.hpp:350
CallTest1 class.
Definition: TestRvsdgs.hpp:425
rvsdg::SimpleNode * alloca_y
Definition: TestRvsdgs.hpp:448
rvsdg::SimpleNode * alloca_z
Definition: TestRvsdgs.hpp:449
jlm::rvsdg::LambdaNode * lambda_g
Definition: TestRvsdgs.hpp:444
jlm::rvsdg::LambdaNode * lambda_f
Definition: TestRvsdgs.hpp:443
rvsdg::SimpleNode * alloca_x
Definition: TestRvsdgs.hpp:447
jlm::rvsdg::LambdaNode * lambda_h
Definition: TestRvsdgs.hpp:445
CallTest2 class.
Definition: TestRvsdgs.hpp:488
jlm::rvsdg::LambdaNode * lambda_test
Definition: TestRvsdgs.hpp:516
const rvsdg::SimpleNode & CallCreate2() const noexcept
Definition: TestRvsdgs.hpp:497
jlm::rvsdg::LambdaNode * lambda_create
Definition: TestRvsdgs.hpp:514
jlm::rvsdg::LambdaNode * lambda_destroy
Definition: TestRvsdgs.hpp:515
const rvsdg::SimpleNode & CallCreate1() const noexcept
Definition: TestRvsdgs.hpp:491
rvsdg::SimpleNode * malloc
Definition: TestRvsdgs.hpp:518
ConstantPointerNullTest class.
Definition: TestRvsdgs.hpp:385
jlm::rvsdg::LambdaNode * lambda
Definition: TestRvsdgs.hpp:391
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 jlm::rvsdg::GraphImport & ExternalGArgument() const noexcept
Definition: TestRvsdgs.hpp:857
const jlm::rvsdg::LambdaNode & LambdaF() const noexcept
Definition: TestRvsdgs.hpp:845
const rvsdg::SimpleNode & CallG() const noexcept
Definition: TestRvsdgs.hpp:851
ExternalMemoryTest class.
jlm::rvsdg::LambdaNode * LambdaF
GammaTest class.
Definition: TestRvsdgs.hpp:961
rvsdg::GammaNode * gamma
Definition: TestRvsdgs.hpp:969
jlm::rvsdg::LambdaNode * lambda
Definition: TestRvsdgs.hpp:967
GetElementPtrTest class.
Definition: TestRvsdgs.hpp:279
jlm::rvsdg::LambdaNode * lambda
Definition: TestRvsdgs.hpp:285
ImportTest class.
jlm::rvsdg::LambdaNode * lambda_f1
jlm::rvsdg::LambdaNode * lambda_f2
jlm::rvsdg::GraphImport * import_d2
jlm::rvsdg::GraphImport * import_d1
IndirectCallTest1 class.
Definition: TestRvsdgs.hpp:566
const jlm::rvsdg::LambdaNode & GetLambdaTest() const noexcept
Definition: TestRvsdgs.hpp:605
const jlm::rvsdg::LambdaNode & GetLambdaIndcall() const noexcept
Definition: TestRvsdgs.hpp:599
const jlm::rvsdg::LambdaNode & GetLambdaFour() const noexcept
Definition: TestRvsdgs.hpp:593
const jlm::rvsdg::LambdaNode & GetLambdaThree() const noexcept
Definition: TestRvsdgs.hpp:587
IndirectCallTest2 class.
Definition: TestRvsdgs.hpp:687
jlm::rvsdg::LambdaNode & GetLambdaFour() const noexcept
Definition: TestRvsdgs.hpp:708
jlm::rvsdg::LambdaNode & GetLambdaThree() const noexcept
Definition: TestRvsdgs.hpp:702
LinkedListTest class.
const jlm::rvsdg::DeltaNode & GetDeltaMyList() const noexcept
const rvsdg::SimpleNode & GetAlloca() const noexcept
const jlm::rvsdg::LambdaNode & GetLambdaNext() const noexcept
LoadFromUndefTest class.
Definition: TestRvsdgs.hpp:236
const jlm::rvsdg::LambdaNode & Lambda() const noexcept
Definition: TestRvsdgs.hpp:243
const rvsdg::Node * UndefValueNode() const noexcept
Definition: TestRvsdgs.hpp:249
LoadTest1 class.
Definition: TestRvsdgs.hpp:161
jlm::rvsdg::LambdaNode * lambda
Definition: TestRvsdgs.hpp:167
rvsdg::Node * load_p
Definition: TestRvsdgs.hpp:169
LoadTest2 class.
Definition: TestRvsdgs.hpp:200
rvsdg::SimpleNode * load_a
Definition: TestRvsdgs.hpp:217
rvsdg::SimpleNode * alloca_p
Definition: TestRvsdgs.hpp:214
jlm::rvsdg::LambdaNode * lambda
Definition: TestRvsdgs.hpp:206
rvsdg::SimpleNode * alloca_y
Definition: TestRvsdgs.hpp:213
rvsdg::SimpleNode * load_x
Definition: TestRvsdgs.hpp:216
rvsdg::SimpleNode * alloca_a
Definition: TestRvsdgs.hpp:210
rvsdg::SimpleNode * alloca_x
Definition: TestRvsdgs.hpp:212
rvsdg::SimpleNode * alloca_b
Definition: TestRvsdgs.hpp:211
MemcpyTest class.
const jlm::rvsdg::DeltaNode & LocalArray() const noexcept
const jlm::rvsdg::DeltaNode & GlobalArray() const noexcept
const jlm::rvsdg::LambdaNode & LambdaF() const noexcept
const jlm::rvsdg::LambdaNode & LambdaG() const noexcept
const rvsdg::SimpleNode & Memcpy() 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()
Definition: TestRvsdgs.hpp:34
StoreTest1 class.
Definition: TestRvsdgs.hpp:89
rvsdg::SimpleNode * alloca_c
Definition: TestRvsdgs.hpp:101
rvsdg::SimpleNode * alloca_a
Definition: TestRvsdgs.hpp:99
rvsdg::SimpleNode * alloca_d
Definition: TestRvsdgs.hpp:102
jlm::rvsdg::LambdaNode * lambda
Definition: TestRvsdgs.hpp:95
rvsdg::SimpleNode * alloca_b
Definition: TestRvsdgs.hpp:100
StoreTest2 class.
Definition: TestRvsdgs.hpp:127
rvsdg::SimpleNode * alloca_p
Definition: TestRvsdgs.hpp:141
jlm::rvsdg::LambdaNode * lambda
Definition: TestRvsdgs.hpp:133
rvsdg::SimpleNode * alloca_y
Definition: TestRvsdgs.hpp:140
rvsdg::SimpleNode * alloca_x
Definition: TestRvsdgs.hpp:139
rvsdg::SimpleNode * alloca_b
Definition: TestRvsdgs.hpp:138
rvsdg::SimpleNode * alloca_a
Definition: TestRvsdgs.hpp:137
ThetaTest class.
jlm::rvsdg::LambdaNode * lambda
jlm::rvsdg::ThetaNode * theta
static Configuration NaiveSolverConfiguration() noexcept
Definition: Andersen.hpp:249
static std::unique_ptr< PointsToGraph > ConstructPointsToGraphFromPointerObjectSet(const PointerObjectSet &set, Statistics &statistics)
Definition: Andersen.cpp:1640
std::unique_ptr< PointsToGraph > Analyze(const rvsdg::RvsdgModule &module, util::StatisticsCollector &statisticsCollector) override
Definition: Andersen.cpp:1531
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)
const util::HashSet< NodeIndex > & getExplicitTargets(NodeIndex index) const
bool isTargetingAllExternallyAvailable(NodeIndex index) const
const std::vector< NodeIndex > & getExternallyAvailableNodes() const noexcept
NodeIndex getExternalMemoryNode() const noexcept
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:57
rvsdg::Output * output() const noexcept
Definition: lambda.cpp:176
std::vector< ContextVar > GetContextVars() const noexcept
Gets all bound context variables.
Definition: lambda.cpp:119
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
Definition: simple-node.hpp:82
NodeOutput * output(size_t index) const noexcept
Definition: simple-node.hpp:88
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
Definition: Statistics.hpp:528
size_t NumCollectedStatistics() const noexcept
Definition: Statistics.hpp:535
Global memory state passed between functions.