Jlm
TestRvsdgs.cpp
Go to the documentation of this file.
1 /*
2  * Copyright 2020 Nico Reißmann <nico.reissmann@gmail.com>
3  * See COPYING for terms of redistribution.
4  */
5 
8 #include <jlm/rvsdg/gamma.hpp>
9 #include <jlm/rvsdg/theta.hpp>
10 
11 namespace jlm::llvm
12 {
13 
14 std::unique_ptr<jlm::llvm::LlvmRvsdgModule>
16 {
17  using namespace jlm::llvm;
18  using namespace jlm::rvsdg;
19 
20  auto pointerType = PointerType::Create();
21  auto fcttype =
23 
25  auto graph = &module->Rvsdg();
26 
27  auto fct = rvsdg::LambdaNode::Create(
30 
31  auto constantOne = &BitConstantOperation::create(*fct->subregion(), { 32, 1 });
32 
33  auto d = AllocaOperation::create(jlm::rvsdg::BitType::Create(32), constantOne, 4);
34  auto c = AllocaOperation::create(pointerType, constantOne, 4);
35  auto b = AllocaOperation::create(pointerType, constantOne, 4);
36  auto a = AllocaOperation::create(pointerType, constantOne, 4);
37 
38  auto merge_d = MemoryStateMergeOperation::Create(
39  std::vector<jlm::rvsdg::Output *>{ d[1], fct->GetFunctionArguments()[0] });
40  auto merge_c =
41  MemoryStateMergeOperation::Create(std::vector<jlm::rvsdg::Output *>({ c[1], merge_d }));
42  auto merge_b =
43  MemoryStateMergeOperation::Create(std::vector<jlm::rvsdg::Output *>({ b[1], merge_c }));
44  auto merge_a =
45  MemoryStateMergeOperation::Create(std::vector<jlm::rvsdg::Output *>({ a[1], merge_b }));
46 
47  auto a_amp_b = StoreNonVolatileOperation::Create(a[0], b[0], { merge_a }, 4);
48  auto b_amp_c = StoreNonVolatileOperation::Create(b[0], c[0], { a_amp_b[0] }, 4);
49  auto c_amp_d = StoreNonVolatileOperation::Create(c[0], d[0], { b_amp_c[0] }, 4);
50 
51  fct->finalize({ c_amp_d[0] });
52 
53  GraphExport::Create(*fct->output(), "f");
54 
55  /* extract nodes */
56 
57  this->lambda = fct;
58 
59  this->size = rvsdg::TryGetOwnerNode<rvsdg::SimpleNode>(*constantOne);
60 
61  this->alloca_a = rvsdg::TryGetOwnerNode<rvsdg::SimpleNode>(*a[0]);
62  this->alloca_b = rvsdg::TryGetOwnerNode<rvsdg::SimpleNode>(*b[0]);
63  this->alloca_c = rvsdg::TryGetOwnerNode<rvsdg::SimpleNode>(*c[0]);
64  this->alloca_d = rvsdg::TryGetOwnerNode<rvsdg::SimpleNode>(*d[0]);
65 
66  return module;
67 }
68 
69 std::unique_ptr<jlm::llvm::LlvmRvsdgModule>
71 {
72  using namespace jlm::llvm;
73  using namespace jlm::rvsdg;
74 
75  auto pointerType = PointerType::Create();
76  auto fcttype =
78 
80  auto graph = &module->Rvsdg();
81 
82  auto fct = rvsdg::LambdaNode::Create(
85 
86  auto constantOne = &BitConstantOperation::create(*fct->subregion(), { 32, 1 });
87 
88  auto a = AllocaOperation::create(jlm::rvsdg::BitType::Create(32), constantOne, 4);
89  auto b = AllocaOperation::create(jlm::rvsdg::BitType::Create(32), constantOne, 4);
90  auto x = AllocaOperation::create(pointerType, constantOne, 4);
91  auto y = AllocaOperation::create(pointerType, constantOne, 4);
92  auto p = AllocaOperation::create(pointerType, constantOne, 4);
93 
94  auto merge_a = MemoryStateMergeOperation::Create(
95  std::vector<jlm::rvsdg::Output *>{ a[1], fct->GetFunctionArguments()[0] });
96  auto merge_b =
97  MemoryStateMergeOperation::Create(std::vector<jlm::rvsdg::Output *>({ b[1], merge_a }));
98  auto merge_x =
99  MemoryStateMergeOperation::Create(std::vector<jlm::rvsdg::Output *>({ x[1], merge_b }));
100  auto merge_y =
101  MemoryStateMergeOperation::Create(std::vector<jlm::rvsdg::Output *>({ y[1], merge_x }));
102  auto merge_p =
103  MemoryStateMergeOperation::Create(std::vector<jlm::rvsdg::Output *>({ p[1], merge_y }));
104 
105  auto x_amp_a = StoreNonVolatileOperation::Create(x[0], a[0], { merge_p }, 4);
106  auto y_amp_b = StoreNonVolatileOperation::Create(y[0], b[0], { x_amp_a[0] }, 4);
107  auto p_amp_x = StoreNonVolatileOperation::Create(p[0], x[0], { y_amp_b[0] }, 4);
108  auto p_amp_y = StoreNonVolatileOperation::Create(p[0], y[0], { p_amp_x[0] }, 4);
109 
110  fct->finalize({ p_amp_y[0] });
111 
112  GraphExport::Create(*fct->output(), "f");
113 
114  /* extract nodes */
115 
116  this->lambda = fct;
117 
118  this->size = rvsdg::TryGetOwnerNode<rvsdg::SimpleNode>(*constantOne);
119 
120  this->alloca_a = rvsdg::TryGetOwnerNode<rvsdg::SimpleNode>(*a[0]);
121  this->alloca_b = rvsdg::TryGetOwnerNode<rvsdg::SimpleNode>(*b[0]);
122  this->alloca_x = rvsdg::TryGetOwnerNode<rvsdg::SimpleNode>(*x[0]);
123  this->alloca_y = rvsdg::TryGetOwnerNode<rvsdg::SimpleNode>(*y[0]);
124  this->alloca_p = rvsdg::TryGetOwnerNode<rvsdg::SimpleNode>(*p[0]);
125 
126  return module;
127 }
128 
129 std::unique_ptr<jlm::llvm::LlvmRvsdgModule>
131 {
132  using namespace jlm::llvm;
133  using namespace jlm::rvsdg;
134 
135  auto mt = MemoryStateType::Create();
136  auto pointerType = PointerType::Create();
137  auto intType = BitType::Create(32);
138  auto fcttype = rvsdg::FunctionType::Create(
140  { intType, MemoryStateType::Create() });
141 
142  auto module = llvm::LlvmRvsdgModule::Create(jlm::util::FilePath("LoadTest1.c"), "", "");
143  auto graph = &module->Rvsdg();
144 
145  auto fct = rvsdg::LambdaNode::Create(
146  graph->GetRootRegion(),
148 
150  fct->GetFunctionArguments()[0],
151  { fct->GetFunctionArguments()[1] },
152  pointerType,
153  4);
154  auto ld2 = LoadNonVolatileOperation::Create(ld1[0], { ld1[1] }, intType, 4);
155 
156  fct->finalize(ld2);
157 
158  GraphExport::Create(*fct->output(), "f");
159 
160  /* extract nodes */
161 
162  this->lambda = fct;
163 
164  this->load_p = rvsdg::TryGetOwnerNode<rvsdg::Node>(*ld1[0]);
165  this->load_x = rvsdg::TryGetOwnerNode<rvsdg::Node>(*ld2[0]);
166 
167  return module;
168 }
169 
170 std::unique_ptr<jlm::llvm::LlvmRvsdgModule>
172 {
173  using namespace jlm::llvm;
174  using namespace jlm::rvsdg;
175 
176  auto mt = MemoryStateType::Create();
177  auto pointerType = PointerType::Create();
178  auto fcttype =
180 
182  auto graph = &module->Rvsdg();
183 
184  auto fct = rvsdg::LambdaNode::Create(
185  graph->GetRootRegion(),
187 
188  auto constantOne = &BitConstantOperation::create(*fct->subregion(), { 32, 1 });
189 
190  auto a = AllocaOperation::create(jlm::rvsdg::BitType::Create(32), constantOne, 4);
191  auto b = AllocaOperation::create(jlm::rvsdg::BitType::Create(32), constantOne, 4);
192  auto x = AllocaOperation::create(pointerType, constantOne, 4);
193  auto y = AllocaOperation::create(pointerType, constantOne, 4);
194  auto p = AllocaOperation::create(pointerType, constantOne, 4);
195 
196  auto merge_a = MemoryStateMergeOperation::Create(
197  std::vector<jlm::rvsdg::Output *>{ a[1], fct->GetFunctionArguments()[0] });
198  auto merge_b =
199  MemoryStateMergeOperation::Create(std::vector<jlm::rvsdg::Output *>({ b[1], merge_a }));
200  auto merge_x =
201  MemoryStateMergeOperation::Create(std::vector<jlm::rvsdg::Output *>({ x[1], merge_b }));
202  auto merge_y =
203  MemoryStateMergeOperation::Create(std::vector<jlm::rvsdg::Output *>({ y[1], merge_x }));
204  auto merge_p =
205  MemoryStateMergeOperation::Create(std::vector<jlm::rvsdg::Output *>({ p[1], merge_y }));
206 
207  auto x_amp_a = StoreNonVolatileOperation::Create(x[0], a[0], { merge_p }, 4);
208  auto y_amp_b = StoreNonVolatileOperation::Create(y[0], b[0], x_amp_a, 4);
209  auto p_amp_x = StoreNonVolatileOperation::Create(p[0], x[0], y_amp_b, 4);
210 
211  auto ld1 = LoadNonVolatileOperation::Create(p[0], p_amp_x, pointerType, 4);
212  auto ld2 = LoadNonVolatileOperation::Create(ld1[0], { ld1[1] }, pointerType, 4);
213  auto y_star_p = StoreNonVolatileOperation::Create(y[0], ld2[0], { ld2[1] }, 4);
214 
215  fct->finalize({ y_star_p[0] });
216 
217  GraphExport::Create(*fct->output(), "f");
218 
219  /* extract nodes */
220 
221  this->lambda = fct;
222 
223  this->size = rvsdg::TryGetOwnerNode<rvsdg::Node>(*constantOne);
224 
225  this->alloca_a = rvsdg::TryGetOwnerNode<rvsdg::SimpleNode>(*a[0]);
226  this->alloca_b = rvsdg::TryGetOwnerNode<rvsdg::SimpleNode>(*b[0]);
227  this->alloca_x = rvsdg::TryGetOwnerNode<rvsdg::SimpleNode>(*x[0]);
228  this->alloca_y = rvsdg::TryGetOwnerNode<rvsdg::SimpleNode>(*y[0]);
229  this->alloca_p = rvsdg::TryGetOwnerNode<rvsdg::SimpleNode>(*p[0]);
230 
231  this->load_x = rvsdg::TryGetOwnerNode<rvsdg::SimpleNode>(*ld1[0]);
232  this->load_a = rvsdg::TryGetOwnerNode<rvsdg::SimpleNode>(*ld2[0]);
233 
234  return module;
235 }
236 
237 std::unique_ptr<jlm::llvm::LlvmRvsdgModule>
239 {
240  using namespace jlm::llvm;
241  using namespace jlm::rvsdg;
242 
243  auto memoryStateType = MemoryStateType::Create();
244  auto functionType = rvsdg::FunctionType::Create(
247  auto pointerType = PointerType::Create();
248 
249  auto rvsdgModule = llvm::LlvmRvsdgModule::Create(jlm::util::FilePath(""), "", "");
250  auto & rvsdg = rvsdgModule->Rvsdg();
251 
252  Lambda_ = rvsdg::LambdaNode::Create(
253  rvsdg.GetRootRegion(),
255 
256  auto undefValue = UndefValueOperation::Create(*Lambda_->subregion(), pointerType);
257  auto loadResults = LoadNonVolatileOperation::Create(
258  undefValue,
259  { Lambda_->GetFunctionArguments()[0] },
261  4);
262 
263  Lambda_->finalize(loadResults);
264  GraphExport::Create(*Lambda_->output(), "f");
265 
266  /*
267  * Extract nodes
268  */
269  UndefValueNode_ = rvsdg::TryGetOwnerNode<rvsdg::Node>(*undefValue);
270 
271  return rvsdgModule;
272 }
273 
274 std::unique_ptr<jlm::llvm::LlvmRvsdgModule>
276 {
277  using namespace jlm::llvm;
278  using namespace jlm::rvsdg;
279 
281  auto graph = &module->Rvsdg();
282 
283  auto structType =
284  StructType::CreateIdentified({ BitType::Create(32), BitType::Create(32) }, false);
285 
286  auto mt = MemoryStateType::Create();
287  auto pointerType = PointerType::Create();
288  auto fcttype = rvsdg::FunctionType::Create(
291 
292  auto fct = rvsdg::LambdaNode::Create(
293  graph->GetRootRegion(),
295 
296  auto zero = &BitConstantOperation::create(*fct->subregion(), { 32, 0 });
297  auto one = &BitConstantOperation::create(*fct->subregion(), { 32, 1 });
298 
299  auto gepx = GetElementPtrOperation::Create(
300  fct->GetFunctionArguments()[0],
301  { zero, zero },
302  structType,
303  pointerType);
305  gepx,
306  { fct->GetFunctionArguments()[1] },
308  4);
309 
310  auto gepy = GetElementPtrOperation::Create(
311  fct->GetFunctionArguments()[0],
312  { zero, one },
313  structType,
314  pointerType);
315  auto ldy = LoadNonVolatileOperation::Create(gepy, { ldx[1] }, jlm::rvsdg::BitType::Create(32), 4);
316 
317  auto sum = jlm::rvsdg::bitadd_op::create(32, ldx[0], ldy[0]);
318 
319  fct->finalize({ sum, ldy[1] });
320 
321  GraphExport::Create(*fct->output(), "f");
322 
323  /*
324  * Assign nodes
325  */
326  this->lambda = fct;
327 
328  this->getElementPtrX = rvsdg::TryGetOwnerNode<rvsdg::Node>(*gepx);
329  this->getElementPtrY = rvsdg::TryGetOwnerNode<rvsdg::Node>(*gepy);
330 
331  return module;
332 }
333 
334 std::unique_ptr<jlm::llvm::LlvmRvsdgModule>
336 {
337  using namespace jlm::llvm;
338  using namespace jlm::rvsdg;
339 
340  auto pointerType = PointerType::Create();
342 
344  auto graph = &module->Rvsdg();
345 
346  auto fct = rvsdg::LambdaNode::Create(
347  graph->GetRootRegion(),
349 
350  auto cast = BitCastOperation::create(fct->GetFunctionArguments()[0], pointerType);
351 
352  fct->finalize({ cast });
353 
354  GraphExport::Create(*fct->output(), "f");
355 
356  // Assign nodes
357  this->lambda = fct;
358  this->bitCast = rvsdg::TryGetOwnerNode<rvsdg::Node>(*cast);
359 
360  return module;
361 }
362 
363 std::unique_ptr<jlm::llvm::LlvmRvsdgModule>
365 {
366  using namespace jlm::llvm;
367  using namespace jlm::rvsdg;
368 
370  auto graph = &module->Rvsdg();
371 
372  auto setupBit2PtrFunction = [&]()
373  {
374  auto pt = PointerType::Create();
375  auto iOStateType = IOStateType::Create();
376  auto memoryStateType = MemoryStateType::Create();
377  auto functionType = rvsdg::FunctionType::Create(
380 
382  graph->GetRootRegion(),
384  auto valueArgument = lambda->GetFunctionArguments()[0];
385  auto iOStateArgument = lambda->GetFunctionArguments()[1];
386  auto memoryStateArgument = lambda->GetFunctionArguments()[2];
387 
388  auto cast = IntegerToPointerOperation::create(valueArgument, pt);
389 
390  lambda->finalize({ cast, iOStateArgument, memoryStateArgument });
391 
392  return std::make_tuple(lambda, rvsdg::TryGetOwnerNode<rvsdg::Node>(*cast));
393  };
394 
395  auto setupTestFunction = [&](rvsdg::Output * b2p)
396  {
397  auto iOStateType = IOStateType::Create();
398  auto memoryStateType = MemoryStateType::Create();
399  auto functionType = rvsdg::FunctionType::Create(
402 
404  graph->GetRootRegion(),
406  auto valueArgument = lambda->GetFunctionArguments()[0];
407  auto iOStateArgument = lambda->GetFunctionArguments()[1];
408  auto memoryStateArgument = lambda->GetFunctionArguments()[2];
409 
410  auto cvbits2ptr = lambda->AddContextVar(*b2p).inner;
411 
412  auto & call = CallOperation::CreateNode(
413  cvbits2ptr,
414  rvsdg::AssertGetOwnerNode<rvsdg::LambdaNode>(*b2p).GetOperation().Type(),
415  { valueArgument, iOStateArgument, memoryStateArgument });
416 
417  lambda->finalize(
419  GraphExport::Create(*lambda->output(), "testfct");
420 
421  return std::make_tuple(lambda, &call);
422  };
423 
424  auto [lambdaBits2Ptr, bitsToPtrNode] = setupBit2PtrFunction();
425  auto [lambdaTest, callNode] = setupTestFunction(lambdaBits2Ptr->output());
426 
427  // Assign nodes
428  this->LambdaBits2Ptr_ = lambdaBits2Ptr;
429  this->LambdaTest_ = lambdaTest;
430 
431  this->BitsToPtrNode_ = bitsToPtrNode;
432 
433  this->CallNode_ = callNode;
434 
435  return module;
436 }
437 
438 std::unique_ptr<jlm::llvm::LlvmRvsdgModule>
440 {
441  using namespace jlm::llvm;
442  using namespace jlm::rvsdg;
443 
444  auto mt = MemoryStateType::Create();
445  auto pointerType = PointerType::Create();
446  auto fcttype = rvsdg::FunctionType::Create(
449 
451  auto graph = &module->Rvsdg();
452 
453  auto fct = rvsdg::LambdaNode::Create(
454  graph->GetRootRegion(),
456 
457  auto constantPointerNullResult =
458  ConstantPointerNullOperation::Create(fct->subregion(), pointerType);
460  fct->GetFunctionArguments()[0],
461  constantPointerNullResult,
462  { fct->GetFunctionArguments()[1] },
463  4);
464 
465  fct->finalize({ st[0] });
466 
467  GraphExport::Create(*fct->output(), "f");
468 
469  /*
470  * Assign nodes
471  */
472  this->lambda = fct;
473  this->constantPointerNullNode = rvsdg::TryGetOwnerNode<rvsdg::Node>(*constantPointerNullResult);
474 
475  return module;
476 }
477 
478 std::unique_ptr<jlm::llvm::LlvmRvsdgModule>
480 {
481  using namespace jlm::llvm;
482  using namespace jlm::rvsdg;
483 
485  auto graph = &module->Rvsdg();
486 
487  auto SetupF = [&]()
488  {
489  auto pt = PointerType::Create();
490  auto iOStateType = IOStateType::Create();
491  auto memoryStateType = MemoryStateType::Create();
492  auto functionType = rvsdg::FunctionType::Create(
498 
500  graph->GetRootRegion(),
502  auto pointerArgument1 = lambda->GetFunctionArguments()[0];
503  auto pointerArgument2 = lambda->GetFunctionArguments()[1];
504  auto iOStateArgument = lambda->GetFunctionArguments()[2];
505  auto memoryStateArgument = lambda->GetFunctionArguments()[3];
506 
508  pointerArgument1,
509  { memoryStateArgument },
511  4);
513  pointerArgument2,
514  { ld1[1] },
516  4);
517 
518  auto sum = jlm::rvsdg::bitadd_op::create(32, ld1[0], ld2[0]);
519 
520  lambda->finalize({ sum, iOStateArgument, ld2[1] });
521 
522  return lambda;
523  };
524 
525  auto SetupG = [&]()
526  {
527  auto pt = PointerType::Create();
528  auto iOStateType = IOStateType::Create();
529  auto memoryStateType = MemoryStateType::Create();
530  auto functionType = rvsdg::FunctionType::Create(
536 
538  graph->GetRootRegion(),
540  auto pointerArgument1 = lambda->GetFunctionArguments()[0];
541  auto pointerArgument2 = lambda->GetFunctionArguments()[1];
542  auto iOStateArgument = lambda->GetFunctionArguments()[2];
543  auto memoryStateArgument = lambda->GetFunctionArguments()[3];
544 
546  pointerArgument1,
547  { memoryStateArgument },
549  4);
551  pointerArgument2,
552  { ld1[1] },
554  4);
555 
556  auto diff = jlm::rvsdg::bitsub_op::create(32, ld1[0], ld2[0]);
557 
558  lambda->finalize({ diff, iOStateArgument, ld2[1] });
559 
560  return lambda;
561  };
562 
563  auto SetupH = [&](rvsdg::LambdaNode * f, rvsdg::LambdaNode * g)
564  {
565  auto iOStateType = IOStateType::Create();
566  auto memoryStateType = MemoryStateType::Create();
567  auto functionType = rvsdg::FunctionType::Create(
570 
572  graph->GetRootRegion(),
574  auto iOStateArgument = lambda->GetFunctionArguments()[0];
575  auto memoryStateArgument = lambda->GetFunctionArguments()[1];
576 
577  auto cvf = lambda->AddContextVar(*f->output()).inner;
578  auto cvg = lambda->AddContextVar(*g->output()).inner;
579 
580  auto constantOne = &BitConstantOperation::create(*lambda->subregion(), { 32, 1 });
581 
582  auto x = AllocaOperation::create(jlm::rvsdg::BitType::Create(32), constantOne, 4);
583  auto y = AllocaOperation::create(jlm::rvsdg::BitType::Create(32), constantOne, 4);
584  auto z = AllocaOperation::create(jlm::rvsdg::BitType::Create(32), constantOne, 4);
585 
587  std::vector<jlm::rvsdg::Output *>({ x[1], memoryStateArgument }));
588  auto my = MemoryStateMergeOperation::Create(std::vector<jlm::rvsdg::Output *>({ y[1], mx }));
589  auto mz = MemoryStateMergeOperation::Create(std::vector<jlm::rvsdg::Output *>({ z[1], my }));
590 
591  auto five = &BitConstantOperation::create(*lambda->subregion(), { 32, 5 });
592  auto six = &BitConstantOperation::create(*lambda->subregion(), { 32, 6 });
593  auto seven = &BitConstantOperation::create(*lambda->subregion(), { 32, 7 });
594 
595  auto stx = StoreNonVolatileOperation::Create(x[0], five, { mz }, 4);
596  auto sty = StoreNonVolatileOperation::Create(y[0], six, { stx[0] }, 4);
597  auto stz = StoreNonVolatileOperation::Create(z[0], seven, { sty[0] }, 4);
598 
599  auto & callF = CallOperation::CreateNode(
600  cvf,
601  f->GetOperation().Type(),
602  { x[0], y[0], iOStateArgument, stz[0] });
603  auto & callG = CallOperation::CreateNode(
604  cvg,
605  g->GetOperation().Type(),
606  { z[0],
607  z[0],
608  &CallOperation::GetIOStateOutput(callF),
609  &CallOperation::GetMemoryStateOutput(callF) });
610 
611  auto sum = jlm::rvsdg::bitadd_op::create(32, callF.output(0), callG.output(0));
612 
613  lambda->finalize({ sum,
616  GraphExport::Create(*lambda->output(), "h");
617 
618  auto allocaX = rvsdg::TryGetOwnerNode<rvsdg::SimpleNode>(*x[0]);
619  auto allocaY = rvsdg::TryGetOwnerNode<rvsdg::SimpleNode>(*y[0]);
620  auto allocaZ = rvsdg::TryGetOwnerNode<rvsdg::SimpleNode>(*z[0]);
621 
622  return std::make_tuple(lambda, allocaX, allocaY, allocaZ, &callF, &callG);
623  };
624 
625  auto lambdaF = SetupF();
626  auto lambdaG = SetupG();
627  auto [lambdaH, allocaX, allocaY, allocaZ, callF, callG] = SetupH(lambdaF, lambdaG);
628 
629  /*
630  * Assign nodes
631  */
632  this->lambda_f = lambdaF;
633  this->lambda_g = lambdaG;
634  this->lambda_h = lambdaH;
635 
636  this->alloca_x = allocaX;
637  this->alloca_y = allocaY;
638  this->alloca_z = allocaZ;
639 
640  this->CallF_ = callF;
641  this->CallG_ = callG;
642 
643  return module;
644 }
645 
646 std::unique_ptr<jlm::llvm::LlvmRvsdgModule>
648 {
649  using namespace jlm::llvm;
650  using namespace jlm::rvsdg;
651 
653  auto graph = &module->Rvsdg();
654 
655  auto SetupCreate = [&]()
656  {
657  auto pt32 = PointerType::Create();
658  auto iOStateType = IOStateType::Create();
659  auto memoryStateType = MemoryStateType::Create();
660  auto functionType = rvsdg::FunctionType::Create(
663 
665  graph->GetRootRegion(),
667  auto valueArgument = lambda->GetFunctionArguments()[0];
668  auto iOStateArgument = lambda->GetFunctionArguments()[1];
669  auto memoryStateArgument = lambda->GetFunctionArguments()[2];
670 
671  auto four = &BitConstantOperation::create(*lambda->subregion(), { 32, 4 });
672  auto prod = jlm::rvsdg::bitmul_op::create(32, valueArgument, four);
673 
674  auto & mallocNode = MallocOperation::createNode(*prod, *iOStateArgument);
675  auto cast = BitCastOperation::create(&MallocOperation::addressOutput(mallocNode), pt32);
677  std::vector({ &MallocOperation::memoryStateOutput(mallocNode), memoryStateArgument }));
678 
679  lambda->finalize({ cast, &MallocOperation::ioStateOutput(mallocNode), mx });
680 
681  return std::make_tuple(lambda, &mallocNode);
682  };
683 
684  auto SetupDestroy = [&]()
685  {
686  auto pointerType = PointerType::Create();
687  auto iOStateType = IOStateType::Create();
688  auto memoryStateType = MemoryStateType::Create();
689  auto functionType = rvsdg::FunctionType::Create(
692 
694  graph->GetRootRegion(),
696  auto pointerArgument = lambda->GetFunctionArguments()[0];
697  auto iOStateArgument = lambda->GetFunctionArguments()[1];
698  auto memoryStateArgument = lambda->GetFunctionArguments()[2];
699 
700  auto cast = BitCastOperation::create(pointerArgument, pointerType);
701  auto freeResults = FreeOperation::Create(cast, { memoryStateArgument }, iOStateArgument);
702 
703  lambda->finalize({ freeResults[1], freeResults[0] });
704 
705  auto freeNode = rvsdg::TryGetOwnerNode<rvsdg::SimpleNode>(*freeResults[0]);
706  return std::make_tuple(lambda, freeNode);
707  };
708 
709  auto SetupTest = [&](rvsdg::LambdaNode * lambdaCreate, rvsdg::LambdaNode * lambdaDestroy)
710  {
711  auto iOStateType = IOStateType::Create();
712  auto memoryStateType = MemoryStateType::Create();
713  auto functionType = rvsdg::FunctionType::Create(
716 
718  graph->GetRootRegion(),
720  auto iOStateArgument = lambda->GetFunctionArguments()[0];
721  auto memoryStateArgument = lambda->GetFunctionArguments()[1];
722 
723  auto create_cv = lambda->AddContextVar(*lambdaCreate->output()).inner;
724  auto destroy_cv = lambda->AddContextVar(*lambdaDestroy->output()).inner;
725 
726  auto six = &BitConstantOperation::create(*lambda->subregion(), { 32, 6 });
727  auto seven = &BitConstantOperation::create(*lambda->subregion(), { 32, 7 });
728 
729  auto & create1 = CallOperation::CreateNode(
730  create_cv,
731  lambdaCreate->GetOperation().Type(),
732  { six, iOStateArgument, memoryStateArgument });
733  auto & create2 = CallOperation::CreateNode(
734  create_cv,
735  lambdaCreate->GetOperation().Type(),
736  { seven,
737  &CallOperation::GetIOStateOutput(create1),
738  &CallOperation::GetMemoryStateOutput(create1) });
739 
740  auto & destroy1 = CallOperation::CreateNode(
741  destroy_cv,
742  lambdaDestroy->GetOperation().Type(),
743  { create1.output(0),
744  &CallOperation::GetIOStateOutput(create2),
745  &CallOperation::GetMemoryStateOutput(create2) });
746  auto & destroy2 = CallOperation::CreateNode(
747  destroy_cv,
748  lambdaDestroy->GetOperation().Type(),
749  { create2.output(0),
750  &CallOperation::GetIOStateOutput(destroy1),
751  &CallOperation::GetMemoryStateOutput(destroy1) });
752 
755  GraphExport::Create(*lambda->output(), "test");
756 
757  return std::make_tuple(lambda, &create1, &create2, &destroy1, &destroy2);
758  };
759 
760  auto [lambdaCreate, mallocNode] = SetupCreate();
761  auto [lambdaDestroy, freeNode] = SetupDestroy();
762  auto [lambdaTest, callCreate1, callCreate2, callDestroy1, callDestroy2] =
763  SetupTest(lambdaCreate, lambdaDestroy);
764 
765  /*
766  * Assign nodes
767  */
768  this->lambda_create = lambdaCreate;
769  this->lambda_destroy = lambdaDestroy;
770  this->lambda_test = lambdaTest;
771 
772  this->malloc = mallocNode;
773  this->free = freeNode;
774 
775  this->CallCreate1_ = callCreate1;
776  this->CallCreate2_ = callCreate2;
777 
778  this->CallDestroy1_ = callCreate1;
779  this->CallDestroy2_ = callCreate2;
780 
781  return module;
782 }
783 
784 std::unique_ptr<jlm::llvm::LlvmRvsdgModule>
786 {
787  using namespace jlm::llvm;
788  using namespace jlm::rvsdg;
789 
790  auto iOStateType = IOStateType::Create();
791  auto memoryStateType = MemoryStateType::Create();
792  auto constantFunctionType = rvsdg::FunctionType::Create(
795  auto pointerType = PointerType::Create();
796 
798  auto graph = &module->Rvsdg();
799 
800  auto SetupConstantFunction = [&](ssize_t n, const std::string & name)
801  {
803  graph->GetRootRegion(),
804  llvm::LlvmLambdaOperation::Create(constantFunctionType, name, Linkage::externalLinkage));
805  auto iOStateArgument = lambda->GetFunctionArguments()[0];
806  auto memoryStateArgument = lambda->GetFunctionArguments()[1];
807 
808  auto constant = &BitConstantOperation::create(*lambda->subregion(), { 32, n });
809 
810  return lambda->finalize({ constant, iOStateArgument, memoryStateArgument });
811  };
812 
813  auto SetupIndirectCallFunction = [&]()
814  {
815  auto iOStateType = IOStateType::Create();
816  auto memoryStateType = MemoryStateType::Create();
817  auto functionType = rvsdg::FunctionType::Create(
820 
822  graph->GetRootRegion(),
824  auto pointerArgument = lambda->GetFunctionArguments()[0];
825  auto functionOfPointer =
826  rvsdg::CreateOpNode<PointerToFunctionOperation>({ pointerArgument }, constantFunctionType)
827  .output(0);
828  auto iOStateArgument = lambda->GetFunctionArguments()[1];
829  auto memoryStateArgument = lambda->GetFunctionArguments()[2];
830 
831  auto & call = CallOperation::CreateNode(
832  functionOfPointer,
833  constantFunctionType,
834  { iOStateArgument, memoryStateArgument });
835 
836  auto lambdaOutput = lambda->finalize(outputs(&call));
837 
838  return std::make_tuple(lambdaOutput, &call);
839  };
840 
841  auto SetupTestFunction =
842  [&](rvsdg::Output * fctindcall, rvsdg::Output * fctthree, rvsdg::Output * fctfour)
843  {
844  auto functionType = rvsdg::FunctionType::Create(
847 
849  graph->GetRootRegion(),
851  auto iOStateArgument = lambda->GetFunctionArguments()[0];
852  auto memoryStateArgument = lambda->GetFunctionArguments()[1];
853 
854  auto fctindcall_cv = lambda->AddContextVar(*fctindcall).inner;
855  auto fctfour_cv = lambda->AddContextVar(*fctfour).inner;
856  auto fctthree_cv = lambda->AddContextVar(*fctthree).inner;
857 
858  auto & call_four = CallOperation::CreateNode(
859  fctindcall_cv,
860  rvsdg::AssertGetOwnerNode<rvsdg::LambdaNode>(*fctindcall).GetOperation().Type(),
861  { fctfour_cv, iOStateArgument, memoryStateArgument });
862  auto & call_three = CallOperation::CreateNode(
863  fctindcall_cv,
864  rvsdg::AssertGetOwnerNode<rvsdg::LambdaNode>(*fctindcall).GetOperation().Type(),
865  { fctthree_cv,
866  &CallOperation::GetIOStateOutput(call_four),
867  &CallOperation::GetMemoryStateOutput(call_four) });
868 
869  auto add = jlm::rvsdg::bitadd_op::create(32, call_four.output(0), call_three.output(0));
870 
871  auto lambdaOutput = lambda->finalize({ add,
872  &CallOperation::GetIOStateOutput(call_three),
873  &CallOperation::GetMemoryStateOutput(call_three) });
874  GraphExport::Create(*lambda->output(), "test");
875 
876  return std::make_tuple(lambdaOutput, &call_three, &call_four);
877  };
878 
879  auto fctfour = SetupConstantFunction(4, "four");
880  auto fctthree = SetupConstantFunction(3, "three");
881  auto [fctindcall, callIndirectFunction] = SetupIndirectCallFunction();
882  auto [fcttest, callFunctionThree, callFunctionFour] = SetupTestFunction(
883  fctindcall,
884  rvsdg::CreateOpNode<FunctionToPointerOperation>({ fctthree }, constantFunctionType).output(0),
885  rvsdg::CreateOpNode<FunctionToPointerOperation>({ fctfour }, constantFunctionType).output(0));
886 
887  /*
888  * Assign
889  */
890  this->LambdaThree_ = &rvsdg::AssertGetOwnerNode<rvsdg::LambdaNode>(*fctthree);
891  this->LambdaFour_ = &rvsdg::AssertGetOwnerNode<rvsdg::LambdaNode>(*fctfour);
892  this->LambdaIndcall_ = &rvsdg::AssertGetOwnerNode<rvsdg::LambdaNode>(*fctindcall);
893  this->LambdaTest_ = &rvsdg::AssertGetOwnerNode<rvsdg::LambdaNode>(*fcttest);
894 
895  this->CallIndcall_ = callIndirectFunction;
896  this->CallThree_ = callFunctionThree;
897  this->CallFour_ = callFunctionFour;
898 
899  return module;
900 }
901 
902 std::unique_ptr<jlm::llvm::LlvmRvsdgModule>
904 {
905  using namespace jlm::llvm;
906  using namespace jlm::rvsdg;
907 
908  auto iOStateType = IOStateType::Create();
909  auto memoryStateType = MemoryStateType::Create();
910  auto constantFunctionType = rvsdg::FunctionType::Create(
913  auto pointerType = PointerType::Create();
914 
916  auto graph = &module->Rvsdg();
917 
918  auto SetupG1 = [&]()
919  {
920  auto delta = rvsdg::DeltaNode::Create(
921  &graph->GetRootRegion(),
924  "g1",
926  "",
927  false));
928 
929  auto constant = &BitConstantOperation::create(*delta->subregion(), { 32, 1 });
930 
931  return &delta->finalize(constant);
932  };
933 
934  auto SetupG2 = [&]()
935  {
936  auto delta = rvsdg::DeltaNode::Create(
937  &graph->GetRootRegion(),
940  "g2",
942  "",
943  false));
944 
945  auto constant = &BitConstantOperation::create(*delta->subregion(), { 32, 2 });
946 
947  return &delta->finalize(constant);
948  };
949 
950  auto SetupConstantFunction = [&](ssize_t n, const std::string & name)
951  {
953  graph->GetRootRegion(),
954  llvm::LlvmLambdaOperation::Create(constantFunctionType, name, Linkage::externalLinkage));
955  auto iOStateArgument = lambda->GetFunctionArguments()[0];
956  auto memoryStateArgument = lambda->GetFunctionArguments()[1];
957 
958  auto constant = &BitConstantOperation::create(*lambda->subregion(), { 32, n });
959 
960  return lambda->finalize({ constant, iOStateArgument, memoryStateArgument });
961  };
962 
963  auto functionIType = rvsdg::FunctionType::Create(
966 
967  auto SetupI = [&]()
968  {
969  auto iOStateType = IOStateType::Create();
970  auto memoryStateType = MemoryStateType::Create();
971 
973  graph->GetRootRegion(),
975  auto pointerArgument = lambda->GetFunctionArguments()[0];
976  auto iOStateArgument = lambda->GetFunctionArguments()[1];
977  auto memoryStateArgument = lambda->GetFunctionArguments()[2];
978 
979  auto & call = CallOperation::CreateNode(
980  rvsdg::CreateOpNode<PointerToFunctionOperation>({ pointerArgument }, constantFunctionType)
981  .output(0),
982  constantFunctionType,
983  { iOStateArgument, memoryStateArgument });
984 
985  auto lambdaOutput = lambda->finalize(outputs(&call));
986 
987  return std::make_tuple(lambdaOutput, &call);
988  };
989 
990  auto SetupIndirectCallFunction = [&](ssize_t n,
991  const std::string & name,
992  rvsdg::Output & functionI,
993  rvsdg::Output & argumentFunction)
994  {
995  auto pointerType = PointerType::Create();
996 
997  auto functionType = rvsdg::FunctionType::Create(
1000 
1002  graph->GetRootRegion(),
1004  auto pointerArgument = lambda->GetFunctionArguments()[0];
1005  auto iOStateArgument = lambda->GetFunctionArguments()[1];
1006  auto memoryStateArgument = lambda->GetFunctionArguments()[2];
1007 
1008  auto functionICv = lambda->AddContextVar(functionI).inner;
1009  auto argumentFunctionCv = lambda->AddContextVar(argumentFunction).inner;
1010  auto argumentFunctionPtr = rvsdg::CreateOpNode<FunctionToPointerOperation>(
1011  { argumentFunctionCv },
1012  constantFunctionType)
1013  .output(0);
1014 
1015  auto five = &BitConstantOperation::create(*lambda->subregion(), { 32, n });
1016  auto storeNode =
1017  StoreNonVolatileOperation::Create(pointerArgument, five, { memoryStateArgument }, 4);
1018 
1019  auto & call = CallOperation::CreateNode(
1020  functionICv,
1021  functionIType,
1022  { argumentFunctionPtr, iOStateArgument, storeNode[0] });
1023 
1024  auto lambdaOutput = lambda->finalize(outputs(&call));
1025 
1026  return std::make_tuple(lambdaOutput, &call);
1027  };
1028 
1029  auto SetupTestFunction = [&](rvsdg::Output & functionX,
1030  rvsdg::Output & functionY,
1031  rvsdg::Output & globalG1,
1032  rvsdg::Output & globalG2)
1033  {
1034  auto functionType = rvsdg::FunctionType::Create(
1037 
1039  graph->GetRootRegion(),
1041  auto iOStateArgument = lambda->GetFunctionArguments()[0];
1042  auto memoryStateArgument = lambda->GetFunctionArguments()[1];
1043 
1044  auto functionXCv = lambda->AddContextVar(functionX).inner;
1045  auto functionYCv = lambda->AddContextVar(functionY).inner;
1046  auto globalG1Cv = lambda->AddContextVar(globalG1).inner;
1047  auto globalG2Cv = lambda->AddContextVar(globalG2).inner;
1048 
1049  auto constantOne = &BitConstantOperation::create(*lambda->subregion(), { 32, 1 });
1050 
1051  auto pxAlloca = AllocaOperation::create(jlm::rvsdg::BitType::Create(32), constantOne, 4);
1052  auto pyAlloca = AllocaOperation::create(jlm::rvsdg::BitType::Create(32), constantOne, 4);
1053 
1054  auto pxMerge = MemoryStateMergeOperation::Create(
1055  std::vector<jlm::rvsdg::Output *>{ pxAlloca[1], memoryStateArgument });
1056  auto pyMerge = MemoryStateMergeOperation::Create(
1057  std::vector<jlm::rvsdg::Output *>({ pyAlloca[1], pxMerge }));
1058 
1059  auto & callX = CallOperation::CreateNode(
1060  functionXCv,
1061  rvsdg::AssertGetOwnerNode<rvsdg::LambdaNode>(functionX).GetOperation().Type(),
1062  { pxAlloca[0], iOStateArgument, pyMerge });
1063 
1064  auto & callY = CallOperation::CreateNode(
1065  functionYCv,
1066  rvsdg::AssertGetOwnerNode<rvsdg::LambdaNode>(functionY).GetOperation().Type(),
1067  { pyAlloca[0],
1070 
1071  auto loadG1 = LoadNonVolatileOperation::Create(
1072  globalG1Cv,
1075  4);
1076  auto loadG2 = LoadNonVolatileOperation::Create(
1077  globalG2Cv,
1078  { loadG1[1] },
1080  4);
1081 
1082  auto sum = jlm::rvsdg::bitadd_op::create(32, callX.output(0), callY.output(0));
1083  sum = jlm::rvsdg::bitadd_op::create(32, sum, loadG1[0]);
1084  sum = jlm::rvsdg::bitadd_op::create(32, sum, loadG2[0]);
1085 
1086  auto lambdaOutput = lambda->finalize({ sum,
1089  GraphExport::Create(*lambdaOutput, "test");
1090 
1091  return std::make_tuple(
1092  lambdaOutput,
1093  &callX,
1094  &callY,
1095  jlm::util::assertedCast<rvsdg::SimpleNode>(
1096  rvsdg::TryGetOwnerNode<rvsdg::SimpleNode>(*pxAlloca[0])),
1097  jlm::util::assertedCast<rvsdg::SimpleNode>(
1098  rvsdg::TryGetOwnerNode<rvsdg::SimpleNode>(*pyAlloca[0])));
1099  };
1100 
1101  auto SetupTest2Function = [&](rvsdg::Output & functionX)
1102  {
1103  auto functionType = rvsdg::FunctionType::Create(
1106 
1108  graph->GetRootRegion(),
1110  auto iOStateArgument = lambda->GetFunctionArguments()[0];
1111  auto memoryStateArgument = lambda->GetFunctionArguments()[1];
1112 
1113  auto constantOne = &BitConstantOperation::create(*lambda->subregion(), { 32, 1 });
1114 
1115  auto pzAlloca = AllocaOperation::create(jlm::rvsdg::BitType::Create(32), constantOne, 4);
1116  auto pzMerge = MemoryStateMergeOperation::Create(
1117  std::vector<jlm::rvsdg::Output *>{ pzAlloca[1], memoryStateArgument });
1118 
1119  auto functionXCv = lambda->AddContextVar(functionX).inner;
1120 
1121  auto & callX = CallOperation::CreateNode(
1122  functionXCv,
1123  rvsdg::AssertGetOwnerNode<rvsdg::LambdaNode>(functionX).GetOperation().Type(),
1124  { pzAlloca[0], iOStateArgument, pzMerge });
1125 
1126  auto lambdaOutput = lambda->finalize(outputs(&callX));
1127  GraphExport::Create(*lambdaOutput, "test2");
1128 
1129  return std::make_tuple(
1130  lambdaOutput,
1131  &callX,
1132  jlm::util::assertedCast<jlm::rvsdg::SimpleNode>(
1133  rvsdg::TryGetOwnerNode<rvsdg::SimpleNode>(*pzAlloca[0])));
1134  };
1135 
1136  auto deltaG1 = SetupG1();
1137  auto deltaG2 = SetupG2();
1138  auto lambdaThree = SetupConstantFunction(3, "three");
1139  auto lambdaFour = SetupConstantFunction(4, "four");
1140  auto [lambdaI, indirectCall] = SetupI();
1141  auto [lambdaX, callIWithThree] = SetupIndirectCallFunction(5, "x", *lambdaI, *lambdaThree);
1142  auto [lambdaY, callIWithFour] = SetupIndirectCallFunction(6, "y", *lambdaI, *lambdaFour);
1143  auto [lambdaTest, testCallX, callY, allocaPx, allocaPy] =
1144  SetupTestFunction(*lambdaX, *lambdaY, *deltaG1, *deltaG2);
1145  auto [lambdaTest2, test2CallX, allocaPz] = SetupTest2Function(*lambdaX);
1146 
1147  /*
1148  * Assign
1149  */
1150  this->DeltaG1_ = &rvsdg::AssertGetOwnerNode<rvsdg::DeltaNode>(*deltaG1);
1151  this->DeltaG2_ = &rvsdg::AssertGetOwnerNode<rvsdg::DeltaNode>(*deltaG2);
1152  this->LambdaThree_ = &rvsdg::AssertGetOwnerNode<rvsdg::LambdaNode>(*lambdaThree);
1153  this->LambdaFour_ = &rvsdg::AssertGetOwnerNode<rvsdg::LambdaNode>(*lambdaFour);
1154  this->LambdaI_ = &rvsdg::AssertGetOwnerNode<rvsdg::LambdaNode>(*lambdaI);
1155  this->LambdaX_ = &rvsdg::AssertGetOwnerNode<rvsdg::LambdaNode>(*lambdaX);
1156  this->LambdaY_ = &rvsdg::AssertGetOwnerNode<rvsdg::LambdaNode>(*lambdaY);
1157  this->LambdaTest_ = &rvsdg::AssertGetOwnerNode<rvsdg::LambdaNode>(*lambdaTest);
1158  this->LambdaTest2_ = &rvsdg::AssertGetOwnerNode<rvsdg::LambdaNode>(*lambdaTest2);
1159 
1160  this->IndirectCall_ = indirectCall;
1161  this->CallIWithThree_ = callIWithThree;
1162  this->CallIWithFour_ = callIWithFour;
1163  this->TestCallX_ = testCallX;
1164  this->Test2CallX_ = test2CallX;
1165  this->CallY_ = callY;
1166 
1167  this->AllocaPx_ = allocaPx;
1168  this->AllocaPy_ = allocaPy;
1169  this->AllocaPz_ = allocaPz;
1170 
1171  return module;
1172 }
1173 
1174 std::unique_ptr<jlm::llvm::LlvmRvsdgModule>
1176 {
1177  using namespace jlm::llvm;
1178  using namespace jlm::rvsdg;
1179 
1180  auto rvsdgModule = llvm::LlvmRvsdgModule::Create(jlm::util::FilePath(""), "", "");
1181  auto rvsdg = &rvsdgModule->Rvsdg();
1182 
1183  auto pointerType = PointerType::Create();
1184  auto iOStateType = IOStateType::Create();
1185  auto memoryStateType = MemoryStateType::Create();
1186  auto functionGType = rvsdg::FunctionType::Create(
1187  { PointerType::Create(),
1192 
1193  auto SetupFunctionGDeclaration = [&]()
1194  {
1196  *rvsdg,
1197  functionGType,
1198  functionGType,
1199  "g",
1201  true);
1202  };
1203 
1204  auto SetupFunctionF = [&](jlm::rvsdg::RegionArgument * functionG)
1205  {
1206  auto pointerType = PointerType::Create();
1207  auto iOStateType = IOStateType::Create();
1208  auto memoryStateType = MemoryStateType::Create();
1209  auto functionType = rvsdg::FunctionType::Create(
1210  { PointerType::Create(),
1215 
1217  rvsdg->GetRootRegion(),
1219  auto pathArgument = lambda->GetFunctionArguments()[0];
1220  auto modeArgument = lambda->GetFunctionArguments()[1];
1221  auto iOStateArgument = lambda->GetFunctionArguments()[2];
1222  auto memoryStateArgument = lambda->GetFunctionArguments()[3];
1223 
1224  auto functionGCv = lambda->AddContextVar(*functionG).inner;
1225 
1226  auto constantOne = &BitConstantOperation::create(*lambda->subregion(), { 32, 1 });
1227 
1228  auto allocaPath = AllocaOperation::create(pointerType, constantOne, 4);
1229  auto allocaMode = AllocaOperation::create(pointerType, constantOne, 4);
1230 
1231  auto mergePath = MemoryStateMergeOperation::Create(
1232  std::vector<jlm::rvsdg::Output *>{ allocaPath[1], memoryStateArgument });
1233  auto mergeMode = MemoryStateMergeOperation::Create(
1234  std::vector<jlm::rvsdg::Output *>({ allocaMode[1], mergePath }));
1235 
1236  auto storePath =
1237  StoreNonVolatileOperation::Create(allocaPath[0], pathArgument, { mergeMode }, 4);
1238  auto storeMode =
1239  StoreNonVolatileOperation::Create(allocaMode[0], modeArgument, { storePath[0] }, 4);
1240 
1241  auto loadPath = LoadNonVolatileOperation::Create(allocaPath[0], storeMode, pointerType, 4);
1242  auto loadMode =
1243  LoadNonVolatileOperation::Create(allocaMode[0], { loadPath[1] }, pointerType, 4);
1244 
1245  auto & callG = CallOperation::CreateNode(
1246  functionGCv,
1247  functionGType,
1248  { loadPath[0], loadMode[0], iOStateArgument, loadMode[1] });
1249 
1250  lambda->finalize(outputs(&callG));
1251  GraphExport::Create(*lambda->output(), "f");
1252 
1253  return std::make_tuple(lambda, &callG);
1254  };
1255 
1256  this->ExternalGArgument_ = SetupFunctionGDeclaration();
1257  auto [lambdaF, callG] = SetupFunctionF(ExternalGArgument_);
1258 
1259  this->LambdaF_ = lambdaF;
1260  this->CallG_ = callG;
1261 
1262  return rvsdgModule;
1263 }
1264 
1265 std::unique_ptr<jlm::llvm::LlvmRvsdgModule>
1267 {
1268  using namespace jlm::llvm;
1269 
1270  auto rvsdgModule = LlvmRvsdgModule::Create(jlm::util::FilePath(""), "", "");
1271  auto & rvsdg = rvsdgModule->Rvsdg();
1272 
1273  auto pointerType = PointerType::Create();
1274  auto structType = StructType::CreateIdentified(
1275  "myStruct",
1277  false);
1278  auto iOStateType = IOStateType::Create();
1279  auto memoryStateType = MemoryStateType::Create();
1280  VariableArgumentType varArgType;
1281  auto lambdaLlvmLifetimeStartType = rvsdg::FunctionType::Create(
1282  { rvsdg::BitType::Create(64),
1287  auto lambdaLlvmLifetimeEndType = rvsdg::FunctionType::Create(
1288  { rvsdg::BitType::Create(64),
1293  auto lambdaFType = rvsdg::FunctionType::Create(
1296  auto lambdaGType = rvsdg::FunctionType::Create(
1298  {
1301  });
1302 
1303  auto llvmLifetimeStart = &LlvmGraphImport::Create(
1304  rvsdg,
1305  lambdaLlvmLifetimeStartType,
1306  lambdaLlvmLifetimeStartType,
1307  "llvm.lifetime.start.p0",
1309  true);
1310  auto llvmLifetimeEnd = &LlvmGraphImport::Create(
1311  rvsdg,
1312  lambdaLlvmLifetimeEndType,
1313  lambdaLlvmLifetimeEndType,
1314  "llvm.lifetime.end.p0",
1316  true);
1317  ExternalFArgument_ = &LlvmGraphImport::Create(
1318  rvsdg,
1319  lambdaFType,
1320  lambdaFType,
1321  "f",
1323  true);
1324 
1325  // Setup function g()
1326  LambdaG_ = rvsdg::LambdaNode::Create(
1327  rvsdg.GetRootRegion(),
1329  auto iOStateArgument = LambdaG_->GetFunctionArguments()[0];
1330  auto memoryStateArgument = LambdaG_->GetFunctionArguments()[1];
1331  auto llvmLifetimeStartArgument = LambdaG_->AddContextVar(*llvmLifetimeStart).inner;
1332  auto llvmLifetimeEndArgument = LambdaG_->AddContextVar(*llvmLifetimeEnd).inner;
1333  auto lambdaFArgument = LambdaG_->AddContextVar(*ExternalFArgument_).inner;
1334 
1335  auto constantOne = &rvsdg::BitConstantOperation::create(*LambdaG_->subregion(), { 64, 1 });
1336  auto twentyFour = &rvsdg::BitConstantOperation::create(*LambdaG_->subregion(), { 64, 24 });
1337 
1338  auto allocaResults = AllocaOperation::create(structType, constantOne, 16);
1339  auto memoryState = MemoryStateMergeOperation::Create(
1340  std::vector<jlm::rvsdg::Output *>{ allocaResults[1], memoryStateArgument });
1341 
1342  auto & callLLvmLifetimeStart = CallOperation::CreateNode(
1343  llvmLifetimeStartArgument,
1344  lambdaLlvmLifetimeStartType,
1345  { twentyFour, allocaResults[0], iOStateArgument, memoryState });
1346 
1347  CallF_ = &CallOperation::CreateNode(
1348  lambdaFArgument,
1349  lambdaFType,
1350  { allocaResults[0],
1351  &CallOperation::GetIOStateOutput(callLLvmLifetimeStart),
1352  &CallOperation::GetMemoryStateOutput(callLLvmLifetimeStart) });
1353 
1354  auto zero = &rvsdg::BitConstantOperation::create(*LambdaG_->subregion(), { 64, 0 });
1355  auto one = &rvsdg::BitConstantOperation::create(*LambdaG_->subregion(), { 32, 1 });
1356  auto two = &rvsdg::BitConstantOperation::create(*LambdaG_->subregion(), { 32, 2 });
1357 
1358  auto gepResult1 =
1359  GetElementPtrOperation::Create(allocaResults[0], { zero, one }, structType, pointerType);
1360  auto loadResults1 = LoadNonVolatileOperation::Create(
1361  gepResult1,
1363  pointerType,
1364  8);
1365  auto loadResults2 =
1366  LoadNonVolatileOperation::Create(loadResults1[0], { loadResults1[1] }, pointerType, 8);
1367 
1368  auto gepResult2 =
1369  GetElementPtrOperation::Create(allocaResults[0], { zero, two }, structType, pointerType);
1370  auto loadResults3 =
1371  LoadNonVolatileOperation::Create(gepResult2, { loadResults2[1] }, pointerType, 8);
1372  auto loadResults4 =
1373  LoadNonVolatileOperation::Create(loadResults1[0], { loadResults3[1] }, pointerType, 8);
1374 
1375  auto storeResults1 =
1376  StoreNonVolatileOperation::Create(loadResults1[0], loadResults4[0], { loadResults4[1] }, 8);
1377 
1378  auto loadResults5 =
1379  LoadNonVolatileOperation::Create(gepResult2, { storeResults1[0] }, pointerType, 8);
1380  auto storeResults2 =
1381  StoreNonVolatileOperation::Create(loadResults5[0], loadResults2[0], { loadResults5[1] }, 8);
1382 
1383  auto & callLLvmLifetimeEnd = CallOperation::CreateNode(
1384  llvmLifetimeEndArgument,
1385  lambdaLlvmLifetimeEndType,
1386  { twentyFour,
1387  allocaResults[0],
1389  storeResults2[0] });
1390 
1391  LambdaG_->finalize(outputs(&callLLvmLifetimeEnd));
1392 
1393  return rvsdgModule;
1394 }
1395 
1396 std::unique_ptr<jlm::llvm::LlvmRvsdgModule>
1398 {
1399  using namespace jlm::llvm;
1400  using namespace jlm::rvsdg;
1401 
1402  auto mt = MemoryStateType::Create();
1403  auto pt = PointerType::Create();
1404  auto fcttype = rvsdg::FunctionType::Create(
1412 
1414  auto graph = &module->Rvsdg();
1415 
1416  auto fct = rvsdg::LambdaNode::Create(
1417  graph->GetRootRegion(),
1419 
1420  auto zero = &BitConstantOperation::create(*fct->subregion(), { 32, 0 });
1421  auto biteq = jlm::rvsdg::biteq_op::create(32, fct->GetFunctionArguments()[0], zero);
1422  auto predicate = jlm::rvsdg::match(1, { { 0, 1 } }, 0, 2, biteq);
1423 
1424  auto gammanode = jlm::rvsdg::GammaNode::create(predicate, 2);
1425  auto p1ev = gammanode->AddEntryVar(fct->GetFunctionArguments()[1]);
1426  auto p2ev = gammanode->AddEntryVar(fct->GetFunctionArguments()[2]);
1427  auto p3ev = gammanode->AddEntryVar(fct->GetFunctionArguments()[3]);
1428  auto p4ev = gammanode->AddEntryVar(fct->GetFunctionArguments()[4]);
1429 
1430  auto tmp1 = gammanode->AddExitVar({ p1ev.branchArgument[0], p3ev.branchArgument[1] });
1431  auto tmp2 = gammanode->AddExitVar({ p2ev.branchArgument[0], p4ev.branchArgument[1] });
1432 
1434  tmp1.output,
1435  { fct->GetFunctionArguments()[5] },
1437  4);
1438  auto ld2 =
1439  LoadNonVolatileOperation::Create(tmp2.output, { ld1[1] }, jlm::rvsdg::BitType::Create(32), 4);
1440  auto sum = jlm::rvsdg::bitadd_op::create(32, ld1[0], ld2[0]);
1441 
1442  fct->finalize({ sum, ld2[1] });
1443 
1444  GraphExport::Create(*fct->output(), "f");
1445 
1446  /*
1447  * Assign nodes
1448  */
1449  this->lambda = fct;
1450  this->gamma = gammanode;
1451 
1452  return module;
1453 }
1454 
1455 std::unique_ptr<llvm::LlvmRvsdgModule>
1457 {
1458  using namespace jlm::llvm;
1459  using namespace jlm::rvsdg;
1460 
1461  auto rvsdgModule = llvm::LlvmRvsdgModule::Create(util::FilePath(""), "", "");
1462  auto rvsdg = &rvsdgModule->Rvsdg();
1463 
1464  auto SetupLambdaF = [&]()
1465  {
1466  auto SetupGamma = [](rvsdg::Output * predicate,
1467  rvsdg::Output * xAddress,
1468  rvsdg::Output * yAddress,
1469  rvsdg::Output * zAddress,
1470  rvsdg::Output * memoryState)
1471  {
1472  auto gammaNode = rvsdg::GammaNode::create(predicate, 2);
1473 
1474  auto gammaInputX = gammaNode->AddEntryVar(xAddress);
1475  auto gammaInputY = gammaNode->AddEntryVar(yAddress);
1476  auto gammaInputZ = gammaNode->AddEntryVar(zAddress);
1477  auto gammaInputMemoryState = gammaNode->AddEntryVar(memoryState);
1478 
1479  // gamma subregion 0
1480  auto loadXResults = LoadNonVolatileOperation::Create(
1481  gammaInputX.branchArgument[0],
1482  { gammaInputMemoryState.branchArgument[0] },
1484  4);
1485 
1486  auto one = &BitConstantOperation::create(*gammaNode->subregion(0), { 32, 1 });
1487  auto storeZRegion0Results = StoreNonVolatileOperation::Create(
1488  gammaInputZ.branchArgument[0],
1489  one,
1490  { loadXResults[1] },
1491  4);
1492 
1493  // gamma subregion 1
1494  auto loadYResults = LoadNonVolatileOperation::Create(
1495  gammaInputY.branchArgument[1],
1496  { gammaInputMemoryState.branchArgument[1] },
1498  4);
1499 
1500  auto two = &BitConstantOperation::create(*gammaNode->subregion(1), { 32, 2 });
1501  auto storeZRegion1Results = StoreNonVolatileOperation::Create(
1502  gammaInputZ.branchArgument[1],
1503  two,
1504  { loadYResults[1] },
1505  4);
1506 
1507  // finalize gamma
1508  auto gammaOutputA = gammaNode->AddExitVar({ loadXResults[0], loadYResults[0] });
1509  auto gammaOutputMemoryState =
1510  gammaNode->AddExitVar({ storeZRegion0Results[0], storeZRegion1Results[0] });
1511 
1512  return std::make_tuple(gammaOutputA.output, gammaOutputMemoryState.output);
1513  };
1514 
1515  auto iOStateType = IOStateType::Create();
1516  auto memoryStateType = MemoryStateType::Create();
1517  auto pointerType = PointerType::Create();
1518  auto functionType = rvsdg::FunctionType::Create(
1519  { rvsdg::BitType::Create(32),
1525 
1527  rvsdg->GetRootRegion(),
1529  auto cArgument = lambda->GetFunctionArguments()[0];
1530  auto xArgument = lambda->GetFunctionArguments()[1];
1531  auto yArgument = lambda->GetFunctionArguments()[2];
1532  auto iOStateArgument = lambda->GetFunctionArguments()[3];
1533  auto memoryStateArgument = lambda->GetFunctionArguments()[4];
1534 
1535  auto constantOne = &BitConstantOperation::create(*lambda->subregion(), { 32, 1 });
1536 
1537  auto allocaZResults = AllocaOperation::create(pointerType, constantOne, 4);
1538 
1539  auto memoryState = MemoryStateMergeOperation::Create(
1540  std::vector<jlm::rvsdg::Output *>{ allocaZResults[1], memoryStateArgument });
1541 
1542  auto nullPointer = ConstantPointerNullOperation::Create(lambda->subregion(), pointerType);
1543  auto storeZResults =
1544  StoreNonVolatileOperation::Create(allocaZResults[0], nullPointer, { memoryState }, 4);
1545 
1546  auto zero = &BitConstantOperation::create(*lambda->subregion(), { 32, 0 });
1547  auto bitEq = rvsdg::biteq_op::create(32, cArgument, zero);
1548  auto predicate = rvsdg::match(1, { { 0, 1 } }, 0, 2, bitEq);
1549 
1550  auto [gammaOutputA, gammaOutputMemoryState] =
1551  SetupGamma(predicate, xArgument, yArgument, allocaZResults[0], memoryState);
1552 
1553  auto loadZResults = LoadNonVolatileOperation::Create(
1554  allocaZResults[0],
1555  { gammaOutputMemoryState },
1557  4);
1558 
1559  auto sum = jlm::rvsdg::bitadd_op::create(32, gammaOutputA, loadZResults[0]);
1560 
1561  lambda->finalize({ sum, iOStateArgument, loadZResults[1] });
1562 
1563  return std::make_tuple(
1564  lambda->output(),
1565  &rvsdg::AssertGetOwnerNode<jlm::rvsdg::GammaNode>(*gammaOutputA),
1566  rvsdg::TryGetOwnerNode<rvsdg::Node>(*allocaZResults[0]));
1567  };
1568 
1569  auto SetupLambdaGH = [&](rvsdg::Output & lambdaF,
1570  int64_t cValue,
1571  int64_t xValue,
1572  int64_t yValue,
1573  const char * functionName)
1574  {
1575  auto iOStateType = IOStateType::Create();
1576  auto memoryStateType = MemoryStateType::Create();
1577  auto pointerType = PointerType::Create();
1578  auto functionType = rvsdg::FunctionType::Create(
1581 
1583  rvsdg->GetRootRegion(),
1584  llvm::LlvmLambdaOperation::Create(functionType, functionName, Linkage::externalLinkage));
1585  auto iOStateArgument = lambda->GetFunctionArguments()[0];
1586  auto memoryStateArgument = lambda->GetFunctionArguments()[1];
1587  auto lambdaFArgument = lambda->AddContextVar(lambdaF).inner;
1588 
1589  auto constantOne = &BitConstantOperation::create(*lambda->subregion(), { 32, 4 });
1590 
1591  auto allocaXResults = AllocaOperation::create(rvsdg::BitType::Create(32), constantOne, 4);
1592  auto allocaYResults = AllocaOperation::create(pointerType, constantOne, 4);
1593 
1594  auto memoryState = MemoryStateMergeOperation::Create(
1595  std::vector<jlm::rvsdg::Output *>{ allocaXResults[1], memoryStateArgument });
1596  memoryState = MemoryStateMergeOperation::Create(
1597  std::vector<jlm::rvsdg::Output *>({ allocaYResults[1], memoryState }));
1598 
1599  auto predicate = &BitConstantOperation::create(*lambda->subregion(), { 32, cValue });
1600  auto x = &BitConstantOperation::create(*lambda->subregion(), { 32, xValue });
1601  auto y = &BitConstantOperation::create(*lambda->subregion(), { 32, yValue });
1602 
1603  auto storeXResults =
1604  StoreNonVolatileOperation::Create(allocaXResults[0], x, { allocaXResults[1] }, 4);
1605 
1606  auto storeYResults =
1607  StoreNonVolatileOperation::Create(allocaYResults[0], y, { storeXResults[0] }, 4);
1608 
1609  auto & call = CallOperation::CreateNode(
1610  lambdaFArgument,
1611  rvsdg::AssertGetOwnerNode<rvsdg::LambdaNode>(lambdaF).GetOperation().Type(),
1612  { predicate, allocaXResults[0], allocaYResults[0], iOStateArgument, storeYResults[0] });
1613 
1614  lambda->finalize(outputs(&call));
1615  GraphExport::Create(*lambda->output(), functionName);
1616 
1617  return std::make_tuple(
1618  lambda->output(),
1619  &call,
1620  rvsdg::TryGetOwnerNode<rvsdg::Node>(*allocaXResults[0]),
1621  rvsdg::TryGetOwnerNode<rvsdg::Node>(*allocaYResults[1]));
1622  };
1623 
1624  auto [lambdaF, gammaNode, allocaZ] = SetupLambdaF();
1625  auto [lambdaG, callFromG, allocaXFromG, allocaYFromG] = SetupLambdaGH(*lambdaF, 0, 1, 2, "g");
1626  auto [lambdaH, callFromH, allocaXFromH, allocaYFromH] = SetupLambdaGH(*lambdaF, 1, 3, 4, "h");
1627 
1628  // Assign nodes
1629  this->LambdaF_ = &rvsdg::AssertGetOwnerNode<rvsdg::LambdaNode>(*lambdaF);
1630  this->LambdaG_ = &rvsdg::AssertGetOwnerNode<rvsdg::LambdaNode>(*lambdaG);
1631  this->LambdaH_ = &rvsdg::AssertGetOwnerNode<rvsdg::LambdaNode>(*lambdaH);
1632 
1633  this->Gamma_ = gammaNode;
1634 
1635  this->CallFromG_ = callFromG;
1636  this->CallFromH_ = callFromH;
1637 
1638  this->AllocaXFromG_ = allocaXFromG;
1639  this->AllocaYFromG_ = allocaYFromG;
1640  this->AllocaXFromH_ = allocaXFromH;
1641  this->AllocaYFromH_ = allocaYFromH;
1642  this->AllocaZ_ = allocaZ;
1643 
1644  return rvsdgModule;
1645 }
1646 
1647 std::unique_ptr<jlm::llvm::LlvmRvsdgModule>
1649 {
1650  using namespace jlm::llvm;
1651  using namespace jlm::rvsdg;
1652 
1653  auto mt = MemoryStateType::Create();
1654  auto pointerType = PointerType::Create();
1655  auto fcttype = rvsdg::FunctionType::Create(
1660  { MemoryStateType::Create() });
1661 
1663  auto graph = &module->Rvsdg();
1664 
1665  auto fct = rvsdg::LambdaNode::Create(
1666  graph->GetRootRegion(),
1668 
1669  auto zero = &BitConstantOperation::create(*fct->subregion(), { 32, 0 });
1670 
1671  auto thetanode = jlm::rvsdg::ThetaNode::create(fct->subregion());
1672 
1673  auto n = thetanode->AddLoopVar(zero);
1674  auto l = thetanode->AddLoopVar(fct->GetFunctionArguments()[0]);
1675  auto a = thetanode->AddLoopVar(fct->GetFunctionArguments()[1]);
1676  auto c = thetanode->AddLoopVar(fct->GetFunctionArguments()[2]);
1677  auto s = thetanode->AddLoopVar(fct->GetFunctionArguments()[3]);
1678 
1679  auto gepnode = GetElementPtrOperation::Create(
1680  a.pre,
1681  { n.pre },
1683  pointerType);
1684  auto store = StoreNonVolatileOperation::Create(gepnode, c.pre, { s.pre }, 4);
1685 
1686  auto one = &BitConstantOperation::create(*thetanode->subregion(), { 32, 1 });
1687  auto sum = jlm::rvsdg::bitadd_op::create(32, n.pre, one);
1688  auto cmp = jlm::rvsdg::bitult_op::create(32, sum, l.pre);
1689  auto predicate = jlm::rvsdg::match(1, { { 1, 1 } }, 0, 2, cmp);
1690 
1691  n.post->divert_to(sum);
1692  s.post->divert_to(store[0]);
1693  thetanode->set_predicate(predicate);
1694 
1695  fct->finalize({ s.output });
1696  GraphExport::Create(*fct->output(), "f");
1697 
1698  /*
1699  * Assign nodes
1700  */
1701  this->lambda = fct;
1702  this->theta = thetanode;
1703  this->gep = rvsdg::TryGetOwnerNode<rvsdg::Node>(*gepnode);
1704 
1705  return module;
1706 }
1707 
1708 std::unique_ptr<jlm::llvm::LlvmRvsdgModule>
1710 {
1711  using namespace jlm::llvm;
1712  using namespace jlm::rvsdg;
1713 
1715  auto graph = &module->Rvsdg();
1716 
1717  auto SetupGlobalF = [&]()
1718  {
1719  auto dfNode = jlm::rvsdg::DeltaNode::Create(
1720  &graph->GetRootRegion(),
1723  "f",
1725  "",
1726  false));
1727 
1728  auto constant = &BitConstantOperation::create(*dfNode->subregion(), { 32, 0 });
1729 
1730  return &dfNode->finalize(constant);
1731  };
1732 
1733  auto SetupFunctionG = [&]()
1734  {
1735  auto pt = PointerType::Create();
1736  auto iOStateType = IOStateType::Create();
1737  auto memoryStateType = MemoryStateType::Create();
1738  auto functionType = rvsdg::FunctionType::Create(
1741 
1743  graph->GetRootRegion(),
1745  auto pointerArgument = lambda->GetFunctionArguments()[0];
1746  auto iOStateArgument = lambda->GetFunctionArguments()[1];
1747  auto memoryStateArgument = lambda->GetFunctionArguments()[2];
1748 
1750  pointerArgument,
1751  { memoryStateArgument },
1753  4);
1754 
1755  return lambda->finalize({ ld[0], iOStateArgument, ld[1] });
1756  };
1757 
1758  auto SetupFunctionH = [&](rvsdg::Output * f, rvsdg::Output * g)
1759  {
1760  auto iOStateType = IOStateType::Create();
1761  auto memoryStateType = MemoryStateType::Create();
1762  auto functionType = rvsdg::FunctionType::Create(
1765 
1767  graph->GetRootRegion(),
1769  auto iOStateArgument = lambda->GetFunctionArguments()[0];
1770  auto memoryStateArgument = lambda->GetFunctionArguments()[1];
1771 
1772  auto cvf = lambda->AddContextVar(*f).inner;
1773  auto cvg = lambda->AddContextVar(*g).inner;
1774 
1775  auto five = &BitConstantOperation::create(*lambda->subregion(), { 32, 5 });
1776  auto st = StoreNonVolatileOperation::Create(cvf, five, { memoryStateArgument }, 4);
1777  auto & callG = CallOperation::CreateNode(
1778  cvg,
1779  rvsdg::AssertGetOwnerNode<rvsdg::LambdaNode>(*g).GetOperation().Type(),
1780  { cvf, iOStateArgument, st[0] });
1781 
1782  auto lambdaOutput = lambda->finalize(outputs(&callG));
1783  GraphExport::Create(*lambda->output(), "h");
1784 
1785  return std::make_tuple(lambdaOutput, &callG, rvsdg::TryGetOwnerNode<rvsdg::Node>(*five));
1786  };
1787 
1788  auto f = SetupGlobalF();
1789  auto g = SetupFunctionG();
1790  auto [h, callFunctionG, constantFive] = SetupFunctionH(f, g);
1791 
1792  /*
1793  * Assign nodes
1794  */
1795  this->lambda_g = &rvsdg::AssertGetOwnerNode<rvsdg::LambdaNode>(*g);
1796  this->lambda_h = &rvsdg::AssertGetOwnerNode<rvsdg::LambdaNode>(*h);
1797 
1798  this->delta_f = &rvsdg::AssertGetOwnerNode<rvsdg::DeltaNode>(*f);
1799 
1800  this->CallG_ = callFunctionG;
1801  this->constantFive = constantFive;
1802 
1803  return module;
1804 }
1805 
1806 std::unique_ptr<jlm::llvm::LlvmRvsdgModule>
1808 {
1809  using namespace jlm::llvm;
1810  using namespace jlm::rvsdg;
1811 
1813  auto graph = &module->Rvsdg();
1814 
1815  auto SetupD1 = [&]()
1816  {
1817  auto delta = jlm::rvsdg::DeltaNode::Create(
1818  &graph->GetRootRegion(),
1821  "d1",
1823  "",
1824  false));
1825 
1826  auto constant = &BitConstantOperation::create(*delta->subregion(), { 32, 0 });
1827 
1828  return &delta->finalize(constant);
1829  };
1830 
1831  auto SetupD2 = [&]()
1832  {
1833  auto delta = jlm::rvsdg::DeltaNode::Create(
1834  &graph->GetRootRegion(),
1837  "d2",
1839  "",
1840  false));
1841 
1842  auto constant = &BitConstantOperation::create(*delta->subregion(), { 32, 0 });
1843 
1844  return &delta->finalize(constant);
1845  };
1846 
1847  auto SetupF1 = [&](rvsdg::Output * d1)
1848  {
1849  auto iOStateType = IOStateType::Create();
1850  auto memoryStateType = MemoryStateType::Create();
1851  auto functionType = rvsdg::FunctionType::Create(
1854 
1856  graph->GetRootRegion(),
1858  auto iOStateArgument = lambda->GetFunctionArguments()[0];
1859  auto memoryStateArgument = lambda->GetFunctionArguments()[1];
1860 
1861  auto cvd1 = lambda->AddContextVar(*d1).inner;
1862  auto b2 = &BitConstantOperation::create(*lambda->subregion(), { 32, 2 });
1863  auto st = StoreNonVolatileOperation::Create(cvd1, b2, { memoryStateArgument }, 4);
1864 
1865  return lambda->finalize({ iOStateArgument, st[0] });
1866  };
1867 
1868  auto SetupF2 = [&](rvsdg::Output * f1, rvsdg::Output * d1, rvsdg::Output * d2)
1869  {
1870  auto iOStateType = IOStateType::Create();
1871  auto memoryStateType = MemoryStateType::Create();
1872  auto functionType = rvsdg::FunctionType::Create(
1875 
1877  graph->GetRootRegion(),
1879  auto iOStateArgument = lambda->GetFunctionArguments()[0];
1880  auto memoryStateArgument = lambda->GetFunctionArguments()[1];
1881 
1882  auto cvd1 = lambda->AddContextVar(*d1).inner;
1883  auto cvd2 = lambda->AddContextVar(*d2).inner;
1884  auto cvf1 = lambda->AddContextVar(*f1).inner;
1885 
1886  auto b5 = &BitConstantOperation::create(*lambda->subregion(), { 32, 5 });
1887  auto b42 = &BitConstantOperation::create(*lambda->subregion(), { 32, 42 });
1888  auto st = StoreNonVolatileOperation::Create(cvd1, b5, { memoryStateArgument }, 4);
1889  auto & call = CallOperation::CreateNode(
1890  cvf1,
1891  rvsdg::AssertGetOwnerNode<rvsdg::LambdaNode>(*f1).GetOperation().Type(),
1892  { iOStateArgument, st[0] });
1894  cvd2,
1895  b42,
1897  4);
1898 
1899  auto lambdaOutput = lambda->finalize(outputs(&call));
1900  GraphExport::Create(*lambdaOutput, "f2");
1901 
1902  return std::make_tuple(lambdaOutput, &call);
1903  };
1904 
1905  auto d1 = SetupD1();
1906  auto d2 = SetupD2();
1907  auto f1 = SetupF1(d1);
1908  auto [f2, callF1] = SetupF2(f1, d1, d2);
1909 
1910  // Assign nodes
1911  this->lambda_f1 = &rvsdg::AssertGetOwnerNode<rvsdg::LambdaNode>(*f1);
1912  this->lambda_f2 = &rvsdg::AssertGetOwnerNode<rvsdg::LambdaNode>(*f2);
1913 
1914  this->delta_d1 = &rvsdg::AssertGetOwnerNode<rvsdg::DeltaNode>(*d1);
1915  this->delta_d2 = &rvsdg::AssertGetOwnerNode<rvsdg::DeltaNode>(*d2);
1916 
1917  this->CallF1_ = callF1;
1918 
1919  return module;
1920 }
1921 
1922 std::unique_ptr<jlm::llvm::LlvmRvsdgModule>
1924 {
1925  using namespace jlm::llvm;
1926  using namespace jlm::rvsdg;
1927 
1929  auto graph = &module->Rvsdg();
1930 
1931  auto SetupG1 = [&]()
1932  {
1933  auto delta = jlm::rvsdg::DeltaNode::Create(
1934  &graph->GetRootRegion(),
1937  "g1",
1939  "",
1940  false));
1941 
1942  auto constant = &BitConstantOperation::create(*delta->subregion(), { 32, 1 });
1943 
1944  return &delta->finalize(constant);
1945  };
1946 
1947  auto SetupG2 = [&](rvsdg::Output & g1)
1948  {
1949  auto pointerType = PointerType::Create();
1950 
1951  auto delta = jlm::rvsdg::DeltaNode::Create(
1952  &graph->GetRootRegion(),
1953  jlm::llvm::DeltaOperation::Create(pointerType, "g2", Linkage::externalLinkage, "", false));
1954 
1955  auto ctxVar = delta->AddContextVar(g1);
1956 
1957  return &delta->finalize(ctxVar.inner);
1958  };
1959 
1960  auto SetupF = [&](rvsdg::Output & g1, rvsdg::Output & g2)
1961  {
1962  auto iOStateType = IOStateType::Create();
1963  auto memoryStateType = MemoryStateType::Create();
1964  auto functionType = rvsdg::FunctionType::Create(
1967 
1969  graph->GetRootRegion(),
1971  auto iOStateArgument = lambda->GetFunctionArguments()[0];
1972  auto memoryStateArgument = lambda->GetFunctionArguments()[1];
1973  auto g1CtxVar = lambda->AddContextVar(g1).inner;
1974  auto g2CtxVar = lambda->AddContextVar(g2).inner;
1975 
1976  auto loadResults = LoadNonVolatileOperation::Create(
1977  g2CtxVar,
1978  { memoryStateArgument },
1980  8);
1981  auto storeResults =
1982  StoreNonVolatileOperation::Create(g2CtxVar, loadResults[0], { loadResults[1] }, 8);
1983 
1984  loadResults = LoadNonVolatileOperation::Create(
1985  g1CtxVar,
1986  storeResults,
1988  8);
1989  auto truncResult = TruncOperation::create(16, loadResults[0]);
1990 
1991  return lambda->finalize({ truncResult, iOStateArgument, loadResults[1] });
1992  };
1993 
1994  auto SetupTest = [&](rvsdg::Output & lambdaF)
1995  {
1996  auto iOStateType = IOStateType::Create();
1997  auto memoryStateType = MemoryStateType::Create();
1998  auto functionType = rvsdg::FunctionType::Create(
2001 
2003  graph->GetRootRegion(),
2005  auto iOStateArgument = lambda->GetFunctionArguments()[0];
2006  auto memoryStateArgument = lambda->GetFunctionArguments()[1];
2007 
2008  auto lambdaFArgument = lambda->AddContextVar(lambdaF).inner;
2009 
2010  auto & call = CallOperation::CreateNode(
2011  lambdaFArgument,
2012  rvsdg::AssertGetOwnerNode<rvsdg::LambdaNode>(lambdaF).GetOperation().Type(),
2013  { iOStateArgument, memoryStateArgument });
2014 
2015  auto lambdaOutput = lambda->finalize(
2017  GraphExport::Create(*lambdaOutput, "test");
2018 
2019  return std::make_tuple(lambdaOutput, &call);
2020  };
2021 
2022  auto g1 = SetupG1();
2023  auto g2 = SetupG2(*g1);
2024  auto f = SetupF(*g1, *g2);
2025  auto [test, callF] = SetupTest(*f);
2026 
2027  /*
2028  * Assign nodes
2029  */
2030  this->LambdaF_ = &rvsdg::AssertGetOwnerNode<rvsdg::LambdaNode>(*f);
2031  this->LambdaTest_ = &rvsdg::AssertGetOwnerNode<rvsdg::LambdaNode>(*test);
2032 
2033  this->DeltaG1_ = &rvsdg::AssertGetOwnerNode<rvsdg::DeltaNode>(*g1);
2034  this->DeltaG2_ = &rvsdg::AssertGetOwnerNode<rvsdg::DeltaNode>(*g2);
2035 
2036  this->CallF_ = callF;
2037 
2038  return module;
2039 }
2040 
2041 std::unique_ptr<jlm::llvm::LlvmRvsdgModule>
2043 {
2044  using namespace jlm::llvm;
2045  using namespace jlm::rvsdg;
2046 
2048  auto graph = &module->Rvsdg();
2049 
2050  auto SetupF1 = [&](jlm::rvsdg::Output * d1)
2051  {
2052  auto iOStateType = IOStateType::Create();
2053  auto memoryStateType = MemoryStateType::Create();
2054  auto functionType = rvsdg::FunctionType::Create(
2057 
2059  graph->GetRootRegion(),
2061  auto iOStateArgument = lambda->GetFunctionArguments()[0];
2062  auto memoryStateArgument = lambda->GetFunctionArguments()[1];
2063 
2064  auto cvd1 = lambda->AddContextVar(*d1).inner;
2065 
2066  auto b5 = &BitConstantOperation::create(*lambda->subregion(), { 32, 5 });
2067  auto st = StoreNonVolatileOperation::Create(cvd1, b5, { memoryStateArgument }, 4);
2068 
2069  return lambda->finalize({ iOStateArgument, st[0] });
2070  };
2071 
2072  auto SetupF2 = [&](rvsdg::Output * f1, jlm::rvsdg::Output * d1, jlm::rvsdg::Output * d2)
2073  {
2074  auto iOStateType = IOStateType::Create();
2075  auto memoryStateType = MemoryStateType::Create();
2076  auto functionType = rvsdg::FunctionType::Create(
2079 
2081  graph->GetRootRegion(),
2083  auto iOStateArgument = lambda->GetFunctionArguments()[0];
2084  auto memoryStateArgument = lambda->GetFunctionArguments()[1];
2085 
2086  auto cvd1 = lambda->AddContextVar(*d1).inner;
2087  auto cvd2 = lambda->AddContextVar(*d2).inner;
2088  auto cvf1 = lambda->AddContextVar(*f1).inner;
2089  auto b2 = &BitConstantOperation::create(*lambda->subregion(), { 32, 2 });
2090  auto b21 = &BitConstantOperation::create(*lambda->subregion(), { 32, 21 });
2091  auto st = StoreNonVolatileOperation::Create(cvd1, b2, { memoryStateArgument }, 4);
2092  auto & call = CallOperation::CreateNode(
2093  cvf1,
2094  rvsdg::AssertGetOwnerNode<rvsdg::LambdaNode>(*f1).GetOperation().Type(),
2095  { iOStateArgument, st[0] });
2097  cvd2,
2098  b21,
2100  4);
2101 
2102  auto lambdaOutput = lambda->finalize(outputs(&call));
2103  GraphExport::Create(*lambda->output(), "f2");
2104 
2105  return std::make_tuple(lambdaOutput, &call);
2106  };
2107 
2108  auto d1 = &llvm::LlvmGraphImport::Create(
2109  *graph,
2112  "d1",
2114  auto d2 = &llvm::LlvmGraphImport::Create(
2115  *graph,
2118  "d2",
2120 
2121  auto f1 = SetupF1(d1);
2122  auto [f2, callF1] = SetupF2(f1, d1, d2);
2123 
2124  // Assign nodes
2125  this->lambda_f1 = &rvsdg::AssertGetOwnerNode<rvsdg::LambdaNode>(*f1);
2126  this->lambda_f2 = &rvsdg::AssertGetOwnerNode<rvsdg::LambdaNode>(*f2);
2127 
2128  this->CallF1_ = callF1;
2129 
2130  this->import_d1 = d1;
2131  this->import_d2 = d2;
2132 
2133  return module;
2134 }
2135 
2136 std::unique_ptr<jlm::llvm::LlvmRvsdgModule>
2138 {
2139  using namespace jlm::llvm;
2140  using namespace jlm::rvsdg;
2141 
2143  auto graph = &module->Rvsdg();
2144 
2145  auto pbit64 = PointerType::Create();
2146  auto iOStateType = IOStateType::Create();
2147  auto memoryStateType = MemoryStateType::Create();
2148  auto fibFunctionType = rvsdg::FunctionType::Create(
2154 
2155  auto SetupFib = [&]()
2156  {
2157  auto pt = PointerType::Create();
2158 
2160  pb.begin(&graph->GetRootRegion());
2161  auto fibrv = pb.AddFixVar(fibFunctionType);
2162 
2164  *pb.subregion(),
2166  auto valueArgument = lambda->GetFunctionArguments()[0];
2167  auto pointerArgument = lambda->GetFunctionArguments()[1];
2168  auto iOStateArgument = lambda->GetFunctionArguments()[2];
2169  auto memoryStateArgument = lambda->GetFunctionArguments()[3];
2170  auto ctxVarFib = lambda->AddContextVar(*fibrv.recref).inner;
2171 
2172  auto two = &BitConstantOperation::create(*lambda->subregion(), { 64, 2 });
2173  auto bitult = jlm::rvsdg::bitult_op::create(64, valueArgument, two);
2174  auto predicate = jlm::rvsdg::match(1, { { 0, 1 } }, 0, 2, bitult);
2175 
2176  auto gammaNode = jlm::rvsdg::GammaNode::create(predicate, 2);
2177  auto nev = gammaNode->AddEntryVar(valueArgument);
2178  auto resultev = gammaNode->AddEntryVar(pointerArgument);
2179  auto fibev = gammaNode->AddEntryVar(ctxVarFib);
2180  auto gIIoState = gammaNode->AddEntryVar(iOStateArgument);
2181  auto gIMemoryState = gammaNode->AddEntryVar(memoryStateArgument);
2182 
2183  /* gamma subregion 0 */
2184  auto one = &BitConstantOperation::create(*gammaNode->subregion(0), { 64, 1 });
2185  auto nm1 = jlm::rvsdg::bitsub_op::create(64, nev.branchArgument[0], one);
2186  auto & callFibm1 = CallOperation::CreateNode(
2187  fibev.branchArgument[0],
2188  fibFunctionType,
2189  { nm1,
2190  resultev.branchArgument[0],
2191  gIIoState.branchArgument[0],
2192  gIMemoryState.branchArgument[0] });
2193 
2194  two = &BitConstantOperation::create(*gammaNode->subregion(0), { 64, 2 });
2195  auto nm2 = jlm::rvsdg::bitsub_op::create(64, nev.branchArgument[0], two);
2196  auto & callFibm2 = CallOperation::CreateNode(
2197  fibev.branchArgument[0],
2198  fibFunctionType,
2199  { nm2,
2200  resultev.branchArgument[0],
2201  &CallOperation::GetIOStateOutput(callFibm1),
2202  &CallOperation::GetMemoryStateOutput(callFibm1) });
2203 
2204  auto gepnm1 = GetElementPtrOperation::Create(
2205  resultev.branchArgument[0],
2206  { nm1 },
2208  pbit64);
2209  auto ldnm1 = LoadNonVolatileOperation::Create(
2210  gepnm1,
2211  { &CallOperation::GetMemoryStateOutput(callFibm2) },
2213  8);
2214 
2215  auto gepnm2 = GetElementPtrOperation::Create(
2216  resultev.branchArgument[0],
2217  { nm2 },
2219  pbit64);
2220  auto ldnm2 =
2221  LoadNonVolatileOperation::Create(gepnm2, { ldnm1[1] }, jlm::rvsdg::BitType::Create(64), 8);
2222 
2223  auto sum = jlm::rvsdg::bitadd_op::create(64, ldnm1[0], ldnm2[0]);
2224 
2225  /* gamma subregion 1 */
2226  /* Nothing needs to be done */
2227 
2228  auto sumex = gammaNode->AddExitVar({ sum, nev.branchArgument[1] });
2229  auto gOIoState = gammaNode->AddExitVar(
2230  { &CallOperation::GetIOStateOutput(callFibm2), gIIoState.branchArgument[1] });
2231  auto gOMemoryState = gammaNode->AddExitVar({ ldnm2[1], gIMemoryState.branchArgument[1] });
2232 
2233  auto gepn = GetElementPtrOperation::Create(
2234  pointerArgument,
2235  { valueArgument },
2237  pbit64);
2238  auto store = StoreNonVolatileOperation::Create(gepn, sumex.output, { gOMemoryState.output }, 8);
2239 
2240  auto lambdaOutput = lambda->finalize({ gOIoState.output, store[0] });
2241 
2242  fibrv.result->divert_to(lambdaOutput);
2243  auto phiNode = pb.end();
2244 
2245  return std::make_tuple(phiNode, lambdaOutput, gammaNode, &callFibm1, &callFibm2);
2246  };
2247 
2248  auto SetupTestFunction = [&](rvsdg::PhiNode * phiNode)
2249  {
2251  auto pbit64 = PointerType::Create();
2252  auto iOStateType = IOStateType::Create();
2253  auto memoryStateType = MemoryStateType::Create();
2254  auto functionType = rvsdg::FunctionType::Create(
2257 
2259  graph->GetRootRegion(),
2261  auto iOStateArgument = lambda->GetFunctionArguments()[0];
2262  auto memoryStateArgument = lambda->GetFunctionArguments()[1];
2263  auto fibcv = lambda->AddContextVar(*phiNode->output(0)).inner;
2264 
2265  auto constantOne = &BitConstantOperation::create(*lambda->subregion(), { 64, 1 });
2266  auto constantTen = &BitConstantOperation::create(*lambda->subregion(), { 64, 10 });
2267 
2268  auto allocaResults = AllocaOperation::create(at, constantOne, 16);
2269  auto state = MemoryStateMergeOperation::Create(
2270  std::vector<jlm::rvsdg::Output *>{ allocaResults[1], memoryStateArgument });
2271 
2272  auto zero = &BitConstantOperation::create(*lambda->subregion(), { 64, 0 });
2273  auto gep = GetElementPtrOperation::Create(allocaResults[0], { zero, zero }, at, pbit64);
2274 
2275  auto & call = CallOperation::CreateNode(
2276  fibcv,
2277  fibFunctionType,
2278  { constantTen, gep, iOStateArgument, state });
2279 
2280  auto lambdaOutput = lambda->finalize(outputs(&call));
2281  GraphExport::Create(*lambdaOutput, "test");
2282 
2283  return std::make_tuple(
2284  lambdaOutput,
2285  &call,
2286  rvsdg::TryGetOwnerNode<rvsdg::SimpleNode>(*allocaResults[0]));
2287  };
2288 
2289  auto [phiNode, fibfct, gammaNode, callFib1, callFib2] = SetupFib();
2290  auto [testfct, callFib, alloca] = SetupTestFunction(phiNode);
2291 
2292  // Assign nodes
2293  this->lambda_fib = &rvsdg::AssertGetOwnerNode<rvsdg::LambdaNode>(*fibfct);
2294  this->lambda_test = &rvsdg::AssertGetOwnerNode<rvsdg::LambdaNode>(*testfct);
2295 
2296  this->gamma = gammaNode;
2297  this->phi = phiNode;
2298 
2299  this->CallFibm1_ = callFib1;
2300  this->CallFibm2_ = callFib2;
2301 
2302  this->CallFib_ = callFib;
2303 
2304  this->alloca = alloca;
2305 
2306  return module;
2307 }
2308 
2309 std::unique_ptr<jlm::llvm::LlvmRvsdgModule>
2311 {
2312  using namespace jlm::llvm;
2313  using namespace jlm::rvsdg;
2314 
2315  auto iOStateType = IOStateType::Create();
2316  auto memoryStateType = MemoryStateType::Create();
2317 
2318  auto pointerType = PointerType::Create();
2319 
2320  auto constantFunctionType = rvsdg::FunctionType::Create(
2323 
2324  auto recursiveFunctionType = rvsdg::FunctionType::Create(
2327 
2328  auto functionIType = rvsdg::FunctionType::Create(
2331 
2332  auto recFunctionType = rvsdg::FunctionType::Create(
2335 
2337  auto graph = &module->Rvsdg();
2338 
2339  auto SetupEight = [&]()
2340  {
2342  graph->GetRootRegion(),
2343  llvm::LlvmLambdaOperation::Create(constantFunctionType, "eight", Linkage::externalLinkage));
2344  auto iOStateArgument = lambda->GetFunctionArguments()[0];
2345  auto memoryStateArgument = lambda->GetFunctionArguments()[1];
2346 
2347  auto constant = &BitConstantOperation::create(*lambda->subregion(), { 32, 8 });
2348 
2349  return lambda->finalize({ constant, iOStateArgument, memoryStateArgument });
2350  };
2351 
2352  auto SetupI = [&]()
2353  {
2355  graph->GetRootRegion(),
2357  auto pointerArgument = lambda->GetFunctionArguments()[0];
2358  auto functionArgument =
2359  rvsdg::CreateOpNode<PointerToFunctionOperation>({ pointerArgument }, constantFunctionType)
2360  .output(0);
2361  auto iOStateArgument = lambda->GetFunctionArguments()[1];
2362  auto memoryStateArgument = lambda->GetFunctionArguments()[2];
2363 
2364  auto & call = CallOperation::CreateNode(
2365  functionArgument,
2366  constantFunctionType,
2367  { iOStateArgument, memoryStateArgument });
2368 
2369  auto lambdaOutput = lambda->finalize(outputs(&call));
2370 
2371  return std::make_tuple(lambdaOutput, &call);
2372  };
2373 
2374  auto SetupA = [&](jlm::rvsdg::Region & region,
2375  jlm::rvsdg::Output & functionB,
2376  jlm::rvsdg::Output & functionD)
2377  {
2379  region,
2381  auto pointerArgument = lambda->GetFunctionArguments()[0];
2382  auto iOStateArgument = lambda->GetFunctionArguments()[1];
2383  auto memoryStateArgument = lambda->GetFunctionArguments()[2];
2384 
2385  auto functionBCv = lambda->AddContextVar(functionB).inner;
2386  auto functionDCv = lambda->AddContextVar(functionD).inner;
2387 
2388  auto one = &BitConstantOperation::create(*lambda->subregion(), { 32, 1 });
2389  auto storeNode =
2390  StoreNonVolatileOperation::Create(pointerArgument, one, { memoryStateArgument }, 4);
2391 
2392  auto constantOne = &BitConstantOperation::create(*lambda->subregion(), { 32, 1 });
2393 
2394  auto paAlloca = AllocaOperation::create(jlm::rvsdg::BitType::Create(32), constantOne, 4);
2395  auto paMerge = MemoryStateMergeOperation::Create(
2396  std::vector<jlm::rvsdg::Output *>({ paAlloca[1], storeNode[0] }));
2397 
2398  auto & callB = CallOperation::CreateNode(
2399  functionBCv,
2400  recFunctionType,
2401  { paAlloca[0], iOStateArgument, paMerge });
2402 
2403  auto & callD = CallOperation::CreateNode(
2404  functionDCv,
2405  recFunctionType,
2406  { paAlloca[0],
2409 
2410  auto sum = jlm::rvsdg::bitadd_op::create(32, callB.output(0), callD.output(0));
2411 
2412  auto lambdaOutput = lambda->finalize({ sum,
2415 
2416  return std::make_tuple(
2417  lambdaOutput,
2418  &callB,
2419  &callD,
2420  jlm::util::assertedCast<jlm::rvsdg::SimpleNode>(
2421  rvsdg::TryGetOwnerNode<rvsdg::Node>(*paAlloca[0])));
2422  };
2423 
2424  auto SetupB = [&](jlm::rvsdg::Region & region,
2425  jlm::rvsdg::Output & functionI,
2426  jlm::rvsdg::Output & functionC,
2427  jlm::rvsdg::Output & functionEight)
2428  {
2430  region,
2432  auto pointerArgument = lambda->GetFunctionArguments()[0];
2433  auto iOStateArgument = lambda->GetFunctionArguments()[1];
2434  auto memoryStateArgument = lambda->GetFunctionArguments()[2];
2435 
2436  auto functionICv = lambda->AddContextVar(functionI).inner;
2437  auto functionCCv = lambda->AddContextVar(functionC).inner;
2438  auto functionEightCv = lambda->AddContextVar(functionEight).inner;
2439 
2440  auto two = &BitConstantOperation::create(*lambda->subregion(), { 32, 2 });
2441  auto storeNode =
2442  StoreNonVolatileOperation::Create(pointerArgument, two, { memoryStateArgument }, 4);
2443 
2444  auto constantOne = &BitConstantOperation::create(*lambda->subregion(), { 32, 1 });
2445 
2446  auto pbAlloca = AllocaOperation::create(jlm::rvsdg::BitType::Create(32), constantOne, 4);
2447  auto pbMerge = MemoryStateMergeOperation::Create(
2448  std::vector<jlm::rvsdg::Output *>({ pbAlloca[1], storeNode[0] }));
2449 
2450  auto & callI = CallOperation::CreateNode(
2451  functionICv,
2452  functionIType,
2453  { rvsdg::CreateOpNode<FunctionToPointerOperation>({ functionEightCv }, constantFunctionType)
2454  .output(0),
2455  iOStateArgument,
2456  pbMerge });
2457 
2458  auto & callC = CallOperation::CreateNode(
2459  functionCCv,
2460  recFunctionType,
2461  { pbAlloca[0],
2464 
2465  auto sum = jlm::rvsdg::bitadd_op::create(32, callI.output(0), callC.output(0));
2466 
2467  auto lambdaOutput = lambda->finalize({ sum,
2470 
2471  return std::make_tuple(
2472  lambdaOutput,
2473  &callI,
2474  &callC,
2475  jlm::util::assertedCast<jlm::rvsdg::SimpleNode>(
2476  rvsdg::TryGetOwnerNode<rvsdg::Node>(*pbAlloca[0])));
2477  };
2478 
2479  auto SetupC = [&](jlm::rvsdg::Region & region, jlm::rvsdg::Output & functionA)
2480  {
2482  region,
2484  auto xArgument = lambda->GetFunctionArguments()[0];
2485  auto iOStateArgument = lambda->GetFunctionArguments()[1];
2486  auto memoryStateArgument = lambda->GetFunctionArguments()[2];
2487 
2488  auto functionACv = lambda->AddContextVar(functionA).inner;
2489 
2490  auto three = &BitConstantOperation::create(*lambda->subregion(), { 32, 3 });
2491  auto storeNode =
2492  StoreNonVolatileOperation::Create(xArgument, three, { memoryStateArgument }, 4);
2493 
2494  auto constanOne = &BitConstantOperation::create(*lambda->subregion(), { 32, 1 });
2495  auto pcAlloca = AllocaOperation::create(jlm::rvsdg::BitType::Create(32), constanOne, 4);
2496  auto pcMerge = MemoryStateMergeOperation::Create(
2497  std::vector<jlm::rvsdg::Output *>({ pcAlloca[1], storeNode[0] }));
2498 
2499  auto & callA = CallOperation::CreateNode(
2500  functionACv,
2501  recFunctionType,
2502  { pcAlloca[0], iOStateArgument, pcMerge });
2503 
2504  auto loadX = LoadNonVolatileOperation::Create(
2505  xArgument,
2508  4);
2509 
2510  auto sum = jlm::rvsdg::bitadd_op::create(32, callA.output(0), loadX[0]);
2511 
2512  auto lambdaOutput =
2513  lambda->finalize({ sum, &CallOperation::GetIOStateOutput(callA), loadX[1] });
2514 
2515  return std::make_tuple(
2516  lambdaOutput,
2517  &callA,
2518  jlm::util::assertedCast<jlm::rvsdg::SimpleNode>(
2519  rvsdg::TryGetOwnerNode<rvsdg::Node>(*pcAlloca[0])));
2520  };
2521 
2522  auto SetupD = [&](jlm::rvsdg::Region & region, jlm::rvsdg::Output & functionA)
2523  {
2525  region,
2527  auto xArgument = lambda->GetFunctionArguments()[0];
2528  auto iOStateArgument = lambda->GetFunctionArguments()[1];
2529  auto memoryStateArgument = lambda->GetFunctionArguments()[2];
2530 
2531  auto functionACv = lambda->AddContextVar(functionA).inner;
2532 
2533  auto four = &BitConstantOperation::create(*lambda->subregion(), { 32, 4 });
2534  auto storeNode = StoreNonVolatileOperation::Create(xArgument, four, { memoryStateArgument }, 4);
2535 
2536  auto constantOne = &BitConstantOperation::create(*lambda->subregion(), { 32, 1 });
2537  auto pdAlloca = AllocaOperation::create(jlm::rvsdg::BitType::Create(32), constantOne, 4);
2538  auto pdMerge = MemoryStateMergeOperation::Create(
2539  std::vector<jlm::rvsdg::Output *>({ pdAlloca[1], storeNode[0] }));
2540 
2541  auto & callA = CallOperation::CreateNode(
2542  functionACv,
2543  recFunctionType,
2544  { pdAlloca[0], iOStateArgument, pdMerge });
2545 
2546  auto lambdaOutput = lambda->finalize(outputs(&callA));
2547 
2548  return std::make_tuple(
2549  lambdaOutput,
2550  &callA,
2551  jlm::util::assertedCast<jlm::rvsdg::SimpleNode>(
2552  rvsdg::TryGetOwnerNode<rvsdg::Node>(*pdAlloca[0])));
2553  };
2554 
2555  auto SetupPhi = [&](rvsdg::Output & lambdaEight, rvsdg::Output & lambdaI)
2556  {
2557  jlm::rvsdg::PhiBuilder phiBuilder;
2558  phiBuilder.begin(&graph->GetRootRegion());
2559  auto lambdaARv = phiBuilder.AddFixVar(recFunctionType);
2560  auto lambdaBRv = phiBuilder.AddFixVar(recFunctionType);
2561  auto lambdaCRv = phiBuilder.AddFixVar(recFunctionType);
2562  auto lambdaDRv = phiBuilder.AddFixVar(recFunctionType);
2563  auto lambdaEightCv = phiBuilder.AddContextVar(lambdaEight);
2564  auto lambdaICv = phiBuilder.AddContextVar(lambdaI);
2565 
2566  auto [lambdaAOutput, callB, callD, paAlloca] =
2567  SetupA(*phiBuilder.subregion(), *lambdaBRv.recref, *lambdaDRv.recref);
2568 
2569  auto [lambdaBOutput, callI, callC, pbAlloca] =
2570  SetupB(*phiBuilder.subregion(), *lambdaICv.inner, *lambdaCRv.recref, *lambdaEightCv.inner);
2571 
2572  auto [lambdaCOutput, callAFromC, pcAlloca] = SetupC(*phiBuilder.subregion(), *lambdaARv.recref);
2573 
2574  auto [lambdaDOutput, callAFromD, pdAlloca] = SetupD(*phiBuilder.subregion(), *lambdaARv.recref);
2575 
2576  lambdaARv.result->divert_to(lambdaAOutput);
2577  lambdaBRv.result->divert_to(lambdaBOutput);
2578  lambdaCRv.result->divert_to(lambdaCOutput);
2579  lambdaDRv.result->divert_to(lambdaDOutput);
2580 
2581  phiBuilder.end();
2582 
2583  return std::make_tuple(
2584  lambdaARv,
2585  lambdaBRv,
2586  lambdaCRv,
2587  lambdaDRv,
2588  callB,
2589  callD,
2590  callI,
2591  callC,
2592  callAFromC,
2593  callAFromD,
2594  paAlloca,
2595  pbAlloca,
2596  pcAlloca,
2597  pdAlloca);
2598  };
2599 
2600  auto SetupTest = [&](rvsdg::Output & functionA)
2601  {
2602  auto pointerType = PointerType::Create();
2603 
2604  auto functionType = rvsdg::FunctionType::Create(
2607 
2609  graph->GetRootRegion(),
2611  auto iOStateArgument = lambda->GetFunctionArguments()[0];
2612  auto memoryStateArgument = lambda->GetFunctionArguments()[1];
2613 
2614  auto functionACv = lambda->AddContextVar(functionA).inner;
2615 
2616  auto constantOne = &BitConstantOperation::create(*lambda->subregion(), { 32, 1 });
2617  auto pTestAlloca = AllocaOperation::create(jlm::rvsdg::BitType::Create(32), constantOne, 4);
2618  auto pTestMerge = MemoryStateMergeOperation::Create(
2619  std::vector<jlm::rvsdg::Output *>({ pTestAlloca[1], memoryStateArgument }));
2620 
2621  auto & callA = CallOperation::CreateNode(
2622  functionACv,
2623  recFunctionType,
2624  { pTestAlloca[0], iOStateArgument, pTestMerge });
2625 
2626  auto lambdaOutput = lambda->finalize(outputs(&callA));
2627  GraphExport::Create(*lambdaOutput, "test");
2628 
2629  return std::make_tuple(
2630  lambdaOutput,
2631  &callA,
2632  jlm::util::assertedCast<jlm::rvsdg::SimpleNode>(
2633  rvsdg::TryGetOwnerNode<rvsdg::Node>(*pTestAlloca[0])));
2634  };
2635 
2636  auto lambdaEight = SetupEight();
2637  auto [lambdaI, indirectCall] = SetupI();
2638 
2639  auto
2640  [lambdaA,
2641  lambdaB,
2642  lambdaC,
2643  lambdaD,
2644  callB,
2645  callD,
2646  callI,
2647  callC,
2648  callAFromC,
2649  callAFromD,
2650  paAlloca,
2651  pbAlloca,
2652  pcAlloca,
2653  pdAlloca] = SetupPhi(*lambdaEight, *lambdaI);
2654 
2655  auto [lambdaTest, callAFromTest, pTestAlloca] = SetupTest(*lambdaA.output);
2656 
2657  /*
2658  * Assign nodes
2659  */
2660  this->LambdaEight_ = &rvsdg::AssertGetOwnerNode<rvsdg::LambdaNode>(*lambdaEight);
2661  this->LambdaI_ = &rvsdg::AssertGetOwnerNode<rvsdg::LambdaNode>(*lambdaI);
2662  this->LambdaA_ = &rvsdg::AssertGetOwnerNode<rvsdg::LambdaNode>(*lambdaA.result->origin());
2663  this->LambdaB_ = &rvsdg::AssertGetOwnerNode<rvsdg::LambdaNode>(*lambdaB.result->origin());
2664  this->LambdaC_ = &rvsdg::AssertGetOwnerNode<rvsdg::LambdaNode>(*lambdaC.result->origin());
2665  this->LambdaD_ = &rvsdg::AssertGetOwnerNode<rvsdg::LambdaNode>(*lambdaD.result->origin());
2666  this->LambdaTest_ = &rvsdg::AssertGetOwnerNode<rvsdg::LambdaNode>(*lambdaTest);
2667 
2668  this->CallAFromTest_ = callAFromTest;
2669  this->CallAFromC_ = callAFromC;
2670  this->CallAFromD_ = callAFromD;
2671  this->CallB_ = callB;
2672  this->CallC_ = callC;
2673  this->CallD_ = callD;
2674  this->CallI_ = callI;
2675  this->IndirectCall_ = indirectCall;
2676 
2677  this->PTestAlloca_ = pTestAlloca;
2678  this->PaAlloca_ = paAlloca;
2679  this->PbAlloca_ = pbAlloca;
2680  this->PcAlloca_ = pcAlloca;
2681  this->PdAlloca_ = pdAlloca;
2682 
2683  return module;
2684 }
2685 
2686 std::unique_ptr<jlm::llvm::LlvmRvsdgModule>
2688 {
2689  using namespace jlm::llvm;
2690  using namespace jlm::rvsdg;
2691 
2692  auto rvsdgModule = llvm::LlvmRvsdgModule::Create(jlm::util::FilePath(""), "", "");
2693  auto & rvsdg = rvsdgModule->Rvsdg();
2694 
2695  auto pointerType = PointerType::Create();
2696  auto structType = StructType::CreateIdentified("myStruct", { PointerType::Create() }, false);
2697  auto arrayType = ArrayType::Create(structType, 2);
2698 
2700  pb.begin(&rvsdg.GetRootRegion());
2701  auto myArrayRecVar = pb.AddFixVar(pointerType);
2702 
2703  auto delta = jlm::rvsdg::DeltaNode::Create(
2704  pb.subregion(),
2705  jlm::llvm::DeltaOperation::Create(arrayType, "myArray", Linkage::externalLinkage, "", false));
2706  auto myArrayArgument = delta->AddContextVar(*myArrayRecVar.recref).inner;
2707 
2708  auto aggregateZero = ConstantAggregateZeroOperation::Create(*delta->subregion(), structType);
2709  auto & constantStruct =
2710  ConstantStruct::Create(*delta->subregion(), { myArrayArgument }, structType);
2711  auto constantArray = ConstantArrayOperation::Create({ aggregateZero, &constantStruct });
2712 
2713  auto deltaOutput = &delta->finalize(constantArray);
2714  Delta_ = &rvsdg::AssertGetOwnerNode<rvsdg::DeltaNode>(*deltaOutput);
2715  myArrayRecVar.result->divert_to(deltaOutput);
2716 
2717  auto phiNode = pb.end();
2718  GraphExport::Create(*phiNode->output(0), "myArray");
2719 
2720  return rvsdgModule;
2721 }
2722 
2723 std::unique_ptr<jlm::llvm::LlvmRvsdgModule>
2725 {
2726  using namespace jlm::llvm;
2727  using namespace jlm::rvsdg;
2728 
2729  auto mt = MemoryStateType::Create();
2730  auto pointerType = PointerType::Create();
2731  auto ft = rvsdg::FunctionType::Create(
2733  { MemoryStateType::Create() });
2734 
2736  auto graph = &module->Rvsdg();
2737 
2741  LambdaF = rvsdg::LambdaNode::Create(
2742  graph->GetRootRegion(),
2744  auto x = LambdaF->GetFunctionArguments()[0];
2745  auto y = LambdaF->GetFunctionArguments()[1];
2746  auto state = LambdaF->GetFunctionArguments()[2];
2747 
2748  auto one = &BitConstantOperation::create(*LambdaF->subregion(), { 32, 1 });
2749  auto two = &BitConstantOperation::create(*LambdaF->subregion(), { 32, 2 });
2750 
2751  auto storeOne = StoreNonVolatileOperation::Create(x, one, { state }, 4);
2752  auto storeTwo = StoreNonVolatileOperation::Create(y, two, { storeOne[0] }, 4);
2753 
2754  LambdaF->finalize(storeTwo);
2755  GraphExport::Create(*LambdaF->output(), "f");
2756 
2757  return module;
2758 }
2759 
2760 std::unique_ptr<jlm::llvm::LlvmRvsdgModule>
2762 {
2763  using namespace jlm::llvm;
2764  using namespace jlm::rvsdg;
2765 
2766  auto rvsdgModule = llvm::LlvmRvsdgModule::Create(jlm::util::FilePath(""), "", "");
2767  auto rvsdg = &rvsdgModule->Rvsdg();
2768 
2769  auto SetupDeltaA = [&]()
2770  {
2771  auto deltaNode = jlm::rvsdg::DeltaNode::Create(
2772  &rvsdg->GetRootRegion(),
2775  "a",
2777  "",
2778  false));
2779 
2780  auto constant = &BitConstantOperation::create(*deltaNode->subregion(), { 32, 1 });
2781 
2782  return &deltaNode->finalize(constant);
2783  };
2784 
2785  auto SetupDeltaB = [&]()
2786  {
2787  auto deltaNode = jlm::rvsdg::DeltaNode::Create(
2788  &rvsdg->GetRootRegion(),
2791  "b",
2793  "",
2794  false));
2795 
2796  auto constant = &BitConstantOperation::create(*deltaNode->subregion(), { 32, 2 });
2797 
2798  return &deltaNode->finalize(constant);
2799  };
2800 
2801  auto SetupDeltaX = [&](rvsdg::Output & deltaA)
2802  {
2803  auto pointerType = PointerType::Create();
2804 
2805  auto deltaNode = jlm::rvsdg::DeltaNode::Create(
2806  &rvsdg->GetRootRegion(),
2807  jlm::llvm::DeltaOperation::Create(pointerType, "x", Linkage::externalLinkage, "", false));
2808 
2809  auto contextVariableA = deltaNode->AddContextVar(deltaA).inner;
2810 
2811  return &deltaNode->finalize(contextVariableA);
2812  };
2813 
2814  auto SetupDeltaY = [&](rvsdg::Output & deltaX)
2815  {
2816  auto pointerType = PointerType::Create();
2817 
2818  auto deltaNode = jlm::rvsdg::DeltaNode::Create(
2819  &rvsdg->GetRootRegion(),
2820  jlm::llvm::DeltaOperation::Create(pointerType, "y", Linkage::externalLinkage, "", false));
2821 
2822  auto contextVariableX = deltaNode->AddContextVar(deltaX).inner;
2823 
2824  auto deltaOutput = &deltaNode->finalize(contextVariableX);
2825  GraphExport::Create(*deltaOutput, "y");
2826 
2827  return deltaOutput;
2828  };
2829 
2830  auto SetupLambdaTest = [&](rvsdg::Output & deltaB)
2831  {
2832  auto pointerType = PointerType::Create();
2833  auto iOStateType = IOStateType::Create();
2834  auto memoryStateType = MemoryStateType::Create();
2835  auto functionType = rvsdg::FunctionType::Create(
2838 
2840  rvsdg->GetRootRegion(),
2842  auto pointerArgument = lambda->GetFunctionArguments()[0];
2843  auto iOStateArgument = lambda->GetFunctionArguments()[1];
2844  auto memoryStateArgument = lambda->GetFunctionArguments()[2];
2845 
2846  auto contextVariableB = lambda->AddContextVar(deltaB).inner;
2847 
2848  auto loadResults1 =
2849  LoadNonVolatileOperation::Create(pointerArgument, { memoryStateArgument }, pointerType, 4);
2850  auto loadResults2 = LoadNonVolatileOperation::Create(
2851  loadResults1[0],
2852  { loadResults1[1] },
2854  4);
2855 
2856  auto five = &BitConstantOperation::create(*lambda->subregion(), { 32, 5 });
2857  auto storeResults =
2858  StoreNonVolatileOperation::Create(contextVariableB, five, { loadResults2[1] }, 4);
2859 
2860  auto lambdaOutput = lambda->finalize({ loadResults2[0], iOStateArgument, storeResults[0] });
2861 
2862  GraphExport::Create(*lambdaOutput, "test");
2863 
2864  return std::make_tuple(
2865  lambdaOutput,
2866  jlm::util::assertedCast<rvsdg::SimpleNode>(
2867  rvsdg::TryGetOwnerNode<rvsdg::SimpleNode>(*loadResults1[0])));
2868  };
2869 
2870  auto deltaA = SetupDeltaA();
2871  auto deltaB = SetupDeltaB();
2872  auto deltaX = SetupDeltaX(*deltaA);
2873  auto deltaY = SetupDeltaY(*deltaX);
2874  auto [lambdaTest, loadNode1] = SetupLambdaTest(*deltaB);
2875 
2876  /*
2877  * Assign nodes
2878  */
2879  this->LambdaTest = &rvsdg::AssertGetOwnerNode<rvsdg::LambdaNode>(*lambdaTest);
2880 
2881  this->DeltaA = &rvsdg::AssertGetOwnerNode<rvsdg::DeltaNode>(*deltaA);
2882  this->DeltaB = &rvsdg::AssertGetOwnerNode<rvsdg::DeltaNode>(*deltaB);
2883  this->DeltaX = &rvsdg::AssertGetOwnerNode<rvsdg::DeltaNode>(*deltaX);
2884  this->DeltaY = &rvsdg::AssertGetOwnerNode<rvsdg::DeltaNode>(*deltaY);
2885 
2886  this->LoadNode1 = loadNode1;
2887 
2888  return rvsdgModule;
2889 }
2890 
2891 std::unique_ptr<jlm::llvm::LlvmRvsdgModule>
2893 {
2894  using namespace jlm::llvm;
2895  using namespace jlm::rvsdg;
2896 
2897  auto rvsdgModule = llvm::LlvmRvsdgModule::Create(jlm::util::FilePath(""), "", "");
2898  auto rvsdg = &rvsdgModule->Rvsdg();
2899 
2900  auto pointerType = PointerType::Create();
2901  auto iOStateType = IOStateType::Create();
2902  auto memoryStateType = MemoryStateType::Create();
2903 
2904  auto externalFunction1Type = rvsdg::FunctionType::Create(
2907 
2908  auto externalFunction2Type = rvsdg::FunctionType::Create(
2911 
2912  auto SetupExternalFunction1Declaration = [&]()
2913  {
2915  *rvsdg,
2916  externalFunction1Type,
2917  externalFunction1Type,
2918  "ExternalFunction1",
2920  true);
2921  };
2922 
2923  auto SetupExternalFunction2Declaration = [&]()
2924  {
2926  *rvsdg,
2927  externalFunction2Type,
2928  externalFunction2Type,
2929  "ExternalFunction2",
2931  true);
2932  };
2933 
2934  auto SetupReturnAddressFunction = [&]()
2935  {
2936  PointerType p8;
2937  auto iOStateType = IOStateType::Create();
2938  auto memoryStateType = MemoryStateType::Create();
2939  auto functionType = rvsdg::FunctionType::Create(
2942 
2944  rvsdg->GetRootRegion(),
2945  llvm::LlvmLambdaOperation::Create(functionType, "ReturnAddress", Linkage::externalLinkage));
2946  auto iOStateArgument = lambda->GetFunctionArguments()[0];
2947  auto memoryStateArgument = lambda->GetFunctionArguments()[1];
2948 
2949  auto eight = &BitConstantOperation::create(*lambda->subregion(), { 32, 8 });
2950 
2951  auto & mallocNode = MallocOperation::createNode(*eight, *iOStateArgument);
2952  auto mergeResults = MemoryStateMergeOperation::Create(
2953  std::vector({ memoryStateArgument, &MallocOperation::memoryStateOutput(mallocNode) }));
2954 
2955  auto lambdaOutput = lambda->finalize({ &MallocOperation::addressOutput(mallocNode),
2956  &MallocOperation::ioStateOutput(mallocNode),
2957  mergeResults });
2958 
2959  GraphExport::Create(*lambdaOutput, "ReturnAddress");
2960 
2961  return std::make_tuple(lambdaOutput, &mallocNode);
2962  };
2963 
2964  auto SetupCallExternalFunction1 = [&](jlm::rvsdg::RegionArgument * externalFunction1Argument)
2965  {
2966  auto iOStateType = IOStateType::Create();
2967  auto memoryStateType = MemoryStateType::Create();
2968  auto functionType = rvsdg::FunctionType::Create(
2971 
2973  rvsdg->GetRootRegion(),
2975  functionType,
2976  "CallExternalFunction1",
2978  auto iOStateArgument = lambda->GetFunctionArguments()[0];
2979  auto memoryStateArgument = lambda->GetFunctionArguments()[1];
2980 
2981  auto externalFunction1 = lambda->AddContextVar(*externalFunction1Argument).inner;
2982 
2983  auto eight = &BitConstantOperation::create(*lambda->subregion(), { 32, 8 });
2984 
2985  auto & mallocNode = MallocOperation::createNode(*eight, *iOStateArgument);
2986  auto mergeResult = MemoryStateMergeOperation::Create(
2987  std::vector({ memoryStateArgument, &MallocOperation::memoryStateOutput(mallocNode) }));
2988 
2989  auto & call = CallOperation::CreateNode(
2990  externalFunction1,
2991  externalFunction1Type,
2992  { &MallocOperation::addressOutput(mallocNode),
2993  &MallocOperation::ioStateOutput(mallocNode),
2994  mergeResult });
2995 
2996  auto lambdaOutput = lambda->finalize(outputs(&call));
2997 
2998  GraphExport::Create(*lambdaOutput, "CallExternalFunction1");
2999 
3000  return std::make_tuple(lambdaOutput, &call, &mallocNode);
3001  };
3002 
3003  auto SetupCallExternalFunction2 = [&](jlm::rvsdg::RegionArgument * externalFunction2Argument)
3004  {
3005  auto iOStateType = IOStateType::Create();
3006  auto memoryStateType = MemoryStateType::Create();
3007  auto functionType = rvsdg::FunctionType::Create(
3010 
3012  rvsdg->GetRootRegion(),
3014  functionType,
3015  "CallExternalFunction2",
3017  auto iOStateArgument = lambda->GetFunctionArguments()[0];
3018  auto memoryStateArgument = lambda->GetFunctionArguments()[1];
3019 
3020  auto externalFunction2 = lambda->AddContextVar(*externalFunction2Argument).inner;
3021 
3022  auto & call = CallOperation::CreateNode(
3023  externalFunction2,
3024  externalFunction2Type,
3025  { iOStateArgument, memoryStateArgument });
3026 
3027  auto loadResults = LoadNonVolatileOperation::Create(
3028  call.output(0),
3029  { &CallOperation::GetMemoryStateOutput(call) },
3031  4);
3032 
3033  auto lambdaOutput = lambda->finalize(
3034  { loadResults[0], &CallOperation::GetIOStateOutput(call), loadResults[1] });
3035 
3036  GraphExport::Create(*lambdaOutput, "CallExternalFunction2");
3037 
3038  return std::make_tuple(
3039  lambdaOutput,
3040  &call,
3041  jlm::util::assertedCast<rvsdg::SimpleNode>(
3042  rvsdg::TryGetOwnerNode<rvsdg::Node>(*loadResults[0])));
3043  };
3044 
3045  auto externalFunction1 = SetupExternalFunction1Declaration();
3046  auto externalFunction2 = SetupExternalFunction2Declaration();
3047  auto [returnAddressFunction, returnAddressMalloc] = SetupReturnAddressFunction();
3048  auto [callExternalFunction1, externalFunction1Call, callExternalFunction1Malloc] =
3049  SetupCallExternalFunction1(externalFunction1);
3050  auto [callExternalFunction2, externalFunction2Call, loadNode] =
3051  SetupCallExternalFunction2(externalFunction2);
3052 
3053  /*
3054  * Assign nodes
3055  */
3056  this->ReturnAddressFunction =
3057  &rvsdg::AssertGetOwnerNode<rvsdg::LambdaNode>(*returnAddressFunction);
3058  this->CallExternalFunction1 =
3059  &rvsdg::AssertGetOwnerNode<rvsdg::LambdaNode>(*callExternalFunction1);
3060  this->CallExternalFunction2 =
3061  &rvsdg::AssertGetOwnerNode<rvsdg::LambdaNode>(*callExternalFunction2);
3062 
3063  this->ExternalFunction1Call = externalFunction1Call;
3064  this->ExternalFunction2Call = externalFunction2Call;
3065 
3066  this->ReturnAddressMalloc = returnAddressMalloc;
3067  this->CallExternalFunction1Malloc = callExternalFunction1Malloc;
3068 
3069  this->ExternalFunction1Import = externalFunction1;
3070  this->ExternalFunction2Import = externalFunction2;
3071 
3072  this->LoadNode = loadNode;
3073 
3074  return rvsdgModule;
3075 }
3076 
3077 std::unique_ptr<jlm::llvm::LlvmRvsdgModule>
3079 {
3080  using namespace jlm::llvm;
3081  using namespace jlm::rvsdg;
3082 
3083  auto rvsdgModule = llvm::LlvmRvsdgModule::Create(jlm::util::FilePath(""), "", "");
3084  auto rvsdg = &rvsdgModule->Rvsdg();
3085 
3086  auto pointerType = PointerType::Create();
3087  auto iOStateType = IOStateType::Create();
3088  auto memoryStateType = MemoryStateType::Create();
3089  auto externalFunctionType = rvsdg::FunctionType::Create(
3092 
3093  auto SetupExternalFunctionDeclaration = [&]()
3094  {
3096  *rvsdg,
3097  externalFunctionType,
3098  externalFunctionType,
3099  "externalFunction",
3101  true);
3102  };
3103 
3104  auto SetupGlobal = [&]()
3105  {
3106  auto delta = jlm::rvsdg::DeltaNode::Create(
3107  &rvsdg->GetRootRegion(),
3110  "global",
3112  "",
3113  false));
3114 
3115  auto constant = &BitConstantOperation::create(*delta->subregion(), { 32, 4 });
3116 
3117  auto deltaOutput = &delta->finalize(constant);
3118 
3119  GraphExport::Create(*deltaOutput, "global");
3120 
3121  return deltaOutput;
3122  };
3123 
3124  auto SetupTestFunction = [&](jlm::rvsdg::RegionArgument * externalFunctionArgument)
3125  {
3126  auto iOStateType = IOStateType::Create();
3127  auto memoryStateType = MemoryStateType::Create();
3128  auto functionType = rvsdg::FunctionType::Create(
3131 
3133  rvsdg->GetRootRegion(),
3135  auto iOStateArgument = lambda->GetFunctionArguments()[0];
3136  auto memoryStateArgument = lambda->GetFunctionArguments()[1];
3137 
3138  auto externalFunction = lambda->AddContextVar(*externalFunctionArgument).inner;
3139 
3140  auto & call = CallOperation::CreateNode(
3141  externalFunction,
3142  externalFunctionType,
3143  { iOStateArgument, memoryStateArgument });
3144 
3145  auto loadResults = LoadNonVolatileOperation::Create(
3146  call.output(0),
3147  { &CallOperation::GetMemoryStateOutput(call) },
3149  4);
3150 
3151  auto lambdaOutput = lambda->finalize(
3152  { loadResults[0], &CallOperation::GetIOStateOutput(call), loadResults[1] });
3153 
3154  GraphExport::Create(*lambdaOutput, "test");
3155 
3156  return std::make_tuple(
3157  lambdaOutput,
3158  &call,
3159  jlm::util::assertedCast<rvsdg::SimpleNode>(
3160  rvsdg::TryGetOwnerNode<rvsdg::Node>(*loadResults[0])));
3161  };
3162 
3163  auto importExternalFunction = SetupExternalFunctionDeclaration();
3164  auto deltaGlobal = SetupGlobal();
3165  auto [lambdaTest, callExternalFunction, loadNode] = SetupTestFunction(importExternalFunction);
3166 
3167  // Assign nodes
3168  this->LambdaTest = &rvsdg::AssertGetOwnerNode<rvsdg::LambdaNode>(*lambdaTest);
3169  this->DeltaGlobal = &rvsdg::AssertGetOwnerNode<rvsdg::DeltaNode>(*deltaGlobal);
3170  this->ImportExternalFunction = importExternalFunction;
3171  this->CallExternalFunction = callExternalFunction;
3172  this->LoadNode = loadNode;
3173 
3174  return rvsdgModule;
3175 }
3176 
3177 std::unique_ptr<jlm::llvm::LlvmRvsdgModule>
3179 {
3180  using namespace jlm::llvm;
3181  using namespace jlm::rvsdg;
3182 
3183  auto rvsdgModule = llvm::LlvmRvsdgModule::Create(jlm::util::FilePath(""), "", "");
3184  auto rvsdg = &rvsdgModule->Rvsdg();
3185 
3186  auto arrayType = ArrayType::Create(jlm::rvsdg::BitType::Create(32), 5);
3187 
3188  auto SetupLocalArray = [&]()
3189  {
3190  auto delta = jlm::rvsdg::DeltaNode::Create(
3191  &rvsdg->GetRootRegion(),
3193  arrayType,
3194  "localArray",
3196  "",
3197  false));
3198 
3199  auto zero = &BitConstantOperation::create(*delta->subregion(), { 32, 0 });
3200  auto one = &BitConstantOperation::create(*delta->subregion(), { 32, 1 });
3201  auto two = &BitConstantOperation::create(*delta->subregion(), { 32, 2 });
3202  auto three = &BitConstantOperation::create(*delta->subregion(), { 32, 3 });
3203  auto four = &BitConstantOperation::create(*delta->subregion(), { 32, 4 });
3204 
3205  auto constantDataArray = ConstantDataArray::Create({ zero, one, two, three, four });
3206 
3207  auto deltaOutput = &delta->finalize(constantDataArray);
3208 
3209  GraphExport::Create(*deltaOutput, "localArray");
3210 
3211  return deltaOutput;
3212  };
3213 
3214  auto SetupGlobalArray = [&]()
3215  {
3216  auto delta = jlm::rvsdg::DeltaNode::Create(
3217  &rvsdg->GetRootRegion(),
3219  arrayType,
3220  "globalArray",
3222  "",
3223  false));
3224 
3225  auto constantAggregateZero =
3226  ConstantAggregateZeroOperation::Create(*delta->subregion(), arrayType);
3227 
3228  auto deltaOutput = &delta->finalize(constantAggregateZero);
3229 
3230  GraphExport::Create(*deltaOutput, "globalArray");
3231 
3232  return deltaOutput;
3233  };
3234 
3235  auto SetupFunctionF = [&](rvsdg::Output & globalArray)
3236  {
3237  auto iOStateType = IOStateType::Create();
3238  auto memoryStateType = MemoryStateType::Create();
3239  auto functionType = rvsdg::FunctionType::Create(
3242 
3244  rvsdg->GetRootRegion(),
3246  auto iOStateArgument = lambda->GetFunctionArguments()[0];
3247  auto memoryStateArgument = lambda->GetFunctionArguments()[1];
3248 
3249  auto globalArrayArgument = lambda->AddContextVar(globalArray).inner;
3250 
3251  auto zero = &BitConstantOperation::create(*lambda->subregion(), { 32, 0 });
3252  auto two = &BitConstantOperation::create(*lambda->subregion(), { 32, 2 });
3253  auto six = &BitConstantOperation::create(*lambda->subregion(), { 32, 6 });
3254 
3255  auto gep = GetElementPtrOperation::Create(
3256  globalArrayArgument,
3257  { zero, two },
3258  arrayType,
3260 
3261  auto storeResults = StoreNonVolatileOperation::Create(gep, six, { memoryStateArgument }, 8);
3262 
3263  auto loadResults = LoadNonVolatileOperation::Create(
3264  gep,
3265  { storeResults[0] },
3267  8);
3268 
3269  auto lambdaOutput = lambda->finalize({ loadResults[0], iOStateArgument, loadResults[1] });
3270 
3271  GraphExport::Create(*lambdaOutput, "f");
3272 
3273  return lambdaOutput;
3274  };
3275 
3276  auto SetupFunctionG =
3277  [&](rvsdg::Output & localArray, rvsdg::Output & globalArray, rvsdg::Output & lambdaF)
3278  {
3279  auto iOStateType = IOStateType::Create();
3280  auto memoryStateType = MemoryStateType::Create();
3281  auto functionType = rvsdg::FunctionType::Create(
3284 
3286  rvsdg->GetRootRegion(),
3288  auto iOStateArgument = lambda->GetFunctionArguments()[0];
3289  auto memoryStateArgument = lambda->GetFunctionArguments()[1];
3290 
3291  auto localArrayArgument = lambda->AddContextVar(localArray).inner;
3292  auto globalArrayArgument = lambda->AddContextVar(globalArray).inner;
3293  auto functionFArgument = lambda->AddContextVar(lambdaF).inner;
3294 
3295  auto bcLocalArray = BitCastOperation::create(localArrayArgument, PointerType::Create());
3296  auto bcGlobalArray = BitCastOperation::create(globalArrayArgument, PointerType::Create());
3297 
3298  auto twenty = &BitConstantOperation::create(*lambda->subregion(), { 32, 20 });
3299 
3300  auto memcpyResults = MemCpyNonVolatileOperation::create(
3301  bcGlobalArray,
3302  bcLocalArray,
3303  twenty,
3304  { memoryStateArgument });
3305 
3306  auto & call = CallOperation::CreateNode(
3307  functionFArgument,
3308  rvsdg::AssertGetOwnerNode<rvsdg::LambdaNode>(lambdaF).GetOperation().Type(),
3309  { iOStateArgument, memcpyResults[0] });
3310 
3311  auto lambdaOutput = lambda->finalize(outputs(&call));
3312 
3313  GraphExport::Create(*lambdaOutput, "g");
3314 
3315  return std::make_tuple(
3316  lambdaOutput,
3317  &call,
3318  &rvsdg::AssertGetOwnerNode<rvsdg::SimpleNode>(*memcpyResults[0]));
3319  };
3320 
3321  auto localArray = SetupLocalArray();
3322  auto globalArray = SetupGlobalArray();
3323  auto lambdaF = SetupFunctionF(*globalArray);
3324  auto [lambdaG, callF, memcpyNode] = SetupFunctionG(*localArray, *globalArray, *lambdaF);
3325 
3326  /*
3327  * Assign nodes
3328  */
3329  this->LambdaF_ = &rvsdg::AssertGetOwnerNode<rvsdg::LambdaNode>(*lambdaF);
3330  this->LambdaG_ = &rvsdg::AssertGetOwnerNode<rvsdg::LambdaNode>(*lambdaG);
3331  this->LocalArray_ = &rvsdg::AssertGetOwnerNode<rvsdg::DeltaNode>(*localArray);
3332  this->GlobalArray_ = &rvsdg::AssertGetOwnerNode<rvsdg::DeltaNode>(*globalArray);
3333  this->CallF_ = callF;
3334  this->Memcpy_ = memcpyNode;
3335 
3336  return rvsdgModule;
3337 }
3338 
3339 std::unique_ptr<jlm::llvm::LlvmRvsdgModule>
3341 {
3342  using namespace jlm::llvm;
3343  using namespace jlm::rvsdg;
3344 
3345  auto rvsdgModule = llvm::LlvmRvsdgModule::Create(jlm::util::FilePath(""), "", "");
3346  auto rvsdg = &rvsdgModule->Rvsdg();
3347 
3348  auto pointerType = PointerType::Create();
3349  auto arrayType = ArrayType::Create(PointerType::Create(), 32);
3350  auto structTypeB = StructType::CreateIdentified("structTypeB", { arrayType }, false);
3351 
3352  auto SetupFunctionG = [&]()
3353  {
3354  auto iOStateType = IOStateType::Create();
3355  auto memoryStateType = MemoryStateType::Create();
3356  auto functionType = rvsdg::FunctionType::Create(
3357  { PointerType::Create(),
3362 
3364  rvsdg->GetRootRegion(),
3366  auto s1Argument = lambda->GetFunctionArguments()[0];
3367  auto s2Argument = lambda->GetFunctionArguments()[1];
3368  auto iOStateArgument = lambda->GetFunctionArguments()[2];
3369  auto memoryStateArgument = lambda->GetFunctionArguments()[3];
3370 
3371  auto c0 = &BitConstantOperation::create(*lambda->subregion(), { 32, 0 });
3372  auto c128 = &BitConstantOperation::create(*lambda->subregion(), { 64, 128 });
3373 
3374  auto gepS21 = GetElementPtrOperation::Create(s2Argument, { c0, c0 }, structTypeB, pointerType);
3375  auto gepS22 = GetElementPtrOperation::Create(gepS21, { c0, c0 }, arrayType, pointerType);
3376  auto ldS2 = LoadNonVolatileOperation::Create(gepS22, { memoryStateArgument }, pointerType, 8);
3377 
3378  auto gepS11 = GetElementPtrOperation::Create(s1Argument, { c0, c0 }, structTypeB, pointerType);
3379  auto gepS12 = GetElementPtrOperation::Create(gepS11, { c0, c0 }, arrayType, pointerType);
3380  auto ldS1 = LoadNonVolatileOperation::Create(gepS12, { ldS2[1] }, pointerType, 8);
3381 
3382  auto memcpyResults = MemCpyNonVolatileOperation::create(ldS2[0], ldS1[0], c128, { ldS1[1] });
3383 
3384  auto lambdaOutput = lambda->finalize({ iOStateArgument, memcpyResults[0] });
3385 
3386  return std::make_tuple(lambdaOutput, rvsdg::TryGetOwnerNode<rvsdg::Node>(*memcpyResults[0]));
3387  };
3388 
3389  auto SetupFunctionF = [&](rvsdg::Output & functionF)
3390  {
3391  auto iOStateType = IOStateType::Create();
3392  auto memoryStateType = MemoryStateType::Create();
3393  auto functionType = rvsdg::FunctionType::Create(
3394  { PointerType::Create(),
3399 
3401  rvsdg->GetRootRegion(),
3403  auto s1Argument = lambda->GetFunctionArguments()[0];
3404  auto s2Argument = lambda->GetFunctionArguments()[1];
3405  auto iOStateArgument = lambda->GetFunctionArguments()[2];
3406  auto memoryStateArgument = lambda->GetFunctionArguments()[3];
3407 
3408  auto functionFArgument = lambda->AddContextVar(functionF).inner;
3409 
3410  auto c0 = &BitConstantOperation::create(*lambda->subregion(), { 32, 0 });
3411 
3412  auto gepS1 = GetElementPtrOperation::Create(s1Argument, { c0, c0 }, structTypeB, pointerType);
3413  auto ldS1 = LoadNonVolatileOperation::Create(gepS1, { memoryStateArgument }, pointerType, 8);
3414 
3415  auto gepS2 = GetElementPtrOperation::Create(s2Argument, { c0, c0 }, structTypeB, pointerType);
3416  auto ldS2 = LoadNonVolatileOperation::Create(gepS2, { ldS1[1] }, pointerType, 8);
3417 
3418  auto & call = CallOperation::CreateNode(
3419  functionFArgument,
3420  rvsdg::AssertGetOwnerNode<rvsdg::LambdaNode>(functionF).GetOperation().Type(),
3421  { ldS1[0], ldS2[0], iOStateArgument, ldS2[1] });
3422 
3423  auto lambdaOutput = lambda->finalize(outputs(&call));
3424 
3425  GraphExport::Create(*lambdaOutput, "f");
3426 
3427  return std::make_tuple(lambdaOutput, &call);
3428  };
3429 
3430  auto [lambdaG, memcpyNode] = SetupFunctionG();
3431  auto [lambdaF, callG] = SetupFunctionF(*lambdaG);
3432 
3433  this->LambdaF_ = &rvsdg::AssertGetOwnerNode<rvsdg::LambdaNode>(*lambdaF);
3434  this->LambdaG_ = &rvsdg::AssertGetOwnerNode<rvsdg::LambdaNode>(*lambdaG);
3435  this->CallG_ = callG;
3436  this->Memcpy_ = memcpyNode;
3437 
3438  return rvsdgModule;
3439 }
3440 
3441 std::unique_ptr<jlm::llvm::LlvmRvsdgModule>
3443 {
3444  using namespace jlm::llvm;
3445  using namespace jlm::rvsdg;
3446 
3447  auto rvsdgModule = llvm::LlvmRvsdgModule::Create(jlm::util::FilePath(""), "", "");
3448  auto rvsdg = &rvsdgModule->Rvsdg();
3449 
3450  auto pointerType = PointerType::Create();
3451  auto structType = StructType::CreateIdentified("myStruct", { PointerType::Create() }, false);
3452 
3453  auto iOStateType = IOStateType::Create();
3454  auto memoryStateType = MemoryStateType::Create();
3455  auto functionType = rvsdg::FunctionType::Create(
3458 
3459  Lambda_ = rvsdg::LambdaNode::Create(
3460  rvsdg->GetRootRegion(),
3462  auto pArgument = Lambda_->GetFunctionArguments()[0];
3463  auto iOStateArgument = Lambda_->GetFunctionArguments()[1];
3464  auto memoryStateArgument = Lambda_->GetFunctionArguments()[2];
3465 
3466  auto eight = &BitConstantOperation::create(*Lambda_->subregion(), { 64, 8 });
3467  auto zero = &BitConstantOperation::create(*Lambda_->subregion(), { 32, 0 });
3468  auto minusFive = &BitConstantOperation::create(*Lambda_->subregion(), { 64, -5 });
3469  auto three = &BitConstantOperation::create(*Lambda_->subregion(), { 64, 3 });
3470 
3471  auto constantOne = &BitConstantOperation::create(*Lambda_->subregion(), { 64, 1 });
3472  auto allocaResults = AllocaOperation::create(structType, constantOne, 8);
3473  auto memoryState = MemoryStateMergeOperation::Create(
3474  std::vector<jlm::rvsdg::Output *>{ allocaResults[1], memoryStateArgument });
3475 
3476  auto memcpyResults =
3477  MemCpyNonVolatileOperation::create(allocaResults[0], pArgument, eight, { memoryState });
3478 
3479  auto gep1 =
3480  GetElementPtrOperation::Create(allocaResults[0], { zero, zero }, structType, pointerType);
3481  auto ld = LoadNonVolatileOperation::Create(gep1, { memcpyResults[0] }, pointerType, 8);
3482 
3483  auto gep2 =
3484  GetElementPtrOperation::Create(allocaResults[0], { minusFive }, structType, pointerType);
3485 
3486  memcpyResults = MemCpyNonVolatileOperation::create(ld[0], gep2, three, { ld[1] });
3487 
3488  auto lambdaOutput = Lambda_->finalize({ iOStateArgument, memcpyResults[0] });
3489 
3490  GraphExport::Create(*lambdaOutput, "f");
3491 
3492  Alloca_ = rvsdg::TryGetOwnerNode<rvsdg::Node>(*allocaResults[0]);
3493  Memcpy_ = rvsdg::TryGetOwnerNode<rvsdg::Node>(*memcpyResults[0]);
3494 
3495  return rvsdgModule;
3496 }
3497 
3498 std::unique_ptr<jlm::llvm::LlvmRvsdgModule>
3500 {
3501  using namespace jlm::llvm;
3502  using namespace jlm::rvsdg;
3503 
3504  auto rvsdgModule = llvm::LlvmRvsdgModule::Create(jlm::util::FilePath(""), "", "");
3505  auto & rvsdg = rvsdgModule->Rvsdg();
3506 
3507  auto pointerType = PointerType::Create();
3508  auto structType = StructType::CreateIdentified("list", { PointerType::Create() }, false);
3509 
3510  auto SetupDeltaMyList = [&]()
3511  {
3512  auto delta = jlm::rvsdg::DeltaNode::Create(
3513  &rvsdg.GetRootRegion(),
3515  pointerType,
3516  "MyList",
3518  "",
3519  false));
3520 
3521  auto constantPointerNullResult =
3522  ConstantPointerNullOperation::Create(delta->subregion(), pointerType);
3523 
3524  auto deltaOutput = &delta->finalize(constantPointerNullResult);
3525  GraphExport::Create(*deltaOutput, "myList");
3526 
3527  return deltaOutput;
3528  };
3529 
3530  auto SetupFunctionNext = [&](rvsdg::Output & myList)
3531  {
3532  auto iOStateType = IOStateType::Create();
3533  auto memoryStateType = MemoryStateType::Create();
3534  auto functionType = rvsdg::FunctionType::Create(
3537 
3539  rvsdg.GetRootRegion(),
3541  auto iOStateArgument = lambda->GetFunctionArguments()[0];
3542  auto memoryStateArgument = lambda->GetFunctionArguments()[1];
3543 
3544  auto myListArgument = lambda->AddContextVar(myList).inner;
3545 
3546  auto zero = &BitConstantOperation::create(*lambda->subregion(), { 32, 0 });
3547  auto constantOne = &BitConstantOperation::create(*lambda->subregion(), { 32, 1 });
3548 
3549  auto alloca = AllocaOperation::create(pointerType, constantOne, 4);
3550  auto mergedMemoryState = MemoryStateMergeOperation::Create(
3551  std::vector<jlm::rvsdg::Output *>{ alloca[1], memoryStateArgument });
3552 
3553  auto load1 =
3554  LoadNonVolatileOperation::Create(myListArgument, { mergedMemoryState }, pointerType, 4);
3555  auto store1 = StoreNonVolatileOperation::Create(alloca[0], load1[0], { load1[1] }, 4);
3556 
3557  auto load2 = LoadNonVolatileOperation::Create(alloca[0], { store1[0] }, pointerType, 4);
3558  auto gep = GetElementPtrOperation::Create(load2[0], { zero, zero }, structType, pointerType);
3559 
3560  auto load3 = LoadNonVolatileOperation::Create(gep, { load2[1] }, pointerType, 4);
3561  auto store2 = StoreNonVolatileOperation::Create(alloca[0], load3[0], { load3[1] }, 4);
3562 
3563  auto load4 = LoadNonVolatileOperation::Create(alloca[0], { store2[0] }, pointerType, 4);
3564 
3565  auto lambdaOutput = lambda->finalize({ load4[0], iOStateArgument, load4[1] });
3566  GraphExport::Create(*lambdaOutput, "next");
3567 
3568  return std::make_tuple(rvsdg::TryGetOwnerNode<rvsdg::SimpleNode>(*alloca[0]), lambdaOutput);
3569  };
3570 
3571  auto deltaMyList = SetupDeltaMyList();
3572  auto [alloca, lambdaNext] = SetupFunctionNext(*deltaMyList);
3573 
3574  /*
3575  * Assign nodes
3576  */
3577  this->DeltaMyList_ = &rvsdg::AssertGetOwnerNode<rvsdg::DeltaNode>(*deltaMyList);
3578  this->LambdaNext_ = &rvsdg::AssertGetOwnerNode<rvsdg::LambdaNode>(*lambdaNext);
3579  this->Alloca_ = alloca;
3580 
3581  return rvsdgModule;
3582 }
3583 
3584 std::unique_ptr<jlm::llvm::LlvmRvsdgModule>
3586 {
3587  using namespace jlm::llvm;
3588  using namespace jlm::rvsdg;
3589 
3590  auto mt = MemoryStateType::Create();
3591  auto pointerType = PointerType::Create();
3592  auto ioStateType = IOStateType::Create();
3593  auto functionType = rvsdg::FunctionType::Create(
3594  { MemoryStateType::Create(), ioStateType },
3595  { MemoryStateType::Create(), ioStateType });
3596 
3598  auto graph = &module->Rvsdg();
3599 
3600  // Create imported symbol "imported"
3601  Import_ = &llvm::LlvmGraphImport::Create(
3602  *graph,
3605  "imported",
3607  false);
3608 
3609  // Create global variable "global"
3611  &graph->GetRootRegion(),
3613  pointerType,
3614  "global",
3616  "",
3617  false));
3618  auto constantPointerNullResult =
3619  ConstantPointerNullOperation::Create(Delta_->subregion(), pointerType);
3620  Delta_->finalize(constantPointerNullResult);
3621 
3622  // Start of function "f"
3623  Lambda_ = rvsdg::LambdaNode::Create(
3624  graph->GetRootRegion(),
3626  auto entryMemoryState = Lambda_->GetFunctionArguments()[0];
3627  auto ioStateArgument = Lambda_->GetFunctionArguments()[1];
3628  auto deltaContextVar = Lambda_->AddContextVar(Delta_->output()).inner;
3629  auto importContextVar = Lambda_->AddContextVar(*Import_).inner;
3630 
3631  // Create alloca node
3632  auto allocaSize = &BitConstantOperation::create(*Lambda_->subregion(), { 32, 1 });
3633  auto allocaOutputs = AllocaOperation::create(pointerType, allocaSize, 8);
3634  Alloca_ = rvsdg::TryGetOwnerNode<rvsdg::SimpleNode>(*allocaOutputs[0]);
3635 
3636  auto afterAllocaMemoryState = MemoryStateMergeOperation::Create(
3637  std::vector<jlm::rvsdg::Output *>{ entryMemoryState, allocaOutputs[1] });
3638 
3639  // Create malloc node
3640  auto mallocSize = &BitConstantOperation::create(*Lambda_->subregion(), { 32, 4 });
3641  Malloc_ = &MallocOperation::createNode(*mallocSize, *ioStateArgument);
3642 
3643  auto afterMallocMemoryState = MemoryStateMergeOperation::Create(
3644  std::vector{ afterAllocaMemoryState, &MallocOperation::memoryStateOutput(*Malloc_) });
3645 
3646  // Store the result of malloc into the alloca'd memory
3647  auto storeAllocaOutputs = StoreNonVolatileOperation::Create(
3648  allocaOutputs[0],
3649  &MallocOperation::addressOutput(*Malloc_),
3650  { afterMallocMemoryState },
3651  8);
3652 
3653  // load the value in the alloca again
3654  auto loadAllocaOutputs =
3655  LoadNonVolatileOperation::Create(allocaOutputs[0], { storeAllocaOutputs[0] }, pointerType, 8);
3656 
3657  // Load the value of the imported symbol "imported"
3658  auto loadImportedOutputs = LoadNonVolatileOperation::Create(
3659  importContextVar,
3660  { loadAllocaOutputs[1] },
3662  4);
3663 
3664  // Store the loaded value from imported, into the address loaded from the alloca (aka. the malloc
3665  // result)
3666  auto storeImportedOutputs = StoreNonVolatileOperation::Create(
3667  loadAllocaOutputs[0],
3668  loadImportedOutputs[0],
3669  { loadImportedOutputs[1] },
3670  4);
3671 
3672  // store the loaded alloca value in the global variable
3673  auto storeOutputs = StoreNonVolatileOperation::Create(
3674  deltaContextVar,
3675  loadAllocaOutputs[0],
3676  { storeImportedOutputs[0] },
3677  8);
3678 
3679  Lambda_->finalize({ storeOutputs[0], &MallocOperation::ioStateOutput(*Malloc_) });
3680 
3681  GraphExport::Create(Delta_->output(), "global");
3682  GraphExport::Create(*Lambda_->output(), "f");
3683 
3684  return module;
3685 }
3686 
3687 std::unique_ptr<jlm::llvm::LlvmRvsdgModule>
3689 {
3690  using namespace jlm::llvm;
3691  using namespace jlm::rvsdg;
3692 
3693  auto mt = MemoryStateType::Create();
3694  auto pointerType = PointerType::Create();
3695  auto fcttype =
3697 
3699  auto graph = &module->Rvsdg();
3700 
3701  Function_ = rvsdg::LambdaNode::Create(
3702  graph->GetRootRegion(),
3704 
3705  auto constantOne = &BitConstantOperation::create(*Function_->subregion(), { 32, 1 });
3706 
3707  jlm::rvsdg::Output * latestMemoryState = Function_->GetFunctionArguments()[0];
3708 
3709  for (size_t i = 0; i < NumAllocaNodes_; i++)
3710  {
3711  auto allocaOutputs = AllocaOperation::create(jlm::rvsdg::BitType::Create(32), constantOne, 4);
3712  auto allocaNode = rvsdg::TryGetOwnerNode<rvsdg::SimpleNode>(*allocaOutputs[0]);
3713 
3714  AllocaNodes_.push_back(allocaNode);
3715 
3716  // Update latestMemoryState to include the alloca memory state output
3717  latestMemoryState =
3718  MemoryStateMergeOperation::Create(std::vector{ latestMemoryState, allocaOutputs[1] });
3719  }
3720 
3721  Function_->finalize({ latestMemoryState });
3722 
3723  GraphExport::Create(*Function_->output(), "f");
3724 
3725  return module;
3726 }
3727 
3728 std::unique_ptr<jlm::llvm::LlvmRvsdgModule>
3730 {
3731  using namespace jlm::llvm;
3732  using namespace jlm::rvsdg;
3733 
3734  auto uint32Type = rvsdg::BitType::Create(32);
3735  auto mt = MemoryStateType::Create();
3736  auto pointerType = PointerType::Create();
3737  auto localFuncType = rvsdg::FunctionType::Create(
3740  auto exportedFuncType = rvsdg::FunctionType::Create(
3743 
3745  const auto graph = &module->Rvsdg();
3746 
3748  &graph->GetRootRegion(),
3749  jlm::llvm::DeltaOperation::Create(uint32Type, "global", Linkage::internalLinkage, "", false));
3750  const auto constantZero = &BitConstantOperation::create(*Global_->subregion(), { 32, 0 });
3751  const auto deltaOutput = &Global_->finalize(constantZero);
3752 
3753  LocalFunc_ = rvsdg::LambdaNode::Create(
3754  graph->GetRootRegion(),
3755  llvm::LlvmLambdaOperation::Create(localFuncType, "localFunction", Linkage::internalLinkage));
3756 
3757  LocalFuncParam_ = LocalFunc_->GetFunctionArguments()[0];
3758 
3759  const auto constantOne = &BitConstantOperation::create(*LocalFunc_->subregion(), { 32, 1 });
3760  const auto allocaOutputs = AllocaOperation::create(uint32Type, constantOne, 4);
3761  LocalFuncParamAllocaNode_ = rvsdg::TryGetOwnerNode<rvsdg::Node>(*allocaOutputs[0]);
3762 
3763  // Merge function's input Memory State and alloca node's memory state
3764  rvsdg::Output * mergedMemoryState = MemoryStateMergeOperation::Create(
3765  std::vector<rvsdg::Output *>{ LocalFunc_->GetFunctionArguments()[1], allocaOutputs[1] });
3766 
3767  // Store the function parameter into the alloca node
3768  auto storeOutputs = StoreNonVolatileOperation::Create(
3769  allocaOutputs[0],
3770  LocalFuncParam_,
3771  { mergedMemoryState },
3772  4);
3773 
3774  // Bring in deltaOuput as a context variable
3775  const auto deltaOutputCtxVar = LocalFunc_->AddContextVar(*deltaOutput).inner;
3776 
3777  // Return &global
3778  LocalFunc_->finalize({ deltaOutputCtxVar, storeOutputs[0] });
3779 
3780  LocalFuncRegister_ =
3781  rvsdg::CreateOpNode<FunctionToPointerOperation>({ LocalFunc_->output() }, localFuncType)
3782  .output(0);
3783 
3784  ExportedFunc_ = rvsdg::LambdaNode::Create(
3785  graph->GetRootRegion(),
3787  exportedFuncType,
3788  "exportedFunc",
3790 
3791  const auto localFuncCtxVar = ExportedFunc_->AddContextVar(*LocalFuncRegister_).inner;
3792 
3793  // Return &localFunc, pass memory state directly through
3794  ExportedFunc_->finalize({ localFuncCtxVar, ExportedFunc_->GetFunctionArguments()[0] });
3795 
3796  GraphExport::Create(*ExportedFunc_->output(), "exportedFunc");
3797 
3798  return module;
3799 }
3800 
3801 std::unique_ptr<llvm::LlvmRvsdgModule>
3803 {
3804  using namespace jlm::llvm;
3805  using namespace jlm::rvsdg;
3806 
3807  auto functionType = rvsdg::FunctionType::Create(
3810 
3812  auto graph = &module->Rvsdg();
3813 
3814  LambdaMain_ = rvsdg::LambdaNode::Create(
3815  graph->GetRootRegion(),
3817  auto iOStateArgument = LambdaMain_->GetFunctionArguments()[0];
3818  auto memoryStateArgument = LambdaMain_->GetFunctionArguments()[1];
3819 
3820  auto constantPointerNullResult =
3821  ConstantPointerNullOperation::Create(LambdaMain_->subregion(), PointerType::Create());
3822 
3823  auto FreeResults =
3824  FreeOperation::Create(constantPointerNullResult, { memoryStateArgument }, iOStateArgument);
3825 
3826  LambdaMain_->finalize({ FreeResults[1], FreeResults[0] });
3827 
3828  GraphExport::Create(*LambdaMain_->output(), "main");
3829 
3830  return module;
3831 }
3832 
3833 std::unique_ptr<llvm::LlvmRvsdgModule>
3835 {
3836  using namespace jlm::llvm;
3837  using namespace jlm::rvsdg;
3838 
3839  auto rvsdgModule = llvm::LlvmRvsdgModule::Create(util::FilePath(""), "", "");
3840  auto & rvsdg = rvsdgModule->Rvsdg();
3841 
3842  auto functionType = rvsdg::FunctionType::Create(
3845  auto variableArgumentType = VariableArgumentType::Create();
3846  auto functionTypeCall = rvsdg::FunctionType::Create(
3847  { rvsdg::BitType::Create(32),
3848  variableArgumentType,
3852 
3853  auto setupLambdaG = [&]()
3854  {
3855  auto iOStateType = IOStateType::Create();
3856  auto memoryStateType = MemoryStateType::Create();
3857 
3859  rvsdg.GetRootRegion(),
3861  auto iOStateArgument = lambda->GetFunctionArguments()[0];
3862  auto memoryStateArgument = lambda->GetFunctionArguments()[1];
3863 
3864  auto five = &BitConstantOperation::create(*lambda->subregion(), { 32, 5 });
3865 
3866  return lambda->finalize({ five, iOStateArgument, memoryStateArgument });
3867  };
3868 
3869  auto setupLambdaMain = [&](rvsdg::Output & lambdaG)
3870  {
3871  auto pointerType = PointerType::Create();
3872  auto iOStateType = IOStateType::Create();
3873  auto memoryStateType = MemoryStateType::Create();
3874  auto functionTypeMain = rvsdg::FunctionType::Create(
3877 
3879  rvsdg.GetRootRegion(),
3880  llvm::LlvmLambdaOperation::Create(functionTypeMain, "main", Linkage::externalLinkage));
3881  auto iOStateArgument = lambda->GetFunctionArguments()[0];
3882  auto memoryStateArgument = lambda->GetFunctionArguments()[1];
3883  auto lambdaGArgument = lambda->AddContextVar(lambdaG).inner;
3884 
3885  auto one = &BitConstantOperation::create(*lambda->subregion(), { 32, 1 });
3886  auto six = &BitConstantOperation::create(*lambda->subregion(), { 32, 6 });
3887 
3889 
3890  auto allocaResults = AllocaOperation::create(rvsdg::BitType::Create(32), one, 4);
3891 
3892  auto memoryState = MemoryStateMergeOperation::Create(
3893  std::vector<rvsdg::Output *>{ memoryStateArgument, allocaResults[1] });
3894 
3895  auto storeResults =
3896  StoreNonVolatileOperation::Create(allocaResults[0], six, { memoryState }, 4);
3897 
3898  auto loadResults = LoadNonVolatileOperation::Create(
3899  allocaResults[0],
3900  storeResults,
3902  4);
3903 
3904  auto & call = CallOperation::CreateNode(
3905  lambdaGArgument,
3906  functionTypeCall,
3907  { loadResults[0], vaList, iOStateArgument, loadResults[1] });
3908 
3909  auto lambdaOutput = lambda->finalize(outputs(&call));
3910 
3911  GraphExport::Create(*lambdaOutput, "main");
3912 
3913  return std::make_tuple(lambdaOutput, &call);
3914  };
3915 
3916  LambdaG_ = &rvsdg::AssertGetOwnerNode<rvsdg::LambdaNode>(*setupLambdaG());
3917 
3918  // Formal arguments and call arguments do not match. Force conversion through pointer
3919  // to hide the mismatch, the call operator would complain otherwise.
3920  // The semantic of this is llvm-specific.
3921  auto ptr =
3922  jlm::rvsdg::CreateOpNode<FunctionToPointerOperation>({ LambdaG_->output() }, functionType)
3923  .output(0);
3924  auto fn =
3925  jlm::rvsdg::CreateOpNode<PointerToFunctionOperation>({ ptr }, functionTypeCall).output(0);
3926  auto [lambdaMainOutput, call] = setupLambdaMain(*fn);
3927  LambdaMain_ = &rvsdg::AssertGetOwnerNode<rvsdg::LambdaNode>(*lambdaMainOutput);
3928  Call_ = call;
3929 
3930  return rvsdgModule;
3931 }
3932 
3933 std::unique_ptr<llvm::LlvmRvsdgModule>
3935 {
3936  using namespace jlm::llvm;
3937 
3938  auto rvsdgModule = LlvmRvsdgModule::Create(util::FilePath(""), "", "");
3939  auto & rvsdg = rvsdgModule->Rvsdg();
3940 
3941  auto pointerType = PointerType::Create();
3942  auto iOStateType = IOStateType::Create();
3943  auto memoryStateType = MemoryStateType::Create();
3944  auto varArgType = VariableArgumentType::Create();
3945  auto lambdaHType = rvsdg::FunctionType::Create(
3947  varArgType,
3951  auto lambdaFType = rvsdg::FunctionType::Create(
3954  auto lambdaGType = rvsdg::FunctionType::Create(
3957 
3958  // Setup h()
3959  ImportH_ = &LlvmGraphImport::Create(
3960  rvsdg,
3961  lambdaHType,
3962  lambdaHType,
3963  "h",
3965  true);
3966 
3967  // Setup f()
3968  {
3969  LambdaF_ = rvsdg::LambdaNode::Create(
3970  rvsdg.GetRootRegion(),
3972  auto iArgument = LambdaF_->GetFunctionArguments()[0];
3973  auto iOStateArgument = LambdaF_->GetFunctionArguments()[1];
3974  auto memoryStateArgument = LambdaF_->GetFunctionArguments()[2];
3975  auto lambdaHArgument = LambdaF_->AddContextVar(*ImportH_).inner;
3976 
3977  auto one = &rvsdg::BitConstantOperation::create(*LambdaF_->subregion(), { 32, 1 });
3978  auto three = &rvsdg::BitConstantOperation::create(*LambdaF_->subregion(), { 32, 3 });
3979 
3980  auto varArgList = VariadicArgumentListOperation::Create(*LambdaF_->subregion(), { iArgument });
3981 
3982  CallH_ = &CallOperation::CreateNode(
3983  lambdaHArgument,
3984  lambdaHType,
3985  { one, varArgList, iOStateArgument, memoryStateArgument });
3986 
3987  auto storeResults = StoreNonVolatileOperation::Create(
3988  CallH_->output(0),
3989  three,
3990  { &CallOperation::GetMemoryStateOutput(*CallH_) },
3991  4);
3992 
3993  LambdaF_->finalize({ &CallOperation::GetIOStateOutput(*CallH_), storeResults[0] });
3994  }
3995 
3996  // Setup g()
3997  {
3998  LambdaG_ = rvsdg::LambdaNode::Create(
3999  rvsdg.GetRootRegion(),
4001  auto iOStateArgument = LambdaG_->GetFunctionArguments()[0];
4002  auto memoryStateArgument = LambdaG_->GetFunctionArguments()[1];
4003  auto lambdaFArgument = LambdaG_->AddContextVar(*LambdaF_->output()).inner;
4004 
4005  auto one = &rvsdg::BitConstantOperation::create(*LambdaG_->subregion(), { 32, 1 });
4006  auto five = &rvsdg::BitConstantOperation::create(*LambdaG_->subregion(), { 32, 5 });
4007 
4008  auto allocaResults = AllocaOperation::create(jlm::rvsdg::BitType::Create(32), one, 4);
4009  auto merge = MemoryStateMergeOperation::Create(
4010  std::vector<jlm::rvsdg::Output *>{ allocaResults[1], memoryStateArgument });
4011  AllocaNode_ = rvsdg::TryGetOwnerNode<rvsdg::Node>(*allocaResults[0]);
4012 
4013  auto storeResults = StoreNonVolatileOperation::Create(allocaResults[0], five, { merge }, 4);
4014 
4015  auto & callF = CallOperation::CreateNode(
4016  lambdaFArgument,
4017  lambdaFType,
4018  { allocaResults[0], iOStateArgument, storeResults[0] });
4019 
4020  LambdaG_->finalize(outputs(&callF));
4021  }
4022 
4023  return rvsdgModule;
4024 }
4025 
4026 std::unique_ptr<jlm::llvm::LlvmRvsdgModule>
4028 {
4029  using namespace jlm::llvm;
4030 
4031  auto rvsdgModule = LlvmRvsdgModule::Create(jlm::util::FilePath(""), "", "");
4032  auto & rvsdg = rvsdgModule->Rvsdg();
4033 
4034  auto pointerType = PointerType::Create();
4035  auto structType = StructType::CreateIdentified(
4036  "struct.__va_list_tag",
4037  { rvsdg::BitType::Create(32),
4040  PointerType::Create() },
4041  false);
4042  auto arrayType = ArrayType::Create(structType, 1);
4043  auto iOStateType = IOStateType::Create();
4044  auto memoryStateType = MemoryStateType::Create();
4045  auto varArgType = VariableArgumentType::Create();
4046  auto lambdaLlvmLifetimeStartType = rvsdg::FunctionType::Create(
4047  { rvsdg::BitType::Create(64),
4052  auto lambdaLlvmLifetimeEndType = rvsdg::FunctionType::Create(
4053  { rvsdg::BitType::Create(64),
4058  auto lambdaVaStartType = rvsdg::FunctionType::Create(
4061  auto lambdaVaEndType = rvsdg::FunctionType::Create(
4064  auto lambdaFstType = rvsdg::FunctionType::Create(
4067  auto lambdaGType = rvsdg::FunctionType::Create(
4070 
4071  auto llvmLifetimeStart = &LlvmGraphImport::Create(
4072  rvsdg,
4073  lambdaLlvmLifetimeStartType,
4074  lambdaLlvmLifetimeStartType,
4075  "llvm.lifetime.start.p0",
4077  true);
4078  auto llvmLifetimeEnd = &LlvmGraphImport::Create(
4079  rvsdg,
4080  lambdaLlvmLifetimeEndType,
4081  lambdaLlvmLifetimeEndType,
4082  "llvm.lifetime.end.p0",
4084  true);
4085  auto llvmVaStart = &LlvmGraphImport::Create(
4086  rvsdg,
4087  lambdaVaStartType,
4088  lambdaVaStartType,
4089  "llvm.va_start",
4091  true);
4092  auto llvmVaEnd = &LlvmGraphImport::Create(
4093  rvsdg,
4094  lambdaVaEndType,
4095  lambdaVaEndType,
4096  "llvm.va_end",
4098  true);
4099 
4100  // Setup function fst()
4101  {
4102  LambdaFst_ = rvsdg::LambdaNode::Create(
4103  rvsdg.GetRootRegion(),
4105  auto iOStateArgument = LambdaFst_->GetFunctionArguments()[2];
4106  auto memoryStateArgument = LambdaFst_->GetFunctionArguments()[3];
4107  auto llvmLifetimeStartArgument = LambdaFst_->AddContextVar(*llvmLifetimeStart).inner;
4108  auto llvmLifetimeEndArgument = LambdaFst_->AddContextVar(*llvmLifetimeEnd).inner;
4109  auto llvmVaStartArgument = LambdaFst_->AddContextVar(*llvmVaStart).inner;
4110  auto llvmVaEndArgument = LambdaFst_->AddContextVar(*llvmVaEnd).inner;
4111 
4112  auto one = &rvsdg::BitConstantOperation::create(*LambdaFst_->subregion(), { 32, 1 });
4113  auto twentyFour = &rvsdg::BitConstantOperation::create(*LambdaFst_->subregion(), { 64, 24 });
4114  auto fortyOne = &rvsdg::BitConstantOperation::create(*LambdaFst_->subregion(), { 32, 41 });
4115 
4116  auto allocaResults = AllocaOperation::create(arrayType, one, 16);
4117  auto memoryState = MemoryStateMergeOperation::Create(
4118  std::vector<jlm::rvsdg::Output *>{ allocaResults[1], memoryStateArgument });
4119  AllocaNode_ = rvsdg::TryGetOwnerNode<rvsdg::Node>(*allocaResults[0]);
4120 
4121  auto & callLLvmLifetimeStart = CallOperation::CreateNode(
4122  llvmLifetimeStartArgument,
4123  lambdaLlvmLifetimeStartType,
4124  { twentyFour, allocaResults[0], iOStateArgument, memoryState });
4125  auto & callVaStart = CallOperation::CreateNode(
4126  llvmVaStartArgument,
4127  lambdaVaStartType,
4128  { allocaResults[0],
4129  &CallOperation::GetIOStateOutput(callLLvmLifetimeStart),
4130  &CallOperation::GetMemoryStateOutput(callLLvmLifetimeStart) });
4131 
4132  auto loadResults = LoadNonVolatileOperation::Create(
4133  allocaResults[0],
4134  { &CallOperation::GetMemoryStateOutput(callVaStart) },
4136  16);
4137  auto icmpResult = rvsdg::bitult_op::create(32, loadResults[0], fortyOne);
4138  auto matchResult = rvsdg::MatchOperation::Create(*icmpResult, { { 1, 1 } }, 0, 2);
4139 
4140  auto gammaNode = rvsdg::GammaNode::create(matchResult, 2);
4141  auto gammaVaAddress = gammaNode->AddEntryVar(allocaResults[0]);
4142  auto gammaLoadResult = gammaNode->AddEntryVar(loadResults[0]);
4143  auto gammaMemoryState = gammaNode->AddEntryVar(loadResults[1]);
4144 
4145  // gamma subregion 0
4146  auto zero = &rvsdg::BitConstantOperation::create(*gammaNode->subregion(0), { 64, 0 });
4147  auto two = &rvsdg::BitConstantOperation::create(*gammaNode->subregion(0), { 32, 2 });
4148  auto eight = &rvsdg::BitConstantOperation::create(*gammaNode->subregion(0), { 64, 8 });
4149  auto gepResult1 = GetElementPtrOperation::Create(
4150  gammaVaAddress.branchArgument[0],
4151  { zero, two },
4152  structType,
4153  pointerType);
4154  auto loadResultsGamma0 = LoadNonVolatileOperation::Create(
4155  gepResult1,
4156  { gammaMemoryState.branchArgument[0] },
4157  pointerType,
4158  8);
4159  auto gepResult2 = GetElementPtrOperation::Create(
4160  loadResultsGamma0[0],
4161  { eight },
4163  pointerType);
4164  auto storeResultsGamma0 =
4165  StoreNonVolatileOperation::Create(gepResult1, gepResult2, { loadResultsGamma0[1] }, 8);
4166 
4167  // gamma subregion 1
4168  zero = &rvsdg::BitConstantOperation::create(*gammaNode->subregion(1), { 64, 0 });
4169  auto eightBit32 = &rvsdg::BitConstantOperation::create(*gammaNode->subregion(1), { 32, 8 });
4170  auto three = &rvsdg::BitConstantOperation::create(*gammaNode->subregion(1), { 32, 3 });
4171  gepResult1 = GetElementPtrOperation::Create(
4172  gammaVaAddress.branchArgument[1],
4173  { zero, three },
4174  structType,
4175  pointerType);
4176  auto loadResultsGamma1 = LoadNonVolatileOperation::Create(
4177  gepResult1,
4178  { gammaMemoryState.branchArgument[1] },
4179  pointerType,
4180  16);
4181  auto & zextResult =
4182  ZExtOperation::Create(*gammaLoadResult.branchArgument[1], rvsdg::BitType::Create(64));
4183  gepResult2 = GetElementPtrOperation::Create(
4184  loadResultsGamma1[0],
4185  { &zextResult },
4187  pointerType);
4188  auto addResult = rvsdg::bitadd_op::create(32, gammaLoadResult.branchArgument[1], eightBit32);
4189  auto storeResultsGamma1 = StoreNonVolatileOperation::Create(
4190  gammaVaAddress.branchArgument[1],
4191  addResult,
4192  { loadResultsGamma1[1] },
4193  16);
4194 
4195  auto gammaAddress = gammaNode->AddExitVar({ loadResultsGamma0[0], gepResult2 });
4196  auto gammaOutputMemoryState =
4197  gammaNode->AddExitVar({ storeResultsGamma0[0], storeResultsGamma1[0] });
4198 
4199  loadResults = LoadNonVolatileOperation::Create(
4200  gammaAddress.output,
4201  { gammaOutputMemoryState.output },
4203  4);
4204  auto & callVaEnd = CallOperation::CreateNode(
4205  llvmVaEndArgument,
4206  lambdaVaEndType,
4207  { allocaResults[0], &CallOperation::GetIOStateOutput(callVaStart), loadResults[1] });
4208  auto & callLLvmLifetimeEnd = CallOperation::CreateNode(
4209  llvmLifetimeEndArgument,
4210  lambdaLlvmLifetimeEndType,
4211  { twentyFour,
4212  allocaResults[0],
4213  &CallOperation::GetIOStateOutput(callVaEnd),
4214  &CallOperation::GetMemoryStateOutput(callVaEnd) });
4215 
4216  LambdaFst_->finalize({ loadResults[0],
4217  &CallOperation::GetIOStateOutput(callLLvmLifetimeEnd),
4218  &CallOperation::GetMemoryStateOutput(callLLvmLifetimeEnd) });
4219  }
4220 
4221  // Setup function g()
4222  {
4223  LambdaG_ = rvsdg::LambdaNode::Create(
4224  rvsdg.GetRootRegion(),
4226  auto iOStateArgument = LambdaG_->GetFunctionArguments()[0];
4227  auto memoryStateArgument = LambdaG_->GetFunctionArguments()[1];
4228  auto lambdaFstArgument = LambdaG_->AddContextVar(*LambdaFst_->output()).inner;
4229 
4230  auto zero = &rvsdg::BitConstantOperation::create(*LambdaG_->subregion(), { 32, 0 });
4231  auto one = &rvsdg::BitConstantOperation::create(*LambdaG_->subregion(), { 32, 1 });
4232  auto two = &rvsdg::BitConstantOperation::create(*LambdaG_->subregion(), { 32, 2 });
4233  auto three = &rvsdg::BitConstantOperation::create(*LambdaG_->subregion(), { 32, 3 });
4234 
4235  auto vaListResult =
4236  VariadicArgumentListOperation::Create(*LambdaG_->subregion(), { zero, one, two });
4237 
4238  auto & callFst = CallOperation::CreateNode(
4239  lambdaFstArgument,
4240  lambdaFstType,
4241  { three, vaListResult, iOStateArgument, memoryStateArgument });
4242 
4243  LambdaG_->finalize(outputs(&callFst));
4244  }
4245 
4246  return rvsdgModule;
4247 }
4248 
4249 }
std::unique_ptr< jlm::llvm::LlvmRvsdgModule > SetupRvsdg() override
Create RVSDG for this test.
static std::unique_ptr< llvm::ThreeAddressCode > create(std::shared_ptr< const rvsdg::Type > allocatedType, const Variable *size, size_t alignment)
Definition: alloca.hpp:90
static std::shared_ptr< const ArrayType > Create(std::shared_ptr< const Type > type, size_t nelements)
Definition: types.hpp:98
static std::unique_ptr< llvm::ThreeAddressCode > create(const Variable *operand, std::shared_ptr< const jlm::rvsdg::Type > type)
Definition: operators.hpp:1502
std::unique_ptr< jlm::llvm::LlvmRvsdgModule > SetupRvsdg() override
Create RVSDG for this test.
Definition: TestRvsdgs.cpp:335
std::unique_ptr< jlm::llvm::LlvmRvsdgModule > SetupRvsdg() override
Create RVSDG for this test.
Definition: TestRvsdgs.cpp:364
static rvsdg::SimpleNode & CreateNode(rvsdg::Region &region, std::unique_ptr< CallOperation > callOperation, const std::vector< rvsdg::Output * > &operands)
Definition: call.hpp:458
static rvsdg::Output & GetIOStateOutput(const rvsdg::Node &node) noexcept
Definition: call.hpp:326
static rvsdg::Output & GetMemoryStateOutput(const rvsdg::Node &node) noexcept
Definition: call.hpp:350
std::unique_ptr< jlm::llvm::LlvmRvsdgModule > SetupRvsdg() override
Create RVSDG for this test.
Definition: TestRvsdgs.cpp:479
std::unique_ptr< jlm::llvm::LlvmRvsdgModule > SetupRvsdg() override
Create RVSDG for this test.
Definition: TestRvsdgs.cpp:647
static jlm::rvsdg::Output * Create(rvsdg::Region &region, std::shared_ptr< const jlm::rvsdg::Type > type)
Definition: operators.hpp:1900
static rvsdg::Output * Create(const std::vector< rvsdg::Output * > &operands)
Definition: operators.hpp:1852
static jlm::rvsdg::Output * Create(const std::vector< jlm::rvsdg::Output * > &elements)
Definition: operators.hpp:668
static std::unique_ptr< llvm::ThreeAddressCode > Create(std::shared_ptr< const rvsdg::Type > type)
Definition: operators.hpp:454
std::unique_ptr< jlm::llvm::LlvmRvsdgModule > SetupRvsdg() override
Create RVSDG for this test.
Definition: TestRvsdgs.cpp:439
static rvsdg::Output & Create(rvsdg::Region &, const std::vector< rvsdg::Output * > &operands, std::shared_ptr< const rvsdg::Type > resultType)
Definition: operators.hpp:1569
static std::unique_ptr< DeltaOperation > Create(std::shared_ptr< const rvsdg::Type > type, const std::string &name, const llvm::Linkage &linkage, std::string section, bool constant)
Definition: delta.hpp:76
std::unique_ptr< jlm::llvm::LlvmRvsdgModule > SetupRvsdg() override
Create RVSDG for this test.
std::unique_ptr< jlm::llvm::LlvmRvsdgModule > SetupRvsdg() override
Create RVSDG for this test.
std::unique_ptr< jlm::llvm::LlvmRvsdgModule > SetupRvsdg() override
Create RVSDG for this test.
std::unique_ptr< jlm::llvm::LlvmRvsdgModule > SetupRvsdg() override
Create RVSDG for this test.
std::unique_ptr< jlm::llvm::LlvmRvsdgModule > SetupRvsdg() override
Create RVSDG for this test.
std::unique_ptr< jlm::llvm::LlvmRvsdgModule > SetupRvsdg() override
Create RVSDG for this test.
std::unique_ptr< jlm::llvm::LlvmRvsdgModule > SetupRvsdg() override
Create RVSDG for this test.
std::unique_ptr< jlm::llvm::LlvmRvsdgModule > SetupRvsdg() override
Create RVSDG for this test.
std::unique_ptr< jlm::llvm::LlvmRvsdgModule > SetupRvsdg() override
Create RVSDG for this test.
std::unique_ptr< jlm::llvm::LlvmRvsdgModule > SetupRvsdg() override
Create RVSDG for this test.
std::unique_ptr< llvm::LlvmRvsdgModule > SetupRvsdg() override
Create RVSDG for this test.
static std::unique_ptr< llvm::ThreeAddressCode > Create(const Variable *pointer, const std::vector< const Variable * > &memoryStates, const Variable *iOState)
Definition: operators.hpp:2554
std::unique_ptr< llvm::LlvmRvsdgModule > SetupRvsdg() override
Create RVSDG for this test.
std::unique_ptr< jlm::llvm::LlvmRvsdgModule > SetupRvsdg() override
Create RVSDG for this test.
static std::unique_ptr< llvm::ThreeAddressCode > Create(const Variable *baseAddress, const std::vector< const Variable * > &offsets, std::shared_ptr< const rvsdg::Type > pointeeType, std::shared_ptr< const rvsdg::Type > resultType)
std::unique_ptr< jlm::llvm::LlvmRvsdgModule > SetupRvsdg() override
Create RVSDG for this test.
Definition: TestRvsdgs.cpp:275
static std::shared_ptr< const IOStateType > Create()
Definition: types.cpp:343
std::unique_ptr< jlm::llvm::LlvmRvsdgModule > SetupRvsdg() override
Create RVSDG for this test.
std::unique_ptr< jlm::llvm::LlvmRvsdgModule > SetupRvsdg() override
Create RVSDG for this test.
Definition: TestRvsdgs.cpp:785
std::unique_ptr< jlm::llvm::LlvmRvsdgModule > SetupRvsdg() override
Create RVSDG for this test.
Definition: TestRvsdgs.cpp:903
static std::unique_ptr< llvm::ThreeAddressCode > create(const Variable *argument, std::shared_ptr< const jlm::rvsdg::Type > type)
Definition: operators.hpp:526
std::unique_ptr< llvm::LlvmRvsdgModule > SetupRvsdg() override
Create RVSDG for this test.
std::unique_ptr< jlm::llvm::LlvmRvsdgModule > SetupRvsdg() override
Create RVSDG for this test.
static LlvmGraphImport & Create(rvsdg::Graph &graph, std::shared_ptr< const rvsdg::Type > valueType, std::shared_ptr< const rvsdg::Type > importedType, std::string name, Linkage linkage, bool isConstant=false)
Definition: RvsdgModule.hpp:81
static std::unique_ptr< LlvmLambdaOperation > Create(std::shared_ptr< const jlm::rvsdg::FunctionType > type, std::string name, const jlm::llvm::Linkage &linkage, jlm::llvm::AttributeSet attributes)
Definition: lambda.hpp:77
static std::unique_ptr< LlvmRvsdgModule > Create(const util::FilePath &sourceFileName, const std::string &targetTriple, const std::string &dataLayout)
std::unique_ptr< jlm::llvm::LlvmRvsdgModule > SetupRvsdg() override
Create RVSDG for this test.
Definition: TestRvsdgs.cpp:238
static std::unique_ptr< llvm::ThreeAddressCode > Create(const Variable *address, const Variable *state, std::shared_ptr< const rvsdg::Type > loadedType, size_t alignment)
Definition: Load.hpp:429
std::unique_ptr< jlm::llvm::LlvmRvsdgModule > SetupRvsdg() override
Create RVSDG for this test.
Definition: TestRvsdgs.cpp:130
std::unique_ptr< jlm::llvm::LlvmRvsdgModule > SetupRvsdg() override
Create RVSDG for this test.
Definition: TestRvsdgs.cpp:171
static rvsdg::Output & ioStateOutput(const rvsdg::Node &node)
Definition: operators.hpp:2463
static rvsdg::SimpleNode & createNode(rvsdg::Output &size, rvsdg::Output &ioState)
Definition: operators.hpp:2489
static rvsdg::Output & addressOutput(const rvsdg::Node &node)
Definition: operators.hpp:2454
static rvsdg::Output & memoryStateOutput(const rvsdg::Node &node)
Definition: operators.hpp:2472
static std::unique_ptr< llvm::ThreeAddressCode > create(const Variable *destination, const Variable *source, const Variable *length, const std::vector< const Variable * > &memoryStates)
Definition: MemCpy.hpp:173
std::unique_ptr< jlm::llvm::LlvmRvsdgModule > SetupRvsdg() override
Create RVSDG for this test.
std::unique_ptr< jlm::llvm::LlvmRvsdgModule > SetupRvsdg() override
Create RVSDG for this test.
std::unique_ptr< jlm::llvm::LlvmRvsdgModule > SetupRvsdg() override
Create RVSDG for this test.
static rvsdg::Output * Create(const std::vector< rvsdg::Output * > &operands)
static std::shared_ptr< const MemoryStateType > Create()
Definition: types.cpp:379
std::unique_ptr< jlm::llvm::LlvmRvsdgModule > SetupRvsdg() override
Create RVSDG for this test.
std::unique_ptr< jlm::llvm::LlvmRvsdgModule > SetupRvsdg() override
Create RVSDG for this test.
std::unique_ptr< jlm::llvm::LlvmRvsdgModule > SetupRvsdg() override
Create RVSDG for this test.
std::unique_ptr< jlm::llvm::LlvmRvsdgModule > SetupRvsdg() override
Create RVSDG for this test.
PointerType class.
Definition: types.hpp:25
static std::shared_ptr< const PointerType > Create()
Definition: types.cpp:45
const rvsdg::Graph & graph()
Definition: TestRvsdgs.hpp:41
jlm::llvm::LlvmRvsdgModule & module()
Definition: TestRvsdgs.hpp:34
static std::unique_ptr< llvm::ThreeAddressCode > Create(const Variable *address, const Variable *value, const Variable *state, size_t alignment)
Definition: Store.hpp:281
rvsdg::SimpleNode * alloca_c
Definition: TestRvsdgs.hpp:101
rvsdg::SimpleNode * alloca_a
Definition: TestRvsdgs.hpp:99
rvsdg::SimpleNode * alloca_d
Definition: TestRvsdgs.hpp:102
std::unique_ptr< jlm::llvm::LlvmRvsdgModule > SetupRvsdg() override
Create RVSDG for this test.
Definition: TestRvsdgs.cpp:15
rvsdg::SimpleNode * size
Definition: TestRvsdgs.hpp:97
jlm::rvsdg::LambdaNode * lambda
Definition: TestRvsdgs.hpp:95
rvsdg::SimpleNode * alloca_b
Definition: TestRvsdgs.hpp:100
std::unique_ptr< jlm::llvm::LlvmRvsdgModule > SetupRvsdg() override
Create RVSDG for this test.
Definition: TestRvsdgs.cpp:70
static std::shared_ptr< const StructType > CreateIdentified(const std::string &name, std::vector< std::shared_ptr< const Type >> types, bool isPacked)
Definition: types.hpp:296
std::unique_ptr< jlm::llvm::LlvmRvsdgModule > SetupRvsdg() override
Create RVSDG for this test.
static std::unique_ptr< llvm::ThreeAddressCode > create(const Variable *operand, const std::shared_ptr< const jlm::rvsdg::Type > &type)
Definition: operators.hpp:1661
static jlm::rvsdg::Output * Create(rvsdg::Region &region, std::shared_ptr< const jlm::rvsdg::Type > type)
Definition: operators.hpp:1024
static std::shared_ptr< const VariableArgumentType > Create()
Definition: types.cpp:180
static rvsdg::Output * Create(rvsdg::Region &region, const std::vector< rvsdg::Output * > &operands)
Definition: operators.hpp:1447
std::unique_ptr< llvm::LlvmRvsdgModule > SetupRvsdg() override
Create RVSDG for this test.
std::unique_ptr< jlm::llvm::LlvmRvsdgModule > SetupRvsdg() override
Create RVSDG for this test.
static rvsdg::Output & Create(rvsdg::Output &operand, const std::shared_ptr< const rvsdg::Type > &resultType)
Definition: operators.hpp:822
static Output & create(Region &region, BitValueRepresentation value)
Definition: constant.hpp:44
static std::shared_ptr< const BitType > Create(std::size_t nbits)
Creates bit type of specified width.
Definition: type.cpp:45
static DeltaNode * Create(rvsdg::Region *parent, std::unique_ptr< DeltaOperation > op)
Definition: delta.hpp:313
static std::shared_ptr< const FunctionType > Create(std::vector< std::shared_ptr< const jlm::rvsdg::Type >> argumentTypes, std::vector< std::shared_ptr< const jlm::rvsdg::Type >> resultTypes)
static GammaNode * create(jlm::rvsdg::Output *predicate, size_t nalternatives)
Definition: gamma.hpp:161
Region & GetRootRegion() const noexcept
Definition: graph.hpp:99
Lambda node.
Definition: lambda.hpp:83
rvsdg::Output * finalize(const std::vector< jlm::rvsdg::Output * > &results)
Definition: lambda.cpp:146
std::vector< rvsdg::Output * > GetFunctionArguments() const
Definition: lambda.cpp:57
rvsdg::Region * subregion() const noexcept
Definition: lambda.hpp:138
ContextVar AddContextVar(jlm::rvsdg::Output &origin)
Adds a context/free variable to the lambda node.
Definition: lambda.cpp:131
static LambdaNode * Create(rvsdg::Region &parent, std::unique_ptr< LambdaOperation > operation)
Definition: lambda.cpp:140
rvsdg::Output * output() const noexcept
Definition: lambda.cpp:176
LambdaOperation & GetOperation() const noexcept override
Definition: lambda.cpp:51
const std::shared_ptr< const FunctionType > & Type() const noexcept
Definition: lambda.hpp:42
std::unique_ptr< BitBinaryOperation > create(size_t nbits) const override
std::unique_ptr< BitCompareOperation > create(size_t nbits) const override
static Output * Create(Output &predicate, const std::unordered_map< uint64_t, uint64_t > &mapping, const uint64_t defaultAlternative, const size_t numAlternatives)
Definition: control.hpp:242
rvsdg::Region * subregion() const noexcept
Definition: Phi.hpp:349
PhiNode * end()
Definition: Phi.cpp:270
PhiNode::ContextVar AddContextVar(jlm::rvsdg::Output &origin)
Definition: Phi.cpp:251
PhiNode::FixVar AddFixVar(std::shared_ptr< const jlm::rvsdg::Type > type)
Definition: Phi.cpp:257
void begin(rvsdg::Region *parent)
Definition: Phi.hpp:355
A phi node represents the fixpoint of mutually recursive definitions.
Definition: Phi.hpp:46
Represents the argument of a region.
Definition: region.hpp:41
Represent acyclic RVSDG subgraphs.
Definition: region.hpp:213
Graph & Rvsdg() noexcept
Definition: RvsdgModule.hpp:57
static ThetaNode * create(rvsdg::Region *parent)
Definition: theta.hpp:73
Global memory state passed between functions.
jlm::rvsdg::Output * match(size_t nbits, const std::unordered_map< uint64_t, uint64_t > &mapping, uint64_t default_alternative, size_t nalternatives, jlm::rvsdg::Output *operand)
Definition: control.cpp:179
static std::vector< jlm::rvsdg::Output * > outputs(const Node *node)
Definition: node.hpp:1058
rvsdg::Output * inner
Access to bound object in subregion.
Definition: lambda.hpp:117