6 #include <gtest/gtest.h>
25 TEST(CallOperationTests, TestCopy)
52 auto node = jlm::rvsdg::TryGetOwnerNode<jlm::rvsdg::SimpleNode>(*callResults[0]);
54 node->copy(&rvsdg.GetRootRegion(), { function2, value2, iOState2, memoryState2 });
59 jlm::util::assertedCast<jlm::rvsdg::SimpleNode>(copiedNode)->GetOperation());
62 TEST(CallOperationTests, TestCallNodeAccessors)
68 auto valueType = TestType::createValueType();
84 *jlm::util::assertedCast<SimpleNode>(jlm::rvsdg::TryGetOwnerNode<Node>(*results[0]));
93 EXPECT_EQ(callNode.noutputs(), 3u);
94 EXPECT_EQ(*callNode.output(0)->Type(), *valueType);
95 EXPECT_EQ(*callNode.output(1)->Type(), *iOStateType);
96 EXPECT_EQ(*callNode.output(2)->Type(), *memoryStateType);
106 TEST(CallOperationTests, TestCallTypeClassifierIndirectCall)
122 auto graph = &module->Rvsdg();
124 auto SetupFunction = [&]()
127 graph->GetRootRegion(),
129 auto iOStateArgument = lambda->GetFunctionArguments()[1];
130 auto memoryStateArgument = lambda->GetFunctionArguments()[2];
138 lambda->GetFunctionArguments()[0],
143 auto fn = jlm::rvsdg::CreateOpNode<PointerToFunctionOperation>({ load[0] }, fcttype1).output(0);
148 lambda->finalize(callResults);
152 return std::make_tuple(
153 jlm::util::assertedCast<jlm::rvsdg::SimpleNode>(
154 jlm::rvsdg::TryGetOwnerNode<jlm::rvsdg::Node>(*callResults[0])),
158 auto [callNode, loadOutput] = SetupFunction();
164 EXPECT_TRUE(callTypeClassifier->IsIndirectCall());
165 EXPECT_EQ(loadOutput, &callTypeClassifier->GetFunctionOrigin());
168 TEST(CallOperationTests, TestCallTypeClassifierNonRecursiveDirectCall)
175 auto graph = &module->Rvsdg();
185 auto SetupFunctionG = [&]()
188 graph->GetRootRegion(),
190 auto iOStateArgument = lambda->GetFunctionArguments()[0];
191 auto memoryStateArgument = lambda->GetFunctionArguments()[1];
193 auto constant = TestOperation::createNode(lambda->subregion(), {}, { vt });
196 lambda->finalize({ constant->output(0), iOStateArgument, memoryStateArgument });
206 auto otf = outerTheta->AddLoopVar(functionG);
209 auto itf = innerTheta->AddLoopVar(otf.pre);
213 auto ev = gamma->AddEntryVar(itf.pre);
214 auto xv = gamma->AddExitVar(ev.branchArgument);
216 itf.post->divert_to(xv.output);
217 otf.post->divert_to(itf.output);
231 graph->GetRootRegion(),
233 auto functionGArgument = lambda->AddContextVar(*g).inner;
234 auto iOStateArgument = lambda->GetFunctionArguments()[0];
235 auto memoryStateArgument = lambda->GetFunctionArguments()[1];
237 auto functionG = SetupOuterTheta(lambda->subregion(), functionGArgument);
242 { iOStateArgument, memoryStateArgument });
244 lambda->finalize(callResults);
246 return std::make_tuple(
248 jlm::util::assertedCast<jlm::rvsdg::SimpleNode>(
249 jlm::rvsdg::TryGetOwnerNode<jlm::rvsdg::Node>(*callResults[0])));
252 auto g = SetupFunctionG();
253 auto [f, callNode] = SetupFunctionF(g);
263 EXPECT_TRUE(callTypeClassifier->IsNonRecursiveDirectCall());
264 EXPECT_EQ(&callTypeClassifier->GetLambdaOutput(), g);
267 TEST(CallOperationTests, TestCallTypeClassifierNonRecursiveDirectCallTheta)
274 auto graph = &module->Rvsdg();
284 auto SetupFunctionG = [&]()
287 graph->GetRootRegion(),
289 auto iOStateArgument = lambda->GetFunctionArguments()[0];
290 auto memoryStateArgument = lambda->GetFunctionArguments()[1];
292 auto c1 = TestOperation::createNode(lambda->subregion(), {}, { vt });
294 return lambda->finalize({ c1->output(0), iOStateArgument, memoryStateArgument });
308 auto thetaOutputG = innerTheta->AddLoopVar(g);
314 auto thetaOutputG = outerTheta->AddLoopVar(g);
315 auto thetaOutputValue = outerTheta->AddLoopVar(value);
316 auto thetaOutputIoState = outerTheta->AddLoopVar(iOState);
317 auto thetaOutputMemoryState = outerTheta->AddLoopVar(memoryState);
319 auto functionG = SetupInnerTheta(outerTheta->subregion(), thetaOutputG.pre);
324 { thetaOutputIoState.pre, thetaOutputMemoryState.pre });
326 thetaOutputG.post->divert_to(functionG.output);
327 thetaOutputValue.post->divert_to(callResults[0]);
328 thetaOutputIoState.post->divert_to(callResults[1]);
329 thetaOutputMemoryState.post->divert_to(callResults[2]);
331 return std::make_tuple(
334 thetaOutputMemoryState,
335 jlm::util::assertedCast<jlm::rvsdg::SimpleNode>(
336 jlm::rvsdg::TryGetOwnerNode<jlm::rvsdg::Node>(*callResults[0])));
348 graph->GetRootRegion(),
350 auto functionG = lambda->AddContextVar(*g).inner;
351 auto iOStateArgument = lambda->GetFunctionArguments()[0];
352 auto memoryStateArgument = lambda->GetFunctionArguments()[1];
354 auto value = TestOperation::createNode(lambda->subregion(), {}, { vt })->output(0);
356 auto [loopValue, iOState, memoryState, callNode] = SetupOuterTheta(
361 memoryStateArgument);
363 auto lambdaOutput = lambda->finalize({ loopValue.output, iOState.output, memoryState.output });
365 return std::make_tuple(lambdaOutput, callNode);
368 auto g = SetupFunctionG();
369 auto [f, callNode] = SetupFunctionF(g);
378 EXPECT_TRUE(callTypeClassifier->IsNonRecursiveDirectCall());
379 EXPECT_EQ(&callTypeClassifier->GetLambdaOutput(), g);
382 TEST(CallOperationTests, TestCallTypeClassifierRecursiveDirectCall)
388 auto graph = &module->Rvsdg();
390 auto SetupFib = [&]()
403 pb.
begin(&graph->GetRootRegion());
409 auto valueArgument = lambda->GetFunctionArguments()[0];
410 auto pointerArgument = lambda->GetFunctionArguments()[1];
411 auto iOStateArgument = lambda->GetFunctionArguments()[2];
412 auto memoryStateArgument = lambda->GetFunctionArguments()[3];
413 auto ctxVarFib = lambda->AddContextVar(*fibrv.recref).inner;
420 auto nev = gammaNode->AddEntryVar(valueArgument);
421 auto resultev = gammaNode->AddEntryVar(pointerArgument);
422 auto fibev = gammaNode->AddEntryVar(ctxVarFib);
423 auto gIIoState = gammaNode->AddEntryVar(iOStateArgument);
424 auto gIMemoryState = gammaNode->AddEntryVar(memoryStateArgument);
430 fibev.branchArgument[0],
433 resultev.branchArgument[0],
434 gIIoState.branchArgument[0],
435 gIMemoryState.branchArgument[0] });
440 fibev.branchArgument[0],
442 { nm2, resultev.branchArgument[0], callfibm1Results[0], callfibm1Results[1] });
445 resultev.branchArgument[0],
450 { callfibm2Results[1] },
455 resultev.branchArgument[0],
466 auto sumex = gammaNode->AddExitVar({ sum, nev.branchArgument[1] });
467 auto gOIoState = gammaNode->AddExitVar({ callfibm2Results[0], gIIoState.branchArgument[1] });
468 auto gOMemoryState = gammaNode->AddExitVar({ ldnm2[1], gIMemoryState.branchArgument[1] });
476 auto lambdaOutput = lambda->finalize({ gOIoState.output, store[0] });
478 fibrv.result->divert_to(lambdaOutput);
483 return std::make_tuple(
485 jlm::util::assertedCast<jlm::rvsdg::SimpleNode>(
486 jlm::rvsdg::TryGetOwnerNode<jlm::rvsdg::Node>(*callfibm1Results[0])),
487 jlm::util::assertedCast<jlm::rvsdg::SimpleNode>(
488 jlm::rvsdg::TryGetOwnerNode<jlm::rvsdg::Node>(*callfibm2Results[0])));
491 auto [fibfct, callFib1, callFib2] = SetupFib();
498 EXPECT_TRUE(callTypeClassifier1->IsRecursiveDirectCall());
499 EXPECT_EQ(&callTypeClassifier1->GetLambdaOutput(), fibfct);
501 EXPECT_TRUE(callTypeClassifier2->IsRecursiveDirectCall());
502 EXPECT_EQ(&callTypeClassifier2->GetLambdaOutput(), fibfct);
TEST(CallOperationTests, TestCopy)
static std::vector< rvsdg::Output * > create(std::shared_ptr< const rvsdg::Type > allocatedType, rvsdg::Output *count, const size_t alignment)
static rvsdg::Input * Argument(const rvsdg::Node &node, const size_t n)
static rvsdg::Input & GetIOStateInput(const rvsdg::Node &node) noexcept
static rvsdg::Input & GetFunctionInput(const rvsdg::Node &node) noexcept
static std::unique_ptr< CallTypeClassifier > ClassifyCall(const rvsdg::SimpleNode &callNode)
Classifies a call node.
static rvsdg::Input & GetMemoryStateInput(const rvsdg::Node &node) noexcept
static size_t NumArguments(const rvsdg::Node &node) noexcept
static rvsdg::Output & GetIOStateOutput(const rvsdg::Node &node) noexcept
static rvsdg::Output & GetMemoryStateOutput(const rvsdg::Node &node) noexcept
static std::vector< rvsdg::Output * > Create(rvsdg::Output *function, std::shared_ptr< const rvsdg::FunctionType > functionType, const std::vector< rvsdg::Output * > &arguments)
static rvsdg::Output * create(rvsdg::Output *baseAddress, const std::vector< rvsdg::Output * > &indices, std::shared_ptr< const rvsdg::Type > pointeeType)
static std::shared_ptr< const IOStateType > Create()
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::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)
static std::shared_ptr< const MemoryStateType > Create()
static std::shared_ptr< const PointerType > Create()
static std::unique_ptr< llvm::ThreeAddressCode > Create(const Variable *address, const Variable *value, const Variable *state, size_t alignment)
static Output & create(Region ®ion, BitValueRepresentation value)
static std::shared_ptr< const BitType > Create(std::size_t nbits)
Creates bit type of specified width.
static Output & createFalse(Region ®ion)
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)
static GraphExport & Create(Output &origin, std::string name)
static GraphImport & Create(Graph &graph, std::shared_ptr< const rvsdg::Type > type, std::string name)
static LambdaNode * Create(rvsdg::Region &parent, std::unique_ptr< LambdaOperation > operation)
std::unique_ptr< BitBinaryOperation > create(size_t nbits) const override
std::unique_ptr< BitCompareOperation > create(size_t nbits) const override
static Node & CreateNode(Output &predicate, const std::unordered_map< uint64_t, uint64_t > &mapping, const uint64_t defaultAlternative, const size_t numAlternatives)
rvsdg::Region * subregion() const noexcept
PhiNode::FixVar AddFixVar(std::shared_ptr< const jlm::rvsdg::Type > type)
void begin(rvsdg::Region *parent)
Represent acyclic RVSDG subgraphs.
static std::shared_ptr< const TestType > createValueType()
static ThetaNode * create(rvsdg::Region *parent)
Global memory state passed between functions.
std::string view(const rvsdg::Region *region)