Jlm
MemoryConverterTests.cpp
Go to the documentation of this file.
1 /*
2  * Copyright 2024 Magnus Sjalander <work@sjalander.com>
3  * See COPYING for terms of redistribution.
4  */
5 
6 #include <gtest/gtest.h>
7 
12 #include <jlm/hls/ir/hls.hpp>
17 #include <jlm/rvsdg/theta.hpp>
18 #include <jlm/rvsdg/view.hpp>
19 #include <jlm/util/Statistics.hpp>
20 
21 TEST(MemoryConverterTests, TestTraceArgument)
22 {
23  using namespace jlm::llvm;
24  using namespace jlm::hls;
25 
26  auto rvsdgModule = LlvmRvsdgModule::Create(jlm::util::FilePath(""), "", "");
27 
28  // Setup the function
29  std::cout << "Function Setup" << std::endl;
30  auto functionType = jlm::rvsdg::FunctionType::Create(
36 
37  auto lambda = jlm::rvsdg::LambdaNode::Create(
38  rvsdgModule->Rvsdg().GetRootRegion(),
40 
41  // Load followed by store
42  auto loadAddress = lambda->GetFunctionArguments()[0];
43  auto memoryStateArgument = lambda->GetFunctionArguments()[3];
44  auto loadOutput = LoadNonVolatileOperation::Create(
45  loadAddress,
46  { memoryStateArgument },
48  32);
49 
50  auto storeAddress = lambda->GetFunctionArguments()[1];
51  auto storeData = lambda->GetFunctionArguments()[2];
52  auto storeOutput =
53  StoreNonVolatileOperation::Create(storeAddress, storeData, { loadOutput[1] }, 32);
54 
55  auto lambdaOutput = lambda->finalize({ storeOutput[0] });
56  jlm::rvsdg::GraphExport::Create(*lambdaOutput, "f");
57 
58  // Act
59  jlm::rvsdg::view(rvsdgModule->Rvsdg(), stdout);
60  const auto tracedPointerNodesVector = TracePointerArguments(lambda);
61  jlm::rvsdg::view(rvsdgModule->Rvsdg(), stdout);
62 
63  // Assert
64  EXPECT_EQ(tracedPointerNodesVector.size(), 2); // 2 pointer arguments
65  EXPECT_EQ(tracedPointerNodesVector[0].loadNodes.size(), 1); // 1 load for the first pointer
66  EXPECT_EQ(tracedPointerNodesVector[0].storeNodes.size(), 0); // 0 store for the first pointer
67  EXPECT_EQ(
68  tracedPointerNodesVector[0].decoupleNodes.size(),
69  0); // 0 decouple for the first pointer
70  EXPECT_EQ(tracedPointerNodesVector[1].loadNodes.size(), 0); // 0 load for the first pointer
71  EXPECT_EQ(tracedPointerNodesVector[1].storeNodes.size(), 1); // 1 store for the second pointer
72  EXPECT_EQ(tracedPointerNodesVector[1].decoupleNodes.size(), 0); // 0 load for the first pointer
73 }
74 
75 TEST(MemoryConverterTests, TestLoad)
76 {
77  using namespace jlm::llvm;
78  using namespace jlm::hls;
79 
80  auto rvsdgModule = LlvmRvsdgModule::Create(jlm::util::FilePath(""), "", "");
81 
82  // Setup the function
83  std::cout << "Function Setup" << std::endl;
84  auto functionType = jlm::rvsdg::FunctionType::Create(
87 
88  auto lambda = jlm::rvsdg::LambdaNode::Create(
89  rvsdgModule->Rvsdg().GetRootRegion(),
91 
92  // Single load
93  auto loadAddress = lambda->GetFunctionArguments()[0];
94  auto memoryStateArgument = lambda->GetFunctionArguments()[1];
95  auto loadOutput = LoadNonVolatileOperation::Create(
96  loadAddress,
97  { memoryStateArgument },
99  32);
100 
101  auto lambdaOutput = lambda->finalize({ loadOutput[0], loadOutput[1] });
102  jlm::rvsdg::GraphExport::Create(*lambdaOutput, "f");
103 
104  jlm::rvsdg::view(rvsdgModule->Rvsdg(), stdout);
105 
106  // Act
108  MemoryConverter::CreateAndRun(*rvsdgModule, statisticsCollector);
109 
110  jlm::rvsdg::view(rvsdgModule->Rvsdg(), stdout);
111 
112  // Memory Converter replaces the lambda so we start from the root of the graph
113  auto region = &rvsdgModule->Rvsdg().GetRootRegion();
114  EXPECT_EQ(region->numNodes(), 1);
115  lambda = jlm::util::assertedCast<jlm::rvsdg::LambdaNode>(region->Nodes().begin().ptr());
116 
117  // Assert
118  auto lambdaRegion = lambda->subregion();
119  EXPECT_EQ(lambdaRegion->numNodes(), 3);
120  EXPECT_EQ(lambdaRegion->narguments(), 3);
121  EXPECT_EQ(lambdaRegion->nresults(), 3);
122 
123  // Memory state
124  EXPECT_TRUE(is<MemoryStateType>(lambdaRegion->result(1)->origin()->Type()));
125 
126  // Load Address
127  auto loadNode =
128  jlm::util::assertedCast<jlm::rvsdg::NodeOutput>(lambdaRegion->result(0)->origin())->node();
129  EXPECT_TRUE(is<jlm::hls::LoadOperation>(loadNode));
130 
131  // Load Data
132  loadNode =
133  jlm::util::assertedCast<jlm::rvsdg::NodeOutput>(lambdaRegion->result(1)->origin())->node();
134  EXPECT_TRUE(is<jlm::hls::LoadOperation>(loadNode));
135 
136  // Request Node
137  auto requestNode =
138  jlm::util::assertedCast<jlm::rvsdg::NodeOutput>(lambdaRegion->result(2)->origin())->node();
139  EXPECT_TRUE(is<MemoryRequestOperation>(requestNode));
140 
141  // Response Node
142  auto responseNode =
143  jlm::util::assertedCast<jlm::rvsdg::NodeOutput>(loadNode->input(2)->origin())->node();
144  EXPECT_TRUE(is<MemoryResponseOperation>(responseNode));
145 
146  // Response source
147  auto responseSource = responseNode->input(0)->origin();
148  auto regionArgument = jlm::util::assertedCast<jlm::rvsdg::RegionArgument>(responseSource);
149  EXPECT_EQ(regionArgument->index(), 2);
150 }
151 
152 TEST(MemoryConverterTests, TestStore)
153 {
154  using namespace jlm::llvm;
155  using namespace jlm::hls;
156 
157  auto rvsdgModule = LlvmRvsdgModule::Create(jlm::util::FilePath(""), "", "");
158 
159  // Setup the function
160  std::cout << "Function Setup" << std::endl;
161  auto functionType = jlm::rvsdg::FunctionType::Create(
166 
167  auto lambda = jlm::rvsdg::LambdaNode::Create(
168  rvsdgModule->Rvsdg().GetRootRegion(),
170 
171  // Single load
172  auto storeAddress = lambda->GetFunctionArguments()[0];
173  auto storeData = lambda->GetFunctionArguments()[1];
174  auto memoryStateArgument = lambda->GetFunctionArguments()[2];
175  auto storeOutput =
176  StoreNonVolatileOperation::Create(storeAddress, storeData, { memoryStateArgument }, 32);
177 
178  auto lambdaOutput = lambda->finalize({ storeOutput[0] });
179  jlm::rvsdg::GraphExport::Create(*lambdaOutput, "f");
180 
181  jlm::rvsdg::view(rvsdgModule->Rvsdg(), stdout);
182 
183  // Act
185  MemoryConverter::CreateAndRun(*rvsdgModule, statisticsCollector);
186 
187  jlm::rvsdg::view(rvsdgModule->Rvsdg(), stdout);
188 
189  // Memory Converter replaces the lambda so we start from the root of the graph
190  auto region = &rvsdgModule->Rvsdg().GetRootRegion();
191  EXPECT_EQ(region->numNodes(), 1);
192  lambda = jlm::util::assertedCast<jlm::rvsdg::LambdaNode>(region->Nodes().begin().ptr());
193 
194  // Assert
195  auto lambdaRegion = lambda->subregion();
196  EXPECT_EQ(lambdaRegion->numNodes(), 4);
197  EXPECT_EQ(lambdaRegion->narguments(), 4);
198  EXPECT_EQ(lambdaRegion->nresults(), 2);
199 
200  EXPECT_TRUE(is<MemoryStateType>(lambdaRegion->result(0)->origin()->Type()));
201  auto bufferNode =
202  jlm::util::assertedCast<jlm::rvsdg::NodeOutput>(lambdaRegion->result(0)->origin())->node();
203  auto storeNode =
204  jlm::util::assertedCast<jlm::rvsdg::NodeOutput>(bufferNode->input(0)->origin())->node();
205  EXPECT_TRUE(is<jlm::hls::StoreOperation>(storeNode));
206  auto requestNode =
207  jlm::util::assertedCast<jlm::rvsdg::NodeOutput>(lambdaRegion->result(1)->origin())->node();
208  EXPECT_TRUE(is<MemoryRequestOperation>(requestNode));
209 
210  // Request source
211  auto requestSource = requestNode->input(0)->origin();
212  storeNode = jlm::util::assertedCast<jlm::rvsdg::NodeOutput>(requestSource)->node();
213  EXPECT_TRUE(is<jlm::hls::StoreOperation>(storeNode));
214 }
215 
216 TEST(MemoryConverterTests, TestLoadStore)
217 {
218  using namespace jlm::llvm;
219  using namespace jlm::hls;
220 
221  auto rvsdgModule = LlvmRvsdgModule::Create(jlm::util::FilePath(""), "", "");
222 
223  // Setup the function
224  std::cout << "Function Setup" << std::endl;
225  auto functionType = jlm::rvsdg::FunctionType::Create(
230 
231  auto lambda = jlm::rvsdg::LambdaNode::Create(
232  rvsdgModule->Rvsdg().GetRootRegion(),
234 
235  // Load followed by store
236  auto loadAddress = lambda->GetFunctionArguments()[0];
237  auto storeData = lambda->GetFunctionArguments()[1];
238  auto memoryStateArgument = lambda->GetFunctionArguments()[2];
239  auto loadOutput = LoadNonVolatileOperation::Create(
240  loadAddress,
241  { memoryStateArgument },
243  32);
244  auto storeOutput =
245  StoreNonVolatileOperation::Create(loadOutput[0], storeData, { loadOutput[1] }, 32);
246 
247  auto lambdaOutput = lambda->finalize({ storeOutput[0] });
248  jlm::rvsdg::GraphExport::Create(*lambdaOutput, "f");
249 
250  jlm::rvsdg::view(rvsdgModule->Rvsdg(), stdout);
251 
252  // Act
254  MemoryConverter::CreateAndRun(*rvsdgModule, statisticsCollector);
255 
256  jlm::rvsdg::view(rvsdgModule->Rvsdg(), stdout);
257 
258  // Memory Converter replaces the lambda so we start from the root of the graph
259  auto region = &rvsdgModule->Rvsdg().GetRootRegion();
260  EXPECT_EQ(region->numNodes(), 1);
261  lambda = jlm::util::assertedCast<jlm::rvsdg::LambdaNode>(region->Nodes().begin().ptr());
262 
263  // Assert
264  auto lambdaRegion = lambda->subregion();
265  EXPECT_EQ(lambdaRegion->numNodes(), 7);
266  EXPECT_EQ(lambdaRegion->narguments(), 5);
267  EXPECT_EQ(lambdaRegion->nresults(), 3);
268 
269  std::cout << lambdaRegion->result(0)->origin()->Type()->debug_string() << std::endl;
270  EXPECT_TRUE(is<MemoryStateType>(lambdaRegion->result(0)->origin()->Type()));
271  auto bufferNode =
272  jlm::util::assertedCast<jlm::rvsdg::NodeOutput>(lambdaRegion->result(0)->origin())->node();
273  auto storeNode =
274  jlm::util::assertedCast<jlm::rvsdg::NodeOutput>(bufferNode->input(0)->origin())->node();
275  EXPECT_TRUE(is<jlm::hls::StoreOperation>(storeNode));
276  auto firstRequestNode =
277  jlm::util::assertedCast<jlm::rvsdg::NodeOutput>(lambdaRegion->result(1)->origin())->node();
278  EXPECT_TRUE(is<MemoryRequestOperation>(firstRequestNode));
279  auto secondRequestNode =
280  jlm::util::assertedCast<jlm::rvsdg::NodeOutput>(lambdaRegion->result(2)->origin())->node();
281  EXPECT_TRUE(is<MemoryRequestOperation>(secondRequestNode));
282  auto loadNode =
283  jlm::util::assertedCast<jlm::rvsdg::NodeOutput>(storeNode->input(0)->origin())->node();
284  EXPECT_TRUE(is<jlm::hls::LoadOperation>(loadNode));
285  auto responseNode =
286  jlm::util::assertedCast<jlm::rvsdg::NodeOutput>(loadNode->input(2)->origin())->node();
287  EXPECT_TRUE(is<MemoryResponseOperation>(responseNode));
288 }
289 
290 TEST(MemoryConverterTests, TestThetaLoad)
291 {
292  using namespace jlm::llvm;
293  using namespace jlm::hls;
294 
295  auto rvsdgModule = LlvmRvsdgModule::Create(jlm::util::FilePath(""), "", "");
296 
297  // Setup the function
298  std::cout << "Function Setup" << std::endl;
299  auto functionType = jlm::rvsdg::FunctionType::Create(
306 
307  auto lambda = jlm::rvsdg::LambdaNode::Create(
308  rvsdgModule->Rvsdg().GetRootRegion(),
310 
311  // Theta
312  auto theta = jlm::rvsdg::ThetaNode::create(lambda->subregion());
313  // Predicate
314  auto idv = theta->AddLoopVar(lambda->GetFunctionArguments()[0]);
315  auto lvs = theta->AddLoopVar(lambda->GetFunctionArguments()[1]);
316  auto lve = theta->AddLoopVar(lambda->GetFunctionArguments()[2]);
317  auto arm = jlm::rvsdg::CreateOpNode<jlm::rvsdg::bitadd_op>({ idv.pre, lvs.pre }, 32).output(0);
318  auto cmp = jlm::rvsdg::CreateOpNode<jlm::rvsdg::bitult_op>({ arm, lve.pre }, 32).output(0);
319  auto & matchNode = jlm::rvsdg::MatchOperation::CreateNode(*cmp, { { 1, 1 } }, 0, 2);
320  idv.post->divert_to(arm);
321  theta->set_predicate(matchNode.output(0));
322 
323  // Load node
324  auto loadAddress = theta->AddLoopVar(lambda->GetFunctionArguments()[3]);
325  auto memoryStateArgument = theta->AddLoopVar(lambda->GetFunctionArguments()[4]);
326  auto loadOutput = LoadNonVolatileOperation::Create(
327  loadAddress.pre,
328  { memoryStateArgument.pre },
330  32);
331  loadAddress.post->divert_to(loadOutput[0]);
332  memoryStateArgument.post->divert_to(loadOutput[1]);
333 
334  auto lambdaOutput = lambda->finalize({ theta->output(3), theta->output(4) });
335  jlm::rvsdg::GraphExport::Create(*lambdaOutput, "f");
336 
337  auto lambdaRegion = lambda->subregion();
338  jlm::rvsdg::view(rvsdgModule->Rvsdg(), stdout);
339 
340  // Act
342  MemoryStateSeparation::CreateAndRun(*rvsdgModule, statisticsCollector);
343 
344  // Assert
345  jlm::rvsdg::view(rvsdgModule->Rvsdg(), stdout);
346  auto & entryMemoryStateSplitInput = lambdaRegion->argument(4)->SingleUser();
347  auto * entryMemoryStateSplitNode =
348  jlm::rvsdg::TryGetOwnerNode<jlm::rvsdg::SimpleNode>(entryMemoryStateSplitInput);
349  EXPECT_TRUE(is<LambdaEntryMemoryStateSplitOperation>(entryMemoryStateSplitNode));
350  auto exitMemoryStateMergeNode =
351  jlm::util::assertedCast<jlm::rvsdg::NodeOutput>(lambdaRegion->result(1)->origin())->node();
352  EXPECT_TRUE(is<LambdaExitMemoryStateMergeOperation>(exitMemoryStateMergeNode));
353 
354  // Act
355  ThetaNodeConversion::CreateAndRun(*rvsdgModule, statisticsCollector);
356  // Simple assert as ConvertThetaNodes() is tested in separate unit tests
357  jlm::rvsdg::view(rvsdgModule->Rvsdg(), stdout);
358  EXPECT_TRUE(jlm::rvsdg::Region::ContainsNodeType<LoopNode>(*lambdaRegion, true));
359 
360  // Act
361  AddressQueueInsertion::CreateAndRun(*rvsdgModule, statisticsCollector);
362 
363  // Simple assert as mem_queue() is tested in separate unit tests
364  jlm::rvsdg::view(rvsdgModule->Rvsdg(), stdout);
365  EXPECT_TRUE(jlm::rvsdg::Region::ContainsOperation<StateGateOperation>(*lambdaRegion, true));
366  EXPECT_TRUE(
367  jlm::rvsdg::Region::ContainsOperation<MemoryStateSplitOperation>(*lambdaRegion, true));
368  EXPECT_TRUE(
369  jlm::rvsdg::Region::ContainsOperation<MemoryStateMergeOperation>(*lambdaRegion, true));
370 
371  // Act
372  MemoryConverter::CreateAndRun(*rvsdgModule, statisticsCollector);
373 
374  // Assert
375  jlm::rvsdg::view(rvsdgModule->Rvsdg(), stdout);
376 
377  // Memory Converter replaces the lambda so we start from the root of the graph
378  auto region = &rvsdgModule->Rvsdg().GetRootRegion();
379  EXPECT_EQ(region->numNodes(), 1);
380  lambda = jlm::util::assertedCast<jlm::rvsdg::LambdaNode>(region->Nodes().begin().ptr());
381  lambdaRegion = lambda->subregion();
382 
383  EXPECT_TRUE(jlm::rvsdg::Region::ContainsOperation<MemoryResponseOperation>(*lambdaRegion, true));
384  EXPECT_TRUE(jlm::rvsdg::Region::ContainsOperation<MemoryRequestOperation>(*lambdaRegion, true));
385 
386  // Request Node
387  auto requestNode =
388  jlm::util::assertedCast<jlm::rvsdg::NodeOutput>(lambdaRegion->result(2)->origin())->node();
389  EXPECT_TRUE(is<MemoryRequestOperation>(requestNode));
390 
391  // HLS_LOOP Node
392  auto loopOutput =
393  jlm::util::assertedCast<const jlm::rvsdg::StructuralOutput>(requestNode->input(0)->origin());
394  auto loopNode = jlm::util::assertedCast<const jlm::rvsdg::StructuralNode>(loopOutput->node());
395  EXPECT_NE(dynamic_cast<const LoopNode *>(loopNode), nullptr);
396  // Loop Result
397  auto & thetaResult = loopOutput->results;
398  EXPECT_EQ(thetaResult.size(), 1);
399  // Load Node
400  auto loadNode =
401  jlm::util::assertedCast<const jlm::rvsdg::NodeOutput>(thetaResult.first()->origin())->node();
402  EXPECT_TRUE(is<DecoupledLoadOperation>(loadNode));
403  // Loop Argument
404  auto thetaArgument =
405  jlm::util::assertedCast<const jlm::rvsdg::RegionArgument>(loadNode->input(1)->origin());
406  auto thetaInput = thetaArgument->input();
407 
408  // Response Node
409  auto responseNode =
410  jlm::util::assertedCast<const jlm::rvsdg::NodeOutput>(thetaInput->origin())->node();
411  EXPECT_TRUE(is<MemoryResponseOperation>(responseNode));
412 
413  // Lambda argument
414  EXPECT_TRUE(is<jlm::rvsdg::RegionArgument>(responseNode->input(0)->origin()));
415 }
416 
417 TEST(MemoryConverterTests, TestThetaStore)
418 {
419  using namespace jlm::llvm;
420  using namespace jlm::hls;
421 
422  auto rvsdgModule = LlvmRvsdgModule::Create(jlm::util::FilePath(""), "", "");
423 
424  // Setup the function
425  std::cout << "Function Setup" << std::endl;
426  auto functionType = jlm::rvsdg::FunctionType::Create(
434 
435  auto lambda = jlm::rvsdg::LambdaNode::Create(
436  rvsdgModule->Rvsdg().GetRootRegion(),
438 
439  // Theta
440  auto theta = jlm::rvsdg::ThetaNode::create(lambda->subregion());
441  // Predicate
442  auto idv = theta->AddLoopVar(lambda->GetFunctionArguments()[0]);
443  auto lvs = theta->AddLoopVar(lambda->GetFunctionArguments()[1]);
444  auto lve = theta->AddLoopVar(lambda->GetFunctionArguments()[2]);
445  auto arm = jlm::rvsdg::CreateOpNode<jlm::rvsdg::bitadd_op>({ idv.pre, lvs.pre }, 32).output(0);
446  auto cmp = jlm::rvsdg::CreateOpNode<jlm::rvsdg::bitult_op>({ arm, lve.pre }, 32).output(0);
447  auto & matchNode = jlm::rvsdg::MatchOperation::CreateNode(*cmp, { { 1, 1 } }, 0, 2);
448  idv.post->divert_to(arm);
449  theta->set_predicate(matchNode.output(0));
450 
451  // Store node
452  auto storeAddress = theta->AddLoopVar(lambda->GetFunctionArguments()[3]);
453  auto storeData = theta->AddLoopVar(lambda->GetFunctionArguments()[4]);
454  auto memoryStateArgument = theta->AddLoopVar(lambda->GetFunctionArguments()[5]);
455  auto storeOutput = StoreNonVolatileOperation::Create(
456  storeAddress.pre,
457  storeData.pre,
458  { memoryStateArgument.pre },
459  32);
460  memoryStateArgument.post->divert_to(storeOutput[0]);
461 
462  auto lambdaOutput = lambda->finalize({ theta->output(5) });
463  jlm::rvsdg::GraphExport::Create(*lambdaOutput, "f");
464 
465  auto lambdaRegion = lambda->subregion();
466  jlm::rvsdg::view(rvsdgModule->Rvsdg(), stdout);
467 
468  // Act
470  MemoryStateSeparation::CreateAndRun(*rvsdgModule, statisticsCollector);
471 
472  // Assert
473  jlm::rvsdg::view(rvsdgModule->Rvsdg(), stdout);
474  auto & entryMemoryStateSplitInput = lambdaRegion->argument(5)->SingleUser();
475  auto * entryMemoryStateSplitNode =
476  jlm::rvsdg::TryGetOwnerNode<jlm::rvsdg::SimpleNode>(entryMemoryStateSplitInput);
477  EXPECT_TRUE(is<LambdaEntryMemoryStateSplitOperation>(entryMemoryStateSplitNode));
478  auto exitMemoryStateMergeNode =
479  jlm::util::assertedCast<jlm::rvsdg::NodeOutput>(lambdaRegion->result(0)->origin())->node();
480  EXPECT_TRUE(is<LambdaExitMemoryStateMergeOperation>(exitMemoryStateMergeNode));
481 
482  // Act
483  ThetaNodeConversion::CreateAndRun(*rvsdgModule, statisticsCollector);
484  // Simple assert as ConvertThetaNodes() is tested in separate unit tests
485  jlm::rvsdg::view(rvsdgModule->Rvsdg(), stdout);
486  EXPECT_TRUE(jlm::rvsdg::Region::ContainsNodeType<LoopNode>(*lambdaRegion, true));
487 
488  // Act
489  AddressQueueInsertion::CreateAndRun(*rvsdgModule, statisticsCollector);
490 
491  // Simple assert as mem_queue() is tested in separate unit tests
492  jlm::rvsdg::view(rvsdgModule->Rvsdg(), stdout);
493  EXPECT_TRUE(
494  jlm::rvsdg::Region::ContainsOperation<MemoryStateSplitOperation>(*lambdaRegion, true));
495  EXPECT_TRUE(
496  jlm::rvsdg::Region::ContainsOperation<MemoryStateMergeOperation>(*lambdaRegion, true));
497 
498  // Act
499  MemoryConverter::CreateAndRun(*rvsdgModule, statisticsCollector);
500 
501  // Assert
502  jlm::rvsdg::view(rvsdgModule->Rvsdg(), stdout);
503 
504  // Memory Converter replaces the lambda so we start from the root of the graph
505  auto region = &rvsdgModule->Rvsdg().GetRootRegion();
506  EXPECT_EQ(region->numNodes(), 1);
507  lambda = jlm::util::assertedCast<jlm::rvsdg::LambdaNode>(region->Nodes().begin().ptr());
508  lambdaRegion = lambda->subregion();
509 
510  EXPECT_TRUE(jlm::rvsdg::Region::ContainsOperation<MemoryRequestOperation>(*lambdaRegion, true));
511 
512  // Request Node
513  auto requestNode =
514  jlm::util::assertedCast<jlm::rvsdg::NodeOutput>(lambdaRegion->result(1)->origin())->node();
515  EXPECT_TRUE(is<MemoryRequestOperation>(requestNode));
516 
517  // HLS_LOOP Node
518  auto loopOutput =
519  jlm::util::assertedCast<const jlm::rvsdg::StructuralOutput>(requestNode->input(0)->origin());
520  auto loopNode = jlm::util::assertedCast<const jlm::rvsdg::StructuralNode>(loopOutput->node());
521  EXPECT_NE(dynamic_cast<const LoopNode *>(loopNode), nullptr);
522  // Loop Result
523  auto & thetaResult = loopOutput->results;
524  EXPECT_EQ(thetaResult.size(), 1);
525  // Load Node
526  auto storeNode =
527  jlm::util::assertedCast<const jlm::rvsdg::NodeOutput>(thetaResult.first()->origin())->node();
528  EXPECT_TRUE(is<jlm::hls::StoreOperation>(storeNode));
529  // NDMux Node
530  auto ndMuxNode =
531  jlm::util::assertedCast<const jlm::rvsdg::NodeOutput>(storeNode->input(2)->origin())->node();
532  EXPECT_TRUE(is<MuxOperation>(ndMuxNode));
533  // Loop Argument
534  EXPECT_TRUE(is<jlm::rvsdg::RegionArgument>(ndMuxNode->input(2)->origin()));
535 }
static jlm::util::StatisticsCollector statisticsCollector
TEST(MemoryConverterTests, TestTraceArgument)
static std::unique_ptr< LlvmLambdaOperation > Create(std::shared_ptr< const jlm::rvsdg::FunctionType > type, std::string name, const jlm::llvm::Linkage &linkage, jlm::llvm::CallingConvention callingConvention, jlm::llvm::AttributeSet attributes)
Definition: lambda.hpp:84
static std::unique_ptr< LlvmRvsdgModule > Create(const util::FilePath &sourceFileName, const std::string &targetTriple, const std::string &dataLayout)
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:444
static std::shared_ptr< const MemoryStateType > Create()
Definition: types.cpp:379
static std::shared_ptr< const PointerType > Create()
Definition: types.cpp:45
static std::unique_ptr< llvm::ThreeAddressCode > Create(const Variable *address, const Variable *value, const Variable *state, size_t alignment)
Definition: Store.hpp:304
static std::shared_ptr< const BitType > Create(std::size_t nbits)
Creates bit type of specified width.
Definition: type.cpp:45
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 GraphExport & Create(Output &origin, std::string name)
Definition: graph.cpp:62
static LambdaNode * Create(rvsdg::Region &parent, std::unique_ptr< LambdaOperation > operation)
Definition: lambda.cpp:140
static Node & CreateNode(Output &predicate, const std::unordered_map< uint64_t, uint64_t > &mapping, const uint64_t defaultAlternative, const size_t numAlternatives)
Definition: control.hpp:226
static ThetaNode * create(rvsdg::Region *parent)
Definition: theta.hpp:73
std::vector< TracedPointerNodes > TracePointerArguments(const rvsdg::LambdaNode *lambda)
Definition: mem-conv.cpp:339
Global memory state passed between functions.
std::string view(const rvsdg::Region *region)
Definition: view.cpp:142