6 #include <gtest/gtest.h>
28 TEST(LoadChainSeparationTests, LoadNonVolatile)
38 const auto valueType = TestType::createValueType();
39 const auto functionType = FunctionType::Create(
40 { pointerType, ioStateType, memoryStateType },
41 { ioStateType, memoryStateType });
44 auto & rvsdg = rvsdgModule.Rvsdg();
46 auto lambdaNode = LambdaNode::Create(
47 rvsdg.GetRootRegion(),
50 auto & addressArgument = *lambdaNode->GetFunctionArguments()[0];
51 auto & ioStateArgument = *lambdaNode->GetFunctionArguments()[1];
52 auto & memoryStateArgument = *lambdaNode->GetFunctionArguments()[2];
54 auto & lambdaEntrySplitNode =
59 { lambdaEntrySplitNode.output(0), lambdaEntrySplitNode.output(1) },
65 { loadNode1.output(1), loadNode1.output(2) },
73 *lambdaNode->subregion(),
74 { loadNode2.output(1), loadNode3.output(1) },
77 lambdaNode->finalize({ &ioStateArgument, lambdaExitMergeNode.output(0) });
94 auto [joinNode, joinOperation] = TryGetSimpleNodeAndOptionalOp<MemoryStateJoinOperation>(
95 *lambdaExitMergeNode.input(0)->origin());
96 EXPECT_TRUE(joinNode && joinOperation);
97 EXPECT_EQ(joinNode->ninputs(), 2u);
99 EXPECT_EQ(TryGetOwnerNode<SimpleNode>(*joinNode->input(0)->origin()), &loadNode2);
100 EXPECT_EQ(TryGetOwnerNode<SimpleNode>(*joinNode->input(1)->origin()), &loadNode1);
102 EXPECT_EQ(loadNode1.input(1)->origin(), lambdaEntrySplitNode.output(0));
103 EXPECT_EQ(loadNode1.input(2)->origin(), lambdaEntrySplitNode.output(1));
105 EXPECT_EQ(loadNode2.input(1)->origin(), lambdaEntrySplitNode.output(0));
106 EXPECT_EQ(loadNode2.input(2)->origin(), lambdaEntrySplitNode.output(1));
111 auto [joinNode, joinOperation] = TryGetSimpleNodeAndOptionalOp<MemoryStateJoinOperation>(
112 *lambdaExitMergeNode.input(1)->origin());
113 EXPECT_TRUE(joinNode && joinOperation);
114 EXPECT_EQ(joinNode->ninputs(), 3u);
116 EXPECT_EQ(TryGetOwnerNode<SimpleNode>(*joinNode->input(0)->origin()), &loadNode3);
117 EXPECT_EQ(TryGetOwnerNode<SimpleNode>(*joinNode->input(1)->origin()), &loadNode2);
118 EXPECT_EQ(TryGetOwnerNode<SimpleNode>(*joinNode->input(2)->origin()), &loadNode1);
120 EXPECT_EQ(loadNode3.input(1)->origin(), lambdaEntrySplitNode.output(1));
124 TEST(LoadChainSeparationTests, LoadVolatile)
134 const auto valueType = TestType::createValueType();
135 const auto functionType = FunctionType::Create(
136 { pointerType, ioStateType, memoryStateType },
137 { ioStateType, memoryStateType });
140 auto & rvsdg = rvsdgModule.Rvsdg();
142 auto lambdaNode = LambdaNode::Create(
143 rvsdg.GetRootRegion(),
146 auto & addressArgument = *lambdaNode->GetFunctionArguments()[0];
147 auto & ioStateArgument = *lambdaNode->GetFunctionArguments()[1];
148 auto & memoryStateArgument = *lambdaNode->GetFunctionArguments()[2];
153 { &memoryStateArgument },
164 lambdaNode->finalize({ &ioStateArgument, loadNode2.output(2) });
180 auto [joinNode, joinOperation] = TryGetSimpleNodeAndOptionalOp<MemoryStateJoinOperation>(
182 EXPECT_TRUE(joinNode && joinOperation);
183 EXPECT_EQ(joinNode->ninputs(), 2u);
185 EXPECT_EQ(TryGetOwnerNode<SimpleNode>(*joinNode->input(0)->origin()), &loadNode2);
186 EXPECT_EQ(TryGetOwnerNode<SimpleNode>(*joinNode->input(1)->origin()), &loadNode1);
188 EXPECT_EQ(loadNode1.input(2)->origin(), &memoryStateArgument);
189 EXPECT_EQ(loadNode2.input(2)->origin(), &memoryStateArgument);
192 TEST(LoadChainSeparationTests, SingleLoad)
202 const auto valueType = TestType::createValueType();
203 const auto functionType = FunctionType::Create(
204 { pointerType, ioStateType, memoryStateType },
205 { ioStateType, memoryStateType });
208 auto & rvsdg = rvsdgModule.Rvsdg();
210 auto lambdaNode = LambdaNode::Create(
211 rvsdg.GetRootRegion(),
214 auto & addressArgument = *lambdaNode->GetFunctionArguments()[0];
215 auto & ioStateArgument = *lambdaNode->GetFunctionArguments()[1];
216 auto & memoryStateArgument = *lambdaNode->GetFunctionArguments()[2];
221 lambdaNode->finalize({ &ioStateArgument, loadNode.output(1) });
240 TEST(LoadChainSeparationTests, LoadAndStore)
250 const auto valueType = TestType::createValueType();
251 const auto functionType = FunctionType::Create(
252 { pointerType, ioStateType, memoryStateType },
253 { ioStateType, memoryStateType });
256 auto & rvsdg = rvsdgModule.Rvsdg();
258 auto lambdaNode = LambdaNode::Create(
259 rvsdg.GetRootRegion(),
262 auto & addressArgument = *lambdaNode->GetFunctionArguments()[0];
263 auto & ioStateArgument = *lambdaNode->GetFunctionArguments()[1];
264 auto & memoryStateArgument = *lambdaNode->GetFunctionArguments()[2];
266 auto valueNode = TestOperation::createNode(lambdaNode->subregion(), {}, { valueType });
276 *valueNode->output(0),
277 { loadNode2.output(1) },
288 *valueNode->output(0),
289 { loadNode4.output(1) },
295 lambdaNode->finalize({ &ioStateArgument, loadNode5.output(1) });
309 auto [joinNode, joinOperation] =
310 TryGetSimpleNodeAndOptionalOp<MemoryStateJoinOperation>(*storeNode2.input(2)->origin());
311 EXPECT_TRUE(joinOperation);
312 EXPECT_EQ(joinNode->ninputs(), 2u);
316 auto [joinNode, joinOperation] =
317 TryGetSimpleNodeAndOptionalOp<MemoryStateJoinOperation>(*storeNode1.input(2)->origin());
318 EXPECT_TRUE(joinOperation);
319 EXPECT_EQ(joinNode->ninputs(), 2u);
323 TEST(LoadChainSeparationTests, GammaWithOnlyLoads)
333 const auto valueType = TestType::createValueType();
334 const auto controlType = ControlType::Create(2);
335 const auto functionType = FunctionType::Create(
336 { controlType, pointerType, ioStateType, memoryStateType },
337 { ioStateType, memoryStateType });
340 auto & rvsdg = rvsdgModule.Rvsdg();
342 auto lambdaNode = LambdaNode::Create(
343 rvsdg.GetRootRegion(),
346 auto & controlArgument = *lambdaNode->GetFunctionArguments()[0];
347 auto & addressArgument = *lambdaNode->GetFunctionArguments()[1];
348 auto & ioStateArgument = *lambdaNode->GetFunctionArguments()[2];
349 auto & memoryStateArgument = *lambdaNode->GetFunctionArguments()[3];
357 auto gammaNode = GammaNode::create(&controlArgument, 2);
358 auto addressEntryVar = gammaNode->AddEntryVar(&addressArgument);
359 auto memoryStateEntryVar = gammaNode->AddEntryVar(loadNode2.output(1));
363 *addressEntryVar.branchArgument[0],
364 { memoryStateEntryVar.branchArgument[0] },
369 *addressEntryVar.branchArgument[0],
370 { loadNode3.output(1) },
376 *addressEntryVar.branchArgument[1],
377 { memoryStateEntryVar.branchArgument[1] },
381 auto memoryStateExitVar = gammaNode->AddExitVar({ loadNode4.output(1), loadNode5.output(1) });
385 { memoryStateExitVar.output },
392 lambdaNode->finalize({ &ioStateArgument, loadNode7.output(1) });
406 auto [joinNode, joinOperation] = TryGetSimpleNodeAndOptionalOp<MemoryStateJoinOperation>(
408 EXPECT_TRUE(joinOperation);
409 EXPECT_EQ(joinNode->ninputs(), 2u);
413 auto [joinNode, joinOperation] = TryGetSimpleNodeAndOptionalOp<MemoryStateJoinOperation>(
414 *gammaNode->GetExitVars()[0].branchResult[0]->origin());
415 EXPECT_TRUE(joinOperation);
416 EXPECT_EQ(joinNode->ninputs(), 2u);
420 auto [joinNode, joinOperation] = TryGetSimpleNodeAndOptionalOp<MemoryStateJoinOperation>(
421 *gammaNode->GetEntryVars()[1].input->origin());
422 EXPECT_TRUE(joinOperation);
423 EXPECT_EQ(joinNode->ninputs(), 2u);
427 TEST(LoadChainSeparationTests, GammaWithLoadsAndStores)
437 const auto valueType = TestType::createValueType();
438 const auto controlType = ControlType::Create(2);
439 const auto functionType = FunctionType::Create(
440 { controlType, pointerType, ioStateType, memoryStateType },
441 { ioStateType, memoryStateType });
444 auto & rvsdg = rvsdgModule.Rvsdg();
446 auto lambdaNode = LambdaNode::Create(
447 rvsdg.GetRootRegion(),
450 auto & controlArgument = *lambdaNode->GetFunctionArguments()[0];
451 auto & addressArgument = *lambdaNode->GetFunctionArguments()[1];
452 auto & ioStateArgument = *lambdaNode->GetFunctionArguments()[2];
453 auto & memoryStateArgument = *lambdaNode->GetFunctionArguments()[3];
458 auto gammaNode = GammaNode::create(&controlArgument, 2);
459 auto addressEntryVar = gammaNode->AddEntryVar(&addressArgument);
460 auto memoryStateEntryVar = gammaNode->AddEntryVar(loadNode1.output(1));
464 *addressEntryVar.branchArgument[0],
465 { memoryStateEntryVar.branchArgument[0] },
470 *addressEntryVar.branchArgument[0],
471 { loadNode2.output(1) },
476 auto value = TestOperation::createNode(gammaNode->subregion(1), {}, { valueType });
478 *addressEntryVar.branchArgument[1],
480 { memoryStateEntryVar.branchArgument[1] },
484 *addressEntryVar.branchArgument[1],
485 { storeNode.output(0) },
489 auto memoryStateExitVar = gammaNode->AddExitVar({ loadNode3.output(1), loadNode4.output(1) });
493 { memoryStateExitVar.output },
500 lambdaNode->finalize({ &ioStateArgument, loadNode6.output(1) });
514 auto [joinNode, joinOperation] = TryGetSimpleNodeAndOptionalOp<MemoryStateJoinOperation>(
516 EXPECT_TRUE(joinOperation);
517 EXPECT_EQ(joinNode->ninputs(), 2u);
521 auto [joinNode, joinOperation] = TryGetSimpleNodeAndOptionalOp<MemoryStateJoinOperation>(
522 *gammaNode->GetExitVars()[0].branchResult[0]->origin());
523 EXPECT_TRUE(joinOperation);
524 EXPECT_EQ(joinNode->ninputs(), 2u);
528 TEST(LoadChainSeparationTests, ThetaWithLoadsOnly)
538 const auto valueType = TestType::createValueType();
539 const auto controlType = ControlType::Create(2);
540 const auto functionType = FunctionType::Create(
541 { controlType, pointerType, ioStateType, memoryStateType },
542 { ioStateType, memoryStateType });
545 auto & rvsdg = rvsdgModule.Rvsdg();
547 auto lambdaNode = LambdaNode::Create(
548 rvsdg.GetRootRegion(),
551 auto & addressArgument = *lambdaNode->GetFunctionArguments()[1];
552 auto & ioStateArgument = *lambdaNode->GetFunctionArguments()[2];
553 auto & memoryStateArgument = *lambdaNode->GetFunctionArguments()[3];
561 auto thetaNode = ThetaNode::create(lambdaNode->subregion());
563 auto addressLoopVar = thetaNode->AddLoopVar(&addressArgument);
564 auto memoryStateLoopVar = thetaNode->AddLoopVar(loadNode2.output(1));
568 { memoryStateLoopVar.pre },
574 { loadNode3.output(1) },
578 memoryStateLoopVar.post->divert_to(loadNode4.output(1));
582 { memoryStateLoopVar.output },
589 lambdaNode->finalize({ &ioStateArgument, loadNode6.output(1) });
603 auto [joinNode, joinOperation] =
604 TryGetSimpleNodeAndOptionalOp<MemoryStateJoinOperation>(*memoryStateLoopVar.post->origin());
605 EXPECT_TRUE(joinOperation);
606 EXPECT_EQ(joinNode->ninputs(), 2u);
611 auto [joinNode, joinOperation] = TryGetSimpleNodeAndOptionalOp<MemoryStateJoinOperation>(
613 EXPECT_TRUE(joinOperation);
614 EXPECT_EQ(joinNode->ninputs(), 5u);
618 TEST(LoadChainSeparationTests, ExternalCall)
628 const auto valueType = TestType::createValueType();
629 const auto controlType = ControlType::Create(2);
630 const auto functionType = FunctionType::Create(
631 { controlType, pointerType, ioStateType, memoryStateType },
632 { ioStateType, memoryStateType });
633 const auto externalFunctionType =
634 FunctionType::Create({ ioStateType, memoryStateType }, { ioStateType, memoryStateType });
637 auto & rvsdg = rvsdgModule.Rvsdg();
641 auto lambdaNode = LambdaNode::Create(
642 rvsdg.GetRootRegion(),
645 auto & addressArgument = *lambdaNode->GetFunctionArguments()[1];
646 auto & ioStateArgument = *lambdaNode->GetFunctionArguments()[2];
647 auto & memoryStateArgument = *lambdaNode->GetFunctionArguments()[3];
648 auto externalFunctionCtxVar = lambdaNode->AddContextVar(externalFunction);
650 auto & lambdaEntrySplitNode =
655 { lambdaEntrySplitNode.output(0) },
664 { lambdaEntrySplitNode.output(1) },
672 *lambdaNode->subregion(),
673 { loadNode2.output(1), loadNode4.output(1) },
677 externalFunctionCtxVar.inner,
678 externalFunctionType,
679 { &ioStateArgument, callEntryMergeNode.output(0) });
681 auto & callExitSplitNode =
686 { callExitSplitNode.output(0) },
695 { callExitSplitNode.output(1) },
703 *lambdaNode->subregion(),
704 { loadNode6.output(1), loadNode8.output(1) },
707 lambdaNode->finalize({ callNode.output(0), lambdaExitMergeNode.output(0) });
721 auto [joinNode, joinOperation] = TryGetSimpleNodeAndOptionalOp<MemoryStateJoinOperation>(
722 *lambdaExitMergeNode.input(0)->origin());
723 EXPECT_TRUE(joinOperation);
725 EXPECT_EQ(joinNode->input(0)->origin(), loadNode6.output(1));
726 EXPECT_EQ(loadNode6.input(1)->origin(), callExitSplitNode.output(0));
728 EXPECT_EQ(joinNode->input(1)->origin(), loadNode5.output(1));
729 EXPECT_EQ(loadNode5.input(1)->origin(), callExitSplitNode.output(0));
733 auto [joinNode, joinOperation] = TryGetSimpleNodeAndOptionalOp<MemoryStateJoinOperation>(
734 *lambdaExitMergeNode.input(1)->origin());
735 EXPECT_TRUE(joinOperation);
737 EXPECT_EQ(joinNode->input(0)->origin(), loadNode8.output(1));
738 EXPECT_EQ(loadNode8.input(1)->origin(), callExitSplitNode.output(1));
740 EXPECT_EQ(joinNode->input(1)->origin(), loadNode7.output(1));
741 EXPECT_EQ(loadNode7.input(1)->origin(), callExitSplitNode.output(1));
745 auto [joinNode, joinOperation] = TryGetSimpleNodeAndOptionalOp<MemoryStateJoinOperation>(
746 *callEntryMergeNode.input(0)->origin());
747 EXPECT_TRUE(joinOperation);
749 EXPECT_EQ(joinNode->input(0)->origin(), loadNode2.output(1));
750 EXPECT_EQ(loadNode2.input(1)->origin(), lambdaEntrySplitNode.output(0));
752 EXPECT_EQ(joinNode->input(1)->origin(), loadNode1.output(1));
753 EXPECT_EQ(loadNode1.input(1)->origin(), lambdaEntrySplitNode.output(0));
757 auto [joinNode, joinOperation] = TryGetSimpleNodeAndOptionalOp<MemoryStateJoinOperation>(
758 *callEntryMergeNode.input(1)->origin());
759 EXPECT_TRUE(joinOperation);
761 EXPECT_EQ(joinNode->input(0)->origin(), loadNode4.output(1));
762 EXPECT_EQ(loadNode4.input(1)->origin(), lambdaEntrySplitNode.output(1));
764 EXPECT_EQ(joinNode->input(1)->origin(), loadNode3.output(1));
765 EXPECT_EQ(loadNode3.input(1)->origin(), lambdaEntrySplitNode.output(1));
769 TEST(LoadChainSeparationTests, DeadOutputs)
776 const auto bit32Type = BitType::Create(32);
780 const auto valueType = TestType::createValueType();
781 const auto functionType = FunctionType::Create(
782 { pointerType, valueType, ioStateType, memoryStateType },
783 { valueType, ioStateType, memoryStateType });
786 auto & rvsdg = rvsdgModule.Rvsdg();
788 auto lambdaNode = LambdaNode::Create(
789 rvsdg.GetRootRegion(),
791 auto & addressArgument = *lambdaNode->GetFunctionArguments()[0];
792 auto & valueArgument = *lambdaNode->GetFunctionArguments()[1];
793 auto & ioStateArgument = *lambdaNode->GetFunctionArguments()[2];
794 auto & memoryStateArgument = *lambdaNode->GetFunctionArguments()[3];
799 { &memoryStateArgument },
810 lambdaNode->finalize({
826 EXPECT_TRUE(loadNode1.output(1)->IsDead());
827 EXPECT_EQ(loadNode1.input(1)->origin(), storeNode.output(0));
828 EXPECT_TRUE(loadNode2.output(1)->IsDead());
829 EXPECT_EQ(loadNode2.input(1)->origin(), storeNode.output(0));
832 TEST(LoadChainSeperationTests, StoreInThetaWithMultipleUsers)
839 const auto bit32Type = BitType::Create(32);
840 const auto controlType = ControlType::Create(2);
841 const auto valueType = TestType::createValueType();
845 const auto functionType = FunctionType::Create(
846 { ioStateType, memoryStateType },
847 { valueType, ioStateType, memoryStateType });
850 auto & rvsdg = rvsdgModule.Rvsdg();
852 auto lambdaNode = LambdaNode::Create(
853 rvsdg.GetRootRegion(),
855 auto & ioStateArgument = *lambdaNode->GetFunctionArguments()[0];
856 auto & memoryStateArgument = *lambdaNode->GetFunctionArguments()[1];
858 auto sizeNode = TestOperation::createNode(lambdaNode->subregion(), {}, { bit32Type });
861 auto lambdaValueNode = TestOperation::createNode(lambdaNode->subregion(), {}, { valueType });
864 *lambdaValueNode->output(0),
865 { allocaResults[1] },
869 auto thetaNode = ThetaNode::create(lambdaNode->subregion());
870 auto loopVar1 = thetaNode->AddLoopVar(&memoryStateArgument);
871 auto loopVar2 = thetaNode->AddLoopVar(lambdaStoreNode.output(0));
873 auto thetaAddressNode = TestOperation::createNode(thetaNode->subregion(), {}, { pointerType });
874 auto thetaValueNode = TestOperation::createNode(thetaNode->subregion(), {}, { valueType });
876 *thetaAddressNode->output(0),
881 *thetaAddressNode->output(0),
882 *thetaValueNode->output(0),
883 { thetaLoadNode.output(1) },
887 auto gammaPredicateNode = TestOperation::createNode(thetaNode->subregion(), {}, { controlType });
888 auto gammaNode = GammaNode::create(gammaPredicateNode->output(0), 2);
890 auto entryVar1 = gammaNode->AddEntryVar(thetaStoreNode.output(0));
891 auto entryVar2 = gammaNode->AddEntryVar(loopVar1.pre);
893 auto gammaAddressNode = TestOperation::createNode(gammaNode->subregion(1), {}, { pointerType });
894 auto gammaValueNode = TestOperation::createNode(gammaNode->subregion(1), {}, { valueType });
896 *gammaAddressNode->output(0),
897 *gammaValueNode->output(0),
898 { entryVar2.branchArgument[1] },
902 gammaNode->AddExitVar({ entryVar1.branchArgument[0], entryVar1.branchArgument[1] });
903 auto exitVar2 = gammaNode->AddExitVar({ entryVar2.branchArgument[0], gammaStoreNode.output(0) });
906 loopVar1.post->divert_to(exitVar2.output);
907 loopVar2.post->divert_to(thetaStoreNode.output(0));
910 auto & lambdaLoadNode =
914 lambdaNode->finalize({ lambdaLoadNode.output(0), &ioStateArgument, loopVar1.output });
916 GraphExport::Create(*lambdaOutput,
"f");
929 EXPECT_EQ(lambdaNode->subregion()->numNodes(), 6u);
930 EXPECT_EQ(thetaNode->subregion()->numNodes(), 7u);
931 EXPECT_EQ(gammaNode->subregion(0)->numNodes(), 0u);
932 EXPECT_EQ(gammaNode->subregion(1)->numNodes(), 3u);
935 EXPECT_NE(TryGetOwnerNode<ThetaNode>(*lambdaLoadNode.input(1)->origin()),
nullptr);
static jlm::util::StatisticsCollector statisticsCollector
TEST(LoadChainSeparationTests, LoadNonVolatile)
static std::vector< rvsdg::Output * > create(std::shared_ptr< const rvsdg::Type > allocatedType, rvsdg::Output *count, const size_t alignment)
static rvsdg::SimpleNode & CreateNode(rvsdg::Region ®ion, const std::vector< rvsdg::Output * > &operands, std::vector< MemoryNodeId > memoryNodeIds)
static rvsdg::SimpleNode & CreateNode(rvsdg::Output &operand, std::vector< MemoryNodeId > memoryNodeIds)
static rvsdg::SimpleNode & CreateNode(rvsdg::Region ®ion, std::unique_ptr< CallOperation > callOperation, const std::vector< rvsdg::Output * > &operands)
static std::shared_ptr< const IOStateType > Create()
static rvsdg::SimpleNode & CreateNode(rvsdg::Output &operand, std::vector< MemoryNodeId > memoryNodeIds)
static rvsdg::SimpleNode & CreateNode(rvsdg::Region ®ion, const std::vector< rvsdg::Output * > &operands, const std::vector< MemoryNodeId > &memoryNodeIds)
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)
void Run(rvsdg::RvsdgModule &module, util::StatisticsCollector &statisticsCollector) override
Perform RVSDG transformation.
static rvsdg::SimpleNode & CreateNode(rvsdg::Region ®ion, std::unique_ptr< LoadNonVolatileOperation > loadOperation, const std::vector< rvsdg::Output * > &operands)
static rvsdg::Node::OutputIteratorRange MemoryStateOutputs(const rvsdg::Node &node) noexcept
static rvsdg::Node::InputIteratorRange MemoryStateInputs(const rvsdg::Node &node) noexcept
static rvsdg::SimpleNode & CreateNode(rvsdg::Region ®ion, std::unique_ptr< LoadVolatileOperation > loadOperation, const std::vector< rvsdg::Output * > &operands)
static rvsdg::Output & IOStateOutput(const rvsdg::Node &node)
static std::shared_ptr< const MemoryStateType > Create()
static std::shared_ptr< const PointerType > Create()
static rvsdg::SimpleNode & CreateNode(rvsdg::Output &address, rvsdg::Output &value, const std::vector< rvsdg::Output * > &memoryStates, size_t alignment)
static jlm::rvsdg::Output * Create(rvsdg::Region ®ion, std::shared_ptr< const jlm::rvsdg::Type > type)
static GraphImport & Create(Graph &graph, std::shared_ptr< const rvsdg::Type > type, std::string name)
Global memory state passed between functions.
rvsdg::Input & GetMemoryStateRegionResult(const rvsdg::LambdaNode &lambdaNode) noexcept
std::string view(const rvsdg::Region *region)