6 #include <gtest/gtest.h>
25 TEST(RvsdgToIpGraphConverterTests, GammaWithMatch)
32 auto valueType = TestType::createValueType();
40 rvsdgModule.Rvsdg().GetRootRegion(),
44 MatchOperation::CreateNode(*lambdaNode->GetFunctionArguments()[0], { { 0, 0 } }, 1, 2);
45 auto gamma = GammaNode::create(matchNode.output(0), 2);
46 auto gammaInput1 = gamma->AddEntryVar(lambdaNode->GetFunctionArguments()[1]);
47 auto gammaInput2 = gamma->AddEntryVar(lambdaNode->GetFunctionArguments()[2]);
49 gamma->AddExitVar({ gammaInput1.branchArgument[0], gammaInput2.branchArgument[1] });
51 auto lambdaOutput = lambdaNode->finalize({ gammaOutput.output });
52 GraphExport::Create(*lambdaOutput,
"");
54 view(rvsdgModule.Rvsdg(), stdout);
59 print(*module, stdout);
62 auto & ipg = module->ipgraph();
63 EXPECT_EQ(ipg.nnodes(), 1u);
65 auto cfg =
dynamic_cast<const FunctionNode &
>(*ipg.begin()).cfg();
66 EXPECT_EQ(cfg->nnodes(), 4u);
69 TEST(RvsdgToIpGraphConverterTests, GammaWithoutMatch)
84 rvsdgModule.Rvsdg().GetRootRegion(),
88 auto gammaInput1 = gammaNode->AddEntryVar(lambdaNode->GetFunctionArguments()[1]);
89 auto gammaInput2 = gammaNode->AddEntryVar(lambdaNode->GetFunctionArguments()[2]);
91 gammaNode->AddExitVar({ gammaInput1.branchArgument[0], gammaInput2.branchArgument[1] });
93 auto lambdaOutput = lambdaNode->finalize({ gammaOutput.output });
94 GraphExport::Create(*lambdaOutput,
"");
101 print(*module, stdout);
104 auto & ipg = module->ipgraph();
105 EXPECT_EQ(ipg.nnodes(), 1u);
107 auto cfg =
dynamic_cast<const FunctionNode &
>(*ipg.begin()).cfg();
108 EXPECT_EQ(cfg->nnodes(), 4u);
111 TEST(RvsdgToIpGraphConverterTests, EmptyGammaWithTwoSubregionsAndMatch)
126 rvsdgModule.Rvsdg().GetRootRegion(),
128 const auto conditionValue = lambdaNode->GetFunctionArguments()[0];
129 const auto trueValue = lambdaNode->GetFunctionArguments()[1];
130 const auto falseValue = lambdaNode->GetFunctionArguments()[2];
133 auto & matchNode = MatchOperation::CreateNode(*conditionValue, { { caseValue, 0 } }, 1, 2);
136 auto [inputTrue, branchArgumentTrue] = gammaNode->AddEntryVar(trueValue);
137 auto [inputFalse, branchArgumentFalse] = gammaNode->AddEntryVar(falseValue);
138 auto [_, gammaOutput] = gammaNode->AddExitVar({ branchArgumentTrue[0], branchArgumentFalse[1] });
140 const auto lambdaOutput = lambdaNode->finalize({ gammaOutput });
141 GraphExport::Create(*lambdaOutput,
"");
143 view(rvsdgModule.Rvsdg(), stdout);
149 print(*module, stdout);
152 const auto & ipGraph = module->ipgraph();
153 EXPECT_EQ(ipGraph.nnodes(), 1u);
155 const auto controlFlowGraph =
dynamic_cast<const FunctionNode &
>(*ipGraph.begin()).cfg();
156 EXPECT_TRUE(
is_closed(*controlFlowGraph));
159 TEST(RvsdgToIpGraphConverterTests, EmptyGammaWithTwoSubregions)
174 rvsdgModule.Rvsdg().GetRootRegion(),
176 const auto trueValue = lambdaNode->GetFunctionArguments()[1];
177 const auto falseValue = lambdaNode->GetFunctionArguments()[2];
180 MatchOperation::CreateNode(*lambdaNode->GetFunctionArguments()[0], { { 0, 0 } }, 1, 2);
183 const auto & c0 = jlm::rvsdg::CreateOpNode<ControlConstantOperation>(
184 *gammaNode0->subregion(0),
186 const auto & c1 = jlm::rvsdg::CreateOpNode<ControlConstantOperation>(
187 *gammaNode0->subregion(1),
189 auto c = gammaNode0->AddExitVar({ c0.output(0), c1.output(0) });
192 auto [inputTrue, branchArgumentTrue] = gammaNode1->AddEntryVar(trueValue);
193 auto [inputFalse, branchArgumentFalse] = gammaNode1->AddEntryVar(falseValue);
194 auto [_, gammaOutput] = gammaNode1->AddExitVar({ branchArgumentFalse[0], branchArgumentTrue[1] });
196 const auto lambdaOutput = lambdaNode->finalize({ gammaOutput });
197 GraphExport::Create(*lambdaOutput,
"");
199 view(rvsdgModule.Rvsdg(), stdout);
205 print(*module, stdout);
208 const auto & ipGraph = module->ipgraph();
209 EXPECT_EQ(ipGraph.nnodes(), 1u);
211 const auto controlFlowGraph =
dynamic_cast<const FunctionNode &
>(*ipGraph.begin()).cfg();
212 EXPECT_TRUE(
is_closed(*controlFlowGraph));
215 TEST(RvsdgToIpGraphConverterTests, EmptyGammaWithThreeSubregions)
230 rvsdgModule.Rvsdg().GetRootRegion(),
233 auto & matchNode = MatchOperation::CreateNode(
234 *lambdaNode->GetFunctionArguments()[0],
235 { { 0, 0 }, { 1, 1 } },
240 auto gammaInput1 = gammaNode->AddEntryVar(lambdaNode->GetFunctionArguments()[1]);
241 auto gammaInput2 = gammaNode->AddEntryVar(lambdaNode->GetFunctionArguments()[2]);
242 auto gammaOutput = gammaNode->AddExitVar({ gammaInput1.branchArgument[0],
243 gammaInput1.branchArgument[1],
244 gammaInput2.branchArgument[2] });
246 auto lambdaOutput = lambdaNode->finalize({ gammaOutput.output });
247 GraphExport::Create(*lambdaOutput,
"");
254 print(*module, stdout);
257 auto & ipg = module->ipgraph();
258 EXPECT_EQ(ipg.nnodes(), 1u);
260 auto cfg =
dynamic_cast<const FunctionNode &
>(*ipg.begin()).cfg();
264 TEST(RvsdgToIpGraphConverterTests, PartialEmptyGamma)
279 rvsdgModule.Rvsdg().GetRootRegion(),
283 MatchOperation::CreateNode(*lambdaNode->GetFunctionArguments()[0], { { 0, 0 } }, 1, 2);
284 auto gammaNode = GammaNode::create(matchNode.output(0), 2);
285 auto gammaInput = gammaNode->AddEntryVar(lambdaNode->GetFunctionArguments()[1]);
286 auto output = TestOperation::createNode(
287 gammaNode->subregion(1),
288 { gammaInput.branchArgument[1] },
291 auto gammaOutput = gammaNode->AddExitVar({ gammaInput.branchArgument[0], output });
293 auto lambdaOutput = lambdaNode->finalize({ gammaOutput.output });
295 GraphExport::Create(*lambdaOutput,
"");
304 auto & ipg = module->ipgraph();
305 EXPECT_EQ(ipg.nnodes(), 1u);
307 auto cfg =
dynamic_cast<const FunctionNode &
>(*ipg.begin()).cfg();
313 TEST(RvsdgToIpGraphConverterTests, RecursiveData)
319 auto vt = TestType::createValueType();
340 Output *delta1 =
nullptr, *delta2 =
nullptr;
342 auto delta = DeltaNode::Create(
345 auto dep1 = delta->AddContextVar(*fixVar2.recref).inner;
346 auto dep2 = delta->AddContextVar(*dep.inner).inner;
347 delta1 = &delta->finalize(
348 TestOperation::createNode(delta->subregion(), { dep1, dep2 }, { vt })->output(0));
352 auto delta = DeltaNode::Create(
355 auto dep1 = delta->AddContextVar(*fixVar1.recref).inner;
356 auto dep2 = delta->AddContextVar(*dep.inner).inner;
357 delta2 = &delta->finalize(
358 TestOperation::createNode(delta->subregion(), { dep1, dep2 }, { vt })->output(0));
361 fixVar1.result->divert_to(delta1);
362 fixVar2.result->divert_to(delta2);
364 auto phi = phiBuilder.
end();
365 GraphExport::Create(*phi->output(0),
"");
372 print(*module, stdout);
375 auto & ipGraph = module->ipgraph();
376 EXPECT_EQ(ipGraph.nnodes(), 3u);
378 auto delta1Node = ipGraph.find(
"delta1");
379 auto delta2Node = ipGraph.find(
"delta2");
380 auto importNode = ipGraph.find(
"import");
381 EXPECT_EQ(delta1Node->numDependencies(), 2u);
382 for (
auto depNode : *delta1Node)
384 EXPECT_TRUE(depNode == delta2Node || depNode == importNode);
387 EXPECT_EQ(delta2Node->numDependencies(), 2u);
388 for (
auto depNode : *delta2Node)
390 EXPECT_TRUE(depNode == delta1Node || depNode == importNode);
393 EXPECT_EQ(importNode->numDependencies(), 0u);
403 for (
const auto tac : basicBlock.
tacs())
405 if (is<SsaPhiOperation>(tac))
412 TEST(RvsdgToIpGraphConverterTests, NestedLoopWithCall)
423 FunctionType::Create({ ioStateType, memoryStateType }, { ioStateType, memoryStateType });
426 auto & rvsdg = rvsdgModule.Rvsdg();
435 auto lambdaNode = LambdaNode::Create(
436 rvsdg.GetRootRegion(),
438 auto ioStateArgument = lambdaNode->GetFunctionArguments()[0];
439 auto memoryStateArgument = lambdaNode->GetFunctionArguments()[1];
440 auto opaqueCtxVar = lambdaNode->AddContextVar(opaque);
442 auto outerThetaNode = ThetaNode::create(lambdaNode->subregion());
443 auto outerIOStateLoopVar = outerThetaNode->AddLoopVar(ioStateArgument);
444 auto outerMemoryStateLoopVar = outerThetaNode->AddLoopVar(memoryStateArgument);
445 auto outerOpaque = outerThetaNode->AddLoopVar(opaqueCtxVar.inner);
447 auto innerThetaNode = ThetaNode::create(outerThetaNode->subregion());
448 auto innerIOStateLoopVar = innerThetaNode->AddLoopVar(outerIOStateLoopVar.pre);
449 auto innerMemoryStateLoopVar = innerThetaNode->AddLoopVar(outerMemoryStateLoopVar.pre);
450 auto innerOpaque = innerThetaNode->AddLoopVar(outerOpaque.pre);
455 { innerIOStateLoopVar.pre, innerMemoryStateLoopVar.pre });
457 innerIOStateLoopVar.post->divert_to(callNode.output(0));
458 innerMemoryStateLoopVar.post->divert_to(callNode.output(1));
460 outerIOStateLoopVar.post->divert_to(innerIOStateLoopVar.output);
461 outerMemoryStateLoopVar.post->divert_to(innerMemoryStateLoopVar.output);
462 outerOpaque.post->divert_to(innerOpaque.output);
465 lambdaNode->finalize({ outerIOStateLoopVar.output, outerMemoryStateLoopVar.output });
467 GraphExport::Create(*lambdaOutput,
"f");
469 view(rvsdgModule.Rvsdg(), stdout);
476 print(*ipGraphModule, stdout);
482 auto & ipGraph = ipGraphModule->ipgraph();
483 EXPECT_EQ(ipGraph.nnodes(), 2u);
485 auto functionNode = ipGraph.find(
"f");
486 auto importNode = ipGraph.find(
"opaque");
487 EXPECT_EQ(functionNode->numDependencies(), 1u);
488 EXPECT_EQ(importNode->numDependencies(), 0u);
489 EXPECT_EQ(*functionNode->begin(), importNode);
491 auto controlFlowGraph =
dynamic_cast<const FunctionNode *
>(ipGraph.find(
"f"))->cfg();
492 EXPECT_EQ(controlFlowGraph->nnodes(), 5u);
494 for (
auto & basicBlock : *controlFlowGraph)
497 EXPECT_TRUE(numSsaPhis == 2 || numSsaPhis == 0);
502 std::shared_ptr<const jlm::rvsdg::Type>,
517 auto [valueType, name, linkage, isConstant, alignment] = GetParam();
535 const auto ipGraphModule =
538 print(*ipGraphModule, stdout);
541 const auto & ipGraph = ipGraphModule->ipgraph();
542 EXPECT_EQ(ipGraph.nnodes(), 1u);
544 const auto dataNode =
dynamic_cast<const DataNode *
>(&*ipGraph.begin());
545 EXPECT_NE(dataNode,
nullptr);
547 EXPECT_EQ(dataNode->GetValueType(), valueType);
548 EXPECT_EQ(dataNode->name(), name);
549 EXPECT_EQ(dataNode->linkage(), linkage);
550 EXPECT_EQ(dataNode->constant(), isConstant);
551 EXPECT_EQ(dataNode->getAlignment(), alignment);
557 ::testing::Values(std::make_tuple(
566 ::testing::Values(std::make_tuple(
575 ::testing::Values(std::make_tuple(
static jlm::util::StatisticsCollector statisticsCollector
INSTANTIATE_TEST_SUITE_P(Test1, DataImportConversionTest, ::testing::Values(std::make_tuple(jlm::rvsdg::TestType::createValueType(), "name", jlm::llvm::Linkage::externalLinkage, false, 4)))
static size_t numSsaPhiOperations(const jlm::llvm::BasicBlock &basicBlock)
TEST_P(DataImportConversionTest, Test)
TEST(RvsdgToIpGraphConverterTests, GammaWithMatch)
const ThreeAddressCodeList & tacs() const noexcept
static rvsdg::SimpleNode & CreateNode(rvsdg::Region ®ion, std::unique_ptr< CallOperation > callOperation, const std::vector< rvsdg::Output * > &operands)
static std::string ToAscii(const ControlFlowGraph &controlFlowGraph)
static std::unique_ptr< DeltaOperation > Create(std::shared_ptr< const rvsdg::Type > type, const std::string &name, const Linkage &linkage, std::string section, bool constant, const size_t alignment)
static std::shared_ptr< const IOStateType > Create()
static LlvmGraphImport & createGlobalImport(rvsdg::Graph &graph, std::shared_ptr< const rvsdg::Type > valueType, std::shared_ptr< const rvsdg::Type > importedType, std::string name, Linkage linkage, const bool isConstant, const size_t alignment)
static LlvmGraphImport & createFunctionImport(rvsdg::Graph &graph, std::shared_ptr< const rvsdg::FunctionType > functionType, std::string name, Linkage linkage, CallingConvention callingConvention)
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)
static std::shared_ptr< const MemoryStateType > Create()
static std::shared_ptr< const PointerType > Create()
static std::unique_ptr< InterProceduralGraphModule > CreateAndConvertModule(LlvmRvsdgModule &rvsdgModule, util::StatisticsCollector &statisticsCollector)
static std::shared_ptr< const BitType > Create(std::size_t nbits)
Creates bit type of specified width.
static std::shared_ptr< const ControlType > Create(std::size_t nalternatives)
Instantiates control type.
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)
Region & GetRootRegion() const noexcept
static LambdaNode * Create(rvsdg::Region &parent, std::unique_ptr< LambdaOperation > operation)
rvsdg::Region * subregion() const noexcept
PhiNode::ContextVar AddContextVar(jlm::rvsdg::Output &origin)
PhiNode::FixVar AddFixVar(std::shared_ptr< const jlm::rvsdg::Type > type)
void begin(rvsdg::Region *parent)
static std::shared_ptr< const TestType > createValueType()
Global memory state passed between functions.
void print(const AggregationNode &n, const AnnotationMap &dm, FILE *out)
bool is_proper_structured(const ControlFlowGraph &cfg)
bool is_closed(const ControlFlowGraph &cfg)
std::string view(const rvsdg::Region *region)